Merge "Revert "Fixed poor behavior of position-based focus order""
diff --git a/Android.mk b/Android.mk
index e766e60..0e5dfed 100644
--- a/Android.mk
+++ b/Android.mk
@@ -37,6 +37,9 @@
 
 include $(CLEAR_VARS)
 
+# Load framework-specific path mappings used later in the build.
+include $(LOCAL_PATH)/pathmap.mk
+
 # FRAMEWORKS_BASE_SUBDIRS comes from build/core/pathmap.mk
 LOCAL_SRC_FILES := \
         $(call find-other-java-files,$(FRAMEWORKS_BASE_SUBDIRS)) \
@@ -81,6 +84,7 @@
 	core/java/android/app/ITaskStackListener.aidl \
 	core/java/android/app/IBackupAgent.aidl \
 	core/java/android/app/IEphemeralResolver.aidl \
+	core/java/android/app/IInstantAppResolver.aidl \
 	core/java/android/app/IInstrumentationWatcher.aidl \
 	core/java/android/app/INotificationManager.aidl \
 	core/java/android/app/IProcessObserver.aidl \
@@ -109,6 +113,7 @@
 	core/java/android/app/backup/IRestoreObserver.aidl \
 	core/java/android/app/backup/IRestoreSession.aidl \
 	core/java/android/app/backup/ISelectBackupTransportCallback.aidl \
+	core/java/android/app/usage/ICacheQuotaService.aidl \
 	core/java/android/app/usage/IStorageStatsManager.aidl \
 	core/java/android/app/usage/IUsageStatsManager.aidl \
 	core/java/android/bluetooth/IBluetooth.aidl \
@@ -135,9 +140,11 @@
 	core/java/android/bluetooth/IBluetoothInputHost.aidl \
 	core/java/android/bluetooth/IBluetoothHidDeviceCallback.aidl \
 	core/java/android/bluetooth/IBluetoothGatt.aidl \
-	core/java/android/bluetooth/IBluetoothGattCallback.aidl \
-	core/java/android/bluetooth/IBluetoothGattServerCallback.aidl \
+	core/java/android/bluetooth/IBluetoothGattCallbackExt.aidl \
+	core/java/android/bluetooth/IBluetoothGattServerCallbackExt.aidl \
 	core/java/android/bluetooth/le/IAdvertiserCallback.aidl \
+	core/java/android/bluetooth/le/IAdvertisingSetCallback.aidl \
+	core/java/android/bluetooth/le/IPeriodicAdvertisingCallback.aidl \
 	core/java/android/bluetooth/le/IScannerCallback.aidl \
 	core/java/android/content/IClipboard.aidl \
 	core/java/android/content/IContentService.aidl \
@@ -212,7 +219,6 @@
 	core/java/android/hardware/usb/IUsbManager.aidl \
 	core/java/android/net/ICaptivePortal.aidl \
 	core/java/android/net/IConnectivityManager.aidl \
-	core/java/android/net/IConnectivityMetricsLogger.aidl \
 	core/java/android/net/IIpConnectivityMetrics.aidl \
 	core/java/android/net/IEthernetManager.aidl \
 	core/java/android/net/IEthernetServiceListener.aidl \
@@ -265,6 +271,7 @@
 	core/java/android/security/IKeystoreService.aidl \
 	core/java/android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl \
 	core/java/android/service/autofill/IAutoFillService.aidl \
+	core/java/android/service/autofill/IAutoFillServiceConnection.aidl \
 	core/java/android/service/autofill/IFillCallback.aidl \
 	core/java/android/service/autofill/ISaveCallback.aidl \
 	core/java/android/service/carrier/ICarrierService.aidl \
@@ -322,6 +329,7 @@
 	core/java/android/view/IAppTransitionAnimationSpecsFuture.aidl \
 	core/java/android/view/IDockedStackListener.aidl \
 	core/java/android/view/IGraphicsStats.aidl \
+	core/java/android/view/IGraphicsStatsCallback.aidl \
 	core/java/android/view/IInputFilter.aidl \
 	core/java/android/view/IInputFilterHost.aidl \
 	core/java/android/view/IOnKeyguardExitResult.aidl \
@@ -407,6 +415,10 @@
 	location/java/android/location/INetInitiatedListener.aidl \
 	location/java/com/android/internal/location/ILocationProvider.aidl \
 	media/java/android/media/IAudioService.aidl \
+	../av/drm/libmediadrm/aidl/android/media/ICas.aidl \
+	../av/drm/libmediadrm/aidl/android/media/ICasListener.aidl \
+	../av/drm/libmediadrm/aidl/android/media/IDescrambler.aidl \
+	../av/drm/libmediadrm/aidl/android/media/IMediaCasService.aidl \
 	media/java/android/media/IAudioFocusDispatcher.aidl \
 	media/java/android/media/IAudioRoutesObserver.aidl \
 	media/java/android/media/IMediaHTTPConnection.aidl \
@@ -436,6 +448,7 @@
 	media/java/android/media/projection/IMediaProjectionManager.aidl \
 	media/java/android/media/projection/IMediaProjectionWatcherCallback.aidl \
 	media/java/android/media/session/IActiveSessionsListener.aidl \
+	media/java/android/media/session/ICallback.aidl \
 	media/java/android/media/session/IOnMediaKeyListener.aidl \
 	media/java/android/media/session/IOnVolumeKeyLongPressListener.aidl \
 	media/java/android/media/session/ISession.aidl \
@@ -532,6 +545,7 @@
 
 LOCAL_AIDL_INCLUDES += \
 	frameworks/av/camera/aidl \
+	frameworks/av/drm/libmediadrm/aidl \
 	frameworks/native/aidl/gui \
 	system/netd/server/binder
 
@@ -561,6 +575,7 @@
 
 LOCAL_MODULE := framework
 
+LOCAL_DX_FLAGS := --core-library --multi-dex
 LOCAL_JACK_FLAGS := --multi-dex native
 
 LOCAL_RMTYPEDEFS := true
@@ -707,6 +722,7 @@
 	frameworks/base/core/java/android/service/notification/StatusBarNotification.aidl \
 	frameworks/base/core/java/android/service/chooser/ChooserTarget.aidl \
 	frameworks/base/core/java/android/speech/tts/Voice.aidl \
+	frameworks/base/core/java/android/app/usage/CacheQuotaHint.aidl \
 	frameworks/base/core/java/android/app/usage/ExternalStorageStats.aidl \
 	frameworks/base/core/java/android/app/usage/StorageStats.aidl \
 	frameworks/base/core/java/android/app/usage/UsageEvents.aidl \
@@ -924,9 +940,32 @@
     -since $(SRC_API_DIR)/23.txt 23 \
     -since $(SRC_API_DIR)/24.txt 24 \
     -since $(SRC_API_DIR)/25.txt 25 \
+    -since ./frameworks/base/api/current.txt O \
 		-werror -hide 111 -hide 113 \
 		-overview $(LOCAL_PATH)/core/java/overview.html
 
+SUPPORT_API_DIR := ./frameworks/support/api
+
+# More API Level information for the Support Library, which is currently
+# included as part of the core framework docs build.
+framework_docs_LOCAL_DROIDDOC_OPTIONS += \
+    -since $(SUPPORT_API_DIR)/22.0.0.txt 22.0.0 \
+    -since $(SUPPORT_API_DIR)/22.0.0.txt 22.0.0 \
+    -since $(SUPPORT_API_DIR)/22.1.0.txt 22.1.0 \
+    -since $(SUPPORT_API_DIR)/22.2.0.txt 22.2.0 \
+    -since $(SUPPORT_API_DIR)/22.2.1.txt 22.2.1 \
+    -since $(SUPPORT_API_DIR)/23.0.0.txt 23.0.0 \
+    -since $(SUPPORT_API_DIR)/23.1.0.txt 23.1.0 \
+    -since $(SUPPORT_API_DIR)/23.1.1.txt 23.1.1 \
+    -since $(SUPPORT_API_DIR)/23.2.0.txt 23.2.0 \
+    -since $(SUPPORT_API_DIR)/23.2.1.txt 23.2.1 \
+    -since $(SUPPORT_API_DIR)/23.4.0.txt 23.4.0 \
+    -since $(SUPPORT_API_DIR)/24.0.0.txt 24.0.0 \
+    -since $(SUPPORT_API_DIR)/24.1.0.txt 24.1.0 \
+    -since $(SUPPORT_API_DIR)/24.2.0.txt 24.2.0 \
+    -since $(SUPPORT_API_DIR)/25.0.0.txt 25.0.0 \
+    -since $(SUPPORT_API_DIR)/25.1.0.txt 25.1.0
+
 framework_docs_LOCAL_API_CHECK_ADDITIONAL_JAVA_DIR:= \
 	$(call intermediates-dir-for,JAVA_LIBRARIES,framework,,COMMON)
 
@@ -967,6 +1006,7 @@
 framework_docs_SDK_REL_ID:=1
 
 framework_docs_LOCAL_DROIDDOC_OPTIONS += \
+		-hdf dac true \
 		-hdf sdk.codename N \
 		-hdf sdk.preview.version 5 \
 		-hdf sdk.version $(framework_docs_SDK_VERSION) \
@@ -996,7 +1036,7 @@
 		-removedApi $(INTERNAL_PLATFORM_REMOVED_API_FILE) \
 		-nodocs
 
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk
+LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=external/doclava/res/assets/templates-sdk
 
 LOCAL_UNINSTALLABLE_MODULE := true
 
@@ -1031,7 +1071,7 @@
 		-removedApi $(INTERNAL_PLATFORM_SYSTEM_REMOVED_API_FILE) \
 		-nodocs
 
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk
+LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=external/doclava/res/assets/templates-sdk
 
 LOCAL_UNINSTALLABLE_MODULE := true
 
@@ -1067,7 +1107,7 @@
                -removedApi $(INTERNAL_PLATFORM_TEST_REMOVED_API_FILE) \
                -nodocs
 
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk
+LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=external/doclava/res/assets/templates-sdk
 
 LOCAL_UNINSTALLABLE_MODULE := true
 
@@ -1097,7 +1137,7 @@
 		-referenceonly \
 		-parsecomments
 
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk
+LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=external/doclava/res/assets/templates-sdk
 
 LOCAL_UNINSTALLABLE_MODULE := true
 
@@ -1133,7 +1173,7 @@
 		-sdkvalues $(OUT_DOCS) \
 		-hdf android.whichdoc offline
 
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk
+LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=external/doclava/res/assets/templates-sdk
 
 include $(BUILD_DROIDDOC)
 
@@ -1172,7 +1212,7 @@
 		-resourcesdir $(LOCAL_PATH)/docs/html/reference/images/ \
 		-resourcesoutdir reference/android/images/
 
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk
+LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=external/doclava/res/assets/templates-sdk
 
 include $(BUILD_DROIDDOC)
 
@@ -1215,7 +1255,7 @@
 		-hdf android.hasSamples true \
 		-samplesdir $(samples_dir)
 
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk
+LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=external/doclava/res/assets/templates-sdk
 
 include $(BUILD_DROIDDOC)
 
@@ -1251,7 +1291,7 @@
 		-hdf android.hasSamples true \
 		-samplesdir $(samples_dir)
 
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk
+LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=external/doclava/res/assets/templates-sdk
 # Don't build by default
 LOCAL_UNINSTALLABLE_MODULE := true
 
@@ -1283,7 +1323,7 @@
 		-hdf android.hasSamples true \
 		-samplesdir $(samples_dir)
 
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk
+LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=external/doclava/res/assets/templates-sdk
 
 include $(BUILD_DROIDDOC)
 
@@ -1311,7 +1351,7 @@
 		-devsite \
 		-ignoreJdLinks
 
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk
+LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=external/doclava/res/assets/templates-sdk
 
 include $(BUILD_DROIDDOC)
 
@@ -1336,7 +1376,7 @@
 		-atLinksNavtree \
 		-navtreeonly
 
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk
+LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=external/doclava/res/assets/templates-sdk
 
 include $(BUILD_DROIDDOC)
 
@@ -1364,7 +1404,7 @@
 		-hdf android.hasSamples true \
 		-samplesdir $(samples_dir)
 
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk
+LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=external/doclava/res/assets/templates-sdk
 
 include $(BUILD_DROIDDOC)
 
@@ -1387,7 +1427,7 @@
 		-title "Android SDK - Including hidden APIs."
 #		-hidden
 
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk
+LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=external/doclava/res/assets/templates-sdk
 
 include $(BUILD_DROIDDOC)
 
@@ -1411,6 +1451,8 @@
 LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE := ext
 
+LOCAL_DX_FLAGS := --core-library
+
 ifneq ($(INCREMENTAL_BUILDS),)
     LOCAL_PROGUARD_ENABLED := disabled
     LOCAL_JACK_ENABLED := incremental
@@ -1418,6 +1460,24 @@
 
 include $(BUILD_JAVA_LIBRARY)
 
+# ====  c++ proto device library  ==============================
+include $(CLEAR_VARS)
+LOCAL_MODULE := libplatformprotos
+# b/34740546, work around clang-tidy segmentation fault.
+LOCAL_TIDY_CHECKS := -modernize*
+LOCAL_PROTOC_OPTIMIZE_TYPE := lite
+LOCAL_PROTOC_FLAGS := \
+    --include_source_info \
+    -Iexternal/protobuf/src
+LOCAL_SRC_FILES := \
+    $(call all-proto-files-under, core/proto) \
+    $(call all-proto-files-under, libs/incident/proto)
+LOCAL_C_INCLUDES := \
+    $(call generated-sources-dir-for,STATIC_LIBRARIES,libplatformprotos,)/proto
+LOCAL_EXPORT_C_INCLUDES := \
+    $(call generated-sources-dir-for,STATIC_LIBRARIES,libplatformprotos,)/proto
+include $(BUILD_STATIC_LIBRARY)
+
 # ====  c++ proto host library  ==============================
 include $(CLEAR_VARS)
 LOCAL_MODULE := libplatformprotos
diff --git a/apct-tests/perftests/core/jni/SystemPerfTest.cpp b/apct-tests/perftests/core/jni/SystemPerfTest.cpp
index eb55408..f102e3e 100644
--- a/apct-tests/perftests/core/jni/SystemPerfTest.cpp
+++ b/apct-tests/perftests/core/jni/SystemPerfTest.cpp
@@ -73,7 +73,7 @@
         return JNI_ERR;
     }
 
-    if (registerNativeMethods(env, "java/lang/perftests/SystemPerfTest",
+    if (registerNativeMethods(env, "android/perftests/SystemPerfTest",
             sMethods, NELEM(sMethods)) == -1) {
         return JNI_ERR;
     }
diff --git a/apct-tests/perftests/core/res/layout/test_autosize_textview_10.xml b/apct-tests/perftests/core/res/layout/test_autosize_textview_10.xml
index a8d3de0..4a4b3b4 100644
--- a/apct-tests/perftests/core/res/layout/test_autosize_textview_10.xml
+++ b/apct-tests/perftests/core/res/layout/test_autosize_textview_10.xml
@@ -35,7 +35,7 @@
           android:layout_width="400dp"
           android:layout_height="600dp"
           android:text="@string/long_text"
-          android:autoSizeText="uniform"
+          android:autoSizeTextType="uniform"
           android:autoSizeMinTextSize="10px"
           android:textSize="20px"
           android:autoSizeStepGranularity="1px"/>
diff --git a/apct-tests/perftests/core/res/layout/test_autosize_textview_100.xml b/apct-tests/perftests/core/res/layout/test_autosize_textview_100.xml
index d991862..0b326e8 100644
--- a/apct-tests/perftests/core/res/layout/test_autosize_textview_100.xml
+++ b/apct-tests/perftests/core/res/layout/test_autosize_textview_100.xml
@@ -19,7 +19,7 @@
           android:layout_width="400dp"
           android:layout_height="600dp"
           android:text="@string/long_text"
-          android:autoSizeText="uniform"
+          android:autoSizeTextType="uniform"
           android:autoSizeMinTextSize="10px"
           android:textSize="110px"
           android:autoSizeStepGranularity="1px"/>
diff --git a/apct-tests/perftests/core/res/layout/test_autosize_textview_1000.xml b/apct-tests/perftests/core/res/layout/test_autosize_textview_1000.xml
index 3b55b6c..2f4239d 100644
--- a/apct-tests/perftests/core/res/layout/test_autosize_textview_1000.xml
+++ b/apct-tests/perftests/core/res/layout/test_autosize_textview_1000.xml
@@ -19,7 +19,7 @@
           android:layout_width="400dp"
           android:layout_height="600dp"
           android:text="@string/long_text"
-          android:autoSizeText="uniform"
+          android:autoSizeTextType="uniform"
           android:autoSizeMinTextSize="10px"
           android:textSize="1010px"
           android:autoSizeStepGranularity="1px"/>
diff --git a/apct-tests/perftests/core/res/layout/test_autosize_textview_10000.xml b/apct-tests/perftests/core/res/layout/test_autosize_textview_10000.xml
index 64a25c2..b6be10a 100644
--- a/apct-tests/perftests/core/res/layout/test_autosize_textview_10000.xml
+++ b/apct-tests/perftests/core/res/layout/test_autosize_textview_10000.xml
@@ -19,7 +19,7 @@
           android:layout_width="400dp"
           android:layout_height="600dp"
           android:text="@string/long_text"
-          android:autoSizeText="uniform"
+          android:autoSizeTextType="uniform"
           android:autoSizeMinTextSize="10px"
           android:textSize="10010px"
           android:autoSizeStepGranularity="1px"/>
diff --git a/apct-tests/perftests/core/res/layout/test_autosize_textview_100000.xml b/apct-tests/perftests/core/res/layout/test_autosize_textview_100000.xml
index 1f60783..aed339c 100644
--- a/apct-tests/perftests/core/res/layout/test_autosize_textview_100000.xml
+++ b/apct-tests/perftests/core/res/layout/test_autosize_textview_100000.xml
@@ -19,7 +19,7 @@
           android:layout_width="400dp"
           android:layout_height="600dp"
           android:text="@string/long_text"
-          android:autoSizeText="uniform"
+          android:autoSizeTextType="uniform"
           android:autoSizeMinTextSize="10px"
           android:textSize="100010px"
           android:autoSizeStepGranularity="1px"/>
diff --git a/apct-tests/perftests/core/res/layout/test_autosize_textview_300.xml b/apct-tests/perftests/core/res/layout/test_autosize_textview_300.xml
index 54c7e71..62522ba 100644
--- a/apct-tests/perftests/core/res/layout/test_autosize_textview_300.xml
+++ b/apct-tests/perftests/core/res/layout/test_autosize_textview_300.xml
@@ -19,7 +19,7 @@
           android:layout_width="400dp"
           android:layout_height="600dp"
           android:text="@string/long_text"
-          android:autoSizeText="uniform"
+          android:autoSizeTextType="uniform"
           android:autoSizeMinTextSize="10px"
           android:textSize="310px"
           android:autoSizeStepGranularity="1px"/>
diff --git a/apct-tests/perftests/core/res/layout/test_autosize_textview_5.xml b/apct-tests/perftests/core/res/layout/test_autosize_textview_5.xml
index 525b2c8..f383fa4 100644
--- a/apct-tests/perftests/core/res/layout/test_autosize_textview_5.xml
+++ b/apct-tests/perftests/core/res/layout/test_autosize_textview_5.xml
@@ -35,7 +35,7 @@
           android:layout_width="400dp"
           android:layout_height="600dp"
           android:text="@string/long_text"
-          android:autoSizeText="uniform"
+          android:autoSizeTextType="uniform"
           android:autoSizeMinTextSize="10px"
           android:textSize="15px"
           android:autoSizeStepGranularity="1px"/>
diff --git a/apct-tests/perftests/core/res/layout/test_autosize_textview_50.xml b/apct-tests/perftests/core/res/layout/test_autosize_textview_50.xml
index 470c4da..04dd6c2 100644
--- a/apct-tests/perftests/core/res/layout/test_autosize_textview_50.xml
+++ b/apct-tests/perftests/core/res/layout/test_autosize_textview_50.xml
@@ -19,7 +19,7 @@
           android:layout_width="400dp"
           android:layout_height="600dp"
           android:text="@string/long_text"
-          android:autoSizeText="uniform"
+          android:autoSizeTextType="uniform"
           android:autoSizeMinTextSize="10px"
           android:textSize="60px"
           android:autoSizeStepGranularity="1px"/>
diff --git a/apct-tests/perftests/core/res/layout/test_autosize_textview_500.xml b/apct-tests/perftests/core/res/layout/test_autosize_textview_500.xml
index b8a6e0a..a8e2b38 100644
--- a/apct-tests/perftests/core/res/layout/test_autosize_textview_500.xml
+++ b/apct-tests/perftests/core/res/layout/test_autosize_textview_500.xml
@@ -19,7 +19,7 @@
           android:layout_width="400dp"
           android:layout_height="600dp"
           android:text="@string/long_text"
-          android:autoSizeText="uniform"
+          android:autoSizeTextType="uniform"
           android:autoSizeMinTextSize="10px"
           android:textSize="510px"
           android:autoSizeStepGranularity="1px"/>
diff --git a/apct-tests/perftests/core/src/java/lang/perftests/SystemPerfTest.java b/apct-tests/perftests/core/src/android/perftests/SystemPerfTest.java
similarity index 98%
rename from apct-tests/perftests/core/src/java/lang/perftests/SystemPerfTest.java
rename to apct-tests/perftests/core/src/android/perftests/SystemPerfTest.java
index afc9d0c..95a7144 100644
--- a/apct-tests/perftests/core/src/java/lang/perftests/SystemPerfTest.java
+++ b/apct-tests/perftests/core/src/android/perftests/SystemPerfTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package java.lang.perftests;
+package android.perftests;
 
 import android.perftests.utils.BenchmarkState;
 import android.perftests.utils.PerfStatusReporter;
diff --git a/apct-tests/perftests/core/src/android/widget/TextViewAutoSizeLayoutPerfTest.java b/apct-tests/perftests/core/src/android/widget/TextViewAutoSizeLayoutPerfTest.java
index 6ee6f70..c310166 100644
--- a/apct-tests/perftests/core/src/android/widget/TextViewAutoSizeLayoutPerfTest.java
+++ b/apct-tests/perftests/core/src/android/widget/TextViewAutoSizeLayoutPerfTest.java
@@ -89,7 +89,7 @@
 
             while (state.keepRunning()) {
                 TextView textView = new TextView(activity);
-                // TextView#onMeasure() gets called, which triggers TextView#autoSizeText()
+                // TextView#onLayout() gets called, which triggers TextView#autoSizeText()
                 // which is the method we want to benchmark.
                 textView.requestLayout();
             }
diff --git a/api/current.txt b/api/current.txt
index f52eb11..6a62fde 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -16,6 +16,7 @@
     field public static final java.lang.String ACCOUNT_MANAGER = "android.permission.ACCOUNT_MANAGER";
     field public static final java.lang.String ADD_VOICEMAIL = "com.android.voicemail.permission.ADD_VOICEMAIL";
     field public static final java.lang.String ALLOCATE_AGGRESSIVE = "android.permission.ALLOCATE_AGGRESSIVE";
+    field public static final java.lang.String ANSWER_PHONE_CALLS = "android.permission.ANSWER_PHONE_CALLS";
     field public static final java.lang.String BATTERY_STATS = "android.permission.BATTERY_STATS";
     field public static final java.lang.String BIND_ACCESSIBILITY_SERVICE = "android.permission.BIND_ACCESSIBILITY_SERVICE";
     field public static final java.lang.String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET";
@@ -297,6 +298,7 @@
     field public static final int authorities = 16842776; // 0x1010018
     field public static final int autoAdvanceViewId = 16843535; // 0x101030f
     field public static final int autoCompleteTextViewStyle = 16842859; // 0x101006b
+    field public static final int autoFillHint = 16844121; // 0x1010559
     field public static final int autoFillMode = 16844116; // 0x1010554
     field public static final int autoLink = 16842928; // 0x10100b0
     field public static final int autoMirrored = 16843754; // 0x10103ea
@@ -305,7 +307,7 @@
     field public static final int autoSizeMinTextSize = 16844088; // 0x1010538
     field public static final int autoSizePresetSizes = 16844087; // 0x1010537
     field public static final int autoSizeStepGranularity = 16844086; // 0x1010536
-    field public static final int autoSizeText = 16844085; // 0x1010535
+    field public static final int autoSizeTextType = 16844085; // 0x1010535
     field public static final int autoStart = 16843445; // 0x10102b5
     field public static final deprecated int autoText = 16843114; // 0x101016a
     field public static final int autoUrlDetect = 16843404; // 0x101028c
@@ -410,6 +412,7 @@
     field public static final int colorControlHighlight = 16843820; // 0x101042c
     field public static final int colorControlNormal = 16843817; // 0x1010429
     field public static final int colorEdgeEffect = 16843982; // 0x10104ce
+    field public static final int colorError = 16844100; // 0x1010544
     field public static final int colorFocusedHighlight = 16843663; // 0x101038f
     field public static final int colorForeground = 16842800; // 0x1010030
     field public static final int colorForegroundInverse = 16843270; // 0x1010206
@@ -604,8 +607,9 @@
     field public static final int fontFamily = 16843692; // 0x10103ac
     field public static final int fontFeatureSettings = 16843959; // 0x10104b7
     field public static final int fontProviderAuthority = 16844114; // 0x1010552
+    field public static final int fontProviderPackage = 16844122; // 0x101055a
     field public static final int fontProviderQuery = 16844115; // 0x1010553
-    field public static final int fontStyle = 16844081; // 0x1010531
+    field public static final int fontStyle = 16844095; // 0x101053f
     field public static final int fontWeight = 16844083; // 0x1010533
     field public static final int footerDividersEnabled = 16843311; // 0x101022f
     field public static final int forceHasOverlappingRendering = 16844065; // 0x1010521
@@ -706,6 +710,7 @@
     field public static final int imeSubtypeMode = 16843501; // 0x10102ed
     field public static final int immersive = 16843456; // 0x10102c0
     field public static final int importantForAccessibility = 16843690; // 0x10103aa
+    field public static final int importantForAutofill = 16844123; // 0x101055b
     field public static final int inAnimation = 16843127; // 0x1010177
     field public static final int includeFontPadding = 16843103; // 0x101015f
     field public static final int includeInGlobalSearch = 16843374; // 0x101026e
@@ -1003,7 +1008,7 @@
     field public static final int preferenceStyle = 16842894; // 0x101008e
     field public static final int presentationTheme = 16843712; // 0x10103c0
     field public static final int previewImage = 16843482; // 0x10102da
-    field public static final int primaryContentAlpha = 16843367; // 0x1010267
+    field public static final int primaryContentAlpha = 16844117; // 0x1010555
     field public static final int priority = 16842780; // 0x101001c
     field public static final int privateImeOptions = 16843299; // 0x1010223
     field public static final int process = 16842769; // 0x1010011
@@ -1059,7 +1064,9 @@
     field public static final int requireDeviceUnlock = 16843756; // 0x10103ec
     field public static final int required = 16843406; // 0x101028e
     field public static final int requiredAccountType = 16843734; // 0x10103d6
+    field public static final int requiredFeature = 16844119; // 0x1010557
     field public static final int requiredForAllUsers = 16843728; // 0x10103d0
+    field public static final int requiredNotFeature = 16844120; // 0x1010558
     field public static final int requiresFadingEdge = 16843685; // 0x10103a5
     field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364
     field public static final int resizeClip = 16843983; // 0x10104cf
@@ -1128,7 +1135,7 @@
     field public static final int searchSuggestSelection = 16843224; // 0x10101d8
     field public static final int searchSuggestThreshold = 16843373; // 0x101026d
     field public static final int searchViewStyle = 16843904; // 0x1010480
-    field public static final int secondaryContentAlpha = 16843688; // 0x10103a8
+    field public static final int secondaryContentAlpha = 16844118; // 0x1010556
     field public static final int secondaryProgress = 16843064; // 0x1010138
     field public static final int secondaryProgressTint = 16843879; // 0x1010467
     field public static final int secondaryProgressTintMode = 16843880; // 0x1010468
@@ -1316,7 +1323,6 @@
     field public static final int textCheckMarkInverse = 16842823; // 0x1010047
     field public static final int textColor = 16842904; // 0x1010098
     field public static final int textColorAlertDialogListItem = 16843526; // 0x1010306
-    field public static final int textColorError = 16844100; // 0x1010544
     field public static final int textColorHighlight = 16842905; // 0x1010099
     field public static final int textColorHighlightInverse = 16843599; // 0x101034f
     field public static final int textColorHint = 16842906; // 0x101009a
@@ -1455,7 +1461,7 @@
     field public static final int viewportWidth = 16843778; // 0x1010402
     field public static final int visibility = 16842972; // 0x10100dc
     field public static final int visible = 16843156; // 0x1010194
-    field public static final int visibleToInstantApps = 16844095; // 0x101053f
+    field public static final int visibleToInstantApps = 16844081; // 0x1010531
     field public static final int vmSafeMode = 16843448; // 0x10102b8
     field public static final int voiceIcon = 16843908; // 0x1010484
     field public static final int voiceLanguage = 16843349; // 0x1010255
@@ -2807,6 +2813,7 @@
     method public android.content.pm.ResolveInfo getResolveInfo();
     method public java.lang.String getSettingsActivityName();
     method public java.lang.String loadDescription(android.content.pm.PackageManager);
+    method public java.lang.String loadSummary(android.content.pm.PackageManager);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int CAPABILITY_CAN_CAPTURE_FINGERPRINT_GESTURES = 64; // 0x40
     field public static final int CAPABILITY_CAN_CONTROL_MAGNIFICATION = 16; // 0x10
@@ -3908,8 +3915,9 @@
     method public void readFromParcel(android.os.Parcel);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.app.ActivityManager.RunningAppProcessInfo> CREATOR;
-    field public static final int IMPORTANCE_BACKGROUND = 400; // 0x190
-    field public static final int IMPORTANCE_EMPTY = 500; // 0x1f4
+    field public static final deprecated int IMPORTANCE_BACKGROUND = 400; // 0x190
+    field public static final int IMPORTANCE_CACHED = 400; // 0x190
+    field public static final deprecated int IMPORTANCE_EMPTY = 500; // 0x1f4
     field public static final int IMPORTANCE_FOREGROUND = 100; // 0x64
     field public static final int IMPORTANCE_FOREGROUND_SERVICE = 125; // 0x7d
     field public static final int IMPORTANCE_GONE = 1000; // 0x3e8
@@ -4143,6 +4151,7 @@
     field public static final int MODE_ERRORED = 2; // 0x2
     field public static final int MODE_IGNORED = 1; // 0x1
     field public static final java.lang.String OPSTR_ADD_VOICEMAIL = "android:add_voicemail";
+    field public static final java.lang.String OPSTR_ANSWER_PHONE_CALLS = "android:answer_phone_calls";
     field public static final java.lang.String OPSTR_BODY_SENSORS = "android:body_sensors";
     field public static final java.lang.String OPSTR_CALL_PHONE = "android:call_phone";
     field public static final java.lang.String OPSTR_CAMERA = "android:camera";
@@ -4737,6 +4746,7 @@
     method public abstract android.app.Fragment getPrimaryNavigationFragment();
     method public void invalidateOptionsMenu();
     method public abstract boolean isDestroyed();
+    method public abstract boolean isStateSaved();
     method public abstract void popBackStack();
     method public abstract void popBackStack(java.lang.String, int);
     method public abstract void popBackStack(int, int);
@@ -5479,6 +5489,7 @@
 
   public final class NotificationChannel implements android.os.Parcelable {
     ctor public NotificationChannel(java.lang.String, java.lang.CharSequence, int);
+    ctor public NotificationChannel(java.lang.String, int, int);
     ctor protected NotificationChannel(android.os.Parcel);
     method public boolean canBypassDnd();
     method public boolean canShowBadge();
@@ -5492,6 +5503,7 @@
     method public int getLightColor();
     method public int getLockscreenVisibility();
     method public java.lang.CharSequence getName();
+    method public int getNameResId();
     method public android.net.Uri getSound();
     method public long[] getVibrationPattern();
     method public void setBypassDnd(boolean);
@@ -5511,12 +5523,14 @@
 
   public final class NotificationChannelGroup implements android.os.Parcelable {
     ctor public NotificationChannelGroup(java.lang.String, java.lang.CharSequence);
+    ctor public NotificationChannelGroup(java.lang.String, int);
     ctor protected NotificationChannelGroup(android.os.Parcel);
     method public android.app.NotificationChannelGroup clone();
     method public int describeContents();
     method public java.util.List<android.app.NotificationChannel> getChannels();
     method public java.lang.String getId();
     method public java.lang.CharSequence getName();
+    method public int getNameResId();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.app.NotificationChannelGroup> CREATOR;
   }
@@ -6546,9 +6560,12 @@
 
   public static class AssistStructure.ViewNode {
     method public float getAlpha();
+    method public int getAutoFillHint();
     method public android.view.autofill.AutoFillId getAutoFillId();
-    method public android.view.autofill.AutoFillType getAutoFillType();
+    method public java.lang.String[] getAutoFillOptions();
+    method public deprecated android.view.autofill.AutoFillType getAutoFillType();
     method public android.view.autofill.AutoFillValue getAutoFillValue();
+    method public int getAutofillType();
     method public android.app.assist.AssistStructure.ViewNode getChildAt(int);
     method public int getChildCount();
     method public java.lang.String getClassName();
@@ -6561,6 +6578,7 @@
     method public java.lang.String getIdEntry();
     method public java.lang.String getIdPackage();
     method public java.lang.String getIdType();
+    method public int getInputType();
     method public int getLeft();
     method public int getScrollX();
     method public int getScrollY();
@@ -6716,6 +6734,7 @@
     method public android.app.job.JobInfo.TriggerContentUri[] getTriggerContentUris();
     method public boolean isPeriodic();
     method public boolean isPersisted();
+    method public boolean isRequireBatteryNotLow();
     method public boolean isRequireCharging();
     method public boolean isRequireDeviceIdle();
     method public void writeToParcel(android.os.Parcel, int);
@@ -6742,6 +6761,7 @@
     method public android.app.job.JobInfo.Builder setPeriodic(long, long);
     method public android.app.job.JobInfo.Builder setPersisted(boolean);
     method public android.app.job.JobInfo.Builder setRequiredNetworkType(int);
+    method public android.app.job.JobInfo.Builder setRequiresBatteryNotLow(boolean);
     method public android.app.job.JobInfo.Builder setRequiresCharging(boolean);
     method public android.app.job.JobInfo.Builder setRequiresDeviceIdle(boolean);
     method public android.app.job.JobInfo.Builder setTransientExtras(android.os.Bundle);
@@ -6882,6 +6902,7 @@
     method public long getFreeBytes(java.lang.String);
     method public long getTotalBytes(java.lang.String);
     method public android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.lang.String, android.os.UserHandle);
+    method public android.app.usage.StorageStats queryStatsForPackage(java.lang.String, java.lang.String, android.os.UserHandle);
     method public android.app.usage.StorageStats queryStatsForUid(java.lang.String, int);
     method public android.app.usage.StorageStats queryStatsForUser(java.lang.String, android.os.UserHandle);
   }
@@ -6987,7 +7008,7 @@
     method public void notifyAppWidgetViewDataChanged(int, int);
     method public void partiallyUpdateAppWidget(int[], android.widget.RemoteViews);
     method public void partiallyUpdateAppWidget(int, android.widget.RemoteViews);
-    method public boolean requestPinAppWidget(android.content.ComponentName, android.app.PendingIntent);
+    method public boolean requestPinAppWidget(android.content.ComponentName, android.os.Bundle, android.app.PendingIntent);
     method public void updateAppWidget(int[], android.widget.RemoteViews);
     method public void updateAppWidget(int, android.widget.RemoteViews);
     method public void updateAppWidget(android.content.ComponentName, android.widget.RemoteViews);
@@ -7006,6 +7027,7 @@
     field public static final java.lang.String EXTRA_APPWIDGET_IDS = "appWidgetIds";
     field public static final java.lang.String EXTRA_APPWIDGET_OLD_IDS = "appWidgetOldIds";
     field public static final java.lang.String EXTRA_APPWIDGET_OPTIONS = "appWidgetOptions";
+    field public static final java.lang.String EXTRA_APPWIDGET_PREVIEW = "appWidgetPreview";
     field public static final java.lang.String EXTRA_APPWIDGET_PROVIDER = "appWidgetProvider";
     field public static final java.lang.String EXTRA_APPWIDGET_PROVIDER_PROFILE = "appWidgetProviderProfile";
     field public static final java.lang.String EXTRA_CUSTOM_EXTRAS = "customExtras";
@@ -7094,6 +7116,7 @@
     method public java.util.Set<android.bluetooth.BluetoothDevice> getBondedDevices();
     method public static synchronized android.bluetooth.BluetoothAdapter getDefaultAdapter();
     method public java.lang.String getName();
+    method public android.bluetooth.le.PeriodicAdvertisingManager getPeriodicAdvertisingManager();
     method public int getProfileConnectionState(int);
     method public boolean getProfileProxy(android.content.Context, android.bluetooth.BluetoothProfile.ServiceListener, int);
     method public android.bluetooth.BluetoothDevice getRemoteDevice(java.lang.String);
@@ -7102,6 +7125,10 @@
     method public int getState();
     method public boolean isDiscovering();
     method public boolean isEnabled();
+    method public boolean isLe2MPhySupported();
+    method public boolean isLeCodedPhySupported();
+    method public boolean isLeExtendedAdvertisingSupported();
+    method public boolean isLePeriodicAdvertisingSupported();
     method public boolean isMultipleAdvertisementSupported();
     method public boolean isOffloadedFilteringSupported();
     method public boolean isOffloadedScanBatchingSupported();
@@ -7470,6 +7497,9 @@
   public final class BluetoothDevice implements android.os.Parcelable {
     method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback);
     method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int);
+    method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallbackExt);
+    method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallbackExt, int);
+    method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallbackExt, int, int);
     method public boolean createBond();
     method public android.bluetooth.BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
     method public android.bluetooth.BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
@@ -7513,6 +7543,13 @@
     field public static final java.lang.String EXTRA_UUID = "android.bluetooth.device.extra.UUID";
     field public static final int PAIRING_VARIANT_PASSKEY_CONFIRMATION = 2; // 0x2
     field public static final int PAIRING_VARIANT_PIN = 0; // 0x0
+    field public static final int PHY_LE_1M = 1; // 0x1
+    field public static final int PHY_LE_2M = 2; // 0x2
+    field public static final int PHY_LE_ANY = 7; // 0x7
+    field public static final int PHY_LE_CODED = 4; // 0x4
+    field public static final int PHY_OPTION_NO_PREFERRED = 0; // 0x0
+    field public static final int PHY_OPTION_S2 = 1; // 0x1
+    field public static final int PHY_OPTION_S8 = 2; // 0x2
     field public static final int TRANSPORT_AUTO = 0; // 0x0
     field public static final int TRANSPORT_BREDR = 1; // 0x1
     field public static final int TRANSPORT_LE = 2; // 0x2
@@ -7535,10 +7572,12 @@
     method public java.util.List<android.bluetooth.BluetoothGattService> getServices();
     method public boolean readCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
     method public boolean readDescriptor(android.bluetooth.BluetoothGattDescriptor);
+    method public void readPhy();
     method public boolean readRemoteRssi();
     method public boolean requestConnectionPriority(int);
     method public boolean requestMtu(int);
     method public boolean setCharacteristicNotification(android.bluetooth.BluetoothGattCharacteristic, boolean);
+    method public void setPreferredPhy(int, int, int);
     method public boolean writeCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
     method public boolean writeDescriptor(android.bluetooth.BluetoothGattDescriptor);
     field public static final int CONNECTION_PRIORITY_BALANCED = 0; // 0x0
@@ -7556,8 +7595,12 @@
     field public static final int GATT_WRITE_NOT_PERMITTED = 3; // 0x3
   }
 
-  public abstract class BluetoothGattCallback {
+  public abstract deprecated class BluetoothGattCallback extends android.bluetooth.BluetoothGattCallbackExt {
     ctor public BluetoothGattCallback();
+  }
+
+  public abstract class BluetoothGattCallbackExt {
+    ctor public BluetoothGattCallbackExt();
     method public void onCharacteristicChanged(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic);
     method public void onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
     method public void onCharacteristicWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
@@ -7565,6 +7608,8 @@
     method public void onDescriptorRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattDescriptor, int);
     method public void onDescriptorWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattDescriptor, int);
     method public void onMtuChanged(android.bluetooth.BluetoothGatt, int, int);
+    method public void onPhyRead(android.bluetooth.BluetoothGatt, int, int, int);
+    method public void onPhyUpdate(android.bluetooth.BluetoothGatt, int, int, int);
     method public void onReadRemoteRssi(android.bluetooth.BluetoothGatt, int, int);
     method public void onReliableWriteCompleted(android.bluetooth.BluetoothGatt, int);
     method public void onServicesDiscovered(android.bluetooth.BluetoothGatt, int);
@@ -7658,12 +7703,18 @@
     method public android.bluetooth.BluetoothGattService getService(java.util.UUID);
     method public java.util.List<android.bluetooth.BluetoothGattService> getServices();
     method public boolean notifyCharacteristicChanged(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothGattCharacteristic, boolean);
+    method public void readPhy(android.bluetooth.BluetoothDevice);
     method public boolean removeService(android.bluetooth.BluetoothGattService);
     method public boolean sendResponse(android.bluetooth.BluetoothDevice, int, int, int, byte[]);
+    method public void setPreferredPhy(android.bluetooth.BluetoothDevice, int, int, int);
   }
 
-  public abstract class BluetoothGattServerCallback {
+  public abstract deprecated class BluetoothGattServerCallback extends android.bluetooth.BluetoothGattServerCallbackExt {
     ctor public BluetoothGattServerCallback();
+  }
+
+  public abstract class BluetoothGattServerCallbackExt {
+    ctor public BluetoothGattServerCallbackExt();
     method public void onCharacteristicReadRequest(android.bluetooth.BluetoothDevice, int, int, android.bluetooth.BluetoothGattCharacteristic);
     method public void onCharacteristicWriteRequest(android.bluetooth.BluetoothDevice, int, android.bluetooth.BluetoothGattCharacteristic, boolean, boolean, int, byte[]);
     method public void onConnectionStateChange(android.bluetooth.BluetoothDevice, int, int);
@@ -7672,6 +7723,8 @@
     method public void onExecuteWrite(android.bluetooth.BluetoothDevice, int, boolean);
     method public void onMtuChanged(android.bluetooth.BluetoothDevice, int);
     method public void onNotificationSent(android.bluetooth.BluetoothDevice, int);
+    method public void onPhyRead(android.bluetooth.BluetoothDevice, int, int, int);
+    method public void onPhyUpdate(android.bluetooth.BluetoothDevice, int, int, int);
     method public void onServiceAdded(int, android.bluetooth.BluetoothGattService);
   }
 
@@ -7872,10 +7925,85 @@
     method public android.bluetooth.le.AdvertiseSettings.Builder setTxPowerLevel(int);
   }
 
+  public final class AdvertisingSet {
+    method public void enableAdvertising(boolean);
+    method public void periodicAdvertisingEnable(boolean);
+    method public void setAdvertisingData(android.bluetooth.le.AdvertiseData);
+    method public void setAdvertisingParameters(android.bluetooth.le.AdvertisingSetParameters);
+    method public void setPeriodicAdvertisingData(android.bluetooth.le.AdvertiseData);
+    method public void setPeriodicAdvertisingParameters(android.bluetooth.le.PeriodicAdvertisingParameters);
+    method public void setScanResponseData(android.bluetooth.le.AdvertiseData);
+  }
+
+  public abstract class AdvertisingSetCallback {
+    ctor public AdvertisingSetCallback();
+    method public void onAdvertisingDataSet(android.bluetooth.le.AdvertisingSet, int);
+    method public void onAdvertisingEnabled(android.bluetooth.le.AdvertisingSet, boolean, int);
+    method public void onAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int);
+    method public void onAdvertisingSetStarted(android.bluetooth.le.AdvertisingSet, int);
+    method public void onAdvertisingSetStopped(android.bluetooth.le.AdvertisingSet);
+    method public void onPeriodicAdvertisingDataSet(android.bluetooth.le.AdvertisingSet, int);
+    method public void onPeriodicAdvertisingEnable(android.bluetooth.le.AdvertisingSet, boolean, int);
+    method public void onPeriodicAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int);
+    method public void onScanResponseDataSet(android.bluetooth.le.AdvertisingSet, int);
+    field public static final int ADVERTISE_FAILED_ALREADY_STARTED = 3; // 0x3
+    field public static final int ADVERTISE_FAILED_DATA_TOO_LARGE = 1; // 0x1
+    field public static final int ADVERTISE_FAILED_FEATURE_UNSUPPORTED = 5; // 0x5
+    field public static final int ADVERTISE_FAILED_INTERNAL_ERROR = 4; // 0x4
+    field public static final int ADVERTISE_FAILED_TOO_MANY_ADVERTISERS = 2; // 0x2
+    field public static final int ADVERTISE_SUCCESS = 0; // 0x0
+  }
+
+  public final class AdvertisingSetParameters implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getInterval();
+    method public int getPrimaryPhy();
+    method public int getSecondaryPhy();
+    method public int getTimeout();
+    method public int getTxPowerLevel();
+    method public boolean includeTxPower();
+    method public boolean isAnonymous();
+    method public boolean isConnectable();
+    method public boolean isLegacy();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.bluetooth.le.AdvertisingSetParameters> CREATOR;
+    field public static final int INTERVAL_HIGH = 160; // 0xa0
+    field public static final int INTERVAL_LOW = 1600; // 0x640
+    field public static final int INTERVAL_MAX = 16777215; // 0xffffff
+    field public static final int INTERVAL_MEDIUM = 400; // 0x190
+    field public static final int INTERVAL_MIN = 160; // 0xa0
+    field public static final int PHY_LE_1M = 1; // 0x1
+    field public static final int PHY_LE_2M = 2; // 0x2
+    field public static final int PHY_LE_CODED = 3; // 0x3
+    field public static final int TX_POWER_HIGH = 1; // 0x1
+    field public static final int TX_POWER_LOW = -15; // 0xfffffff1
+    field public static final int TX_POWER_MAX = 1; // 0x1
+    field public static final int TX_POWER_MEDIUM = -7; // 0xfffffff9
+    field public static final int TX_POWER_MIN = -127; // 0xffffff81
+    field public static final int TX_POWER_ULTRA_LOW = -21; // 0xffffffeb
+  }
+
+  public static final class AdvertisingSetParameters.Builder {
+    ctor public AdvertisingSetParameters.Builder();
+    method public android.bluetooth.le.AdvertisingSetParameters build();
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setAnonymouus(boolean);
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setConnectable(boolean);
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setIncludeTxPower(boolean);
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setInterval(int);
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setLegacyMode(boolean);
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setPrimaryPhy(int);
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setSecondaryPhy(int);
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setTimeout(int);
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setTxPowerLevel(int);
+  }
+
   public final class BluetoothLeAdvertiser {
     method public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback);
     method public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback);
+    method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback);
+    method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
     method public void stopAdvertising(android.bluetooth.le.AdvertiseCallback);
+    method public void stopAdvertisingSet(android.bluetooth.le.AdvertisingSetCallback);
   }
 
   public final class BluetoothLeScanner {
@@ -7885,6 +8013,53 @@
     method public void stopScan(android.bluetooth.le.ScanCallback);
   }
 
+  public abstract class PeriodicAdvertisingCallback {
+    ctor public PeriodicAdvertisingCallback();
+    method public void onPeriodicAdvertisingReport(android.bluetooth.le.PeriodicAdvertisingReport);
+    method public void onSyncEstablished(int, android.bluetooth.BluetoothDevice, int, int, int, int);
+    method public void onSyncLost(int);
+    field public static final int SYNC_NO_RESOURCES = 2; // 0x2
+    field public static final int SYNC_NO_RESPONSE = 1; // 0x1
+  }
+
+  public final class PeriodicAdvertisingManager {
+    method public void registerSync(android.bluetooth.le.ScanResult, int, int, android.bluetooth.le.PeriodicAdvertisingCallback);
+    method public void registerSync(android.bluetooth.le.ScanResult, int, int, android.bluetooth.le.PeriodicAdvertisingCallback, android.os.Handler);
+    method public void unregisterSync(android.bluetooth.le.PeriodicAdvertisingCallback);
+  }
+
+  public final class PeriodicAdvertisingParameters implements android.os.Parcelable {
+    method public int describeContents();
+    method public boolean getEnable();
+    method public boolean getIncludeTxPower();
+    method public int getInterval();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.bluetooth.le.PeriodicAdvertisingParameters> CREATOR;
+  }
+
+  public static final class PeriodicAdvertisingParameters.Builder {
+    ctor public PeriodicAdvertisingParameters.Builder();
+    method public android.bluetooth.le.PeriodicAdvertisingParameters build();
+    method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setEnable(boolean);
+    method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setIncludeTxPower(boolean);
+    method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setInterval(int);
+  }
+
+  public final class PeriodicAdvertisingReport implements android.os.Parcelable {
+    ctor public PeriodicAdvertisingReport(int, int, int, int, android.bluetooth.le.ScanRecord);
+    method public int describeContents();
+    method public android.bluetooth.le.ScanRecord getData();
+    method public int getDataStatus();
+    method public int getRssi();
+    method public int getSyncHandle();
+    method public long getTimestampNanos();
+    method public int getTxPower();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.bluetooth.le.PeriodicAdvertisingReport> CREATOR;
+    field public static final int DATA_COMPLETE = 0; // 0x0
+    field public static final int DATA_INCOMPLETE_TRUNCATED = 2; // 0x2
+  }
+
   public abstract class ScanCallback {
     ctor public ScanCallback();
     method public void onBatchScanResults(java.util.List<android.bluetooth.le.ScanResult>);
@@ -7939,19 +8114,37 @@
   }
 
   public final class ScanResult implements android.os.Parcelable {
-    ctor public ScanResult(android.bluetooth.BluetoothDevice, android.bluetooth.le.ScanRecord, int, long);
+    ctor public deprecated ScanResult(android.bluetooth.BluetoothDevice, android.bluetooth.le.ScanRecord, int, long);
+    ctor public ScanResult(android.bluetooth.BluetoothDevice, int, int, int, int, int, int, int, android.bluetooth.le.ScanRecord, long);
     method public int describeContents();
+    method public int getAdvertisingSid();
+    method public int getDataStatus();
     method public android.bluetooth.BluetoothDevice getDevice();
+    method public int getPeriodicAdvertisingInterval();
+    method public int getPrimaryPhy();
     method public int getRssi();
     method public android.bluetooth.le.ScanRecord getScanRecord();
+    method public int getSecondaryPhy();
     method public long getTimestampNanos();
+    method public int getTxPower();
+    method public boolean isConnectable();
+    method public boolean isLegacy();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.bluetooth.le.ScanResult> CREATOR;
+    field public static final int DATA_COMPLETE = 0; // 0x0
+    field public static final int DATA_TRUNCATED = 2; // 0x2
+    field public static final int PHY_LE_1M = 1; // 0x1
+    field public static final int PHY_LE_2M = 2; // 0x2
+    field public static final int PHY_LE_CODED = 3; // 0x3
+    field public static final int PHY_UNUSED = 0; // 0x0
+    field public static final int SID_NOT_PRESENT = 255; // 0xff
   }
 
   public final class ScanSettings implements android.os.Parcelable {
     method public int describeContents();
     method public int getCallbackType();
+    method public boolean getLegacy();
+    method public int getPhy();
     method public long getReportDelayMillis();
     method public int getScanMode();
     method public int getScanResultType();
@@ -7965,6 +8158,9 @@
     field public static final int MATCH_NUM_FEW_ADVERTISEMENT = 2; // 0x2
     field public static final int MATCH_NUM_MAX_ADVERTISEMENT = 3; // 0x3
     field public static final int MATCH_NUM_ONE_ADVERTISEMENT = 1; // 0x1
+    field public static final int PHY_LE_1M = 1; // 0x1
+    field public static final int PHY_LE_ALL_SUPPORTED = 255; // 0xff
+    field public static final int PHY_LE_CODED = 3; // 0x3
     field public static final int SCAN_MODE_BALANCED = 1; // 0x1
     field public static final int SCAN_MODE_LOW_LATENCY = 2; // 0x2
     field public static final int SCAN_MODE_LOW_POWER = 0; // 0x0
@@ -7975,8 +8171,10 @@
     ctor public ScanSettings.Builder();
     method public android.bluetooth.le.ScanSettings build();
     method public android.bluetooth.le.ScanSettings.Builder setCallbackType(int);
+    method public android.bluetooth.le.ScanSettings.Builder setLegacy(boolean);
     method public android.bluetooth.le.ScanSettings.Builder setMatchMode(int);
     method public android.bluetooth.le.ScanSettings.Builder setNumOfMatches(int);
+    method public android.bluetooth.le.ScanSettings.Builder setPhy(int);
     method public android.bluetooth.le.ScanSettings.Builder setReportDelay(long);
     method public android.bluetooth.le.ScanSettings.Builder setScanMode(int);
   }
@@ -8028,6 +8226,8 @@
 
   public final class CompanionDeviceManager {
     method public void associate(android.companion.AssociationRequest<?>, android.companion.CompanionDeviceManager.Callback, android.os.Handler);
+    method public void disassociate(java.lang.String);
+    method public java.util.List<java.lang.String> getAssociations();
     field public static final java.lang.String EXTRA_DEVICE = "android.companion.extra.DEVICE";
   }
 
@@ -8438,8 +8638,10 @@
     field public static final java.lang.String ANY_CURSOR_ITEM_TYPE = "vnd.android.cursor.item/*";
     field public static final java.lang.String CURSOR_DIR_BASE_TYPE = "vnd.android.cursor.dir";
     field public static final java.lang.String CURSOR_ITEM_BASE_TYPE = "vnd.android.cursor.item";
+    field public static final java.lang.String EXTRA_HONORED_ARGS = "android.content.extra.HONORED_ARGS";
     field public static final java.lang.String EXTRA_REFRESH_SUPPORTED = "android.content.extra.REFRESH_SUPPORTED";
     field public static final java.lang.String EXTRA_SIZE = "android.content.extra.SIZE";
+    field public static final java.lang.String EXTRA_TOTAL_SIZE = "android.content.extra.TOTAL_SIZE";
     field public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 2; // 0x2
     field public static final int NOTIFY_SYNC_TO_NETWORK = 1; // 0x1
     field public static final java.lang.String QUERY_ARG_LIMIT = "android:query-page-limit";
@@ -8450,7 +8652,6 @@
     field public static final java.lang.String QUERY_ARG_SQL_SELECTION = "android:query-sql-selection";
     field public static final java.lang.String QUERY_ARG_SQL_SELECTION_ARGS = "android:query-sql-selection-args";
     field public static final java.lang.String QUERY_ARG_SQL_SORT_ORDER = "android:query-sql-sort-order";
-    field public static final java.lang.String QUERY_RESULT_SIZE = "android:query-result-size";
     field public static final int QUERY_SORT_DIRECTION_ASCENDING = 0; // 0x0
     field public static final int QUERY_SORT_DIRECTION_DESCENDING = 1; // 0x1
     field public static final java.lang.String SCHEME_ANDROID_RESOURCE = "android.resource";
@@ -8669,6 +8870,7 @@
     field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardware_properties";
     field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method";
     field public static final java.lang.String INPUT_SERVICE = "input";
+    field public static final java.lang.String IPSEC_SERVICE = "ipsec";
     field public static final java.lang.String JOB_SCHEDULER_SERVICE = "jobscheduler";
     field public static final java.lang.String KEYGUARD_SERVICE = "keyguard";
     field public static final java.lang.String LAUNCHER_APPS_SERVICE = "launcherapps";
@@ -9038,6 +9240,7 @@
     field public static final java.lang.String ACTION_CALL = "android.intent.action.CALL";
     field public static final java.lang.String ACTION_CALL_BUTTON = "android.intent.action.CALL_BUTTON";
     field public static final java.lang.String ACTION_CAMERA_BUTTON = "android.intent.action.CAMERA_BUTTON";
+    field public static final java.lang.String ACTION_CARRIER_SETUP = "android.intent.action.CARRIER_SETUP";
     field public static final java.lang.String ACTION_CHOOSER = "android.intent.action.CHOOSER";
     field public static final java.lang.String ACTION_CLEAR_PACKAGE = "android.intent.action.CLEAR_PACKAGE";
     field public static final java.lang.String ACTION_CLOSE_SYSTEM_DIALOGS = "android.intent.action.CLOSE_SYSTEM_DIALOGS";
@@ -10086,6 +10289,7 @@
     method public boolean accept();
     method public int describeContents();
     method public android.appwidget.AppWidgetProviderInfo getAppWidgetProviderInfo(android.content.Context);
+    method public android.os.Bundle getExtras();
     method public int getRequestType();
     method public android.content.pm.ShortcutInfo getShortcutInfo();
     method public boolean isValid();
@@ -10099,10 +10303,12 @@
     ctor public LauncherApps.ShortcutQuery();
     method public android.content.pm.LauncherApps.ShortcutQuery setActivity(android.content.ComponentName);
     method public android.content.pm.LauncherApps.ShortcutQuery setChangedSince(long);
+    method public android.content.pm.LauncherApps.ShortcutQuery setIntent(android.content.Intent);
     method public android.content.pm.LauncherApps.ShortcutQuery setPackage(java.lang.String);
     method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int);
     method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(java.util.List<java.lang.String>);
     field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
+    field public static final int FLAG_MATCH_CHOOSER = 16; // 0x10
     field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1
     field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8
     field public static final int FLAG_MATCH_PINNED = 2; // 0x2
@@ -10158,9 +10364,11 @@
     method public void unregisterSessionCallback(android.content.pm.PackageInstaller.SessionCallback);
     method public void updateSessionAppIcon(int, android.graphics.Bitmap);
     method public void updateSessionAppLabel(int, java.lang.CharSequence);
+    field public static final java.lang.String ACTION_SESSION_COMMITTED = "android.content.pm.action.SESSION_COMMITTED";
     field public static final java.lang.String ACTION_SESSION_DETAILS = "android.content.pm.action.SESSION_DETAILS";
     field public static final java.lang.String EXTRA_OTHER_PACKAGE_NAME = "android.content.pm.extra.OTHER_PACKAGE_NAME";
     field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.content.pm.extra.PACKAGE_NAME";
+    field public static final java.lang.String EXTRA_SESSION = "android.content.pm.extra.SESSION";
     field public static final java.lang.String EXTRA_SESSION_ID = "android.content.pm.extra.SESSION_ID";
     field public static final java.lang.String EXTRA_STATUS = "android.content.pm.extra.STATUS";
     field public static final java.lang.String EXTRA_STATUS_MESSAGE = "android.content.pm.extra.STATUS_MESSAGE";
@@ -10203,10 +10411,12 @@
     method public android.graphics.Bitmap getAppIcon();
     method public java.lang.CharSequence getAppLabel();
     method public java.lang.String getAppPackageName();
+    method public int getInstallReason();
     method public java.lang.String getInstallerPackageName();
     method public float getProgress();
     method public int getSessionId();
     method public boolean isActive();
+    method public boolean isSealed();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.content.pm.PackageInstaller.SessionInfo> CREATOR;
   }
@@ -10331,6 +10541,7 @@
     method public abstract boolean hasSystemFeature(java.lang.String);
     method public abstract boolean hasSystemFeature(java.lang.String, int);
     method public abstract boolean isInstantApp();
+    method public abstract boolean isInstantApp(java.lang.String);
     method public abstract boolean isPermissionRevokedByPolicy(java.lang.String, java.lang.String);
     method public abstract boolean isSafeMode();
     method public abstract java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(android.content.Intent, int);
@@ -10462,8 +10673,11 @@
     field public static final int GET_SIGNATURES = 64; // 0x40
     field public static final deprecated int GET_UNINSTALLED_PACKAGES = 8192; // 0x2000
     field public static final int GET_URI_PERMISSION_PATTERNS = 2048; // 0x800
+    field public static final int INSTALL_REASON_DEVICE_RESTORE = 2; // 0x2
+    field public static final int INSTALL_REASON_DEVICE_SETUP = 3; // 0x3
     field public static final int INSTALL_REASON_POLICY = 1; // 0x1
     field public static final int INSTALL_REASON_UNKNOWN = 0; // 0x0
+    field public static final int INSTALL_REASON_USER = 4; // 0x4
     field public static final int MATCH_ALL = 131072; // 0x20000
     field public static final int MATCH_DEFAULT_ONLY = 65536; // 0x10000
     field public static final int MATCH_DIRECT_BOOT_AWARE = 524288; // 0x80000
@@ -10491,7 +10705,7 @@
     ctor public PackageManager.NameNotFoundException(java.lang.String);
   }
 
-  public class PackageStats implements android.os.Parcelable {
+  public deprecated class PackageStats implements android.os.Parcelable {
     ctor public PackageStats(java.lang.String);
     ctor public PackageStats(android.os.Parcel);
     ctor public PackageStats(android.content.pm.PackageStats);
@@ -10592,6 +10806,7 @@
     field public android.content.pm.ActivityInfo activityInfo;
     field public android.content.IntentFilter filter;
     field public int icon;
+    field public boolean instantAppAvailable;
     field public boolean isDefault;
     field public int labelRes;
     field public int match;
@@ -10641,6 +10856,9 @@
     method public int describeContents();
     method public android.content.ComponentName getActivity();
     method public java.util.Set<java.lang.String> getCategories();
+    method public android.content.ComponentName[] getChooserComponentNames();
+    method public android.os.PersistableBundle getChooserExtras();
+    method public android.content.IntentFilter[] getChooserIntentFilters();
     method public java.lang.CharSequence getDisabledMessage();
     method public android.os.PersistableBundle getExtras();
     method public java.lang.String getId();
@@ -10653,6 +10871,7 @@
     method public java.lang.CharSequence getShortLabel();
     method public android.os.UserHandle getUserHandle();
     method public boolean hasKeyFieldsOnly();
+    method public boolean isChooser();
     method public boolean isDeclaredInManifest();
     method public boolean isDynamic();
     method public boolean isEnabled();
@@ -10665,9 +10884,11 @@
 
   public static class ShortcutInfo.Builder {
     ctor public ShortcutInfo.Builder(android.content.Context, java.lang.String);
+    method public android.content.pm.ShortcutInfo.Builder addChooserIntentFilter(android.content.IntentFilter, android.content.ComponentName);
     method public android.content.pm.ShortcutInfo build();
     method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName);
     method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>);
+    method public android.content.pm.ShortcutInfo.Builder setChooserExtras(android.os.PersistableBundle);
     method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence);
     method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
     method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
@@ -12171,6 +12392,7 @@
     method public android.graphics.Bitmap extractAlpha(android.graphics.Paint, int[]);
     method public final int getAllocationByteCount();
     method public final int getByteCount();
+    method public final android.graphics.ColorSpace getColorSpace();
     method public final android.graphics.Bitmap.Config getConfig();
     method public int getDensity();
     method public int getGenerationId();
@@ -12553,6 +12775,7 @@
     method public java.lang.String getName();
     method public boolean isSrgb();
     method public abstract boolean isWideGamut();
+    method public static android.graphics.ColorSpace match(float[], android.graphics.ColorSpace.Rgb.TransferParameters);
     method public float[] toXyz(float, float, float);
     method public abstract float[] toXyz(float[]);
     field public static final float[] ILLUMINANT_A;
@@ -12572,6 +12795,7 @@
     method public static android.graphics.ColorSpace.Adaptation valueOf(java.lang.String);
     method public static final android.graphics.ColorSpace.Adaptation[] values();
     enum_constant public static final android.graphics.ColorSpace.Adaptation BRADFORD;
+    enum_constant public static final android.graphics.ColorSpace.Adaptation CIECAT02;
     enum_constant public static final android.graphics.ColorSpace.Adaptation VON_KRIES;
   }
 
@@ -12636,6 +12860,10 @@
   public static class ColorSpace.Rgb extends android.graphics.ColorSpace {
     ctor public ColorSpace.Rgb(java.lang.String, float[], java.util.function.DoubleUnaryOperator, java.util.function.DoubleUnaryOperator);
     ctor public ColorSpace.Rgb(java.lang.String, float[], float[], java.util.function.DoubleUnaryOperator, java.util.function.DoubleUnaryOperator, float, float);
+    ctor public ColorSpace.Rgb(java.lang.String, float[], android.graphics.ColorSpace.Rgb.TransferParameters);
+    ctor public ColorSpace.Rgb(java.lang.String, float[], float[], android.graphics.ColorSpace.Rgb.TransferParameters);
+    ctor public ColorSpace.Rgb(java.lang.String, float[], double);
+    ctor public ColorSpace.Rgb(java.lang.String, float[], float[], double);
     method public float[] fromLinear(float, float, float);
     method public float[] fromLinear(float[]);
     method public float[] fromXyz(float[]);
@@ -12647,6 +12875,7 @@
     method public java.util.function.DoubleUnaryOperator getOetf();
     method public float[] getPrimaries(float[]);
     method public float[] getPrimaries();
+    method public android.graphics.ColorSpace.Rgb.TransferParameters getTransferParameters();
     method public float[] getTransform(float[]);
     method public float[] getTransform();
     method public float[] getWhitePoint(float[]);
@@ -12657,6 +12886,18 @@
     method public float[] toXyz(float[]);
   }
 
+  public static class ColorSpace.Rgb.TransferParameters {
+    ctor public ColorSpace.Rgb.TransferParameters(double, double, double, double, double);
+    ctor public ColorSpace.Rgb.TransferParameters(double, double, double, double, double, double, double);
+    field public final double a;
+    field public final double b;
+    field public final double c;
+    field public final double d;
+    field public final double e;
+    field public final double f;
+    field public final double g;
+  }
+
   public class ComposePathEffect extends android.graphics.PathEffect {
     ctor public ComposePathEffect(android.graphics.PathEffect, android.graphics.PathEffect);
   }
@@ -13491,6 +13732,21 @@
 
 package android.graphics.drawable {
 
+  public class AdaptiveIconDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
+    method public void draw(android.graphics.Canvas);
+    method public android.graphics.drawable.Drawable getBackground();
+    method public static float getExtraInsetPercentage();
+    method public android.graphics.drawable.Drawable getForeground();
+    method public android.graphics.Path getIconMask();
+    method public int getOpacity();
+    method public void invalidateDrawable(android.graphics.drawable.Drawable);
+    method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
+    method public void setAlpha(int);
+    method public void setColorFilter(android.graphics.ColorFilter);
+    method public void setOpacity(int);
+    method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
+  }
+
   public abstract interface Animatable {
     method public abstract boolean isRunning();
     method public abstract void start();
@@ -13792,12 +14048,12 @@
   }
 
   public final class Icon implements android.os.Parcelable {
+    method public static android.graphics.drawable.Icon createWithAdaptiveBitmap(android.graphics.Bitmap);
     method public static android.graphics.drawable.Icon createWithBitmap(android.graphics.Bitmap);
     method public static android.graphics.drawable.Icon createWithContentUri(java.lang.String);
     method public static android.graphics.drawable.Icon createWithContentUri(android.net.Uri);
     method public static android.graphics.drawable.Icon createWithData(byte[], int, int);
     method public static android.graphics.drawable.Icon createWithFilePath(java.lang.String);
-    method public static android.graphics.drawable.Icon createWithMaskableBitmap(android.graphics.Bitmap);
     method public static android.graphics.drawable.Icon createWithResource(android.content.Context, int);
     method public static android.graphics.drawable.Icon createWithResource(java.lang.String, int);
     method public int describeContents();
@@ -13880,21 +14136,6 @@
     method public void addLevel(int, int, android.graphics.drawable.Drawable);
   }
 
-  public class MaskableIconDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
-    method public void draw(android.graphics.Canvas);
-    method public android.graphics.drawable.Drawable getBackground();
-    method public static float getExtraInsetPercentage();
-    method public android.graphics.drawable.Drawable getForeground();
-    method public android.graphics.Path getIconMask();
-    method public int getOpacity();
-    method public void invalidateDrawable(android.graphics.drawable.Drawable);
-    method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
-    method public void setAlpha(int);
-    method public void setColorFilter(android.graphics.ColorFilter);
-    method public void setOpacity(int);
-    method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
-  }
-
   public class NinePatchDrawable extends android.graphics.drawable.Drawable {
     ctor public deprecated NinePatchDrawable(android.graphics.Bitmap, byte[], android.graphics.Rect, java.lang.String);
     ctor public NinePatchDrawable(android.content.res.Resources, android.graphics.Bitmap, byte[], android.graphics.Rect, java.lang.String);
@@ -14008,6 +14249,8 @@
 
   public class ArcShape extends android.graphics.drawable.shapes.RectShape {
     ctor public ArcShape(float, float);
+    method public final float getStartAngle();
+    method public final float getSweepAngle();
   }
 
   public class OvalShape extends android.graphics.drawable.shapes.RectShape {
@@ -14046,9 +14289,12 @@
 package android.graphics.fonts {
 
   public final class FontRequest implements android.os.Parcelable {
-    ctor public FontRequest(java.lang.String, java.lang.String);
+    ctor public FontRequest(java.lang.String, java.lang.String, java.lang.String);
+    ctor public FontRequest(java.lang.String, java.lang.String, java.lang.String, java.util.List<java.util.List<byte[]>>);
     method public int describeContents();
+    method public java.util.List<java.util.List<byte[]>> getCertificates();
     method public java.lang.String getProviderAuthority();
+    method public java.lang.String getProviderPackage();
     method public java.lang.String getQuery();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.graphics.fonts.FontRequest> CREATOR;
@@ -19592,6 +19838,8 @@
     field public static final int SHORT_COMMONLY_USED = 6; // 0x6
     field public static final int SHORT_GENERIC = 2; // 0x2
     field public static final int SHORT_GMT = 4; // 0x4
+    field public static final int TIMEZONE_ICU = 0; // 0x0
+    field public static final int TIMEZONE_JDK = 1; // 0x1
     field public static final android.icu.util.TimeZone UNKNOWN_ZONE;
     field public static final java.lang.String UNKNOWN_ZONE_ID = "Etc/Unknown";
   }
@@ -20643,6 +20891,26 @@
     field public static final int TYPE_WIRED_HEADSET = 3; // 0x3
   }
 
+  public final class AudioFocusRequest {
+    method public boolean acceptsDelayedFocusGain();
+    method public android.media.AudioAttributes getAudioAttributes();
+    method public int getFocusGain();
+    method public android.media.AudioManager.OnAudioFocusChangeListener getOnAudioFocusChangeListener();
+    method public android.os.Handler getOnAudioFocusChangeListenerHandler();
+    method public boolean willPauseWhenDucked();
+  }
+
+  public static final class AudioFocusRequest.Builder {
+    ctor public AudioFocusRequest.Builder(int);
+    ctor public AudioFocusRequest.Builder(android.media.AudioFocusRequest);
+    method public android.media.AudioFocusRequest build();
+    method public android.media.AudioFocusRequest.Builder setAcceptsDelayedFocusGain(boolean);
+    method public android.media.AudioFocusRequest.Builder setAudioAttributes(android.media.AudioAttributes);
+    method public android.media.AudioFocusRequest.Builder setFocusGain(int);
+    method public android.media.AudioFocusRequest.Builder setOnAudioFocusChangeListener(android.media.AudioManager.OnAudioFocusChangeListener, android.os.Handler);
+    method public android.media.AudioFocusRequest.Builder setWillPauseWhenDucked(boolean);
+  }
+
   public final class AudioFormat implements android.os.Parcelable {
     method public int describeContents();
     method public int getChannelCount();
@@ -20719,6 +20987,7 @@
 
   public class AudioManager {
     method public int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener);
+    method public int abandonAudioFocusRequest(android.media.AudioFocusRequest);
     method public void adjustStreamVolume(int, int, int);
     method public void adjustSuggestedStreamVolume(int, int, int);
     method public void adjustVolume(int, int);
@@ -20755,6 +21024,7 @@
     method public deprecated void registerRemoteControlClient(android.media.RemoteControlClient);
     method public deprecated boolean registerRemoteController(android.media.RemoteController);
     method public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int);
+    method public int requestAudioFocus(android.media.AudioFocusRequest);
     method public deprecated void setBluetoothA2dpOn(boolean);
     method public void setBluetoothScoOn(boolean);
     method public void setMicrophoneMute(boolean);
@@ -20797,6 +21067,8 @@
     field public static final int AUDIOFOCUS_LOSS = -1; // 0xffffffff
     field public static final int AUDIOFOCUS_LOSS_TRANSIENT = -2; // 0xfffffffe
     field public static final int AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK = -3; // 0xfffffffd
+    field public static final int AUDIOFOCUS_NONE = 0; // 0x0
+    field public static final int AUDIOFOCUS_REQUEST_DELAYED = 2; // 0x2
     field public static final int AUDIOFOCUS_REQUEST_FAILED = 0; // 0x0
     field public static final int AUDIOFOCUS_REQUEST_GRANTED = 1; // 0x1
     field public static final int AUDIO_SESSION_ID_GENERATE = 0; // 0x0
@@ -20993,13 +21265,14 @@
     field public long nanoTime;
   }
 
-  public class AudioTrack implements android.media.AudioRouting {
+  public class AudioTrack implements android.media.AudioRouting android.media.VolumeAutomation {
     ctor public deprecated AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
     ctor public deprecated AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
     ctor public AudioTrack(android.media.AudioAttributes, android.media.AudioFormat, int, int, int) throws java.lang.IllegalArgumentException;
     method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
     method public deprecated void addOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener, android.os.Handler);
     method public int attachAuxEffect(int);
+    method public android.media.VolumeShaper createVolumeShaper(android.media.VolumeShaper.Configuration);
     method public void flush();
     method public int getAudioFormat();
     method public int getAudioSessionId();
@@ -21467,8 +21740,42 @@
     field public static final int STOP_VIDEO_RECORDING = 3; // 0x3
   }
 
+  public final class MediaCas {
+    ctor public MediaCas(int) throws android.media.UnsupportedCasException;
+    method public void closeSession(byte[]);
+    method public static android.media.MediaCas.PluginDescriptor[] enumeratePlugins();
+    method public static boolean isSystemIdSupported(int);
+    method public byte[] openSession(int);
+    method public byte[] openSession(int, int);
+    method public void processEcm(byte[], byte[], int, int);
+    method public void processEcm(byte[], byte[]);
+    method public void processEmm(byte[], int, int);
+    method public void processEmm(byte[]);
+    method public void provision(java.lang.String);
+    method public void refreshEntitlements(int, byte[]);
+    method public void release();
+    method public void sendEvent(int, int, byte[]);
+    method public void setEventListener(android.media.MediaCas.EventListener, android.os.Handler);
+    method public void setPrivateData(byte[]);
+    method public void setSessionPrivateData(byte[], byte[]);
+  }
+
+  public static abstract interface MediaCas.EventListener {
+    method public abstract void onEvent(android.media.MediaCas, int, int, byte[]);
+  }
+
+  public static class MediaCas.PluginDescriptor {
+    method public java.lang.String getName();
+    method public int getSystemId();
+  }
+
+  public class MediaCasException extends java.lang.Exception {
+    ctor public MediaCasException(java.lang.String);
+  }
+
   public final class MediaCodec {
     method public void configure(android.media.MediaFormat, android.view.Surface, android.media.MediaCrypto, int);
+    method public void configure(android.media.MediaFormat, android.view.Surface, int, android.media.MediaDescrambler);
     method public static android.media.MediaCodec createByCodecName(java.lang.String) throws java.io.IOException;
     method public static android.media.MediaCodec createDecoderByType(java.lang.String) throws java.io.IOException;
     method public static android.media.MediaCodec createEncoderByType(java.lang.String) throws java.io.IOException;
@@ -21508,6 +21815,7 @@
     field public static final int BUFFER_FLAG_CODEC_CONFIG = 2; // 0x2
     field public static final int BUFFER_FLAG_END_OF_STREAM = 4; // 0x4
     field public static final int BUFFER_FLAG_KEY_FRAME = 1; // 0x1
+    field public static final int BUFFER_FLAG_PARTIAL_FRAME = 8; // 0x8
     field public static final deprecated int BUFFER_FLAG_SYNC_FRAME = 1; // 0x1
     field public static final int CONFIGURE_FLAG_ENCODE = 1; // 0x1
     field public static final int CRYPTO_MODE_AES_CBC = 2; // 0x2
@@ -21664,6 +21972,7 @@
     field public static final deprecated int COLOR_TI_FormatYUV420PackedSemiPlanar = 2130706688; // 0x7f000100
     field public static final java.lang.String FEATURE_AdaptivePlayback = "adaptive-playback";
     field public static final java.lang.String FEATURE_IntraRefresh = "intra-refresh";
+    field public static final java.lang.String FEATURE_PartialFrame = "partial-frame";
     field public static final java.lang.String FEATURE_SecurePlayback = "secure-playback";
     field public static final java.lang.String FEATURE_TunneledPlayback = "tunneled-playback";
     field public int[] colorFormats;
@@ -21888,6 +22197,14 @@
     method public abstract int readAt(long, byte[], int, int) throws java.io.IOException;
   }
 
+  public final class MediaDescrambler {
+    ctor public MediaDescrambler(int) throws android.media.UnsupportedCasException;
+    method public final int descramble(java.nio.ByteBuffer, int, java.nio.ByteBuffer, int, android.media.MediaCodec.CryptoInfo);
+    method public final void release();
+    method public final boolean requiresSecureDecoderComponent(java.lang.String);
+    method public final void setMediaCasSession(byte[]);
+  }
+
   public class MediaDescription implements android.os.Parcelable {
     method public int describeContents();
     method public java.lang.CharSequence getDescription();
@@ -22044,8 +22361,10 @@
     method public final void setDataSource(android.content.res.AssetFileDescriptor) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
     method public final void setDataSource(java.io.FileDescriptor) throws java.io.IOException;
     method public final void setDataSource(java.io.FileDescriptor, long, long) throws java.io.IOException;
+    method public final void setMediaCas(android.media.MediaCas);
     method public void unselectTrack(int);
     field public static final int SAMPLE_FLAG_ENCRYPTED = 2; // 0x2
+    field public static final int SAMPLE_FLAG_PARTIAL_FRAME = 4; // 0x4
     field public static final int SAMPLE_FLAG_SYNC = 1; // 0x1
     field public static final int SEEK_TO_CLOSEST_SYNC = 2; // 0x2
     field public static final int SEEK_TO_NEXT_SYNC = 1; // 0x1
@@ -22111,6 +22430,7 @@
     field public static final java.lang.String KEY_IS_FORCED_SUBTITLE = "is-forced-subtitle";
     field public static final java.lang.String KEY_I_FRAME_INTERVAL = "i-frame-interval";
     field public static final java.lang.String KEY_LANGUAGE = "language";
+    field public static final java.lang.String KEY_LATENCY = "latency";
     field public static final java.lang.String KEY_LEVEL = "level";
     field public static final java.lang.String KEY_MAX_HEIGHT = "max-height";
     field public static final java.lang.String KEY_MAX_INPUT_SIZE = "max-input-size";
@@ -22142,6 +22462,7 @@
     field public static final java.lang.String MIMETYPE_AUDIO_OPUS = "audio/opus";
     field public static final java.lang.String MIMETYPE_AUDIO_QCELP = "audio/qcelp";
     field public static final java.lang.String MIMETYPE_AUDIO_RAW = "audio/raw";
+    field public static final java.lang.String MIMETYPE_AUDIO_SCRAMBLED = "audio/scrambled";
     field public static final java.lang.String MIMETYPE_AUDIO_VORBIS = "audio/vorbis";
     field public static final java.lang.String MIMETYPE_TEXT_CEA_608 = "text/cea-608";
     field public static final java.lang.String MIMETYPE_TEXT_VTT = "text/vtt";
@@ -22152,6 +22473,7 @@
     field public static final java.lang.String MIMETYPE_VIDEO_MPEG2 = "video/mpeg2";
     field public static final java.lang.String MIMETYPE_VIDEO_MPEG4 = "video/mp4v-es";
     field public static final java.lang.String MIMETYPE_VIDEO_RAW = "video/raw";
+    field public static final java.lang.String MIMETYPE_VIDEO_SCRAMBLED = "video/scrambled";
     field public static final java.lang.String MIMETYPE_VIDEO_VP8 = "video/x-vnd.on2.vp8";
     field public static final java.lang.String MIMETYPE_VIDEO_VP9 = "video/x-vnd.on2.vp9";
   }
@@ -22292,7 +22614,7 @@
     field public static final int MUXER_OUTPUT_WEBM = 1; // 0x1
   }
 
-  public class MediaPlayer {
+  public class MediaPlayer implements android.media.VolumeAutomation {
     ctor public MediaPlayer();
     method public void addTimedTextSource(java.lang.String, java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
     method public void addTimedTextSource(android.content.Context, android.net.Uri, java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
@@ -22304,6 +22626,7 @@
     method public static android.media.MediaPlayer create(android.content.Context, android.net.Uri, android.view.SurfaceHolder, android.media.AudioAttributes, int);
     method public static android.media.MediaPlayer create(android.content.Context, int);
     method public static android.media.MediaPlayer create(android.content.Context, int, android.media.AudioAttributes, int);
+    method public android.media.VolumeShaper createVolumeShaper(android.media.VolumeShaper.Configuration);
     method public void deselectTrack(int) throws java.lang.IllegalStateException;
     method public int getAudioSessionId();
     method public android.media.BufferingParams getBufferingParams();
@@ -23123,10 +23446,18 @@
     field public static final int TONE_SUP_RINGTONE = 23; // 0x17
   }
 
+  public final class UnsupportedCasException extends android.media.MediaCasException {
+    ctor public UnsupportedCasException(java.lang.String);
+  }
+
   public final class UnsupportedSchemeException extends android.media.MediaDrmException {
     ctor public UnsupportedSchemeException(java.lang.String);
   }
 
+  public abstract interface VolumeAutomation {
+    method public abstract android.media.VolumeShaper createVolumeShaper(android.media.VolumeShaper.Configuration);
+  }
+
   public abstract class VolumeProvider {
     ctor public VolumeProvider(int, int, int);
     method public final int getCurrentVolume();
@@ -23140,6 +23471,53 @@
     field public static final int VOLUME_CONTROL_RELATIVE = 1; // 0x1
   }
 
+  public final class VolumeShaper implements java.lang.AutoCloseable {
+    method public void apply(android.media.VolumeShaper.Operation);
+    method public void close();
+    method public float getVolume();
+    method public void replace(android.media.VolumeShaper.Configuration, android.media.VolumeShaper.Operation, boolean);
+  }
+
+  public static final class VolumeShaper.Configuration implements android.os.Parcelable {
+    method public int describeContents();
+    method public double getDurationMs();
+    method public int getInterpolatorType();
+    method public static int getMaximumCurvePoints();
+    method public float[] getTimes();
+    method public float[] getVolumes();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.media.VolumeShaper.Configuration> CREATOR;
+    field public static final android.media.VolumeShaper.Configuration CUBIC_RAMP;
+    field public static final int INTERPOLATOR_TYPE_CUBIC = 2; // 0x2
+    field public static final int INTERPOLATOR_TYPE_CUBIC_MONOTONIC = 3; // 0x3
+    field public static final int INTERPOLATOR_TYPE_LINEAR = 1; // 0x1
+    field public static final int INTERPOLATOR_TYPE_STEP = 0; // 0x0
+    field public static final android.media.VolumeShaper.Configuration LINEAR_RAMP;
+    field public static final android.media.VolumeShaper.Configuration SCURVE_RAMP;
+    field public static final android.media.VolumeShaper.Configuration SINE_RAMP;
+  }
+
+  public static final class VolumeShaper.Configuration.Builder {
+    ctor public VolumeShaper.Configuration.Builder();
+    ctor public VolumeShaper.Configuration.Builder(android.media.VolumeShaper.Configuration);
+    method public android.media.VolumeShaper.Configuration build();
+    method public android.media.VolumeShaper.Configuration.Builder invertVolumes();
+    method public android.media.VolumeShaper.Configuration.Builder reflectTimes();
+    method public android.media.VolumeShaper.Configuration.Builder scaleToEndVolume(float);
+    method public android.media.VolumeShaper.Configuration.Builder scaleToStartVolume(float);
+    method public android.media.VolumeShaper.Configuration.Builder setCurve(float[], float[]);
+    method public android.media.VolumeShaper.Configuration.Builder setDurationMs(double);
+    method public android.media.VolumeShaper.Configuration.Builder setInterpolatorType(int);
+  }
+
+  public static final class VolumeShaper.Operation implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.media.VolumeShaper.Operation> CREATOR;
+    field public static final android.media.VolumeShaper.Operation PLAY;
+    field public static final android.media.VolumeShaper.Operation REVERSE;
+  }
+
 }
 
 package android.media.audiofx {
@@ -23985,17 +24363,79 @@
     method public static final android.net.Uri buildProgramsUriForChannel(long, long, long);
     method public static final android.net.Uri buildProgramsUriForChannel(android.net.Uri, long, long);
     method public static final android.net.Uri buildRecordedProgramUri(long);
+    method public static final android.net.Uri buildWatchNextProgramUri(long);
     method public static final boolean isChannelUri(android.net.Uri);
     method public static final boolean isChannelUriForPassthroughInput(android.net.Uri);
     method public static final boolean isChannelUriForTunerInput(android.net.Uri);
     method public static final boolean isProgramUri(android.net.Uri);
+    field public static final java.lang.String ACTION_MAKE_CHANNEL_BROWSABLE = "android.media.tv.action.MAKE_CHANNEL_BROWSABLE";
+    field public static final java.lang.String ACTION_PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT = "android.media.tv.action.PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT";
+    field public static final java.lang.String ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED = "android.media.tv.action.PREVIEW_PROGRAM_BROWSABLE_DISABLED";
+    field public static final java.lang.String ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED = "android.media.tv.action.WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED";
     field public static final java.lang.String AUTHORITY = "android.media.tv";
+    field public static final java.lang.String EXTRA_CHANNEL_ID = "android.media.tv.extra.CHANNEL_ID";
+    field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.media.tv.extra.PACKAGE_NAME";
+    field public static final java.lang.String EXTRA_PREVIEW_PROGRAM_ID = "android.media.tv.extra.PREVIEW_PROGRAM_ID";
+    field public static final java.lang.String EXTRA_WATCH_NEXT_PROGRAM_ID = "android.media.tv.extra.WATCH_NEXT_PROGRAM_ID";
+  }
+
+  public static abstract interface TvContract.BasePreviewProgramColumns implements android.media.tv.TvContract.BaseProgramColumns {
+    field public static final java.lang.String ASPECT_RATIO_16_9 = "ASPECT_RATIO_16_9";
+    field public static final java.lang.String ASPECT_RATIO_1_1 = "ASPECT_RATIO_1_1";
+    field public static final java.lang.String ASPECT_RATIO_2_3 = "ASPECT_RATIO_2_3";
+    field public static final java.lang.String ASPECT_RATIO_3_2 = "ASPECT_RATIO_3_2";
+    field public static final java.lang.String AVAILABILITY_AVAILABLE = "AVAILABILITY_AVAILABLE";
+    field public static final java.lang.String AVAILABILITY_FREE_WITH_SUBSCRIPTION = "AVAILABILITY_FREE_WITH_SUBSCRIPTION";
+    field public static final java.lang.String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT";
+    field public static final java.lang.String COLUMN_APP_LINK_INTENT_URI = "app_link_intent_uri";
+    field public static final java.lang.String COLUMN_AUTHOR = "author";
+    field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
+    field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
+    field public static final java.lang.String COLUMN_CONTENT_ID = "content_id";
+    field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
+    field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count";
+    field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
+    field public static final java.lang.String COLUMN_ITEM_COUNT = "item_count";
+    field public static final java.lang.String COLUMN_LAST_PLAYBACK_POSITION_MILLIS = "last_playback_position_millis";
+    field public static final java.lang.String COLUMN_LIVE = "live";
+    field public static final java.lang.String COLUMN_LOGO_URI = "logo_uri";
+    field public static final java.lang.String COLUMN_OFFER_PRICE = "offer_price";
+    field public static final java.lang.String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
+    field public static final java.lang.String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri";
+    field public static final java.lang.String COLUMN_RELEASE_DATE = "release_date";
+    field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating";
+    field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
+    field public static final java.lang.String COLUMN_STARTING_PRICE = "starting_price";
+    field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
+    field public static final java.lang.String COLUMN_TYPE = "type";
+    field public static final java.lang.String INTERACTION_TYPE_FANS = "INTERACTION_TYPE_FANS";
+    field public static final java.lang.String INTERACTION_TYPE_FOLLOWERS = "INTERACTION_TYPE_FOLLOWERS";
+    field public static final java.lang.String INTERACTION_TYPE_LIKES = "INTERACTION_TYPE_LIKES";
+    field public static final java.lang.String INTERACTION_TYPE_LISTENS = "INTERACTION_TYPE_LISTENS";
+    field public static final java.lang.String INTERACTION_TYPE_THUMBS = "INTERACTION_TYPE_THUMBS";
+    field public static final java.lang.String INTERACTION_TYPE_VIEWERS = "INTERACTION_TYPE_VIEWERS";
+    field public static final java.lang.String INTERACTION_TYPE_VIEWS = "INTERACTION_TYPE_VIEWS";
+    field public static final java.lang.String REVIEW_RATING_STYLE_PERCENTAGE = "REVIEW_RATING_STYLE_PERCENTAGE";
+    field public static final java.lang.String REVIEW_RATING_STYLE_STARS = "REVIEW_RATING_STYLE_STARS";
+    field public static final java.lang.String REVIEW_RATING_STYLE_THUMBS_UP_DOWN = "REVIEW_RATING_STYLE_THUMBS_UP_DOWN";
+    field public static final java.lang.String TYPE_ALBUM = "TYPE_ALBUM";
+    field public static final java.lang.String TYPE_ARTIST = "TYPE_ARTIST";
+    field public static final java.lang.String TYPE_CHANNEL = "TYPE_CHANNEL";
+    field public static final java.lang.String TYPE_CLIP = "TYPE_CLIP";
+    field public static final java.lang.String TYPE_EVENT = "TYPE_EVENT";
+    field public static final java.lang.String TYPE_MOVIE = "TYPE_MOVIE";
+    field public static final java.lang.String TYPE_PLAYLIST = "TYPE_PLAYLIST";
+    field public static final java.lang.String TYPE_STATION = "TYPE_STATION";
+    field public static final java.lang.String TYPE_TRACK = "TYPE_TRACK";
+    field public static final java.lang.String TYPE_TV_EPISODE = "TYPE_TV_EPISODE";
+    field public static final java.lang.String TYPE_TV_SEASON = "TYPE_TV_SEASON";
+    field public static final java.lang.String TYPE_TV_SERIES = "TYPE_TV_SERIES";
   }
 
   public static abstract interface TvContract.BaseProgramColumns implements android.media.tv.TvContract.BaseTvColumns {
     field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
     field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
-    field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
     field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
     field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
     field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
@@ -24028,6 +24468,7 @@
     field public static final java.lang.String COLUMN_APP_LINK_INTENT_URI = "app_link_intent_uri";
     field public static final java.lang.String COLUMN_APP_LINK_POSTER_ART_URI = "app_link_poster_art_uri";
     field public static final java.lang.String COLUMN_APP_LINK_TEXT = "app_link_text";
+    field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
     field public static final java.lang.String COLUMN_DESCRIPTION = "description";
     field public static final java.lang.String COLUMN_DISPLAY_NAME = "display_name";
     field public static final java.lang.String COLUMN_DISPLAY_NUMBER = "display_number";
@@ -24100,69 +24541,17 @@
     field public static final java.lang.String CONTENT_DIRECTORY = "logo";
   }
 
-  public static final class TvContract.PreviewPrograms implements android.media.tv.TvContract.BaseProgramColumns {
-    field public static final java.lang.String ASPECT_RATIO_16_9 = "ASPECT_RATIO_16_9";
-    field public static final java.lang.String ASPECT_RATIO_1_1 = "ASPECT_RATIO_1_1";
-    field public static final java.lang.String ASPECT_RATIO_2_3 = "ASPECT_RATIO_2_3";
-    field public static final java.lang.String ASPECT_RATIO_3_2 = "ASPECT_RATIO_3_2";
-    field public static final java.lang.String AVAILABILITY_AVAILABLE = "AVAILABILITY_AVAILABLE";
-    field public static final java.lang.String AVAILABILITY_FREE_WITH_SUBSCRIPTION = "AVAILABILITY_FREE_WITH_SUBSCRIPTION";
-    field public static final java.lang.String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT";
-    field public static final java.lang.String COLUMN_APP_LINK_INTENT_URI = "app_link_intent_uri";
-    field public static final java.lang.String COLUMN_AUTHOR = "author";
-    field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
-    field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
-    field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
-    field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count";
-    field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type";
-    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
-    field public static final java.lang.String COLUMN_ITEM_COUNT = "item_count";
-    field public static final java.lang.String COLUMN_LAST_PLAYBACK_POSITION_MILLIS = "last_playback_position_millis";
-    field public static final java.lang.String COLUMN_LIVE = "live";
-    field public static final java.lang.String COLUMN_LOGO_URI = "logo_uri";
-    field public static final java.lang.String COLUMN_OFFER_PRICE = "offer_price";
-    field public static final java.lang.String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
-    field public static final java.lang.String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri";
-    field public static final java.lang.String COLUMN_RELEASE_DATE = "release_date";
-    field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating";
-    field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
-    field public static final java.lang.String COLUMN_STARTING_PRICE = "starting_price";
-    field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
-    field public static final java.lang.String COLUMN_TYPE = "type";
-    field public static final java.lang.String COLUMN_WATCH_NEXT_TYPE = "watch_next_type";
+  public static final class TvContract.PreviewPrograms implements android.media.tv.TvContract.BasePreviewProgramColumns {
+    field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
     field public static final java.lang.String COLUMN_WEIGHT = "weight";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/preview_program";
     field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/preview_program";
     field public static final android.net.Uri CONTENT_URI;
-    field public static final java.lang.String INTERACTION_TYPE_FANS = "INTERACTION_TYPE_FANS";
-    field public static final java.lang.String INTERACTION_TYPE_FOLLOWERS = "INTERACTION_TYPE_FOLLOWERS";
-    field public static final java.lang.String INTERACTION_TYPE_LIKES = "INTERACTION_TYPE_LIKES";
-    field public static final java.lang.String INTERACTION_TYPE_LISTENS = "INTERACTION_TYPE_LISTENS";
-    field public static final java.lang.String INTERACTION_TYPE_THUMBS = "INTERACTION_TYPE_THUMBS";
-    field public static final java.lang.String INTERACTION_TYPE_VIEWERS = "INTERACTION_TYPE_VIEWERS";
-    field public static final java.lang.String INTERACTION_TYPE_VIEWS = "INTERACTION_TYPE_VIEWS";
-    field public static final java.lang.String REVIEW_RATING_STYLE_PERCENTAGE = "REVIEW_RATING_STYLE_PERCENTAGE";
-    field public static final java.lang.String REVIEW_RATING_STYLE_STARS = "REVIEW_RATING_STYLE_STARS";
-    field public static final java.lang.String REVIEW_RATING_STYLE_THUMBS_UP_DOWN = "REVIEW_RATING_STYLE_THUMBS_UP_DOWN";
-    field public static final java.lang.String TYPE_ALBUM = "TYPE_ALBUM";
-    field public static final java.lang.String TYPE_ARTIST = "TYPE_ARTIST";
-    field public static final java.lang.String TYPE_CHANNEL = "TYPE_CHANNEL";
-    field public static final java.lang.String TYPE_CLIP = "TYPE_CLIP";
-    field public static final java.lang.String TYPE_EVENT = "TYPE_EVENT";
-    field public static final java.lang.String TYPE_MOVIE = "TYPE_MOVIE";
-    field public static final java.lang.String TYPE_PLAYLIST = "TYPE_PLAYLIST";
-    field public static final java.lang.String TYPE_STATION = "TYPE_STATION";
-    field public static final java.lang.String TYPE_TRACK = "TYPE_TRACK";
-    field public static final java.lang.String TYPE_TV_EPISODE = "TYPE_TV_EPISODE";
-    field public static final java.lang.String TYPE_TV_SEASON = "TYPE_TV_SEASON";
-    field public static final java.lang.String TYPE_TV_SERIES = "TYPE_TV_SERIES";
-    field public static final java.lang.String WATCH_NEXT_TYPE_CONTINUE = "WATCH_NEXT_TYPE_CONTINUE";
-    field public static final java.lang.String WATCH_NEXT_TYPE_NEW = "WATCH_NEXT_TYPE_NEW";
-    field public static final java.lang.String WATCH_NEXT_TYPE_NEXT = "WATCH_NEXT_TYPE_NEXT";
   }
 
   public static final class TvContract.Programs implements android.media.tv.TvContract.BaseProgramColumns {
     field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre";
+    field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
     field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
     field public static final deprecated java.lang.String COLUMN_EPISODE_NUMBER = "episode_number";
     field public static final java.lang.String COLUMN_RECORDING_PROHIBITED = "recording_prohibited";
@@ -24198,6 +24587,7 @@
 
   public static final class TvContract.RecordedPrograms implements android.media.tv.TvContract.BaseProgramColumns {
     field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre";
+    field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
     field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
     field public static final java.lang.String COLUMN_INPUT_ID = "input_id";
     field public static final java.lang.String COLUMN_RECORDING_DATA_BYTES = "recording_data_bytes";
@@ -24210,6 +24600,19 @@
     field public static final android.net.Uri CONTENT_URI;
   }
 
+  public static final class TvContract.WatchNextPrograms implements android.media.tv.TvContract.BasePreviewProgramColumns {
+    ctor public TvContract.WatchNextPrograms();
+    field public static final java.lang.String COLUMN_LAST_ENGAGEMENT_TIME_UTC_MILLIS = "last_engagement_time_utc_millis";
+    field public static final java.lang.String COLUMN_WATCH_NEXT_TYPE = "watch_next_type";
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/watch_next_program";
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/watch_next_program";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String WATCH_NEXT_TYPE_CONTINUE = "WATCH_NEXT_TYPE_CONTINUE";
+    field public static final java.lang.String WATCH_NEXT_TYPE_NEW = "WATCH_NEXT_TYPE_NEW";
+    field public static final java.lang.String WATCH_NEXT_TYPE_NEXT = "WATCH_NEXT_TYPE_NEXT";
+    field public static final java.lang.String WATCH_NEXT_TYPE_WATCHLIST = "WATCH_NEXT_TYPE_WATCHLIST";
+  }
+
   public final class TvInputInfo implements android.os.Parcelable {
     method public boolean canRecord();
     method public android.content.Intent createSettingsIntent();
@@ -24259,15 +24662,10 @@
     method public void unregisterCallback(android.media.tv.TvInputManager.TvInputCallback);
     method public void updateTvInputInfo(android.media.tv.TvInputInfo);
     field public static final java.lang.String ACTION_BLOCKED_RATINGS_CHANGED = "android.media.tv.action.BLOCKED_RATINGS_CHANGED";
-    field public static final java.lang.String ACTION_MAKE_CHANNEL_BROWSABLE = "android.media.tv.action.MAKE_CHANNEL_BROWSABLE";
     field public static final java.lang.String ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED = "android.media.tv.action.PARENTAL_CONTROLS_ENABLED_CHANGED";
-    field public static final java.lang.String ACTION_PROGRAM_BROWSABLE_DISABLED = "android.media.tv.action.PROGRAM_BROWSABLE_DISABLED";
     field public static final java.lang.String ACTION_QUERY_CONTENT_RATING_SYSTEMS = "android.media.tv.action.QUERY_CONTENT_RATING_SYSTEMS";
     field public static final java.lang.String ACTION_SETUP_INPUTS = "android.media.tv.action.SETUP_INPUTS";
     field public static final java.lang.String ACTION_VIEW_RECORDING_SCHEDULES = "android.media.tv.action.VIEW_RECORDING_SCHEDULES";
-    field public static final java.lang.String EXTRA_CHANNEL_ID = "android.media.tv.extra.CHANNEL_ID";
-    field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.media.tv.extra.PACKAGE_NAME";
-    field public static final java.lang.String EXTRA_PROGRAM_ID = "android.media.tv.extra.PROGRAM_ID";
     field public static final int INPUT_STATE_CONNECTED = 0; // 0x0
     field public static final int INPUT_STATE_CONNECTED_STANDBY = 1; // 0x1
     field public static final int INPUT_STATE_DISCONNECTED = 2; // 0x2
@@ -24756,6 +25154,7 @@
     method public void reportNetworkConnectivity(android.net.Network, boolean);
     method public boolean requestBandwidthUpdate(android.net.Network);
     method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
+    method public void requestNetwork(android.net.NetworkRequest, int, android.net.ConnectivityManager.NetworkCallback);
     method public void requestNetwork(android.net.NetworkRequest, android.app.PendingIntent);
     method public deprecated void setNetworkPreference(int);
     method public static deprecated boolean setProcessDefaultNetwork(android.net.Network);
@@ -24803,6 +25202,7 @@
     method public void onLinkPropertiesChanged(android.net.Network, android.net.LinkProperties);
     method public void onLosing(android.net.Network, int);
     method public void onLost(android.net.Network);
+    method public void onUnavailable();
   }
 
   public static abstract interface ConnectivityManager.OnNetworkActiveListener {
@@ -24839,6 +25239,68 @@
     field public static final android.os.Parcelable.Creator<android.net.IpPrefix> CREATOR;
   }
 
+  public final class IpSecAlgorithm implements android.os.Parcelable {
+    ctor public IpSecAlgorithm(java.lang.String, byte[]);
+    ctor public IpSecAlgorithm(java.lang.String, byte[], int);
+    method public int describeContents();
+    method public byte[] getKey();
+    method public java.lang.String getName();
+    method public int getTruncationLengthBits();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final java.lang.String ALGO_AUTH_HMAC_MD5 = "hmac(md5)";
+    field public static final java.lang.String ALGO_AUTH_HMAC_SHA1 = "hmac(sha1)";
+    field public static final java.lang.String ALGO_AUTH_HMAC_SHA256 = "hmac(sha256)";
+    field public static final java.lang.String ALGO_AUTH_HMAC_SHA384 = "hmac(sha384)";
+    field public static final java.lang.String ALGO_AUTH_HMAC_SHA512 = "hmac(sha512)";
+    field public static final java.lang.String ALGO_CRYPT_AES_CBC = "cbc(aes)";
+    field public static final android.os.Parcelable.Creator<android.net.IpSecAlgorithm> CREATOR;
+  }
+
+  public final class IpSecManager {
+    method public void applyTransportModeTransform(java.net.Socket, android.net.IpSecTransform) throws java.io.IOException;
+    method public void applyTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform) throws java.io.IOException;
+    method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket(int) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
+    method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket() throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
+    method public void removeTransportModeTransform(java.net.Socket, android.net.IpSecTransform);
+    method public void removeTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform);
+    method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(java.net.InetAddress, int) throws android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
+    field public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; // 0x0
+  }
+
+  public static final class IpSecManager.ResourceUnavailableException extends android.util.AndroidException {
+  }
+
+  public static final class IpSecManager.SecurityParameterIndex implements java.lang.AutoCloseable {
+    method public void close();
+    method public int getSpi();
+  }
+
+  public static final class IpSecManager.SpiUnavailableException extends android.util.AndroidException {
+    method public int getSpi();
+  }
+
+  public static final class IpSecManager.UdpEncapsulationSocket implements java.lang.AutoCloseable {
+    method public void close();
+    method public int getPort();
+    method public java.io.FileDescriptor getSocket();
+  }
+
+  public final class IpSecTransform implements java.lang.AutoCloseable {
+    method public void close();
+    field public static final int DIRECTION_IN = 0; // 0x0
+    field public static final int DIRECTION_OUT = 1; // 0x1
+  }
+
+  public static class IpSecTransform.Builder {
+    ctor public IpSecTransform.Builder(android.content.Context);
+    method public android.net.IpSecTransform buildTransportModeTransform(java.net.InetAddress) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
+    method public android.net.IpSecTransform.Builder setAuthentication(int, android.net.IpSecAlgorithm);
+    method public android.net.IpSecTransform.Builder setEncryption(int, android.net.IpSecAlgorithm);
+    method public android.net.IpSecTransform.Builder setIpv4Encapsulation(android.net.IpSecManager.UdpEncapsulationSocket, int);
+    method public android.net.IpSecTransform.Builder setSpi(int, int);
+    method public android.net.IpSecTransform.Builder setSpi(int, android.net.IpSecManager.SecurityParameterIndex);
+  }
+
   public class LinkAddress implements android.os.Parcelable {
     method public int describeContents();
     method public java.net.InetAddress getAddress();
@@ -26019,8 +26481,6 @@
   public class DiscoverySession {
     method public java.lang.String createNetworkSpecifier(android.net.wifi.aware.PeerHandle, byte[]);
     method public void destroy();
-    method public static int getMaxSendRetryCount();
-    method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[], int);
     method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[]);
   }
 
@@ -29891,12 +30351,12 @@
     field public static final int BATTERY_PLUGGED_AC = 1; // 0x1
     field public static final int BATTERY_PLUGGED_USB = 2; // 0x2
     field public static final int BATTERY_PLUGGED_WIRELESS = 4; // 0x4
-    field public static final int BATTERY_PROPERTY_BATTERY_STATUS = 6; // 0x6
     field public static final int BATTERY_PROPERTY_CAPACITY = 4; // 0x4
     field public static final int BATTERY_PROPERTY_CHARGE_COUNTER = 1; // 0x1
     field public static final int BATTERY_PROPERTY_CURRENT_AVERAGE = 3; // 0x3
     field public static final int BATTERY_PROPERTY_CURRENT_NOW = 2; // 0x2
     field public static final int BATTERY_PROPERTY_ENERGY_COUNTER = 5; // 0x5
+    field public static final int BATTERY_PROPERTY_STATUS = 6; // 0x6
     field public static final int BATTERY_STATUS_CHARGING = 2; // 0x2
     field public static final int BATTERY_STATUS_DISCHARGING = 3; // 0x3
     field public static final int BATTERY_STATUS_FULL = 5; // 0x5
@@ -30017,7 +30477,7 @@
     ctor public Bundle(android.os.Bundle);
     ctor public Bundle(android.os.PersistableBundle);
     method public java.lang.Object clone();
-    method public android.os.Bundle deepcopy();
+    method public android.os.Bundle deepCopy();
     method public int describeContents();
     method public android.os.IBinder getBinder(java.lang.String);
     method public android.os.Bundle getBundle(java.lang.String);
@@ -30742,6 +31202,7 @@
     method public boolean match(java.lang.String);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.os.PatternMatcher> CREATOR;
+    field public static final int PATTERN_ADVANCED_GLOB = 3; // 0x3
     field public static final int PATTERN_LITERAL = 0; // 0x0
     field public static final int PATTERN_PREFIX = 1; // 0x1
     field public static final int PATTERN_SIMPLE_GLOB = 2; // 0x2
@@ -30752,7 +31213,7 @@
     ctor public PersistableBundle(int);
     ctor public PersistableBundle(android.os.PersistableBundle);
     method public java.lang.Object clone();
-    method public android.os.PersistableBundle deepcopy();
+    method public android.os.PersistableBundle deepCopy();
     method public int describeContents();
     method public android.os.PersistableBundle getPersistableBundle(java.lang.String);
     method public void putPersistableBundle(java.lang.String, android.os.PersistableBundle);
@@ -30860,6 +31321,7 @@
     method public E getBroadcastItem(int);
     method public java.lang.Object getRegisteredCallbackCookie(int);
     method public int getRegisteredCallbackCount();
+    method public E getRegisteredCallbackItem(int);
     method public void kill();
     method public void onCallbackDied(E);
     method public void onCallbackDied(E, java.lang.Object);
@@ -31255,10 +31717,8 @@
     method public void allocateBytes(java.io.File, long, int) throws java.io.IOException;
     method public void allocateBytes(java.io.FileDescriptor, long, int) throws java.io.IOException;
     method public long getAllocatableBytes(java.io.File, int) throws java.io.IOException;
-    method public long getCacheQuotaBytes();
-    method public long getCacheSizeBytes();
-    method public long getExternalCacheQuotaBytes();
-    method public long getExternalCacheSizeBytes();
+    method public long getCacheQuotaBytes(java.io.File);
+    method public long getCacheSizeBytes(java.io.File);
     method public java.lang.String getMountedObbPath(java.lang.String);
     method public android.os.storage.StorageVolume getPrimaryStorageVolume();
     method public android.os.storage.StorageVolume getStorageVolume(java.io.File);
@@ -33701,6 +34161,7 @@
     field public static final int FLAG_SUPPORTS_IS_CHILD = 16; // 0x10
     field public static final int FLAG_SUPPORTS_RECENTS = 4; // 0x4
     field public static final int FLAG_SUPPORTS_SEARCH = 8; // 0x8
+    field public static final java.lang.String MIME_TYPE_ITEM = "vnd.android.document/root";
   }
 
   public abstract class DocumentsProvider extends android.content.ContentProvider {
@@ -34266,7 +34727,7 @@
     method public static final deprecated void setLocationProviderEnabled(android.content.ContentResolver, java.lang.String, boolean);
     field public static final java.lang.String ACCESSIBILITY_DISPLAY_INVERSION_ENABLED = "accessibility_display_inversion_enabled";
     field public static final java.lang.String ACCESSIBILITY_ENABLED = "accessibility_enabled";
-    field public static final java.lang.String ACCESSIBILITY_SPEAK_PASSWORD = "speak_password";
+    field public static final deprecated java.lang.String ACCESSIBILITY_SPEAK_PASSWORD = "speak_password";
     field public static final deprecated java.lang.String ADB_ENABLED = "adb_enabled";
     field public static final java.lang.String ALLOWED_GEOLOCATION_ORIGINS = "allowed_geolocation_origins";
     field public static final deprecated java.lang.String ALLOW_MOCK_LOCATION = "mock_location";
@@ -36178,7 +36639,6 @@
     field public static final int PURPOSE_ENCRYPT = 1; // 0x1
     field public static final int PURPOSE_SIGN = 4; // 0x4
     field public static final int PURPOSE_VERIFY = 8; // 0x8
-    field public static final int PURPOSE_WRAP_KEY = 16; // 0x10
     field public static final java.lang.String SIGNATURE_PADDING_RSA_PKCS1 = "PKCS1";
     field public static final java.lang.String SIGNATURE_PADDING_RSA_PSS = "PSS";
   }
@@ -36230,6 +36690,7 @@
 
   public abstract class AutoFillService extends android.app.Service {
     ctor public AutoFillService();
+    method public final void disableSelf();
     method public final android.os.IBinder onBind(android.content.Intent);
     method public void onConnected();
     method public void onDisconnected();
@@ -36246,7 +36707,7 @@
   }
 
   public static final class Dataset.Builder {
-    ctor public Dataset.Builder(java.lang.CharSequence);
+    ctor public Dataset.Builder(android.widget.RemoteViews);
     method public android.service.autofill.Dataset build();
     method public android.service.autofill.Dataset.Builder setAuthentication(android.content.IntentSender);
     method public android.service.autofill.Dataset.Builder setValue(android.view.autofill.AutoFillId, android.view.autofill.AutoFillValue);
@@ -36266,10 +36727,10 @@
   public static final class FillResponse.Builder {
     ctor public FillResponse.Builder();
     method public android.service.autofill.FillResponse.Builder addDataset(android.service.autofill.Dataset);
-    method public android.service.autofill.FillResponse.Builder addSavableFields(android.view.autofill.AutoFillId...);
     method public android.service.autofill.FillResponse build();
-    method public android.service.autofill.FillResponse.Builder setAuthentication(android.content.IntentSender);
+    method public android.service.autofill.FillResponse.Builder setAuthentication(android.content.IntentSender, android.widget.RemoteViews);
     method public android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
+    method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo);
   }
 
   public final class SaveCallback {
@@ -36277,6 +36738,24 @@
     method public void onSuccess();
   }
 
+  public final class SaveInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.SaveInfo> CREATOR;
+    field public static final int SAVE_DATA_TYPE_ADDRESS = 2; // 0x2
+    field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 3; // 0x3
+    field public static final int SAVE_DATA_TYPE_GENERIC = 0; // 0x0
+    field public static final int SAVE_DATA_TYPE_PASSWORD = 1; // 0x1
+  }
+
+  public static final class SaveInfo.Builder {
+    ctor public SaveInfo.Builder(int);
+    method public android.service.autofill.SaveInfo.Builder addSavableIds(android.view.autofill.AutoFillId...);
+    method public android.service.autofill.SaveInfo build();
+    method public android.service.autofill.SaveInfo.Builder setDescription(java.lang.CharSequence);
+    method public android.service.autofill.SaveInfo.Builder setNegativeAction(java.lang.CharSequence, android.content.IntentSender);
+  }
+
 }
 
 package android.service.carrier {
@@ -36672,6 +37151,7 @@
     method public final void unlockAndRun(java.lang.Runnable);
     field public static final java.lang.String ACTION_QS_TILE = "android.service.quicksettings.action.QS_TILE";
     field public static final java.lang.String ACTION_QS_TILE_PREFERENCES = "android.service.quicksettings.action.QS_TILE_PREFERENCES";
+    field public static final java.lang.String EXTRA_COMPONENT = "android.service.quicksettings.extra.COMPONENT";
     field public static final java.lang.String META_DATA_ACTIVE_TILE = "android.service.quicksettings.ACTIVE_TILE";
   }
 
@@ -37879,9 +38359,11 @@
     method public android.telecom.Call.Details getDetails();
     method public android.telecom.Call getParent();
     method public java.lang.String getRemainingPostDialSequence();
+    method public android.telecom.Call.RttCall getRttCall();
     method public int getState();
     method public android.telecom.InCallService.VideoCall getVideoCall();
     method public void hold();
+    method public boolean isRttActive();
     method public void mergeConference();
     method public void phoneAccountSelected(android.telecom.PhoneAccountHandle, boolean);
     method public void playDtmfTone(char);
@@ -37893,9 +38375,12 @@
     method public void reject(boolean, java.lang.String);
     method public final void removeExtras(java.util.List<java.lang.String>);
     method public final void removeExtras(java.lang.String...);
+    method public void respondToRttRequest(int, boolean);
     method public void sendCallEvent(java.lang.String, android.os.Bundle);
+    method public void sendRttRequest();
     method public void splitFromConference();
     method public void stopDtmfTone();
+    method public void stopRtt();
     method public void swapConference();
     method public void unhold();
     method public void unregisterCallback(android.telecom.Call.Callback);
@@ -37923,6 +38408,10 @@
     method public void onDetailsChanged(android.telecom.Call, android.telecom.Call.Details);
     method public void onParentChanged(android.telecom.Call, android.telecom.Call);
     method public void onPostDialWait(android.telecom.Call, java.lang.String);
+    method public void onRttInitiationFailure(android.telecom.Call, int);
+    method public void onRttModeChanged(android.telecom.Call, int);
+    method public void onRttRequest(android.telecom.Call, int);
+    method public void onRttStatusChanged(android.telecom.Call, boolean, android.telecom.Call.RttCall);
     method public void onStateChanged(android.telecom.Call, int);
     method public void onVideoCallChanged(android.telecom.Call, android.telecom.InCallService.VideoCall);
   }
@@ -37973,9 +38462,20 @@
     field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 128; // 0x80
     field public static final int PROPERTY_HIGH_DEF_AUDIO = 16; // 0x10
     field public static final int PROPERTY_IS_EXTERNAL_CALL = 64; // 0x40
+    field public static final int PROPERTY_SELF_MANAGED = 256; // 0x100
     field public static final int PROPERTY_WIFI = 8; // 0x8
   }
 
+  public static final class Call.RttCall {
+    method public int getRttAudioMode();
+    method public java.lang.String read();
+    method public void setRttMode(int);
+    method public void write(java.lang.String) throws java.io.IOException;
+    field public static final int RTT_MODE_FULL = 1; // 0x1
+    field public static final int RTT_MODE_HCO = 2; // 0x2
+    field public static final int RTT_MODE_VCO = 3; // 0x3
+  }
+
   public final class CallAudioState implements android.os.Parcelable {
     ctor public CallAudioState(boolean, int, int);
     method public static java.lang.String audioRouteToString(int);
@@ -38175,6 +38675,15 @@
     field public static final int STATE_RINGING = 2; // 0x2
   }
 
+  public static final class Connection.RttModifyStatus {
+    ctor public Connection.RttModifyStatus();
+    field public static final int SESSION_MODIFY_REQUEST_FAIL = 2; // 0x2
+    field public static final int SESSION_MODIFY_REQUEST_INVALID = 3; // 0x3
+    field public static final int SESSION_MODIFY_REQUEST_REJECTED_BY_REMOTE = 5; // 0x5
+    field public static final int SESSION_MODIFY_REQUEST_SUCCESS = 1; // 0x1
+    field public static final int SESSION_MODIFY_REQUEST_TIMED_OUT = 4; // 0x4
+  }
+
   public static abstract class Connection.VideoProvider {
     ctor public Connection.VideoProvider();
     method public void changeCameraCapabilities(android.telecom.VideoProfile.CameraCapabilities);
@@ -38232,9 +38741,9 @@
     method public final android.os.IBinder onBind(android.content.Intent);
     method public void onConference(android.telecom.Connection, android.telecom.Connection);
     method public android.telecom.Connection onCreateIncomingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
-    method public void onCreateIncomingConnectionFailed(android.telecom.ConnectionRequest);
+    method public void onCreateIncomingConnectionFailed(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
     method public android.telecom.Connection onCreateOutgoingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
-    method public void onCreateOutgoingConnectionFailed(android.telecom.ConnectionRequest);
+    method public void onCreateOutgoingConnectionFailed(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
     method public void onRemoteConferenceAdded(android.telecom.RemoteConference);
     method public void onRemoteExistingConnectionAdded(android.telecom.RemoteConnection);
     field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.ConnectionService";
@@ -38347,6 +38856,7 @@
     field public static final int CAPABILITY_CALL_SUBJECT = 64; // 0x40
     field public static final int CAPABILITY_CONNECTION_MANAGER = 1; // 0x1
     field public static final int CAPABILITY_PLACE_EMERGENCY_CALLS = 16; // 0x10
+    field public static final int CAPABILITY_RTT = 4096; // 0x1000
     field public static final int CAPABILITY_SELF_MANAGED = 2048; // 0x800
     field public static final int CAPABILITY_SIM_SUBSCRIPTION = 4; // 0x4
     field public static final int CAPABILITY_SUPPORTS_VIDEO_CALLING = 1024; // 0x400
@@ -38515,6 +39025,8 @@
   }
 
   public class TelecomManager {
+    method public void acceptRingingCall();
+    method public void acceptRingingCall(int);
     method public void addNewIncomingCall(android.telecom.PhoneAccountHandle, android.os.Bundle);
     method public void cancelMissedCallsNotification();
     method public android.content.Intent createManageBlockedNumbersIntent();
@@ -38529,6 +39041,7 @@
     method public boolean handleMmi(java.lang.String);
     method public boolean handleMmi(java.lang.String, android.telecom.PhoneAccountHandle);
     method public boolean isInCall();
+    method public boolean isInManagedCall();
     method public boolean isIncomingCallPermitted(android.telecom.PhoneAccountHandle);
     method public boolean isOutgoingCallPermitted(android.telecom.PhoneAccountHandle);
     method public boolean isVoiceMailNumber(android.telecom.PhoneAccountHandle, java.lang.String);
@@ -38559,11 +39072,13 @@
     field public static final java.lang.String EXTRA_NOTIFICATION_PHONE_NUMBER = "android.telecom.extra.NOTIFICATION_PHONE_NUMBER";
     field public static final java.lang.String EXTRA_OUTGOING_CALL_EXTRAS = "android.telecom.extra.OUTGOING_CALL_EXTRAS";
     field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.telecom.extra.PHONE_ACCOUNT_HANDLE";
+    field public static final java.lang.String EXTRA_START_CALL_WITH_RTT = "android.telecom.extra.START_CALL_WITH_RTT";
     field public static final java.lang.String EXTRA_START_CALL_WITH_SPEAKERPHONE = "android.telecom.extra.START_CALL_WITH_SPEAKERPHONE";
     field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE";
     field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS";
     field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE";
     field public static final java.lang.String METADATA_INCLUDE_EXTERNAL_CALLS = "android.telecom.INCLUDE_EXTERNAL_CALLS";
+    field public static final java.lang.String METADATA_INCLUDE_SELF_MANAGED_CALLS = "android.telecom.INCLUDE_SELF_MANAGED_CALLS";
     field public static final java.lang.String METADATA_IN_CALL_SERVICE_RINGING = "android.telecom.IN_CALL_SERVICE_RINGING";
     field public static final java.lang.String METADATA_IN_CALL_SERVICE_UI = "android.telecom.IN_CALL_SERVICE_UI";
     field public static final int PRESENTATION_ALLOWED = 1; // 0x1
@@ -39251,6 +39766,7 @@
     method public java.lang.String getDeviceId();
     method public java.lang.String getDeviceId(int);
     method public java.lang.String getDeviceSoftwareVersion();
+    method public java.lang.String[] getForbiddenPlmns();
     method public java.lang.String getGroupIdLevel1();
     method public java.lang.String getIccAuthentication(int, int, java.lang.String);
     method public java.lang.String getLine1Number();
@@ -39332,6 +39848,7 @@
     field public static final java.lang.String EXTRA_INCOMING_NUMBER = "incoming_number";
     field public static final java.lang.String EXTRA_LAUNCH_VOICEMAIL_SETTINGS_INTENT = "android.telephony.extra.LAUNCH_VOICEMAIL_SETTINGS_INTENT";
     field public static final java.lang.String EXTRA_NOTIFICATION_COUNT = "android.telephony.extra.NOTIFICATION_COUNT";
+    field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.telephony.extra.PHONE_ACCOUNT_HANDLE";
     field public static final java.lang.String EXTRA_STATE = "state";
     field public static final java.lang.String EXTRA_STATE_IDLE;
     field public static final java.lang.String EXTRA_STATE_OFFHOOK;
@@ -40099,6 +40616,7 @@
     method public boolean hasSystemFeature(java.lang.String);
     method public boolean hasSystemFeature(java.lang.String, int);
     method public boolean isInstantApp();
+    method public boolean isInstantApp(java.lang.String);
     method public boolean isPermissionRevokedByPolicy(java.lang.String, java.lang.String);
     method public boolean isSafeMode();
     method public java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(android.content.Intent, int);
@@ -40130,7 +40648,7 @@
 
 package android.test.suitebuilder {
 
-  public class TestMethod {
+  public deprecated class TestMethod {
     ctor public TestMethod(java.lang.reflect.Method, java.lang.Class<? extends junit.framework.TestCase>);
     ctor public TestMethod(java.lang.String, java.lang.Class<? extends junit.framework.TestCase>);
     ctor public TestMethod(junit.framework.TestCase);
@@ -40141,7 +40659,7 @@
     method public java.lang.String getName();
   }
 
-  public class TestSuiteBuilder {
+  public deprecated class TestSuiteBuilder {
     ctor public TestSuiteBuilder(java.lang.Class);
     ctor public TestSuiteBuilder(java.lang.String, java.lang.ClassLoader);
     method public android.test.suitebuilder.TestSuiteBuilder addRequirements(java.util.List<com.android.internal.util.Predicate<android.test.suitebuilder.TestMethod>>);
@@ -40154,7 +40672,7 @@
     method public android.test.suitebuilder.TestSuiteBuilder named(java.lang.String);
   }
 
-  public static class TestSuiteBuilder.FailedToCreateTests extends junit.framework.TestCase {
+  public static deprecated class TestSuiteBuilder.FailedToCreateTests extends junit.framework.TestCase {
     ctor public TestSuiteBuilder.FailedToCreateTests(java.lang.Exception);
     method public void testSuiteConstructionFailed();
   }
@@ -42369,30 +42887,51 @@
     method public abstract void setValue(T, float);
   }
 
-  public final class Half {
+  public final class Half extends java.lang.Number implements java.lang.Comparable {
+    ctor public Half(short);
+    ctor public Half(float);
+    ctor public Half(double);
+    ctor public Half(java.lang.String) throws java.lang.NumberFormatException;
     method public static short abs(short);
     method public static short ceil(short);
+    method public static int compare(short, short);
+    method public int compareTo(android.util.Half);
     method public static short copySign(short, short);
+    method public double doubleValue();
     method public static boolean equals(short, short);
+    method public float floatValue();
     method public static short floor(short);
     method public static int getExponent(short);
     method public static int getSign(short);
     method public static int getSignificand(short);
     method public static boolean greater(short, short);
     method public static boolean greaterEquals(short, short);
+    method public static int halfToIntBits(short);
+    method public static int halfToRawIntBits(short);
+    method public static short halfToShortBits(short);
+    method public short halfValue();
+    method public static int hashCode(short);
+    method public static short intBitsToHalf(int);
+    method public int intValue();
     method public static boolean isInfinite(short);
+    method public boolean isNaN();
     method public static boolean isNaN(short);
     method public static boolean isNormalized(short);
     method public static boolean less(short, short);
     method public static boolean lessEquals(short, short);
+    method public long longValue();
     method public static short max(short, short);
     method public static short min(short, short);
+    method public static short parseHalf(java.lang.String) throws java.lang.NumberFormatException;
     method public static short round(short);
     method public static float toFloat(short);
+    method public static short toHalf(float);
     method public static java.lang.String toHexString(short);
     method public static java.lang.String toString(short);
     method public static short trunc(short);
-    method public static short valueOf(float);
+    method public static android.util.Half valueOf(short);
+    method public static android.util.Half valueOf(float);
+    method public static android.util.Half valueOf(java.lang.String);
     field public static final short EPSILON = 5120; // 0x1400
     field public static final short LOWEST_VALUE = -1025; // 0xfffffbff
     field public static final int MAX_EXPONENT = 15; // 0xf
@@ -43049,6 +43588,7 @@
     field public static final int STATE_OFF = 1; // 0x1
     field public static final int STATE_ON = 2; // 0x2
     field public static final int STATE_UNKNOWN = 0; // 0x0
+    field public static final int STATE_VR = 5; // 0x5
   }
 
   public static final class Display.HdrCapabilities implements android.os.Parcelable {
@@ -43117,11 +43657,13 @@
     field public static final int DRAW_DURATION = 4; // 0x4
     field public static final int FIRST_DRAW_FRAME = 9; // 0x9
     field public static final int INPUT_HANDLING_DURATION = 1; // 0x1
+    field public static final int INTENDED_VSYNC_TIMESTAMP = 10; // 0xa
     field public static final int LAYOUT_MEASURE_DURATION = 3; // 0x3
     field public static final int SWAP_BUFFERS_DURATION = 7; // 0x7
     field public static final int SYNC_DURATION = 5; // 0x5
     field public static final int TOTAL_DURATION = 8; // 0x8
     field public static final int UNKNOWN_DELAY_DURATION = 0; // 0x0
+    field public static final int VSYNC_TIMESTAMP = 11; // 0xb
   }
 
   public abstract class FrameStats {
@@ -44494,8 +45036,8 @@
     method public void drawableHotspotChanged(float, float);
     method protected void drawableStateChanged();
     method public android.view.View findFocus();
-    method public final android.view.View findViewById(int);
-    method public final android.view.View findViewWithTag(java.lang.Object);
+    method public final <T extends android.view.View> T findViewById(int);
+    method public final <T extends android.view.View> T findViewWithTag(java.lang.Object);
     method public void findViewsWithText(java.util.ArrayList<android.view.View>, java.lang.CharSequence, int);
     method protected deprecated boolean fitSystemWindows(android.graphics.Rect);
     method public android.view.View focusSearch(int);
@@ -44510,9 +45052,11 @@
     method public float getAlpha();
     method public android.view.animation.Animation getAnimation();
     method public android.os.IBinder getApplicationWindowToken();
+    method public int getAutoFillHint();
     method public int getAutoFillMode();
-    method public android.view.autofill.AutoFillType getAutoFillType();
+    method public final deprecated android.view.autofill.AutoFillType getAutoFillType();
     method public android.view.autofill.AutoFillValue getAutoFillValue();
+    method public int getAutofillType();
     method public android.graphics.drawable.Drawable getBackground();
     method public android.content.res.ColorStateList getBackgroundTintList();
     method public android.graphics.PorterDuff.Mode getBackgroundTintMode();
@@ -44556,6 +45100,7 @@
     method protected int getHorizontalScrollbarHeight();
     method public int getId();
     method public int getImportantForAccessibility();
+    method public int getImportantForAutofill();
     method public boolean getKeepScreenOn();
     method public android.view.KeyEvent.DispatcherState getKeyDispatcherState();
     method public int getLabelFor();
@@ -44597,6 +45142,7 @@
     method public float getPivotX();
     method public float getPivotY();
     method public android.view.PointerIcon getPointerIcon();
+    method public int getResolvedAutoFillMode();
     method public android.content.res.Resources getResources();
     method public final boolean getRevealOnFocusHint();
     method public final int getRight();
@@ -44684,6 +45230,7 @@
     method public boolean isHorizontalScrollBarEnabled();
     method public boolean isHovered();
     method public boolean isImportantForAccessibility();
+    method public final boolean isImportantForAutofill();
     method public boolean isInEditMode();
     method public boolean isInLayout();
     method public boolean isInTouchMode();
@@ -44827,6 +45374,7 @@
     method public void setActivated(boolean);
     method public void setAlpha(float);
     method public void setAnimation(android.view.animation.Animation);
+    method public void setAutoFillHint(int);
     method public void setAutoFillMode(int);
     method public void setBackground(android.graphics.drawable.Drawable);
     method public void setBackgroundColor(int);
@@ -44865,6 +45413,7 @@
     method public void setHovered(boolean);
     method public void setId(int);
     method public void setImportantForAccessibility(int);
+    method public void setImportantForAutofill(int);
     method public void setKeepScreenOn(boolean);
     method public void setKeyboardNavigationCluster(boolean);
     method public void setLabelFor(int);
@@ -44968,6 +45517,25 @@
     field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
     field public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 1; // 0x1
     field public static final android.util.Property<android.view.View, java.lang.Float> ALPHA;
+    field public static final int AUTOFILL_TYPE_DATE = 4; // 0x4
+    field public static final int AUTOFILL_TYPE_LIST = 3; // 0x3
+    field public static final int AUTOFILL_TYPE_NONE = 0; // 0x0
+    field public static final int AUTOFILL_TYPE_TEXT = 1; // 0x1
+    field public static final int AUTOFILL_TYPE_TOGGLE = 2; // 0x2
+    field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_DATE = 512; // 0x200
+    field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_DAY = 4096; // 0x1000
+    field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_MONTH = 1024; // 0x400
+    field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_YEAR = 2048; // 0x800
+    field public static final int AUTO_FILL_HINT_CREDIT_CARD_NUMBER = 128; // 0x80
+    field public static final int AUTO_FILL_HINT_CREDIT_CARD_SECURITY_CODE = 256; // 0x100
+    field public static final int AUTO_FILL_HINT_EMAIL_ADDRESS = 1; // 0x1
+    field public static final int AUTO_FILL_HINT_NAME = 2; // 0x2
+    field public static final int AUTO_FILL_HINT_NONE = 0; // 0x0
+    field public static final int AUTO_FILL_HINT_PASSWORD = 8; // 0x8
+    field public static final int AUTO_FILL_HINT_PHONE = 16; // 0x10
+    field public static final int AUTO_FILL_HINT_POSTAL_ADDRESS = 32; // 0x20
+    field public static final int AUTO_FILL_HINT_POSTAL_CODE = 64; // 0x40
+    field public static final int AUTO_FILL_HINT_USERNAME = 4; // 0x4
     field public static final int AUTO_FILL_MODE_AUTO = 1; // 0x1
     field public static final int AUTO_FILL_MODE_INHERIT = 0; // 0x0
     field public static final int AUTO_FILL_MODE_MANUAL = 2; // 0x2
@@ -45011,6 +45579,9 @@
     field public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 2; // 0x2
     field public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 4; // 0x4
     field public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 1; // 0x1
+    field public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0; // 0x0
+    field public static final int IMPORTANT_FOR_AUTOFILL_NO = 2; // 0x2
+    field public static final int IMPORTANT_FOR_AUTOFILL_YES = 1; // 0x1
     field public static final int INVISIBLE = 4; // 0x4
     field public static final int KEEP_SCREEN_ON = 67108864; // 0x4000000
     field public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
@@ -45529,6 +46100,7 @@
     method public abstract int getLayoutDirection();
     method public abstract android.view.ViewParent getParent();
     method public abstract android.view.ViewParent getParentForAccessibility();
+    method public default int getResolvedAutoFillMode();
     method public abstract int getTextAlignment();
     method public abstract int getTextDirection();
     method public abstract deprecated void invalidateChild(android.view.View, android.graphics.Rect);
@@ -45607,7 +46179,7 @@
     method public abstract int addChildCount(int);
     method public abstract void asyncCommit();
     method public abstract android.view.ViewStructure asyncNewChild(int);
-    method public abstract android.view.ViewStructure asyncNewChild(int, int, int);
+    method public abstract android.view.ViewStructure asyncNewChildForAutoFill(int, int, int);
     method public abstract int getChildCount();
     method public abstract android.os.Bundle getExtras();
     method public abstract java.lang.CharSequence getHint();
@@ -45616,12 +46188,15 @@
     method public abstract int getTextSelectionStart();
     method public abstract boolean hasExtras();
     method public abstract android.view.ViewStructure newChild(int);
-    method public abstract android.view.ViewStructure newChild(int, int, int);
+    method public abstract android.view.ViewStructure newChildForAutoFill(int, int, int);
     method public abstract void setAccessibilityFocused(boolean);
     method public abstract void setActivated(boolean);
     method public abstract void setAlpha(float);
-    method public abstract void setAutoFillType(android.view.autofill.AutoFillType);
+    method public abstract void setAutoFillHint(int);
+    method public abstract void setAutoFillOptions(java.lang.String[]);
+    method public abstract deprecated void setAutoFillType(android.view.autofill.AutoFillType);
     method public abstract void setAutoFillValue(android.view.autofill.AutoFillValue);
+    method public abstract void setAutofillType(int);
     method public abstract void setCheckable(boolean);
     method public abstract void setChecked(boolean);
     method public abstract void setChildCount(int);
@@ -45636,7 +46211,9 @@
     method public abstract void setFocused(boolean);
     method public abstract void setHint(java.lang.CharSequence);
     method public abstract void setId(int, java.lang.String, java.lang.String, java.lang.String);
+    method public abstract void setInputType(int);
     method public abstract void setLongClickable(boolean);
+    method public abstract void setSanitized(boolean);
     method public abstract void setSelected(boolean);
     method public abstract void setText(java.lang.CharSequence);
     method public abstract void setText(java.lang.CharSequence, int, int);
@@ -45645,7 +46222,6 @@
     method public abstract void setTransformation(android.graphics.Matrix);
     method public abstract void setUrl(java.lang.String);
     method public abstract void setVisibility(int);
-    field public static final int AUTO_FILL_FLAG_SANITIZED = 1; // 0x1
   }
 
   public final class ViewStub extends android.view.View {
@@ -46876,21 +47452,34 @@
   }
 
   public final class AutoFillManager {
-    method public void focusChanged(android.view.View, boolean);
+    method public void registerCallback(android.view.autofill.AutoFillManager.AutofillCallback);
     method public void reset();
+    method public void startAutoFillRequest(android.view.View);
+    method public void startAutoFillRequestOnVirtualView(android.view.View, int, android.graphics.Rect);
+    method public void stopAutoFillRequest(android.view.View);
+    method public void stopAutoFillRequestOnVirtualView(android.view.View, int);
+    method public void unregisterCallback(android.view.autofill.AutoFillManager.AutofillCallback);
     method public void valueChanged(android.view.View);
-    method public void virtualFocusChanged(android.view.View, int, android.graphics.Rect, boolean);
     method public void virtualValueChanged(android.view.View, int, android.view.autofill.AutoFillValue);
     field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE";
     field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT";
   }
 
+  public static abstract class AutoFillManager.AutofillCallback {
+    ctor public AutoFillManager.AutofillCallback();
+    method public void onAutofillEvent(android.view.View, int);
+    method public void onAutofillEventVirtual(android.view.View, int, int);
+    field public static final int EVENT_INPUT_HIDDEN = 2; // 0x2
+    field public static final int EVENT_INPUT_SHOWN = 1; // 0x1
+  }
+
   public final class AutoFillType implements android.os.Parcelable {
     method public int describeContents();
+    method public static android.view.autofill.AutoFillType forDate();
     method public static android.view.autofill.AutoFillType forList();
-    method public static android.view.autofill.AutoFillType forText(int);
+    method public static android.view.autofill.AutoFillType forText();
     method public static android.view.autofill.AutoFillType forToggle();
-    method public int getSubType();
+    method public boolean isDate();
     method public boolean isList();
     method public boolean isText();
     method public boolean isToggle();
@@ -46900,9 +47489,11 @@
 
   public final class AutoFillValue implements android.os.Parcelable {
     method public int describeContents();
+    method public static android.view.autofill.AutoFillValue forDate(long);
     method public static android.view.autofill.AutoFillValue forList(int);
     method public static android.view.autofill.AutoFillValue forText(java.lang.CharSequence);
     method public static android.view.autofill.AutoFillValue forToggle(boolean);
+    method public long getDateValue();
     method public int getListValue();
     method public java.lang.CharSequence getTextValue();
     method public boolean getToggleValue();
@@ -47346,9 +47937,9 @@
   }
 
   public abstract interface TextClassifier {
-    method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int);
-    method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int);
-    method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int);
+    method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int, android.os.LocaleList);
+    method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int, android.os.LocaleList);
+    method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int, android.os.LocaleList);
     field public static final android.view.textclassifier.TextClassifier NO_OP;
     field public static final java.lang.String TYPE_ADDRESS = "address";
     field public static final java.lang.String TYPE_EMAIL = "email";
@@ -50517,11 +51108,9 @@
     method public void removeTextChangedListener(android.text.TextWatcher);
     method public void setAllCaps(boolean);
     method public final void setAutoLinkMask(int);
-    method public void setAutoSizeMaxTextSize(int, float);
-    method public void setAutoSizeMinTextSize(int, float);
-    method public void setAutoSizeStepGranularity(int, float);
-    method public void setAutoSizeTextPresetSizes(int[]);
-    method public void setAutoSizeTextType(int);
+    method public void setAutoSizeTextTypeUniformWithConfiguration(int, int, int, int) throws java.lang.IllegalArgumentException;
+    method public void setAutoSizeTextTypeUniformWithPresetSizes(int[], int) throws java.lang.IllegalArgumentException;
+    method public void setAutoSizeTextTypeWithDefaults(int);
     method public void setBreakStrategy(int);
     method public void setCompoundDrawablePadding(int);
     method public void setCompoundDrawableTintList(android.content.res.ColorStateList);
@@ -50804,6 +51393,8 @@
     method public int resolveAdjustedSize(int, int);
     method public void resume();
     method public void seekTo(int);
+    method public void setAudioAttributes(android.media.AudioAttributes);
+    method public void setAudioFocusRequest(int);
     method public void setMediaController(android.widget.MediaController);
     method public void setOnCompletionListener(android.media.MediaPlayer.OnCompletionListener);
     method public void setOnErrorListener(android.media.MediaPlayer.OnErrorListener);
@@ -50908,7 +51499,7 @@
 
 package com.android.internal.util {
 
-  public abstract interface Predicate<T> {
+  public abstract deprecated interface Predicate<T> {
     method public abstract boolean apply(T);
   }
 
@@ -51238,7 +51829,7 @@
     method public static dalvik.system.DexFile loadDex(java.lang.String, java.lang.String, int) throws java.io.IOException;
   }
 
-  public final class InMemoryDexClassLoader extends java.lang.ClassLoader {
+  public final class InMemoryDexClassLoader extends dalvik.system.BaseDexClassLoader {
     ctor public InMemoryDexClassLoader(java.nio.ByteBuffer, java.lang.ClassLoader);
   }
 
diff --git a/api/removed.txt b/api/removed.txt
index ab22b6e..148f3f1 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -20,25 +20,14 @@
 package android.content {
 
   public abstract class Context {
-    method public deprecated android.content.Context createCredentialEncryptedStorageContext();
-    method public deprecated android.content.Context createDeviceEncryptedStorageContext();
     method public abstract android.content.SharedPreferences getSharedPreferences(java.io.File, int);
     method public abstract java.io.File getSharedPreferencesPath(java.lang.String);
-    method public deprecated boolean isCredentialEncryptedStorage();
-    method public deprecated boolean isDeviceEncryptedStorage();
-    method public deprecated boolean migrateDatabaseFrom(android.content.Context, java.lang.String);
-    method public deprecated boolean migrateSharedPreferencesFrom(android.content.Context, java.lang.String);
   }
 
 }
 
 package android.content.pm {
 
-  public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
-    field public deprecated java.lang.String credentialEncryptedDataDir;
-    field public deprecated java.lang.String deviceEncryptedDataDir;
-  }
-
   public class ComponentInfo extends android.content.pm.PackageItemInfo {
     field public deprecated boolean encryptionAware;
   }
@@ -47,12 +36,6 @@
     field public static final int REQUESTED_PERMISSION_REQUIRED = 1; // 0x1
   }
 
-  public abstract class PackageManager {
-    field public static final deprecated int MATCH_ENCRYPTION_AWARE = 524288; // 0x80000
-    field public static final deprecated int MATCH_ENCRYPTION_AWARE_AND_UNAWARE = 786432; // 0xc0000
-    field public static final deprecated int MATCH_ENCRYPTION_UNAWARE = 262144; // 0x40000
-  }
-
 }
 
 package android.database {
@@ -169,10 +152,6 @@
     method public android.graphics.drawable.Drawable getBadgedDrawableForUser(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int);
     method public android.graphics.drawable.Drawable getBadgedIconForUser(android.graphics.drawable.Drawable, android.os.UserHandle);
     method public java.lang.CharSequence getBadgedLabelForUser(java.lang.CharSequence, android.os.UserHandle);
-    method public deprecated boolean isUserRunningAndLocked();
-    method public deprecated boolean isUserRunningAndLocked(android.os.UserHandle);
-    method public deprecated boolean isUserRunningAndUnlocked();
-    method public deprecated boolean isUserRunningAndUnlocked(android.os.UserHandle);
   }
 
 }
@@ -180,21 +159,16 @@
 package android.os.storage {
 
   public class StorageManager {
+    method public deprecated long getCacheQuotaBytes();
+    method public deprecated long getCacheSizeBytes();
+    method public deprecated long getExternalCacheQuotaBytes();
+    method public deprecated long getExternalCacheSizeBytes();
     method public android.os.storage.StorageVolume getPrimaryVolume();
     method public android.os.storage.StorageVolume[] getVolumeList();
   }
 
 }
 
-package android.preference {
-
-  public class PreferenceManager {
-    method public deprecated void setStorageCredentialEncrypted();
-    method public deprecated void setStorageDeviceEncrypted();
-  }
-
-}
-
 package android.provider {
 
   public class Browser {
@@ -395,6 +369,16 @@
 
 }
 
+package android.view.textclassifier {
+
+  public abstract interface TextClassifier {
+    method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int);
+    method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int);
+    method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int);
+  }
+
+}
+
 package android.webkit {
 
   public class WebViewClient {
diff --git a/api/system-current.txt b/api/system-current.txt
index d674c9a..339f40b 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -25,6 +25,7 @@
     field public static final java.lang.String ADD_VOICEMAIL = "com.android.voicemail.permission.ADD_VOICEMAIL";
     field public static final java.lang.String ALLOCATE_AGGRESSIVE = "android.permission.ALLOCATE_AGGRESSIVE";
     field public static final java.lang.String ALLOW_ANY_CODEC_FOR_PLAYBACK = "android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK";
+    field public static final java.lang.String ANSWER_PHONE_CALLS = "android.permission.ANSWER_PHONE_CALLS";
     field public static final java.lang.String BACKUP = "android.permission.BACKUP";
     field public static final java.lang.String BATTERY_STATS = "android.permission.BATTERY_STATS";
     field public static final java.lang.String BIND_ACCESSIBILITY_SERVICE = "android.permission.BIND_ACCESSIBILITY_SERVICE";
@@ -206,7 +207,6 @@
     field public static final java.lang.String REQUEST_DELETE_PACKAGES = "android.permission.REQUEST_DELETE_PACKAGES";
     field public static final java.lang.String REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
     field public static final java.lang.String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES";
-    field public static final java.lang.String REQUEST_NETWORK_SCORES = "android.permission.REQUEST_NETWORK_SCORES";
     field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
     field public static final java.lang.String RESTRICTED_VR_ACCESS = "android.permission.RESTRICTED_VR_ACCESS";
     field public static final java.lang.String RETRIEVE_WINDOW_CONTENT = "android.permission.RETRIEVE_WINDOW_CONTENT";
@@ -410,6 +410,7 @@
     field public static final int authorities = 16842776; // 0x1010018
     field public static final int autoAdvanceViewId = 16843535; // 0x101030f
     field public static final int autoCompleteTextViewStyle = 16842859; // 0x101006b
+    field public static final int autoFillHint = 16844121; // 0x1010559
     field public static final int autoFillMode = 16844116; // 0x1010554
     field public static final int autoLink = 16842928; // 0x10100b0
     field public static final int autoMirrored = 16843754; // 0x10103ea
@@ -418,7 +419,7 @@
     field public static final int autoSizeMinTextSize = 16844088; // 0x1010538
     field public static final int autoSizePresetSizes = 16844087; // 0x1010537
     field public static final int autoSizeStepGranularity = 16844086; // 0x1010536
-    field public static final int autoSizeText = 16844085; // 0x1010535
+    field public static final int autoSizeTextType = 16844085; // 0x1010535
     field public static final int autoStart = 16843445; // 0x10102b5
     field public static final deprecated int autoText = 16843114; // 0x101016a
     field public static final int autoUrlDetect = 16843404; // 0x101028c
@@ -523,6 +524,7 @@
     field public static final int colorControlHighlight = 16843820; // 0x101042c
     field public static final int colorControlNormal = 16843817; // 0x1010429
     field public static final int colorEdgeEffect = 16843982; // 0x10104ce
+    field public static final int colorError = 16844100; // 0x1010544
     field public static final int colorFocusedHighlight = 16843663; // 0x101038f
     field public static final int colorForeground = 16842800; // 0x1010030
     field public static final int colorForegroundInverse = 16843270; // 0x1010206
@@ -717,8 +719,9 @@
     field public static final int fontFamily = 16843692; // 0x10103ac
     field public static final int fontFeatureSettings = 16843959; // 0x10104b7
     field public static final int fontProviderAuthority = 16844114; // 0x1010552
+    field public static final int fontProviderPackage = 16844122; // 0x101055a
     field public static final int fontProviderQuery = 16844115; // 0x1010553
-    field public static final int fontStyle = 16844081; // 0x1010531
+    field public static final int fontStyle = 16844095; // 0x101053f
     field public static final int fontWeight = 16844083; // 0x1010533
     field public static final int footerDividersEnabled = 16843311; // 0x101022f
     field public static final int forceHasOverlappingRendering = 16844065; // 0x1010521
@@ -819,6 +822,7 @@
     field public static final int imeSubtypeMode = 16843501; // 0x10102ed
     field public static final int immersive = 16843456; // 0x10102c0
     field public static final int importantForAccessibility = 16843690; // 0x10103aa
+    field public static final int importantForAutofill = 16844123; // 0x101055b
     field public static final int inAnimation = 16843127; // 0x1010177
     field public static final int includeFontPadding = 16843103; // 0x101015f
     field public static final int includeInGlobalSearch = 16843374; // 0x101026e
@@ -1116,7 +1120,7 @@
     field public static final int preferenceStyle = 16842894; // 0x101008e
     field public static final int presentationTheme = 16843712; // 0x10103c0
     field public static final int previewImage = 16843482; // 0x10102da
-    field public static final int primaryContentAlpha = 16843367; // 0x1010267
+    field public static final int primaryContentAlpha = 16844117; // 0x1010555
     field public static final int priority = 16842780; // 0x101001c
     field public static final int privateImeOptions = 16843299; // 0x1010223
     field public static final int process = 16842769; // 0x1010011
@@ -1172,7 +1176,9 @@
     field public static final int requireDeviceUnlock = 16843756; // 0x10103ec
     field public static final int required = 16843406; // 0x101028e
     field public static final int requiredAccountType = 16843734; // 0x10103d6
+    field public static final int requiredFeature = 16844119; // 0x1010557
     field public static final int requiredForAllUsers = 16843728; // 0x10103d0
+    field public static final int requiredNotFeature = 16844120; // 0x1010558
     field public static final int requiresFadingEdge = 16843685; // 0x10103a5
     field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364
     field public static final int resizeClip = 16843983; // 0x10104cf
@@ -1245,7 +1251,7 @@
     field public static final int searchSuggestSelection = 16843224; // 0x10101d8
     field public static final int searchSuggestThreshold = 16843373; // 0x101026d
     field public static final int searchViewStyle = 16843904; // 0x1010480
-    field public static final int secondaryContentAlpha = 16843688; // 0x10103a8
+    field public static final int secondaryContentAlpha = 16844118; // 0x1010556
     field public static final int secondaryProgress = 16843064; // 0x1010138
     field public static final int secondaryProgressTint = 16843879; // 0x1010467
     field public static final int secondaryProgressTintMode = 16843880; // 0x1010468
@@ -1433,7 +1439,6 @@
     field public static final int textCheckMarkInverse = 16842823; // 0x1010047
     field public static final int textColor = 16842904; // 0x1010098
     field public static final int textColorAlertDialogListItem = 16843526; // 0x1010306
-    field public static final int textColorError = 16844100; // 0x1010544
     field public static final int textColorHighlight = 16842905; // 0x1010099
     field public static final int textColorHighlightInverse = 16843599; // 0x101034f
     field public static final int textColorHint = 16842906; // 0x101009a
@@ -1572,7 +1577,7 @@
     field public static final int viewportWidth = 16843778; // 0x1010402
     field public static final int visibility = 16842972; // 0x10100dc
     field public static final int visible = 16843156; // 0x1010194
-    field public static final int visibleToInstantApps = 16844095; // 0x101053f
+    field public static final int visibleToInstantApps = 16844081; // 0x1010531
     field public static final int vmSafeMode = 16843448; // 0x10102b8
     field public static final int voiceIcon = 16843908; // 0x1010484
     field public static final int voiceLanguage = 16843349; // 0x1010255
@@ -2927,6 +2932,7 @@
     method public android.content.pm.ResolveInfo getResolveInfo();
     method public java.lang.String getSettingsActivityName();
     method public java.lang.String loadDescription(android.content.pm.PackageManager);
+    method public java.lang.String loadSummary(android.content.pm.PackageManager);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int CAPABILITY_CAN_CAPTURE_FINGERPRINT_GESTURES = 64; // 0x40
     field public static final int CAPABILITY_CAN_CONTROL_MAGNIFICATION = 16; // 0x10
@@ -4047,8 +4053,9 @@
     method public void readFromParcel(android.os.Parcel);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.app.ActivityManager.RunningAppProcessInfo> CREATOR;
-    field public static final int IMPORTANCE_BACKGROUND = 400; // 0x190
-    field public static final int IMPORTANCE_EMPTY = 500; // 0x1f4
+    field public static final deprecated int IMPORTANCE_BACKGROUND = 400; // 0x190
+    field public static final int IMPORTANCE_CACHED = 400; // 0x190
+    field public static final deprecated int IMPORTANCE_EMPTY = 500; // 0x1f4
     field public static final int IMPORTANCE_FOREGROUND = 100; // 0x64
     field public static final int IMPORTANCE_FOREGROUND_SERVICE = 125; // 0x7d
     field public static final int IMPORTANCE_GONE = 1000; // 0x3e8
@@ -4286,6 +4293,7 @@
     field public static final int MODE_IGNORED = 1; // 0x1
     field public static final java.lang.String OPSTR_ACTIVATE_VPN = "android:activate_vpn";
     field public static final java.lang.String OPSTR_ADD_VOICEMAIL = "android:add_voicemail";
+    field public static final java.lang.String OPSTR_ANSWER_PHONE_CALLS = "android:answer_phone_calls";
     field public static final java.lang.String OPSTR_BODY_SENSORS = "android:body_sensors";
     field public static final java.lang.String OPSTR_CALL_PHONE = "android:call_phone";
     field public static final java.lang.String OPSTR_CAMERA = "android:camera";
@@ -4657,16 +4665,12 @@
     field public static final int VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION = 3; // 0x3
   }
 
-  public abstract class EphemeralResolverService extends android.app.Service {
+  public abstract deprecated class EphemeralResolverService extends android.app.InstantAppResolverService {
     ctor public EphemeralResolverService();
-    method public final void attachBaseContext(android.content.Context);
     method public android.os.Looper getLooper();
-    method public final android.os.IBinder onBind(android.content.Intent);
     method public abstract deprecated java.util.List<android.content.pm.EphemeralResolveInfo> onEphemeralResolveInfoList(int[], int);
     method public android.content.pm.EphemeralResolveInfo onGetEphemeralIntentFilter(java.lang.String);
     method public java.util.List<android.content.pm.EphemeralResolveInfo> onGetEphemeralResolveInfo(int[]);
-    field public static final java.lang.String EXTRA_RESOLVE_INFO = "android.app.extra.RESOLVE_INFO";
-    field public static final java.lang.String EXTRA_SEQUENCE = "android.app.extra.SEQUENCE";
   }
 
   public class ExpandableListActivity extends android.app.Activity implements android.widget.ExpandableListView.OnChildClickListener android.widget.ExpandableListView.OnGroupCollapseListener android.widget.ExpandableListView.OnGroupExpandListener android.view.View.OnCreateContextMenuListener {
@@ -4898,6 +4902,7 @@
     method public abstract android.app.Fragment getPrimaryNavigationFragment();
     method public void invalidateOptionsMenu();
     method public abstract boolean isDestroyed();
+    method public abstract boolean isStateSaved();
     method public abstract void popBackStack();
     method public abstract void popBackStack(java.lang.String, int);
     method public abstract void popBackStack(int, int);
@@ -4986,6 +4991,20 @@
     field public static final int TRANSIT_UNSET = -1; // 0xffffffff
   }
 
+  public abstract class InstantAppResolverService extends android.app.Service {
+    ctor public InstantAppResolverService();
+    method public final void attachBaseContext(android.content.Context);
+    method public final android.os.IBinder onBind(android.content.Intent);
+    method public void onGetInstantAppIntentFilter(int[], android.app.InstantAppResolverService.InstantAppResolutionCallback);
+    method public void onGetInstantAppResolveInfo(int[], android.app.InstantAppResolverService.InstantAppResolutionCallback);
+    field public static final java.lang.String EXTRA_RESOLVE_INFO = "android.app.extra.RESOLVE_INFO";
+    field public static final java.lang.String EXTRA_SEQUENCE = "android.app.extra.SEQUENCE";
+  }
+
+  public static final class InstantAppResolverService.InstantAppResolutionCallback {
+    method public void onInstantAppResolveInfo(java.util.List<android.content.pm.InstantAppResolveInfo>);
+  }
+
   public class Instrumentation {
     ctor public Instrumentation();
     method public void addMonitor(android.app.Instrumentation.ActivityMonitor);
@@ -5656,6 +5675,7 @@
 
   public final class NotificationChannel implements android.os.Parcelable {
     ctor public NotificationChannel(java.lang.String, java.lang.CharSequence, int);
+    ctor public NotificationChannel(java.lang.String, int, int);
     ctor protected NotificationChannel(android.os.Parcel);
     method public boolean canBypassDnd();
     method public boolean canShowBadge();
@@ -5669,6 +5689,7 @@
     method public int getLightColor();
     method public int getLockscreenVisibility();
     method public java.lang.CharSequence getName();
+    method public int getNameResId();
     method public android.net.Uri getSound();
     method public int getUserLockedFields();
     method public long[] getVibrationPattern();
@@ -5705,6 +5726,7 @@
 
   public final class NotificationChannelGroup implements android.os.Parcelable {
     ctor public NotificationChannelGroup(java.lang.String, java.lang.CharSequence);
+    ctor public NotificationChannelGroup(java.lang.String, int);
     ctor protected NotificationChannelGroup(android.os.Parcel);
     method public void addChannel(android.app.NotificationChannel);
     method public android.app.NotificationChannelGroup clone();
@@ -5712,6 +5734,7 @@
     method public java.util.List<android.app.NotificationChannel> getChannels();
     method public java.lang.String getId();
     method public java.lang.CharSequence getName();
+    method public int getNameResId();
     method public org.json.JSONObject toJson() throws org.json.JSONException;
     method public void writeToParcel(android.os.Parcel, int);
     method public void writeXml(org.xmlpull.v1.XmlSerializer) throws java.io.IOException;
@@ -6786,9 +6809,12 @@
 
   public static class AssistStructure.ViewNode {
     method public float getAlpha();
+    method public int getAutoFillHint();
     method public android.view.autofill.AutoFillId getAutoFillId();
-    method public android.view.autofill.AutoFillType getAutoFillType();
+    method public java.lang.String[] getAutoFillOptions();
+    method public deprecated android.view.autofill.AutoFillType getAutoFillType();
     method public android.view.autofill.AutoFillValue getAutoFillValue();
+    method public int getAutofillType();
     method public android.app.assist.AssistStructure.ViewNode getChildAt(int);
     method public int getChildCount();
     method public java.lang.String getClassName();
@@ -6801,6 +6827,7 @@
     method public java.lang.String getIdEntry();
     method public java.lang.String getIdPackage();
     method public java.lang.String getIdType();
+    method public int getInputType();
     method public int getLeft();
     method public int getScrollX();
     method public int getScrollY();
@@ -6938,18 +6965,64 @@
   public class BackupManagerMonitor {
     ctor public BackupManagerMonitor();
     method public void onEvent(android.os.Bundle);
+    field public static final java.lang.String EXTRA_LOG_CANCEL_ALL = "android.app.backup.extra.LOG_CANCEL_ALL";
     field public static final java.lang.String EXTRA_LOG_EVENT_CATEGORY = "android.app.backup.extra.LOG_EVENT_CATEGORY";
     field public static final java.lang.String EXTRA_LOG_EVENT_ID = "android.app.backup.extra.LOG_EVENT_ID";
     field public static final java.lang.String EXTRA_LOG_EVENT_PACKAGE_NAME = "android.app.backup.extra.LOG_EVENT_PACKAGE_NAME";
     field public static final java.lang.String EXTRA_LOG_EVENT_PACKAGE_VERSION = "android.app.backup.extra.LOG_EVENT_PACKAGE_VERSION";
+    field public static final java.lang.String EXTRA_LOG_EXCEPTION_FULL_BACKUP = "android.app.backup.extra.LOG_EXCEPTION_FULL_BACKUP";
+    field public static final java.lang.String EXTRA_LOG_ILLEGAL_KEY = "android.app.backup.extra.LOG_ILLEGAL_KEY";
+    field public static final java.lang.String EXTRA_LOG_MANIFEST_PACKAGE_NAME = "android.app.backup.extra.LOG_MANIFEST_PACKAGE_NAME";
+    field public static final java.lang.String EXTRA_LOG_OLD_VERSION = "android.app.backup.extra.LOG_OLD_VERSION";
+    field public static final java.lang.String EXTRA_LOG_POLICY_ALLOW_APKS = "android.app.backup.extra.LOG_POLICY_ALLOW_APKS";
+    field public static final java.lang.String EXTRA_LOG_PREFLIGHT_ERROR = "android.app.backup.extra.LOG_PREFLIGHT_ERROR";
+    field public static final java.lang.String EXTRA_LOG_RESTORE_ANYWAY = "android.app.backup.extra.LOG_RESTORE_ANYWAY";
+    field public static final java.lang.String EXTRA_LOG_RESTORE_VERSION = "android.app.backup.extra.LOG_RESTORE_VERSION";
+    field public static final java.lang.String EXTRA_LOG_WIDGET_PACKAGE_NAME = "android.app.backup.extra.LOG_WIDGET_PACKAGE_NAME";
     field public static final int LOG_EVENT_CATEGORY_AGENT = 2; // 0x2
     field public static final int LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY = 3; // 0x3
     field public static final int LOG_EVENT_CATEGORY_TRANSPORT = 1; // 0x1
-    field public static final int LOG_EVENT_ID_FULL_BACKUP_TIMEOUT = 4; // 0x4
+    field public static final int LOG_EVENT_ID_APK_NOT_INSTALLED = 40; // 0x28
+    field public static final int LOG_EVENT_ID_APP_HAS_NO_AGENT = 28; // 0x1c
+    field public static final int LOG_EVENT_ID_BACKUP_DISABLED = 13; // 0xd
+    field public static final int LOG_EVENT_ID_CANNOT_RESTORE_WITHOUT_APK = 41; // 0x29
+    field public static final int LOG_EVENT_ID_CANT_FIND_AGENT = 30; // 0x1e
+    field public static final int LOG_EVENT_ID_CORRUPT_MANIFEST = 46; // 0x2e
+    field public static final int LOG_EVENT_ID_DEVICE_NOT_PROVISIONED = 14; // 0xe
+    field public static final int LOG_EVENT_ID_ERROR_PREFLIGHT = 16; // 0x10
+    field public static final int LOG_EVENT_ID_EXCEPTION_FULL_BACKUP = 19; // 0x13
+    field public static final int LOG_EVENT_ID_EXPECTED_DIFFERENT_PACKAGE = 43; // 0x2b
+    field public static final int LOG_EVENT_ID_FULL_BACKUP_CANCEL = 4; // 0x4
+    field public static final int LOG_EVENT_ID_FULL_RESTORE_ALLOW_BACKUP_FALSE = 39; // 0x27
+    field public static final int LOG_EVENT_ID_FULL_RESTORE_SIGNATURE_MISMATCH = 37; // 0x25
     field public static final int LOG_EVENT_ID_FULL_RESTORE_TIMEOUT = 45; // 0x2d
-    field public static final int LOG_EVENT_ID_KEY_VALUE_BACKUP_TIMEOUT = 21; // 0x15
+    field public static final int LOG_EVENT_ID_ILLEGAL_KEY = 5; // 0x5
+    field public static final int LOG_EVENT_ID_KEY_VALUE_BACKUP_CANCEL = 21; // 0x15
     field public static final int LOG_EVENT_ID_KEY_VALUE_RESTORE_TIMEOUT = 31; // 0x1f
+    field public static final int LOG_EVENT_ID_LOST_TRANSPORT = 25; // 0x19
+    field public static final int LOG_EVENT_ID_MISSING_SIGNATURE = 42; // 0x2a
+    field public static final int LOG_EVENT_ID_NO_DATA_TO_SEND = 7; // 0x7
     field public static final int LOG_EVENT_ID_NO_PACKAGES = 49; // 0x31
+    field public static final int LOG_EVENT_ID_NO_PM_METADATA_RECEIVED = 23; // 0x17
+    field public static final int LOG_EVENT_ID_NO_RESTORE_METADATA_AVAILABLE = 22; // 0x16
+    field public static final int LOG_EVENT_ID_PACKAGE_INELIGIBLE = 9; // 0x9
+    field public static final int LOG_EVENT_ID_PACKAGE_KEY_VALUE_PARTICIPANT = 10; // 0xa
+    field public static final int LOG_EVENT_ID_PACKAGE_NOT_FOUND = 12; // 0xc
+    field public static final int LOG_EVENT_ID_PACKAGE_NOT_PRESENT = 26; // 0x1a
+    field public static final int LOG_EVENT_ID_PACKAGE_STOPPED = 11; // 0xb
+    field public static final int LOG_EVENT_ID_PACKAGE_TRANSPORT_NOT_PRESENT = 15; // 0xf
+    field public static final int LOG_EVENT_ID_PM_AGENT_HAS_NO_METADATA = 24; // 0x18
+    field public static final int LOG_EVENT_ID_QUOTA_HIT_PREFLIGHT = 18; // 0x12
+    field public static final int LOG_EVENT_ID_RESTORE_ANY_VERSION = 34; // 0x22
+    field public static final int LOG_EVENT_ID_RESTORE_VERSION_HIGHER = 27; // 0x1b
+    field public static final int LOG_EVENT_ID_SIGNATURE_MISMATCH = 29; // 0x1d
+    field public static final int LOG_EVENT_ID_SYSTEM_APP_NO_AGENT = 38; // 0x26
+    field public static final int LOG_EVENT_ID_TRANSPORT_IS_NULL = 50; // 0x32
+    field public static final int LOG_EVENT_ID_UNKNOWN_VERSION = 44; // 0x2c
+    field public static final int LOG_EVENT_ID_VERSIONS_MATCH = 35; // 0x23
+    field public static final int LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER = 36; // 0x24
+    field public static final int LOG_EVENT_ID_WIDGET_METADATA_MISMATCH = 47; // 0x2f
+    field public static final int LOG_EVENT_ID_WIDGET_UNKNOWN_VERSION = 48; // 0x30
   }
 
   public abstract class BackupObserver {
@@ -7100,6 +7173,7 @@
     method public android.app.job.JobInfo.TriggerContentUri[] getTriggerContentUris();
     method public boolean isPeriodic();
     method public boolean isPersisted();
+    method public boolean isRequireBatteryNotLow();
     method public boolean isRequireCharging();
     method public boolean isRequireDeviceIdle();
     method public void writeToParcel(android.os.Parcel, int);
@@ -7126,6 +7200,7 @@
     method public android.app.job.JobInfo.Builder setPeriodic(long, long);
     method public android.app.job.JobInfo.Builder setPersisted(boolean);
     method public android.app.job.JobInfo.Builder setRequiredNetworkType(int);
+    method public android.app.job.JobInfo.Builder setRequiresBatteryNotLow(boolean);
     method public android.app.job.JobInfo.Builder setRequiresCharging(boolean);
     method public android.app.job.JobInfo.Builder setRequiresDeviceIdle(boolean);
     method public android.app.job.JobInfo.Builder setTransientExtras(android.os.Bundle);
@@ -7180,6 +7255,35 @@
 
 package android.app.usage {
 
+  public final class CacheQuotaHint implements android.os.Parcelable {
+    ctor public CacheQuotaHint(android.app.usage.CacheQuotaHint.Builder);
+    method public int describeContents();
+    method public long getQuota();
+    method public int getUid();
+    method public android.app.usage.UsageStats getUsageStats();
+    method public java.lang.String getVolumeUuid();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.usage.CacheQuotaHint> CREATOR;
+    field public static final long QUOTA_NOT_SET = -1L; // 0xffffffffffffffffL
+  }
+
+  public static final class CacheQuotaHint.Builder {
+    ctor public CacheQuotaHint.Builder();
+    ctor public CacheQuotaHint.Builder(android.app.usage.CacheQuotaHint);
+    method public android.app.usage.CacheQuotaHint build();
+    method public android.app.usage.CacheQuotaHint.Builder setQuota(long);
+    method public android.app.usage.CacheQuotaHint.Builder setUid(int);
+    method public android.app.usage.CacheQuotaHint.Builder setUsageStats(android.app.usage.UsageStats);
+    method public android.app.usage.CacheQuotaHint.Builder setVolumeUuid(java.lang.String);
+  }
+
+  public abstract class CacheQuotaService extends android.app.Service {
+    ctor public CacheQuotaService();
+    method public android.os.IBinder onBind(android.content.Intent);
+    method public abstract java.util.List<android.app.usage.CacheQuotaHint> onComputeCacheQuotaHints(java.util.List<android.app.usage.CacheQuotaHint>);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.app.usage.CacheQuotaService";
+  }
+
   public final class ConfigurationStats implements android.os.Parcelable {
     ctor public ConfigurationStats(android.app.usage.ConfigurationStats);
     method public int describeContents();
@@ -7267,6 +7371,7 @@
     method public long getFreeBytes(java.lang.String);
     method public long getTotalBytes(java.lang.String);
     method public android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.lang.String, android.os.UserHandle);
+    method public android.app.usage.StorageStats queryStatsForPackage(java.lang.String, java.lang.String, android.os.UserHandle);
     method public android.app.usage.StorageStats queryStatsForUid(java.lang.String, int);
     method public android.app.usage.StorageStats queryStatsForUser(java.lang.String, android.os.UserHandle);
   }
@@ -7373,7 +7478,7 @@
     method public void notifyAppWidgetViewDataChanged(int, int);
     method public void partiallyUpdateAppWidget(int[], android.widget.RemoteViews);
     method public void partiallyUpdateAppWidget(int, android.widget.RemoteViews);
-    method public boolean requestPinAppWidget(android.content.ComponentName, android.app.PendingIntent);
+    method public boolean requestPinAppWidget(android.content.ComponentName, android.os.Bundle, android.app.PendingIntent);
     method public void updateAppWidget(int[], android.widget.RemoteViews);
     method public void updateAppWidget(int, android.widget.RemoteViews);
     method public void updateAppWidget(android.content.ComponentName, android.widget.RemoteViews);
@@ -7392,6 +7497,7 @@
     field public static final java.lang.String EXTRA_APPWIDGET_IDS = "appWidgetIds";
     field public static final java.lang.String EXTRA_APPWIDGET_OLD_IDS = "appWidgetOldIds";
     field public static final java.lang.String EXTRA_APPWIDGET_OPTIONS = "appWidgetOptions";
+    field public static final java.lang.String EXTRA_APPWIDGET_PREVIEW = "appWidgetPreview";
     field public static final java.lang.String EXTRA_APPWIDGET_PROVIDER = "appWidgetProvider";
     field public static final java.lang.String EXTRA_APPWIDGET_PROVIDER_PROFILE = "appWidgetProviderProfile";
     field public static final java.lang.String EXTRA_CUSTOM_EXTRAS = "customExtras";
@@ -7482,6 +7588,7 @@
     method public java.util.Set<android.bluetooth.BluetoothDevice> getBondedDevices();
     method public static synchronized android.bluetooth.BluetoothAdapter getDefaultAdapter();
     method public java.lang.String getName();
+    method public android.bluetooth.le.PeriodicAdvertisingManager getPeriodicAdvertisingManager();
     method public int getProfileConnectionState(int);
     method public boolean getProfileProxy(android.content.Context, android.bluetooth.BluetoothProfile.ServiceListener, int);
     method public android.bluetooth.BluetoothDevice getRemoteDevice(java.lang.String);
@@ -7491,7 +7598,11 @@
     method public boolean isBleScanAlwaysAvailable();
     method public boolean isDiscovering();
     method public boolean isEnabled();
+    method public boolean isLe2MPhySupported();
+    method public boolean isLeCodedPhySupported();
     method public boolean isLeEnabled();
+    method public boolean isLeExtendedAdvertisingSupported();
+    method public boolean isLePeriodicAdvertisingSupported();
     method public boolean isMultipleAdvertisementSupported();
     method public boolean isOffloadedFilteringSupported();
     method public boolean isOffloadedScanBatchingSupported();
@@ -7862,6 +7973,9 @@
   public final class BluetoothDevice implements android.os.Parcelable {
     method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback);
     method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int);
+    method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallbackExt);
+    method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallbackExt, int);
+    method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallbackExt, int, int);
     method public boolean createBond();
     method public android.bluetooth.BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
     method public android.bluetooth.BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
@@ -7907,6 +8021,13 @@
     field public static final java.lang.String EXTRA_UUID = "android.bluetooth.device.extra.UUID";
     field public static final int PAIRING_VARIANT_PASSKEY_CONFIRMATION = 2; // 0x2
     field public static final int PAIRING_VARIANT_PIN = 0; // 0x0
+    field public static final int PHY_LE_1M = 1; // 0x1
+    field public static final int PHY_LE_2M = 2; // 0x2
+    field public static final int PHY_LE_ANY = 7; // 0x7
+    field public static final int PHY_LE_CODED = 4; // 0x4
+    field public static final int PHY_OPTION_NO_PREFERRED = 0; // 0x0
+    field public static final int PHY_OPTION_S2 = 1; // 0x1
+    field public static final int PHY_OPTION_S8 = 2; // 0x2
     field public static final int TRANSPORT_AUTO = 0; // 0x0
     field public static final int TRANSPORT_BREDR = 1; // 0x1
     field public static final int TRANSPORT_LE = 2; // 0x2
@@ -7929,10 +8050,12 @@
     method public java.util.List<android.bluetooth.BluetoothGattService> getServices();
     method public boolean readCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
     method public boolean readDescriptor(android.bluetooth.BluetoothGattDescriptor);
+    method public void readPhy();
     method public boolean readRemoteRssi();
     method public boolean requestConnectionPriority(int);
     method public boolean requestMtu(int);
     method public boolean setCharacteristicNotification(android.bluetooth.BluetoothGattCharacteristic, boolean);
+    method public void setPreferredPhy(int, int, int);
     method public boolean writeCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
     method public boolean writeDescriptor(android.bluetooth.BluetoothGattDescriptor);
     field public static final int CONNECTION_PRIORITY_BALANCED = 0; // 0x0
@@ -7950,8 +8073,12 @@
     field public static final int GATT_WRITE_NOT_PERMITTED = 3; // 0x3
   }
 
-  public abstract class BluetoothGattCallback {
+  public abstract deprecated class BluetoothGattCallback extends android.bluetooth.BluetoothGattCallbackExt {
     ctor public BluetoothGattCallback();
+  }
+
+  public abstract class BluetoothGattCallbackExt {
+    ctor public BluetoothGattCallbackExt();
     method public void onCharacteristicChanged(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic);
     method public void onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
     method public void onCharacteristicWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
@@ -7959,6 +8086,8 @@
     method public void onDescriptorRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattDescriptor, int);
     method public void onDescriptorWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattDescriptor, int);
     method public void onMtuChanged(android.bluetooth.BluetoothGatt, int, int);
+    method public void onPhyRead(android.bluetooth.BluetoothGatt, int, int, int);
+    method public void onPhyUpdate(android.bluetooth.BluetoothGatt, int, int, int);
     method public void onReadRemoteRssi(android.bluetooth.BluetoothGatt, int, int);
     method public void onReliableWriteCompleted(android.bluetooth.BluetoothGatt, int);
     method public void onServicesDiscovered(android.bluetooth.BluetoothGatt, int);
@@ -8052,12 +8181,18 @@
     method public android.bluetooth.BluetoothGattService getService(java.util.UUID);
     method public java.util.List<android.bluetooth.BluetoothGattService> getServices();
     method public boolean notifyCharacteristicChanged(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothGattCharacteristic, boolean);
+    method public void readPhy(android.bluetooth.BluetoothDevice);
     method public boolean removeService(android.bluetooth.BluetoothGattService);
     method public boolean sendResponse(android.bluetooth.BluetoothDevice, int, int, int, byte[]);
+    method public void setPreferredPhy(android.bluetooth.BluetoothDevice, int, int, int);
   }
 
-  public abstract class BluetoothGattServerCallback {
+  public abstract deprecated class BluetoothGattServerCallback extends android.bluetooth.BluetoothGattServerCallbackExt {
     ctor public BluetoothGattServerCallback();
+  }
+
+  public abstract class BluetoothGattServerCallbackExt {
+    ctor public BluetoothGattServerCallbackExt();
     method public void onCharacteristicReadRequest(android.bluetooth.BluetoothDevice, int, int, android.bluetooth.BluetoothGattCharacteristic);
     method public void onCharacteristicWriteRequest(android.bluetooth.BluetoothDevice, int, android.bluetooth.BluetoothGattCharacteristic, boolean, boolean, int, byte[]);
     method public void onConnectionStateChange(android.bluetooth.BluetoothDevice, int, int);
@@ -8066,6 +8201,8 @@
     method public void onExecuteWrite(android.bluetooth.BluetoothDevice, int, boolean);
     method public void onMtuChanged(android.bluetooth.BluetoothDevice, int);
     method public void onNotificationSent(android.bluetooth.BluetoothDevice, int);
+    method public void onPhyRead(android.bluetooth.BluetoothDevice, int, int, int);
+    method public void onPhyUpdate(android.bluetooth.BluetoothDevice, int, int, int);
     method public void onServiceAdded(int, android.bluetooth.BluetoothGattService);
   }
 
@@ -8266,10 +8403,85 @@
     method public android.bluetooth.le.AdvertiseSettings.Builder setTxPowerLevel(int);
   }
 
+  public final class AdvertisingSet {
+    method public void enableAdvertising(boolean);
+    method public void periodicAdvertisingEnable(boolean);
+    method public void setAdvertisingData(android.bluetooth.le.AdvertiseData);
+    method public void setAdvertisingParameters(android.bluetooth.le.AdvertisingSetParameters);
+    method public void setPeriodicAdvertisingData(android.bluetooth.le.AdvertiseData);
+    method public void setPeriodicAdvertisingParameters(android.bluetooth.le.PeriodicAdvertisingParameters);
+    method public void setScanResponseData(android.bluetooth.le.AdvertiseData);
+  }
+
+  public abstract class AdvertisingSetCallback {
+    ctor public AdvertisingSetCallback();
+    method public void onAdvertisingDataSet(android.bluetooth.le.AdvertisingSet, int);
+    method public void onAdvertisingEnabled(android.bluetooth.le.AdvertisingSet, boolean, int);
+    method public void onAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int);
+    method public void onAdvertisingSetStarted(android.bluetooth.le.AdvertisingSet, int);
+    method public void onAdvertisingSetStopped(android.bluetooth.le.AdvertisingSet);
+    method public void onPeriodicAdvertisingDataSet(android.bluetooth.le.AdvertisingSet, int);
+    method public void onPeriodicAdvertisingEnable(android.bluetooth.le.AdvertisingSet, boolean, int);
+    method public void onPeriodicAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int);
+    method public void onScanResponseDataSet(android.bluetooth.le.AdvertisingSet, int);
+    field public static final int ADVERTISE_FAILED_ALREADY_STARTED = 3; // 0x3
+    field public static final int ADVERTISE_FAILED_DATA_TOO_LARGE = 1; // 0x1
+    field public static final int ADVERTISE_FAILED_FEATURE_UNSUPPORTED = 5; // 0x5
+    field public static final int ADVERTISE_FAILED_INTERNAL_ERROR = 4; // 0x4
+    field public static final int ADVERTISE_FAILED_TOO_MANY_ADVERTISERS = 2; // 0x2
+    field public static final int ADVERTISE_SUCCESS = 0; // 0x0
+  }
+
+  public final class AdvertisingSetParameters implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getInterval();
+    method public int getPrimaryPhy();
+    method public int getSecondaryPhy();
+    method public int getTimeout();
+    method public int getTxPowerLevel();
+    method public boolean includeTxPower();
+    method public boolean isAnonymous();
+    method public boolean isConnectable();
+    method public boolean isLegacy();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.bluetooth.le.AdvertisingSetParameters> CREATOR;
+    field public static final int INTERVAL_HIGH = 160; // 0xa0
+    field public static final int INTERVAL_LOW = 1600; // 0x640
+    field public static final int INTERVAL_MAX = 16777215; // 0xffffff
+    field public static final int INTERVAL_MEDIUM = 400; // 0x190
+    field public static final int INTERVAL_MIN = 160; // 0xa0
+    field public static final int PHY_LE_1M = 1; // 0x1
+    field public static final int PHY_LE_2M = 2; // 0x2
+    field public static final int PHY_LE_CODED = 3; // 0x3
+    field public static final int TX_POWER_HIGH = 1; // 0x1
+    field public static final int TX_POWER_LOW = -15; // 0xfffffff1
+    field public static final int TX_POWER_MAX = 1; // 0x1
+    field public static final int TX_POWER_MEDIUM = -7; // 0xfffffff9
+    field public static final int TX_POWER_MIN = -127; // 0xffffff81
+    field public static final int TX_POWER_ULTRA_LOW = -21; // 0xffffffeb
+  }
+
+  public static final class AdvertisingSetParameters.Builder {
+    ctor public AdvertisingSetParameters.Builder();
+    method public android.bluetooth.le.AdvertisingSetParameters build();
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setAnonymouus(boolean);
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setConnectable(boolean);
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setIncludeTxPower(boolean);
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setInterval(int);
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setLegacyMode(boolean);
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setPrimaryPhy(int);
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setSecondaryPhy(int);
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setTimeout(int);
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setTxPowerLevel(int);
+  }
+
   public final class BluetoothLeAdvertiser {
     method public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback);
     method public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback);
+    method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback);
+    method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
     method public void stopAdvertising(android.bluetooth.le.AdvertiseCallback);
+    method public void stopAdvertisingSet(android.bluetooth.le.AdvertisingSetCallback);
   }
 
   public final class BluetoothLeScanner {
@@ -8282,6 +8494,53 @@
     method public void stopScan(android.bluetooth.le.ScanCallback);
   }
 
+  public abstract class PeriodicAdvertisingCallback {
+    ctor public PeriodicAdvertisingCallback();
+    method public void onPeriodicAdvertisingReport(android.bluetooth.le.PeriodicAdvertisingReport);
+    method public void onSyncEstablished(int, android.bluetooth.BluetoothDevice, int, int, int, int);
+    method public void onSyncLost(int);
+    field public static final int SYNC_NO_RESOURCES = 2; // 0x2
+    field public static final int SYNC_NO_RESPONSE = 1; // 0x1
+  }
+
+  public final class PeriodicAdvertisingManager {
+    method public void registerSync(android.bluetooth.le.ScanResult, int, int, android.bluetooth.le.PeriodicAdvertisingCallback);
+    method public void registerSync(android.bluetooth.le.ScanResult, int, int, android.bluetooth.le.PeriodicAdvertisingCallback, android.os.Handler);
+    method public void unregisterSync(android.bluetooth.le.PeriodicAdvertisingCallback);
+  }
+
+  public final class PeriodicAdvertisingParameters implements android.os.Parcelable {
+    method public int describeContents();
+    method public boolean getEnable();
+    method public boolean getIncludeTxPower();
+    method public int getInterval();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.bluetooth.le.PeriodicAdvertisingParameters> CREATOR;
+  }
+
+  public static final class PeriodicAdvertisingParameters.Builder {
+    ctor public PeriodicAdvertisingParameters.Builder();
+    method public android.bluetooth.le.PeriodicAdvertisingParameters build();
+    method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setEnable(boolean);
+    method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setIncludeTxPower(boolean);
+    method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setInterval(int);
+  }
+
+  public final class PeriodicAdvertisingReport implements android.os.Parcelable {
+    ctor public PeriodicAdvertisingReport(int, int, int, int, android.bluetooth.le.ScanRecord);
+    method public int describeContents();
+    method public android.bluetooth.le.ScanRecord getData();
+    method public int getDataStatus();
+    method public int getRssi();
+    method public int getSyncHandle();
+    method public long getTimestampNanos();
+    method public int getTxPower();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.bluetooth.le.PeriodicAdvertisingReport> CREATOR;
+    field public static final int DATA_COMPLETE = 0; // 0x0
+    field public static final int DATA_INCOMPLETE_TRUNCATED = 2; // 0x2
+  }
+
   public final class ResultStorageDescriptor implements android.os.Parcelable {
     ctor public ResultStorageDescriptor(int, int, int);
     method public int describeContents();
@@ -8346,19 +8605,37 @@
   }
 
   public final class ScanResult implements android.os.Parcelable {
-    ctor public ScanResult(android.bluetooth.BluetoothDevice, android.bluetooth.le.ScanRecord, int, long);
+    ctor public deprecated ScanResult(android.bluetooth.BluetoothDevice, android.bluetooth.le.ScanRecord, int, long);
+    ctor public ScanResult(android.bluetooth.BluetoothDevice, int, int, int, int, int, int, int, android.bluetooth.le.ScanRecord, long);
     method public int describeContents();
+    method public int getAdvertisingSid();
+    method public int getDataStatus();
     method public android.bluetooth.BluetoothDevice getDevice();
+    method public int getPeriodicAdvertisingInterval();
+    method public int getPrimaryPhy();
     method public int getRssi();
     method public android.bluetooth.le.ScanRecord getScanRecord();
+    method public int getSecondaryPhy();
     method public long getTimestampNanos();
+    method public int getTxPower();
+    method public boolean isConnectable();
+    method public boolean isLegacy();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.bluetooth.le.ScanResult> CREATOR;
+    field public static final int DATA_COMPLETE = 0; // 0x0
+    field public static final int DATA_TRUNCATED = 2; // 0x2
+    field public static final int PHY_LE_1M = 1; // 0x1
+    field public static final int PHY_LE_2M = 2; // 0x2
+    field public static final int PHY_LE_CODED = 3; // 0x3
+    field public static final int PHY_UNUSED = 0; // 0x0
+    field public static final int SID_NOT_PRESENT = 255; // 0xff
   }
 
   public final class ScanSettings implements android.os.Parcelable {
     method public int describeContents();
     method public int getCallbackType();
+    method public boolean getLegacy();
+    method public int getPhy();
     method public long getReportDelayMillis();
     method public int getScanMode();
     method public int getScanResultType();
@@ -8372,6 +8649,9 @@
     field public static final int MATCH_NUM_FEW_ADVERTISEMENT = 2; // 0x2
     field public static final int MATCH_NUM_MAX_ADVERTISEMENT = 3; // 0x3
     field public static final int MATCH_NUM_ONE_ADVERTISEMENT = 1; // 0x1
+    field public static final int PHY_LE_1M = 1; // 0x1
+    field public static final int PHY_LE_ALL_SUPPORTED = 255; // 0xff
+    field public static final int PHY_LE_CODED = 3; // 0x3
     field public static final int SCAN_MODE_BALANCED = 1; // 0x1
     field public static final int SCAN_MODE_LOW_LATENCY = 2; // 0x2
     field public static final int SCAN_MODE_LOW_POWER = 0; // 0x0
@@ -8384,8 +8664,10 @@
     ctor public ScanSettings.Builder();
     method public android.bluetooth.le.ScanSettings build();
     method public android.bluetooth.le.ScanSettings.Builder setCallbackType(int);
+    method public android.bluetooth.le.ScanSettings.Builder setLegacy(boolean);
     method public android.bluetooth.le.ScanSettings.Builder setMatchMode(int);
     method public android.bluetooth.le.ScanSettings.Builder setNumOfMatches(int);
+    method public android.bluetooth.le.ScanSettings.Builder setPhy(int);
     method public android.bluetooth.le.ScanSettings.Builder setReportDelay(long);
     method public android.bluetooth.le.ScanSettings.Builder setScanMode(int);
     method public android.bluetooth.le.ScanSettings.Builder setScanResultType(int);
@@ -8444,6 +8726,8 @@
 
   public final class CompanionDeviceManager {
     method public void associate(android.companion.AssociationRequest<?>, android.companion.CompanionDeviceManager.Callback, android.os.Handler);
+    method public void disassociate(java.lang.String);
+    method public java.util.List<java.lang.String> getAssociations();
     field public static final java.lang.String EXTRA_DEVICE = "android.companion.extra.DEVICE";
   }
 
@@ -8854,8 +9138,10 @@
     field public static final java.lang.String ANY_CURSOR_ITEM_TYPE = "vnd.android.cursor.item/*";
     field public static final java.lang.String CURSOR_DIR_BASE_TYPE = "vnd.android.cursor.dir";
     field public static final java.lang.String CURSOR_ITEM_BASE_TYPE = "vnd.android.cursor.item";
+    field public static final java.lang.String EXTRA_HONORED_ARGS = "android.content.extra.HONORED_ARGS";
     field public static final java.lang.String EXTRA_REFRESH_SUPPORTED = "android.content.extra.REFRESH_SUPPORTED";
     field public static final java.lang.String EXTRA_SIZE = "android.content.extra.SIZE";
+    field public static final java.lang.String EXTRA_TOTAL_SIZE = "android.content.extra.TOTAL_SIZE";
     field public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 2; // 0x2
     field public static final int NOTIFY_SYNC_TO_NETWORK = 1; // 0x1
     field public static final java.lang.String QUERY_ARG_LIMIT = "android:query-page-limit";
@@ -8866,7 +9152,6 @@
     field public static final java.lang.String QUERY_ARG_SQL_SELECTION = "android:query-sql-selection";
     field public static final java.lang.String QUERY_ARG_SQL_SELECTION_ARGS = "android:query-sql-selection-args";
     field public static final java.lang.String QUERY_ARG_SQL_SORT_ORDER = "android:query-sql-sort-order";
-    field public static final java.lang.String QUERY_RESULT_SIZE = "android:query-result-size";
     field public static final int QUERY_SORT_DIRECTION_ASCENDING = 0; // 0x0
     field public static final int QUERY_SORT_DIRECTION_DESCENDING = 1; // 0x1
     field public static final java.lang.String SCHEME_ANDROID_RESOURCE = "android.resource";
@@ -9095,6 +9380,7 @@
     field public static final java.lang.String HDMI_CONTROL_SERVICE = "hdmi_control";
     field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method";
     field public static final java.lang.String INPUT_SERVICE = "input";
+    field public static final java.lang.String IPSEC_SERVICE = "ipsec";
     field public static final java.lang.String JOB_SCHEDULER_SERVICE = "jobscheduler";
     field public static final java.lang.String KEYGUARD_SERVICE = "keyguard";
     field public static final java.lang.String LAUNCHER_APPS_SERVICE = "launcherapps";
@@ -9475,6 +9761,7 @@
     field public static final java.lang.String ACTION_CALL = "android.intent.action.CALL";
     field public static final java.lang.String ACTION_CALL_BUTTON = "android.intent.action.CALL_BUTTON";
     field public static final java.lang.String ACTION_CAMERA_BUTTON = "android.intent.action.CAMERA_BUTTON";
+    field public static final java.lang.String ACTION_CARRIER_SETUP = "android.intent.action.CARRIER_SETUP";
     field public static final java.lang.String ACTION_CHOOSER = "android.intent.action.CHOOSER";
     field public static final java.lang.String ACTION_CLEAR_PACKAGE = "android.intent.action.CLEAR_PACKAGE";
     field public static final java.lang.String ACTION_CLOSE_SYSTEM_DIALOGS = "android.intent.action.CLOSE_SYSTEM_DIALOGS";
@@ -9518,6 +9805,7 @@
     field public static final java.lang.String ACTION_MANAGE_PACKAGE_STORAGE = "android.intent.action.MANAGE_PACKAGE_STORAGE";
     field public static final java.lang.String ACTION_MANAGE_PERMISSIONS = "android.intent.action.MANAGE_PERMISSIONS";
     field public static final java.lang.String ACTION_MANAGE_PERMISSION_APPS = "android.intent.action.MANAGE_PERMISSION_APPS";
+    field public static final java.lang.String ACTION_MASTER_CLEAR_NOTIFICATION = "android.intent.action.MASTER_CLEAR_NOTIFICATION";
     field public static final java.lang.String ACTION_MEDIA_BAD_REMOVAL = "android.intent.action.MEDIA_BAD_REMOVAL";
     field public static final java.lang.String ACTION_MEDIA_BUTTON = "android.intent.action.MEDIA_BUTTON";
     field public static final java.lang.String ACTION_MEDIA_CHECKING = "android.intent.action.MEDIA_CHECKING";
@@ -9554,6 +9842,7 @@
     field public static final java.lang.String ACTION_POWER_CONNECTED = "android.intent.action.ACTION_POWER_CONNECTED";
     field public static final java.lang.String ACTION_POWER_DISCONNECTED = "android.intent.action.ACTION_POWER_DISCONNECTED";
     field public static final java.lang.String ACTION_POWER_USAGE_SUMMARY = "android.intent.action.POWER_USAGE_SUMMARY";
+    field public static final java.lang.String ACTION_PRE_BOOT_COMPLETED = "android.intent.action.PRE_BOOT_COMPLETED";
     field public static final java.lang.String ACTION_PROCESS_TEXT = "android.intent.action.PROCESS_TEXT";
     field public static final java.lang.String ACTION_PROVIDER_CHANGED = "android.intent.action.PROVIDER_CHANGED";
     field public static final java.lang.String ACTION_QUERY_PACKAGE_RESTART = "android.intent.action.QUERY_PACKAGE_RESTART";
@@ -9572,6 +9861,7 @@
     field public static final java.lang.String ACTION_SET_WALLPAPER = "android.intent.action.SET_WALLPAPER";
     field public static final java.lang.String ACTION_SHOW_APP_INFO = "android.intent.action.SHOW_APP_INFO";
     field public static final java.lang.String ACTION_SHUTDOWN = "android.intent.action.ACTION_SHUTDOWN";
+    field public static final java.lang.String ACTION_SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED";
     field public static final java.lang.String ACTION_SYNC = "android.intent.action.SYNC";
     field public static final java.lang.String ACTION_SYSTEM_TUTORIAL = "android.intent.action.SYSTEM_TUTORIAL";
     field public static final java.lang.String ACTION_TIMEZONE_CHANGED = "android.intent.action.TIMEZONE_CHANGED";
@@ -9587,6 +9877,7 @@
     field public static final java.lang.String ACTION_USER_PRESENT = "android.intent.action.USER_PRESENT";
     field public static final java.lang.String ACTION_USER_UNLOCKED = "android.intent.action.USER_UNLOCKED";
     field public static final java.lang.String ACTION_VIEW = "android.intent.action.VIEW";
+    field public static final java.lang.String ACTION_VOICE_ASSIST = "android.intent.action.VOICE_ASSIST";
     field public static final java.lang.String ACTION_VOICE_COMMAND = "android.intent.action.VOICE_COMMAND";
     field public static final deprecated java.lang.String ACTION_WALLPAPER_CHANGED = "android.intent.action.WALLPAPER_CHANGED";
     field public static final java.lang.String ACTION_WEB_SEARCH = "android.intent.action.WEB_SEARCH";
@@ -9797,6 +10088,7 @@
     method public final java.lang.String getDataScheme(int);
     method public final android.os.PatternMatcher getDataSchemeSpecificPart(int);
     method public final java.lang.String getDataType(int);
+    method public final int getOrder();
     method public final int getPriority();
     method public final boolean hasAction(java.lang.String);
     method public final boolean hasCategory(java.lang.String);
@@ -9815,6 +10107,7 @@
     method public void readFromXml(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public final java.util.Iterator<android.os.PatternMatcher> schemeSpecificPartsIterator();
     method public final java.util.Iterator<java.lang.String> schemesIterator();
+    method public final void setOrder(int);
     method public final void setPriority(int);
     method public final java.util.Iterator<java.lang.String> typesIterator();
     method public final void writeToParcel(android.os.Parcel, int);
@@ -10429,7 +10722,7 @@
     field public int reqTouchScreen;
   }
 
-  public final class EphemeralIntentFilter implements android.os.Parcelable {
+  public final deprecated class EphemeralIntentFilter implements android.os.Parcelable {
     ctor public EphemeralIntentFilter(java.lang.String, java.util.List<android.content.IntentFilter>);
     method public int describeContents();
     method public java.util.List<android.content.IntentFilter> getFilters();
@@ -10438,7 +10731,7 @@
     field public static final android.os.Parcelable.Creator<android.content.pm.EphemeralIntentFilter> CREATOR;
   }
 
-  public final class EphemeralResolveInfo implements android.os.Parcelable {
+  public final deprecated class EphemeralResolveInfo implements android.os.Parcelable {
     ctor public deprecated EphemeralResolveInfo(android.net.Uri, java.lang.String, java.util.List<android.content.IntentFilter>);
     ctor public deprecated EphemeralResolveInfo(android.content.pm.EphemeralResolveInfo.EphemeralDigest, java.lang.String, java.util.List<android.content.pm.EphemeralIntentFilter>);
     ctor public EphemeralResolveInfo(android.content.pm.EphemeralResolveInfo.EphemeralDigest, java.lang.String, java.util.List<android.content.pm.EphemeralIntentFilter>, int);
@@ -10488,6 +10781,52 @@
     field public int version;
   }
 
+  public final class InstantAppInfo implements android.os.Parcelable {
+    ctor public InstantAppInfo(android.content.pm.ApplicationInfo, java.lang.String[], java.lang.String[]);
+    ctor public InstantAppInfo(java.lang.String, java.lang.CharSequence, java.lang.String[], java.lang.String[]);
+    method public int describeContents();
+    method public android.content.pm.ApplicationInfo getApplicationInfo();
+    method public java.lang.String[] getGrantedPermissions();
+    method public java.lang.String getPackageName();
+    method public java.lang.String[] getRequestedPermissions();
+    method public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager);
+    method public java.lang.CharSequence loadLabel(android.content.pm.PackageManager);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.content.pm.InstantAppInfo> CREATOR;
+  }
+
+  public final class InstantAppIntentFilter implements android.os.Parcelable {
+    ctor public InstantAppIntentFilter(java.lang.String, java.util.List<android.content.IntentFilter>);
+    method public int describeContents();
+    method public java.util.List<android.content.IntentFilter> getFilters();
+    method public java.lang.String getSplitName();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.content.pm.InstantAppIntentFilter> CREATOR;
+  }
+
+  public final class InstantAppResolveInfo implements android.os.Parcelable {
+    ctor public InstantAppResolveInfo(android.content.pm.InstantAppResolveInfo.InstantAppDigest, java.lang.String, java.util.List<android.content.pm.InstantAppIntentFilter>, int);
+    ctor public InstantAppResolveInfo(java.lang.String, java.lang.String, java.util.List<android.content.pm.InstantAppIntentFilter>);
+    method public int describeContents();
+    method public byte[] getDigestBytes();
+    method public int getDigestPrefix();
+    method public java.util.List<android.content.pm.InstantAppIntentFilter> getIntentFilters();
+    method public java.lang.String getPackageName();
+    method public int getVersionCode();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.content.pm.InstantAppResolveInfo> CREATOR;
+    field public static final java.lang.String SHA_ALGORITHM = "SHA-256";
+  }
+
+  public static final class InstantAppResolveInfo.InstantAppDigest implements android.os.Parcelable {
+    ctor public InstantAppResolveInfo.InstantAppDigest(java.lang.String);
+    method public int describeContents();
+    method public byte[][] getDigestBytes();
+    method public int[] getDigestPrefix();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.content.pm.InstantAppResolveInfo.InstantAppDigest> CREATOR;
+  }
+
   public class InstrumentationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
     ctor public InstrumentationInfo();
     ctor public InstrumentationInfo(android.content.pm.InstrumentationInfo);
@@ -10583,6 +10922,7 @@
     method public boolean accept();
     method public int describeContents();
     method public android.appwidget.AppWidgetProviderInfo getAppWidgetProviderInfo(android.content.Context);
+    method public android.os.Bundle getExtras();
     method public int getRequestType();
     method public android.content.pm.ShortcutInfo getShortcutInfo();
     method public boolean isValid();
@@ -10596,10 +10936,12 @@
     ctor public LauncherApps.ShortcutQuery();
     method public android.content.pm.LauncherApps.ShortcutQuery setActivity(android.content.ComponentName);
     method public android.content.pm.LauncherApps.ShortcutQuery setChangedSince(long);
+    method public android.content.pm.LauncherApps.ShortcutQuery setIntent(android.content.Intent);
     method public android.content.pm.LauncherApps.ShortcutQuery setPackage(java.lang.String);
     method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int);
     method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(java.util.List<java.lang.String>);
     field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
+    field public static final int FLAG_MATCH_CHOOSER = 16; // 0x10
     field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1
     field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8
     field public static final int FLAG_MATCH_PINNED = 2; // 0x2
@@ -10650,14 +10992,17 @@
     method public android.content.pm.PackageInstaller.Session openSession(int) throws java.io.IOException;
     method public void registerSessionCallback(android.content.pm.PackageInstaller.SessionCallback);
     method public void registerSessionCallback(android.content.pm.PackageInstaller.SessionCallback, android.os.Handler);
+    method public void setPermissionsResult(int, boolean);
     method public void uninstall(java.lang.String, android.content.IntentSender);
     method public void uninstall(android.content.pm.VersionedPackage, android.content.IntentSender);
     method public void unregisterSessionCallback(android.content.pm.PackageInstaller.SessionCallback);
     method public void updateSessionAppIcon(int, android.graphics.Bitmap);
     method public void updateSessionAppLabel(int, java.lang.CharSequence);
+    field public static final java.lang.String ACTION_SESSION_COMMITTED = "android.content.pm.action.SESSION_COMMITTED";
     field public static final java.lang.String ACTION_SESSION_DETAILS = "android.content.pm.action.SESSION_DETAILS";
     field public static final java.lang.String EXTRA_OTHER_PACKAGE_NAME = "android.content.pm.extra.OTHER_PACKAGE_NAME";
     field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.content.pm.extra.PACKAGE_NAME";
+    field public static final java.lang.String EXTRA_SESSION = "android.content.pm.extra.SESSION";
     field public static final java.lang.String EXTRA_SESSION_ID = "android.content.pm.extra.SESSION_ID";
     field public static final java.lang.String EXTRA_STATUS = "android.content.pm.extra.STATUS";
     field public static final java.lang.String EXTRA_STATUS_MESSAGE = "android.content.pm.extra.STATUS_MESSAGE";
@@ -10700,10 +11045,12 @@
     method public android.graphics.Bitmap getAppIcon();
     method public java.lang.CharSequence getAppLabel();
     method public java.lang.String getAppPackageName();
+    method public int getInstallReason();
     method public java.lang.String getInstallerPackageName();
     method public float getProgress();
     method public int getSessionId();
     method public boolean isActive();
+    method public boolean isSealed();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.content.pm.PackageInstaller.SessionInfo> CREATOR;
   }
@@ -10803,6 +11150,8 @@
     method public abstract java.lang.String getInstallerPackageName(java.lang.String);
     method public abstract byte[] getInstantAppCookie();
     method public abstract int getInstantAppCookieMaxSize();
+    method public abstract android.graphics.drawable.Drawable getInstantAppIcon(java.lang.String);
+    method public abstract java.util.List<android.content.pm.InstantAppInfo> getInstantApps();
     method public abstract android.content.pm.InstrumentationInfo getInstrumentationInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract java.util.List<android.content.pm.IntentFilterVerificationInfo> getIntentFilterVerifications(java.lang.String);
     method public abstract int getIntentVerificationStatusAsUser(java.lang.String, int);
@@ -10841,6 +11190,7 @@
     method public abstract boolean hasSystemFeature(java.lang.String);
     method public abstract boolean hasSystemFeature(java.lang.String, int);
     method public abstract boolean isInstantApp();
+    method public abstract boolean isInstantApp(java.lang.String);
     method public abstract boolean isPermissionRevokedByPolicy(java.lang.String, java.lang.String);
     method public abstract boolean isSafeMode();
     method public abstract java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(android.content.Intent, int);
@@ -11025,8 +11375,11 @@
     field public static final int INSTALL_PARSE_FAILED_NOT_APK = -100; // 0xffffff9c
     field public static final int INSTALL_PARSE_FAILED_NO_CERTIFICATES = -103; // 0xffffff99
     field public static final int INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION = -102; // 0xffffff9a
+    field public static final int INSTALL_REASON_DEVICE_RESTORE = 2; // 0x2
+    field public static final int INSTALL_REASON_DEVICE_SETUP = 3; // 0x3
     field public static final int INSTALL_REASON_POLICY = 1; // 0x1
     field public static final int INSTALL_REASON_UNKNOWN = 0; // 0x0
+    field public static final int INSTALL_REASON_USER = 4; // 0x4
     field public static final int INSTALL_SUCCEEDED = 1; // 0x1
     field public static final int INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS = 2; // 0x2
     field public static final int INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK = 4; // 0x4
@@ -11043,6 +11396,7 @@
     field public static final int MATCH_DIRECT_BOOT_UNAWARE = 262144; // 0x40000
     field public static final int MATCH_DISABLED_COMPONENTS = 512; // 0x200
     field public static final int MATCH_DISABLED_UNTIL_USED_COMPONENTS = 32768; // 0x8000
+    field public static final int MATCH_INSTANT = 8388608; // 0x800000
     field public static final int MATCH_SYSTEM_ONLY = 1048576; // 0x100000
     field public static final int MATCH_UNINSTALLED_PACKAGES = 8192; // 0x2000
     field public static final long MAXIMUM_VERIFICATION_TIMEOUT = 3600000L; // 0x36ee80L
@@ -11071,7 +11425,7 @@
   public static abstract class PackageManager.PermissionFlags implements java.lang.annotation.Annotation {
   }
 
-  public class PackageStats implements android.os.Parcelable {
+  public deprecated class PackageStats implements android.os.Parcelable {
     ctor public PackageStats(java.lang.String);
     ctor public PackageStats(android.os.Parcel);
     ctor public PackageStats(android.content.pm.PackageStats);
@@ -11174,6 +11528,7 @@
     field public android.content.pm.ActivityInfo activityInfo;
     field public android.content.IntentFilter filter;
     field public int icon;
+    field public boolean instantAppAvailable;
     field public boolean isDefault;
     field public int labelRes;
     field public int match;
@@ -11223,6 +11578,9 @@
     method public int describeContents();
     method public android.content.ComponentName getActivity();
     method public java.util.Set<java.lang.String> getCategories();
+    method public android.content.ComponentName[] getChooserComponentNames();
+    method public android.os.PersistableBundle getChooserExtras();
+    method public android.content.IntentFilter[] getChooserIntentFilters();
     method public java.lang.CharSequence getDisabledMessage();
     method public android.os.PersistableBundle getExtras();
     method public java.lang.String getId();
@@ -11235,6 +11593,7 @@
     method public java.lang.CharSequence getShortLabel();
     method public android.os.UserHandle getUserHandle();
     method public boolean hasKeyFieldsOnly();
+    method public boolean isChooser();
     method public boolean isDeclaredInManifest();
     method public boolean isDynamic();
     method public boolean isEnabled();
@@ -11247,9 +11606,11 @@
 
   public static class ShortcutInfo.Builder {
     ctor public ShortcutInfo.Builder(android.content.Context, java.lang.String);
+    method public android.content.pm.ShortcutInfo.Builder addChooserIntentFilter(android.content.IntentFilter, android.content.ComponentName);
     method public android.content.pm.ShortcutInfo build();
     method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName);
     method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>);
+    method public android.content.pm.ShortcutInfo.Builder setChooserExtras(android.os.PersistableBundle);
     method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence);
     method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
     method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
@@ -12767,6 +13128,7 @@
     method public android.graphics.Bitmap extractAlpha(android.graphics.Paint, int[]);
     method public final int getAllocationByteCount();
     method public final int getByteCount();
+    method public final android.graphics.ColorSpace getColorSpace();
     method public final android.graphics.Bitmap.Config getConfig();
     method public int getDensity();
     method public int getGenerationId();
@@ -13149,6 +13511,7 @@
     method public java.lang.String getName();
     method public boolean isSrgb();
     method public abstract boolean isWideGamut();
+    method public static android.graphics.ColorSpace match(float[], android.graphics.ColorSpace.Rgb.TransferParameters);
     method public float[] toXyz(float, float, float);
     method public abstract float[] toXyz(float[]);
     field public static final float[] ILLUMINANT_A;
@@ -13168,6 +13531,7 @@
     method public static android.graphics.ColorSpace.Adaptation valueOf(java.lang.String);
     method public static final android.graphics.ColorSpace.Adaptation[] values();
     enum_constant public static final android.graphics.ColorSpace.Adaptation BRADFORD;
+    enum_constant public static final android.graphics.ColorSpace.Adaptation CIECAT02;
     enum_constant public static final android.graphics.ColorSpace.Adaptation VON_KRIES;
   }
 
@@ -13232,6 +13596,10 @@
   public static class ColorSpace.Rgb extends android.graphics.ColorSpace {
     ctor public ColorSpace.Rgb(java.lang.String, float[], java.util.function.DoubleUnaryOperator, java.util.function.DoubleUnaryOperator);
     ctor public ColorSpace.Rgb(java.lang.String, float[], float[], java.util.function.DoubleUnaryOperator, java.util.function.DoubleUnaryOperator, float, float);
+    ctor public ColorSpace.Rgb(java.lang.String, float[], android.graphics.ColorSpace.Rgb.TransferParameters);
+    ctor public ColorSpace.Rgb(java.lang.String, float[], float[], android.graphics.ColorSpace.Rgb.TransferParameters);
+    ctor public ColorSpace.Rgb(java.lang.String, float[], double);
+    ctor public ColorSpace.Rgb(java.lang.String, float[], float[], double);
     method public float[] fromLinear(float, float, float);
     method public float[] fromLinear(float[]);
     method public float[] fromXyz(float[]);
@@ -13243,6 +13611,7 @@
     method public java.util.function.DoubleUnaryOperator getOetf();
     method public float[] getPrimaries(float[]);
     method public float[] getPrimaries();
+    method public android.graphics.ColorSpace.Rgb.TransferParameters getTransferParameters();
     method public float[] getTransform(float[]);
     method public float[] getTransform();
     method public float[] getWhitePoint(float[]);
@@ -13253,6 +13622,18 @@
     method public float[] toXyz(float[]);
   }
 
+  public static class ColorSpace.Rgb.TransferParameters {
+    ctor public ColorSpace.Rgb.TransferParameters(double, double, double, double, double);
+    ctor public ColorSpace.Rgb.TransferParameters(double, double, double, double, double, double, double);
+    field public final double a;
+    field public final double b;
+    field public final double c;
+    field public final double d;
+    field public final double e;
+    field public final double f;
+    field public final double g;
+  }
+
   public class ComposePathEffect extends android.graphics.PathEffect {
     ctor public ComposePathEffect(android.graphics.PathEffect, android.graphics.PathEffect);
   }
@@ -14087,6 +14468,21 @@
 
 package android.graphics.drawable {
 
+  public class AdaptiveIconDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
+    method public void draw(android.graphics.Canvas);
+    method public android.graphics.drawable.Drawable getBackground();
+    method public static float getExtraInsetPercentage();
+    method public android.graphics.drawable.Drawable getForeground();
+    method public android.graphics.Path getIconMask();
+    method public int getOpacity();
+    method public void invalidateDrawable(android.graphics.drawable.Drawable);
+    method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
+    method public void setAlpha(int);
+    method public void setColorFilter(android.graphics.ColorFilter);
+    method public void setOpacity(int);
+    method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
+  }
+
   public abstract interface Animatable {
     method public abstract boolean isRunning();
     method public abstract void start();
@@ -14388,12 +14784,12 @@
   }
 
   public final class Icon implements android.os.Parcelable {
+    method public static android.graphics.drawable.Icon createWithAdaptiveBitmap(android.graphics.Bitmap);
     method public static android.graphics.drawable.Icon createWithBitmap(android.graphics.Bitmap);
     method public static android.graphics.drawable.Icon createWithContentUri(java.lang.String);
     method public static android.graphics.drawable.Icon createWithContentUri(android.net.Uri);
     method public static android.graphics.drawable.Icon createWithData(byte[], int, int);
     method public static android.graphics.drawable.Icon createWithFilePath(java.lang.String);
-    method public static android.graphics.drawable.Icon createWithMaskableBitmap(android.graphics.Bitmap);
     method public static android.graphics.drawable.Icon createWithResource(android.content.Context, int);
     method public static android.graphics.drawable.Icon createWithResource(java.lang.String, int);
     method public int describeContents();
@@ -14476,21 +14872,6 @@
     method public void addLevel(int, int, android.graphics.drawable.Drawable);
   }
 
-  public class MaskableIconDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
-    method public void draw(android.graphics.Canvas);
-    method public android.graphics.drawable.Drawable getBackground();
-    method public static float getExtraInsetPercentage();
-    method public android.graphics.drawable.Drawable getForeground();
-    method public android.graphics.Path getIconMask();
-    method public int getOpacity();
-    method public void invalidateDrawable(android.graphics.drawable.Drawable);
-    method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
-    method public void setAlpha(int);
-    method public void setColorFilter(android.graphics.ColorFilter);
-    method public void setOpacity(int);
-    method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
-  }
-
   public class NinePatchDrawable extends android.graphics.drawable.Drawable {
     ctor public deprecated NinePatchDrawable(android.graphics.Bitmap, byte[], android.graphics.Rect, java.lang.String);
     ctor public NinePatchDrawable(android.content.res.Resources, android.graphics.Bitmap, byte[], android.graphics.Rect, java.lang.String);
@@ -14604,6 +14985,8 @@
 
   public class ArcShape extends android.graphics.drawable.shapes.RectShape {
     ctor public ArcShape(float, float);
+    method public final float getStartAngle();
+    method public final float getSweepAngle();
   }
 
   public class OvalShape extends android.graphics.drawable.shapes.RectShape {
@@ -14642,9 +15025,12 @@
 package android.graphics.fonts {
 
   public final class FontRequest implements android.os.Parcelable {
-    ctor public FontRequest(java.lang.String, java.lang.String);
+    ctor public FontRequest(java.lang.String, java.lang.String, java.lang.String);
+    ctor public FontRequest(java.lang.String, java.lang.String, java.lang.String, java.util.List<java.util.List<byte[]>>);
     method public int describeContents();
+    method public java.util.List<java.util.List<byte[]>> getCertificates();
     method public java.lang.String getProviderAuthority();
+    method public java.lang.String getProviderPackage();
     method public java.lang.String getQuery();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.graphics.fonts.FontRequest> CREATOR;
@@ -15426,10 +15812,14 @@
     method public abstract void createCaptureSession(java.util.List<android.view.Surface>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
     method public abstract void createCaptureSessionByOutputConfigurations(java.util.List<android.hardware.camera2.params.OutputConfiguration>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
     method public abstract void createConstrainedHighSpeedCaptureSession(java.util.List<android.view.Surface>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
+    method public abstract void createCustomCaptureSession(android.hardware.camera2.params.InputConfiguration, java.util.List<android.hardware.camera2.params.OutputConfiguration>, int, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
     method public abstract android.hardware.camera2.CaptureRequest.Builder createReprocessCaptureRequest(android.hardware.camera2.TotalCaptureResult) throws android.hardware.camera2.CameraAccessException;
     method public abstract void createReprocessableCaptureSession(android.hardware.camera2.params.InputConfiguration, java.util.List<android.view.Surface>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
     method public abstract void createReprocessableCaptureSessionByConfigurations(android.hardware.camera2.params.InputConfiguration, java.util.List<android.hardware.camera2.params.OutputConfiguration>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
     method public abstract java.lang.String getId();
+    field public static final int SESSION_OPERATION_MODE_CONSTRAINED_HIGH_SPEED = 1; // 0x1
+    field public static final int SESSION_OPERATION_MODE_NORMAL = 0; // 0x0
+    field public static final int SESSION_OPERATION_MODE_VENDOR_START = 32768; // 0x8000
     field public static final int TEMPLATE_MANUAL = 6; // 0x6
     field public static final int TEMPLATE_PREVIEW = 1; // 0x1
     field public static final int TEMPLATE_RECORD = 3; // 0x3
@@ -16103,6 +16493,7 @@
     method public android.hardware.hdmi.HdmiPlaybackClient getPlaybackClient();
     method public android.hardware.hdmi.HdmiTvClient getTvClient();
     method public void removeHotplugEventListener(android.hardware.hdmi.HdmiControlManager.HotplugEventListener);
+    method public void setStandbyMode(boolean);
     field public static final java.lang.String ACTION_OSD_MESSAGE = "android.hardware.hdmi.action.OSD_MESSAGE";
     field public static final int AVR_VOLUME_MUTED = 101; // 0x65
     field public static final int CLEAR_TIMER_STATUS_CEC_DISABLE = 162; // 0xa2
@@ -16547,10 +16938,11 @@
 
   public class NanoApp {
     ctor public NanoApp();
-    ctor public NanoApp(int, byte[]);
+    ctor public deprecated NanoApp(int, byte[]);
+    ctor public NanoApp(long, byte[]);
     method public int describeContents();
     method public byte[] getAppBinary();
-    method public int getAppId();
+    method public long getAppId();
     method public int getAppVersion();
     method public java.lang.String getName();
     method public int getNeededExecMemBytes();
@@ -16560,7 +16952,7 @@
     method public int[] getOutputEvents();
     method public java.lang.String getPublisher();
     method public void setAppBinary(byte[]);
-    method public void setAppId(int);
+    method public void setAppId(long);
     method public void setAppVersion(int);
     method public void setName(java.lang.String);
     method public void setNeededExecMemBytes(int);
@@ -20910,6 +21302,8 @@
     field public static final int SHORT_COMMONLY_USED = 6; // 0x6
     field public static final int SHORT_GENERIC = 2; // 0x2
     field public static final int SHORT_GMT = 4; // 0x4
+    field public static final int TIMEZONE_ICU = 0; // 0x0
+    field public static final int TIMEZONE_JDK = 1; // 0x1
     field public static final android.icu.util.TimeZone UNKNOWN_ZONE;
     field public static final java.lang.String UNKNOWN_ZONE_ID = "Etc/Unknown";
   }
@@ -22261,6 +22655,26 @@
     field public static final android.os.Parcelable.Creator<android.media.AudioFocusInfo> CREATOR;
   }
 
+  public final class AudioFocusRequest {
+    method public boolean acceptsDelayedFocusGain();
+    method public android.media.AudioAttributes getAudioAttributes();
+    method public int getFocusGain();
+    method public android.media.AudioManager.OnAudioFocusChangeListener getOnAudioFocusChangeListener();
+    method public android.os.Handler getOnAudioFocusChangeListenerHandler();
+    method public boolean willPauseWhenDucked();
+  }
+
+  public static final class AudioFocusRequest.Builder {
+    ctor public AudioFocusRequest.Builder(int);
+    ctor public AudioFocusRequest.Builder(android.media.AudioFocusRequest);
+    method public android.media.AudioFocusRequest build();
+    method public android.media.AudioFocusRequest.Builder setAcceptsDelayedFocusGain(boolean);
+    method public android.media.AudioFocusRequest.Builder setAudioAttributes(android.media.AudioAttributes);
+    method public android.media.AudioFocusRequest.Builder setFocusGain(int);
+    method public android.media.AudioFocusRequest.Builder setOnAudioFocusChangeListener(android.media.AudioManager.OnAudioFocusChangeListener, android.os.Handler);
+    method public android.media.AudioFocusRequest.Builder setWillPauseWhenDucked(boolean);
+  }
+
   public final class AudioFormat implements android.os.Parcelable {
     method public int describeContents();
     method public int getChannelCount();
@@ -22338,6 +22752,7 @@
   public class AudioManager {
     method public int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener);
     method public int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes);
+    method public int abandonAudioFocusRequest(android.media.AudioFocusRequest);
     method public void adjustStreamVolume(int, int, int);
     method public void adjustSuggestedStreamVolume(int, int, int);
     method public void adjustVolume(int, int);
@@ -22376,6 +22791,7 @@
     method public deprecated void registerRemoteControlClient(android.media.RemoteControlClient);
     method public deprecated boolean registerRemoteController(android.media.RemoteController);
     method public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int);
+    method public int requestAudioFocus(android.media.AudioFocusRequest);
     method public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes, int, int) throws java.lang.IllegalArgumentException;
     method public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes, int, int, android.media.audiopolicy.AudioPolicy) throws java.lang.IllegalArgumentException;
     method public deprecated void setBluetoothA2dpOn(boolean);
@@ -22424,6 +22840,8 @@
     field public static final int AUDIOFOCUS_LOSS = -1; // 0xffffffff
     field public static final int AUDIOFOCUS_LOSS_TRANSIENT = -2; // 0xfffffffe
     field public static final int AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK = -3; // 0xfffffffd
+    field public static final int AUDIOFOCUS_NONE = 0; // 0x0
+    field public static final int AUDIOFOCUS_REQUEST_DELAYED = 2; // 0x2
     field public static final int AUDIOFOCUS_REQUEST_FAILED = 0; // 0x0
     field public static final int AUDIOFOCUS_REQUEST_GRANTED = 1; // 0x1
     field public static final int AUDIO_SESSION_ID_GENERATE = 0; // 0x0
@@ -22641,13 +23059,14 @@
     field public long nanoTime;
   }
 
-  public class AudioTrack implements android.media.AudioRouting {
+  public class AudioTrack implements android.media.AudioRouting android.media.VolumeAutomation {
     ctor public deprecated AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
     ctor public deprecated AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
     ctor public AudioTrack(android.media.AudioAttributes, android.media.AudioFormat, int, int, int) throws java.lang.IllegalArgumentException;
     method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
     method public deprecated void addOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener, android.os.Handler);
     method public int attachAuxEffect(int);
+    method public android.media.VolumeShaper createVolumeShaper(android.media.VolumeShaper.Configuration);
     method public void flush();
     method public int getAudioFormat();
     method public int getAudioSessionId();
@@ -23115,8 +23534,42 @@
     field public static final int STOP_VIDEO_RECORDING = 3; // 0x3
   }
 
+  public final class MediaCas {
+    ctor public MediaCas(int) throws android.media.UnsupportedCasException;
+    method public void closeSession(byte[]);
+    method public static android.media.MediaCas.PluginDescriptor[] enumeratePlugins();
+    method public static boolean isSystemIdSupported(int);
+    method public byte[] openSession(int);
+    method public byte[] openSession(int, int);
+    method public void processEcm(byte[], byte[], int, int);
+    method public void processEcm(byte[], byte[]);
+    method public void processEmm(byte[], int, int);
+    method public void processEmm(byte[]);
+    method public void provision(java.lang.String);
+    method public void refreshEntitlements(int, byte[]);
+    method public void release();
+    method public void sendEvent(int, int, byte[]);
+    method public void setEventListener(android.media.MediaCas.EventListener, android.os.Handler);
+    method public void setPrivateData(byte[]);
+    method public void setSessionPrivateData(byte[], byte[]);
+  }
+
+  public static abstract interface MediaCas.EventListener {
+    method public abstract void onEvent(android.media.MediaCas, int, int, byte[]);
+  }
+
+  public static class MediaCas.PluginDescriptor {
+    method public java.lang.String getName();
+    method public int getSystemId();
+  }
+
+  public class MediaCasException extends java.lang.Exception {
+    ctor public MediaCasException(java.lang.String);
+  }
+
   public final class MediaCodec {
     method public void configure(android.media.MediaFormat, android.view.Surface, android.media.MediaCrypto, int);
+    method public void configure(android.media.MediaFormat, android.view.Surface, int, android.media.MediaDescrambler);
     method public static android.media.MediaCodec createByCodecName(java.lang.String) throws java.io.IOException;
     method public static android.media.MediaCodec createDecoderByType(java.lang.String) throws java.io.IOException;
     method public static android.media.MediaCodec createEncoderByType(java.lang.String) throws java.io.IOException;
@@ -23156,6 +23609,7 @@
     field public static final int BUFFER_FLAG_CODEC_CONFIG = 2; // 0x2
     field public static final int BUFFER_FLAG_END_OF_STREAM = 4; // 0x4
     field public static final int BUFFER_FLAG_KEY_FRAME = 1; // 0x1
+    field public static final int BUFFER_FLAG_PARTIAL_FRAME = 8; // 0x8
     field public static final deprecated int BUFFER_FLAG_SYNC_FRAME = 1; // 0x1
     field public static final int CONFIGURE_FLAG_ENCODE = 1; // 0x1
     field public static final int CRYPTO_MODE_AES_CBC = 2; // 0x2
@@ -23312,6 +23766,7 @@
     field public static final deprecated int COLOR_TI_FormatYUV420PackedSemiPlanar = 2130706688; // 0x7f000100
     field public static final java.lang.String FEATURE_AdaptivePlayback = "adaptive-playback";
     field public static final java.lang.String FEATURE_IntraRefresh = "intra-refresh";
+    field public static final java.lang.String FEATURE_PartialFrame = "partial-frame";
     field public static final java.lang.String FEATURE_SecurePlayback = "secure-playback";
     field public static final java.lang.String FEATURE_TunneledPlayback = "tunneled-playback";
     field public int[] colorFormats;
@@ -23536,6 +23991,14 @@
     method public abstract int readAt(long, byte[], int, int) throws java.io.IOException;
   }
 
+  public final class MediaDescrambler {
+    ctor public MediaDescrambler(int) throws android.media.UnsupportedCasException;
+    method public final int descramble(java.nio.ByteBuffer, int, java.nio.ByteBuffer, int, android.media.MediaCodec.CryptoInfo);
+    method public final void release();
+    method public final boolean requiresSecureDecoderComponent(java.lang.String);
+    method public final void setMediaCasSession(byte[]);
+  }
+
   public class MediaDescription implements android.os.Parcelable {
     method public int describeContents();
     method public java.lang.CharSequence getDescription();
@@ -23692,8 +24155,10 @@
     method public final void setDataSource(android.content.res.AssetFileDescriptor) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
     method public final void setDataSource(java.io.FileDescriptor) throws java.io.IOException;
     method public final void setDataSource(java.io.FileDescriptor, long, long) throws java.io.IOException;
+    method public final void setMediaCas(android.media.MediaCas);
     method public void unselectTrack(int);
     field public static final int SAMPLE_FLAG_ENCRYPTED = 2; // 0x2
+    field public static final int SAMPLE_FLAG_PARTIAL_FRAME = 4; // 0x4
     field public static final int SAMPLE_FLAG_SYNC = 1; // 0x1
     field public static final int SEEK_TO_CLOSEST_SYNC = 2; // 0x2
     field public static final int SEEK_TO_NEXT_SYNC = 1; // 0x1
@@ -23759,6 +24224,7 @@
     field public static final java.lang.String KEY_IS_FORCED_SUBTITLE = "is-forced-subtitle";
     field public static final java.lang.String KEY_I_FRAME_INTERVAL = "i-frame-interval";
     field public static final java.lang.String KEY_LANGUAGE = "language";
+    field public static final java.lang.String KEY_LATENCY = "latency";
     field public static final java.lang.String KEY_LEVEL = "level";
     field public static final java.lang.String KEY_MAX_HEIGHT = "max-height";
     field public static final java.lang.String KEY_MAX_INPUT_SIZE = "max-input-size";
@@ -23790,6 +24256,7 @@
     field public static final java.lang.String MIMETYPE_AUDIO_OPUS = "audio/opus";
     field public static final java.lang.String MIMETYPE_AUDIO_QCELP = "audio/qcelp";
     field public static final java.lang.String MIMETYPE_AUDIO_RAW = "audio/raw";
+    field public static final java.lang.String MIMETYPE_AUDIO_SCRAMBLED = "audio/scrambled";
     field public static final java.lang.String MIMETYPE_AUDIO_VORBIS = "audio/vorbis";
     field public static final java.lang.String MIMETYPE_TEXT_CEA_608 = "text/cea-608";
     field public static final java.lang.String MIMETYPE_TEXT_VTT = "text/vtt";
@@ -23800,6 +24267,7 @@
     field public static final java.lang.String MIMETYPE_VIDEO_MPEG2 = "video/mpeg2";
     field public static final java.lang.String MIMETYPE_VIDEO_MPEG4 = "video/mp4v-es";
     field public static final java.lang.String MIMETYPE_VIDEO_RAW = "video/raw";
+    field public static final java.lang.String MIMETYPE_VIDEO_SCRAMBLED = "video/scrambled";
     field public static final java.lang.String MIMETYPE_VIDEO_VP8 = "video/x-vnd.on2.vp8";
     field public static final java.lang.String MIMETYPE_VIDEO_VP9 = "video/x-vnd.on2.vp9";
   }
@@ -23940,7 +24408,7 @@
     field public static final int MUXER_OUTPUT_WEBM = 1; // 0x1
   }
 
-  public class MediaPlayer {
+  public class MediaPlayer implements android.media.VolumeAutomation {
     ctor public MediaPlayer();
     method public void addTimedTextSource(java.lang.String, java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
     method public void addTimedTextSource(android.content.Context, android.net.Uri, java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
@@ -23952,6 +24420,7 @@
     method public static android.media.MediaPlayer create(android.content.Context, android.net.Uri, android.view.SurfaceHolder, android.media.AudioAttributes, int);
     method public static android.media.MediaPlayer create(android.content.Context, int);
     method public static android.media.MediaPlayer create(android.content.Context, int, android.media.AudioAttributes, int);
+    method public android.media.VolumeShaper createVolumeShaper(android.media.VolumeShaper.Configuration);
     method public void deselectTrack(int) throws java.lang.IllegalStateException;
     method public int getAudioSessionId();
     method public android.media.BufferingParams getBufferingParams();
@@ -24782,10 +25251,18 @@
     field public static final int TONE_SUP_RINGTONE = 23; // 0x17
   }
 
+  public final class UnsupportedCasException extends android.media.MediaCasException {
+    ctor public UnsupportedCasException(java.lang.String);
+  }
+
   public final class UnsupportedSchemeException extends android.media.MediaDrmException {
     ctor public UnsupportedSchemeException(java.lang.String);
   }
 
+  public abstract interface VolumeAutomation {
+    method public abstract android.media.VolumeShaper createVolumeShaper(android.media.VolumeShaper.Configuration);
+  }
+
   public abstract class VolumeProvider {
     ctor public VolumeProvider(int, int, int);
     method public final int getCurrentVolume();
@@ -24799,6 +25276,53 @@
     field public static final int VOLUME_CONTROL_RELATIVE = 1; // 0x1
   }
 
+  public final class VolumeShaper implements java.lang.AutoCloseable {
+    method public void apply(android.media.VolumeShaper.Operation);
+    method public void close();
+    method public float getVolume();
+    method public void replace(android.media.VolumeShaper.Configuration, android.media.VolumeShaper.Operation, boolean);
+  }
+
+  public static final class VolumeShaper.Configuration implements android.os.Parcelable {
+    method public int describeContents();
+    method public double getDurationMs();
+    method public int getInterpolatorType();
+    method public static int getMaximumCurvePoints();
+    method public float[] getTimes();
+    method public float[] getVolumes();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.media.VolumeShaper.Configuration> CREATOR;
+    field public static final android.media.VolumeShaper.Configuration CUBIC_RAMP;
+    field public static final int INTERPOLATOR_TYPE_CUBIC = 2; // 0x2
+    field public static final int INTERPOLATOR_TYPE_CUBIC_MONOTONIC = 3; // 0x3
+    field public static final int INTERPOLATOR_TYPE_LINEAR = 1; // 0x1
+    field public static final int INTERPOLATOR_TYPE_STEP = 0; // 0x0
+    field public static final android.media.VolumeShaper.Configuration LINEAR_RAMP;
+    field public static final android.media.VolumeShaper.Configuration SCURVE_RAMP;
+    field public static final android.media.VolumeShaper.Configuration SINE_RAMP;
+  }
+
+  public static final class VolumeShaper.Configuration.Builder {
+    ctor public VolumeShaper.Configuration.Builder();
+    ctor public VolumeShaper.Configuration.Builder(android.media.VolumeShaper.Configuration);
+    method public android.media.VolumeShaper.Configuration build();
+    method public android.media.VolumeShaper.Configuration.Builder invertVolumes();
+    method public android.media.VolumeShaper.Configuration.Builder reflectTimes();
+    method public android.media.VolumeShaper.Configuration.Builder scaleToEndVolume(float);
+    method public android.media.VolumeShaper.Configuration.Builder scaleToStartVolume(float);
+    method public android.media.VolumeShaper.Configuration.Builder setCurve(float[], float[]);
+    method public android.media.VolumeShaper.Configuration.Builder setDurationMs(double);
+    method public android.media.VolumeShaper.Configuration.Builder setInterpolatorType(int);
+  }
+
+  public static final class VolumeShaper.Operation implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.media.VolumeShaper.Operation> CREATOR;
+    field public static final android.media.VolumeShaper.Operation PLAY;
+    field public static final android.media.VolumeShaper.Operation REVERSE;
+  }
+
 }
 
 package android.media.audiofx {
@@ -25775,17 +26299,86 @@
     method public static final android.net.Uri buildProgramsUriForChannel(long, long, long);
     method public static final android.net.Uri buildProgramsUriForChannel(android.net.Uri, long, long);
     method public static final android.net.Uri buildRecordedProgramUri(long);
+    method public static final android.net.Uri buildWatchNextProgramUri(long);
     method public static final boolean isChannelUri(android.net.Uri);
     method public static final boolean isChannelUriForPassthroughInput(android.net.Uri);
     method public static final boolean isChannelUriForTunerInput(android.net.Uri);
     method public static final boolean isProgramUri(android.net.Uri);
+    field public static final java.lang.String ACTION_MAKE_CHANNEL_BROWSABLE = "android.media.tv.action.MAKE_CHANNEL_BROWSABLE";
+    field public static final java.lang.String ACTION_PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT = "android.media.tv.action.PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT";
+    field public static final java.lang.String ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED = "android.media.tv.action.PREVIEW_PROGRAM_BROWSABLE_DISABLED";
+    field public static final java.lang.String ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED = "android.media.tv.action.WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED";
     field public static final java.lang.String AUTHORITY = "android.media.tv";
+    field public static final java.lang.String EXTRA_CHANNEL_ID = "android.media.tv.extra.CHANNEL_ID";
+    field public static final java.lang.String EXTRA_COLUMN_NAME = "android.media.tv.extra.COLUMN_NAME";
+    field public static final java.lang.String EXTRA_DATA_TYPE = "android.media.tv.extra.DATA_TYPE";
+    field public static final java.lang.String EXTRA_DEFAULT_VALUE = "android.media.tv.extra.DEFAULT_VALUE";
+    field public static final java.lang.String EXTRA_EXISTING_COLUMN_NAMES = "android.media.tv.extra.EXISTING_COLUMN_NAMES";
+    field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.media.tv.extra.PACKAGE_NAME";
+    field public static final java.lang.String EXTRA_PREVIEW_PROGRAM_ID = "android.media.tv.extra.PREVIEW_PROGRAM_ID";
+    field public static final java.lang.String EXTRA_WATCH_NEXT_PROGRAM_ID = "android.media.tv.extra.WATCH_NEXT_PROGRAM_ID";
+    field public static final java.lang.String METHOD_ADD_COLUMN = "add_column";
+    field public static final java.lang.String METHOD_GET_COLUMNS = "get_columns";
+  }
+
+  public static abstract interface TvContract.BasePreviewProgramColumns implements android.media.tv.TvContract.BaseProgramColumns {
+    field public static final java.lang.String ASPECT_RATIO_16_9 = "ASPECT_RATIO_16_9";
+    field public static final java.lang.String ASPECT_RATIO_1_1 = "ASPECT_RATIO_1_1";
+    field public static final java.lang.String ASPECT_RATIO_2_3 = "ASPECT_RATIO_2_3";
+    field public static final java.lang.String ASPECT_RATIO_3_2 = "ASPECT_RATIO_3_2";
+    field public static final java.lang.String AVAILABILITY_AVAILABLE = "AVAILABILITY_AVAILABLE";
+    field public static final java.lang.String AVAILABILITY_FREE_WITH_SUBSCRIPTION = "AVAILABILITY_FREE_WITH_SUBSCRIPTION";
+    field public static final java.lang.String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT";
+    field public static final java.lang.String COLUMN_APP_LINK_INTENT_URI = "app_link_intent_uri";
+    field public static final java.lang.String COLUMN_AUTHOR = "author";
+    field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
+    field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
+    field public static final java.lang.String COLUMN_CONTENT_ID = "content_id";
+    field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
+    field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count";
+    field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
+    field public static final java.lang.String COLUMN_ITEM_COUNT = "item_count";
+    field public static final java.lang.String COLUMN_LAST_PLAYBACK_POSITION_MILLIS = "last_playback_position_millis";
+    field public static final java.lang.String COLUMN_LIVE = "live";
+    field public static final java.lang.String COLUMN_LOGO_URI = "logo_uri";
+    field public static final java.lang.String COLUMN_OFFER_PRICE = "offer_price";
+    field public static final java.lang.String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
+    field public static final java.lang.String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri";
+    field public static final java.lang.String COLUMN_RELEASE_DATE = "release_date";
+    field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating";
+    field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
+    field public static final java.lang.String COLUMN_STARTING_PRICE = "starting_price";
+    field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
+    field public static final java.lang.String COLUMN_TRANSIENT = "transient";
+    field public static final java.lang.String COLUMN_TYPE = "type";
+    field public static final java.lang.String INTERACTION_TYPE_FANS = "INTERACTION_TYPE_FANS";
+    field public static final java.lang.String INTERACTION_TYPE_FOLLOWERS = "INTERACTION_TYPE_FOLLOWERS";
+    field public static final java.lang.String INTERACTION_TYPE_LIKES = "INTERACTION_TYPE_LIKES";
+    field public static final java.lang.String INTERACTION_TYPE_LISTENS = "INTERACTION_TYPE_LISTENS";
+    field public static final java.lang.String INTERACTION_TYPE_THUMBS = "INTERACTION_TYPE_THUMBS";
+    field public static final java.lang.String INTERACTION_TYPE_VIEWERS = "INTERACTION_TYPE_VIEWERS";
+    field public static final java.lang.String INTERACTION_TYPE_VIEWS = "INTERACTION_TYPE_VIEWS";
+    field public static final java.lang.String REVIEW_RATING_STYLE_PERCENTAGE = "REVIEW_RATING_STYLE_PERCENTAGE";
+    field public static final java.lang.String REVIEW_RATING_STYLE_STARS = "REVIEW_RATING_STYLE_STARS";
+    field public static final java.lang.String REVIEW_RATING_STYLE_THUMBS_UP_DOWN = "REVIEW_RATING_STYLE_THUMBS_UP_DOWN";
+    field public static final java.lang.String TYPE_ALBUM = "TYPE_ALBUM";
+    field public static final java.lang.String TYPE_ARTIST = "TYPE_ARTIST";
+    field public static final java.lang.String TYPE_CHANNEL = "TYPE_CHANNEL";
+    field public static final java.lang.String TYPE_CLIP = "TYPE_CLIP";
+    field public static final java.lang.String TYPE_EVENT = "TYPE_EVENT";
+    field public static final java.lang.String TYPE_MOVIE = "TYPE_MOVIE";
+    field public static final java.lang.String TYPE_PLAYLIST = "TYPE_PLAYLIST";
+    field public static final java.lang.String TYPE_STATION = "TYPE_STATION";
+    field public static final java.lang.String TYPE_TRACK = "TYPE_TRACK";
+    field public static final java.lang.String TYPE_TV_EPISODE = "TYPE_TV_EPISODE";
+    field public static final java.lang.String TYPE_TV_SEASON = "TYPE_TV_SEASON";
+    field public static final java.lang.String TYPE_TV_SERIES = "TYPE_TV_SERIES";
   }
 
   public static abstract interface TvContract.BaseProgramColumns implements android.media.tv.TvContract.BaseTvColumns {
     field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
     field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
-    field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
     field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
     field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
     field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
@@ -25894,70 +26487,17 @@
     field public static final java.lang.String CONTENT_DIRECTORY = "logo";
   }
 
-  public static final class TvContract.PreviewPrograms implements android.media.tv.TvContract.BaseProgramColumns {
-    field public static final java.lang.String ASPECT_RATIO_16_9 = "ASPECT_RATIO_16_9";
-    field public static final java.lang.String ASPECT_RATIO_1_1 = "ASPECT_RATIO_1_1";
-    field public static final java.lang.String ASPECT_RATIO_2_3 = "ASPECT_RATIO_2_3";
-    field public static final java.lang.String ASPECT_RATIO_3_2 = "ASPECT_RATIO_3_2";
-    field public static final java.lang.String AVAILABILITY_AVAILABLE = "AVAILABILITY_AVAILABLE";
-    field public static final java.lang.String AVAILABILITY_FREE_WITH_SUBSCRIPTION = "AVAILABILITY_FREE_WITH_SUBSCRIPTION";
-    field public static final java.lang.String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT";
-    field public static final java.lang.String COLUMN_APP_LINK_INTENT_URI = "app_link_intent_uri";
-    field public static final java.lang.String COLUMN_AUTHOR = "author";
-    field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
-    field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
-    field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
-    field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count";
-    field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type";
-    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
-    field public static final java.lang.String COLUMN_ITEM_COUNT = "item_count";
-    field public static final java.lang.String COLUMN_LAST_PLAYBACK_POSITION_MILLIS = "last_playback_position_millis";
-    field public static final java.lang.String COLUMN_LIVE = "live";
-    field public static final java.lang.String COLUMN_LOGO_URI = "logo_uri";
-    field public static final java.lang.String COLUMN_OFFER_PRICE = "offer_price";
-    field public static final java.lang.String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
-    field public static final java.lang.String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri";
-    field public static final java.lang.String COLUMN_RELEASE_DATE = "release_date";
-    field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating";
-    field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
-    field public static final java.lang.String COLUMN_STARTING_PRICE = "starting_price";
-    field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
-    field public static final java.lang.String COLUMN_TRANSIENT = "transient";
-    field public static final java.lang.String COLUMN_TYPE = "type";
-    field public static final java.lang.String COLUMN_WATCH_NEXT_TYPE = "watch_next_type";
+  public static final class TvContract.PreviewPrograms implements android.media.tv.TvContract.BasePreviewProgramColumns {
+    field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
     field public static final java.lang.String COLUMN_WEIGHT = "weight";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/preview_program";
     field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/preview_program";
     field public static final android.net.Uri CONTENT_URI;
-    field public static final java.lang.String INTERACTION_TYPE_FANS = "INTERACTION_TYPE_FANS";
-    field public static final java.lang.String INTERACTION_TYPE_FOLLOWERS = "INTERACTION_TYPE_FOLLOWERS";
-    field public static final java.lang.String INTERACTION_TYPE_LIKES = "INTERACTION_TYPE_LIKES";
-    field public static final java.lang.String INTERACTION_TYPE_LISTENS = "INTERACTION_TYPE_LISTENS";
-    field public static final java.lang.String INTERACTION_TYPE_THUMBS = "INTERACTION_TYPE_THUMBS";
-    field public static final java.lang.String INTERACTION_TYPE_VIEWERS = "INTERACTION_TYPE_VIEWERS";
-    field public static final java.lang.String INTERACTION_TYPE_VIEWS = "INTERACTION_TYPE_VIEWS";
-    field public static final java.lang.String REVIEW_RATING_STYLE_PERCENTAGE = "REVIEW_RATING_STYLE_PERCENTAGE";
-    field public static final java.lang.String REVIEW_RATING_STYLE_STARS = "REVIEW_RATING_STYLE_STARS";
-    field public static final java.lang.String REVIEW_RATING_STYLE_THUMBS_UP_DOWN = "REVIEW_RATING_STYLE_THUMBS_UP_DOWN";
-    field public static final java.lang.String TYPE_ALBUM = "TYPE_ALBUM";
-    field public static final java.lang.String TYPE_ARTIST = "TYPE_ARTIST";
-    field public static final java.lang.String TYPE_CHANNEL = "TYPE_CHANNEL";
-    field public static final java.lang.String TYPE_CLIP = "TYPE_CLIP";
-    field public static final java.lang.String TYPE_EVENT = "TYPE_EVENT";
-    field public static final java.lang.String TYPE_MOVIE = "TYPE_MOVIE";
-    field public static final java.lang.String TYPE_PLAYLIST = "TYPE_PLAYLIST";
-    field public static final java.lang.String TYPE_STATION = "TYPE_STATION";
-    field public static final java.lang.String TYPE_TRACK = "TYPE_TRACK";
-    field public static final java.lang.String TYPE_TV_EPISODE = "TYPE_TV_EPISODE";
-    field public static final java.lang.String TYPE_TV_SEASON = "TYPE_TV_SEASON";
-    field public static final java.lang.String TYPE_TV_SERIES = "TYPE_TV_SERIES";
-    field public static final java.lang.String WATCH_NEXT_TYPE_CONTINUE = "WATCH_NEXT_TYPE_CONTINUE";
-    field public static final java.lang.String WATCH_NEXT_TYPE_NEW = "WATCH_NEXT_TYPE_NEW";
-    field public static final java.lang.String WATCH_NEXT_TYPE_NEXT = "WATCH_NEXT_TYPE_NEXT";
   }
 
   public static final class TvContract.Programs implements android.media.tv.TvContract.BaseProgramColumns {
     field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre";
+    field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
     field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
     field public static final deprecated java.lang.String COLUMN_EPISODE_NUMBER = "episode_number";
     field public static final java.lang.String COLUMN_RECORDING_PROHIBITED = "recording_prohibited";
@@ -25993,6 +26533,7 @@
 
   public static final class TvContract.RecordedPrograms implements android.media.tv.TvContract.BaseProgramColumns {
     field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre";
+    field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
     field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
     field public static final java.lang.String COLUMN_INPUT_ID = "input_id";
     field public static final java.lang.String COLUMN_RECORDING_DATA_BYTES = "recording_data_bytes";
@@ -26005,6 +26546,19 @@
     field public static final android.net.Uri CONTENT_URI;
   }
 
+  public static final class TvContract.WatchNextPrograms implements android.media.tv.TvContract.BasePreviewProgramColumns {
+    ctor public TvContract.WatchNextPrograms();
+    field public static final java.lang.String COLUMN_LAST_ENGAGEMENT_TIME_UTC_MILLIS = "last_engagement_time_utc_millis";
+    field public static final java.lang.String COLUMN_WATCH_NEXT_TYPE = "watch_next_type";
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/watch_next_program";
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/watch_next_program";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String WATCH_NEXT_TYPE_CONTINUE = "WATCH_NEXT_TYPE_CONTINUE";
+    field public static final java.lang.String WATCH_NEXT_TYPE_NEW = "WATCH_NEXT_TYPE_NEW";
+    field public static final java.lang.String WATCH_NEXT_TYPE_NEXT = "WATCH_NEXT_TYPE_NEXT";
+    field public static final java.lang.String WATCH_NEXT_TYPE_WATCHLIST = "WATCH_NEXT_TYPE_WATCHLIST";
+  }
+
   public static final class TvContract.WatchedPrograms implements android.media.tv.TvContract.BaseTvColumns {
     field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
     field public static final java.lang.String COLUMN_DESCRIPTION = "description";
@@ -26134,15 +26688,10 @@
     method public void unregisterCallback(android.media.tv.TvInputManager.TvInputCallback);
     method public void updateTvInputInfo(android.media.tv.TvInputInfo);
     field public static final java.lang.String ACTION_BLOCKED_RATINGS_CHANGED = "android.media.tv.action.BLOCKED_RATINGS_CHANGED";
-    field public static final java.lang.String ACTION_MAKE_CHANNEL_BROWSABLE = "android.media.tv.action.MAKE_CHANNEL_BROWSABLE";
     field public static final java.lang.String ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED = "android.media.tv.action.PARENTAL_CONTROLS_ENABLED_CHANGED";
-    field public static final java.lang.String ACTION_PROGRAM_BROWSABLE_DISABLED = "android.media.tv.action.PROGRAM_BROWSABLE_DISABLED";
     field public static final java.lang.String ACTION_QUERY_CONTENT_RATING_SYSTEMS = "android.media.tv.action.QUERY_CONTENT_RATING_SYSTEMS";
     field public static final java.lang.String ACTION_SETUP_INPUTS = "android.media.tv.action.SETUP_INPUTS";
     field public static final java.lang.String ACTION_VIEW_RECORDING_SCHEDULES = "android.media.tv.action.VIEW_RECORDING_SCHEDULES";
-    field public static final java.lang.String EXTRA_CHANNEL_ID = "android.media.tv.extra.CHANNEL_ID";
-    field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.media.tv.extra.PACKAGE_NAME";
-    field public static final java.lang.String EXTRA_PROGRAM_ID = "android.media.tv.extra.PROGRAM_ID";
     field public static final int INPUT_STATE_CONNECTED = 0; // 0x0
     field public static final int INPUT_STATE_CONNECTED_STANDBY = 1; // 0x1
     field public static final int INPUT_STATE_DISCONNECTED = 2; // 0x2
@@ -26404,7 +26953,12 @@
     ctor public LogMaker(int);
     ctor public LogMaker(java.lang.Object[]);
     method public android.metrics.LogMaker addTaggedData(int, java.lang.Object);
+    method public android.metrics.LogMaker clearCategory();
+    method public android.metrics.LogMaker clearPackageName();
+    method public android.metrics.LogMaker clearSubtype();
     method public android.metrics.LogMaker clearTaggedData(int);
+    method public android.metrics.LogMaker clearTimestamp();
+    method public android.metrics.LogMaker clearType();
     method public void deserialize(java.lang.Object[]);
     method public int getCategory();
     method public long getCounterBucket();
@@ -26723,6 +27277,7 @@
     method public void reportNetworkConnectivity(android.net.Network, boolean);
     method public boolean requestBandwidthUpdate(android.net.Network);
     method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
+    method public void requestNetwork(android.net.NetworkRequest, int, android.net.ConnectivityManager.NetworkCallback);
     method public void requestNetwork(android.net.NetworkRequest, android.app.PendingIntent);
     method public deprecated void setNetworkPreference(int);
     method public static deprecated boolean setProcessDefaultNetwork(android.net.Network);
@@ -26776,6 +27331,7 @@
     method public void onLinkPropertiesChanged(android.net.Network, android.net.LinkProperties);
     method public void onLosing(android.net.Network, int);
     method public void onLost(android.net.Network);
+    method public void onUnavailable();
   }
 
   public static abstract interface ConnectivityManager.OnNetworkActiveListener {
@@ -26788,44 +27344,6 @@
     method public void onTetheringStarted();
   }
 
-  public final class ConnectivityMetricsEvent implements android.os.Parcelable {
-    ctor public ConnectivityMetricsEvent(long, int, int, android.os.Parcelable);
-    method public int describeContents();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.net.ConnectivityMetricsEvent> CREATOR;
-    field public final int componentTag;
-    field public final android.os.Parcelable data;
-    field public final int eventTag;
-    field public final long timestamp;
-  }
-
-  public static final class ConnectivityMetricsEvent.Reference implements android.os.Parcelable {
-    ctor public ConnectivityMetricsEvent.Reference(long);
-    method public int describeContents();
-    method public long getValue();
-    method public void readFromParcel(android.os.Parcel);
-    method public void setValue(long);
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.net.ConnectivityMetricsEvent.Reference> CREATOR;
-  }
-
-  public class ConnectivityMetricsLogger {
-    ctor public ConnectivityMetricsLogger();
-    method public android.net.ConnectivityMetricsEvent[] getEvents(android.net.ConnectivityMetricsEvent.Reference);
-    method public void logEvent(long, int, int, android.os.Parcelable);
-    method public boolean register(android.app.PendingIntent);
-    method public boolean unregister(android.app.PendingIntent);
-    field public static final int COMPONENT_TAG_BLUETOOTH = 1; // 0x1
-    field public static final int COMPONENT_TAG_CONNECTIVITY = 0; // 0x0
-    field public static final int COMPONENT_TAG_TELECOM = 3; // 0x3
-    field public static final int COMPONENT_TAG_TELEPHONY = 4; // 0x4
-    field public static final int COMPONENT_TAG_WIFI = 2; // 0x2
-    field public static final java.lang.String CONNECTIVITY_METRICS_LOGGER_SERVICE = "connectivity_metrics_logger";
-    field public static final java.lang.String DATA_KEY_EVENTS_COUNT = "count";
-    field public static final int NUMBER_OF_COMPONENTS = 5; // 0x5
-    field public static final int TAG_SKIPPED_EVENTS = -1; // 0xffffffff
-  }
-
   public class Credentials {
     ctor public Credentials(int, int, int);
     method public int getGid();
@@ -26856,6 +27374,73 @@
     field public static final android.os.Parcelable.Creator<android.net.IpPrefix> CREATOR;
   }
 
+  public final class IpSecAlgorithm implements android.os.Parcelable {
+    ctor public IpSecAlgorithm(java.lang.String, byte[]);
+    ctor public IpSecAlgorithm(java.lang.String, byte[], int);
+    method public int describeContents();
+    method public byte[] getKey();
+    method public java.lang.String getName();
+    method public int getTruncationLengthBits();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final java.lang.String ALGO_AUTH_HMAC_MD5 = "hmac(md5)";
+    field public static final java.lang.String ALGO_AUTH_HMAC_SHA1 = "hmac(sha1)";
+    field public static final java.lang.String ALGO_AUTH_HMAC_SHA256 = "hmac(sha256)";
+    field public static final java.lang.String ALGO_AUTH_HMAC_SHA384 = "hmac(sha384)";
+    field public static final java.lang.String ALGO_AUTH_HMAC_SHA512 = "hmac(sha512)";
+    field public static final java.lang.String ALGO_CRYPT_AES_CBC = "cbc(aes)";
+    field public static final android.os.Parcelable.Creator<android.net.IpSecAlgorithm> CREATOR;
+  }
+
+  public final class IpSecManager {
+    method public void applyTransportModeTransform(java.net.Socket, android.net.IpSecTransform) throws java.io.IOException;
+    method public void applyTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform) throws java.io.IOException;
+    method public void applyTunnelModeTransform(android.net.Network, android.net.IpSecTransform);
+    method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket(int) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
+    method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket() throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
+    method public void removeTransportModeTransform(java.net.Socket, android.net.IpSecTransform);
+    method public void removeTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform);
+    method public void removeTunnelModeTransform(android.net.Network, android.net.IpSecTransform);
+    method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(java.net.InetAddress, int) throws android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
+    field public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; // 0x0
+  }
+
+  public static final class IpSecManager.ResourceUnavailableException extends android.util.AndroidException {
+  }
+
+  public static final class IpSecManager.SecurityParameterIndex implements java.lang.AutoCloseable {
+    method public void close();
+    method public int getSpi();
+  }
+
+  public static final class IpSecManager.SpiUnavailableException extends android.util.AndroidException {
+    method public int getSpi();
+  }
+
+  public static final class IpSecManager.UdpEncapsulationSocket implements java.lang.AutoCloseable {
+    method public void close();
+    method public int getPort();
+    method public java.io.FileDescriptor getSocket();
+  }
+
+  public final class IpSecTransform implements java.lang.AutoCloseable {
+    method public void close();
+    field public static final int DIRECTION_IN = 0; // 0x0
+    field public static final int DIRECTION_OUT = 1; // 0x1
+  }
+
+  public static class IpSecTransform.Builder {
+    ctor public IpSecTransform.Builder(android.content.Context);
+    method public android.net.IpSecTransform buildTransportModeTransform(java.net.InetAddress) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
+    method public android.net.IpSecTransform buildTunnelModeTransform(java.net.InetAddress, java.net.InetAddress);
+    method public android.net.IpSecTransform.Builder setAuthentication(int, android.net.IpSecAlgorithm);
+    method public android.net.IpSecTransform.Builder setEncryption(int, android.net.IpSecAlgorithm);
+    method public android.net.IpSecTransform.Builder setIpv4Encapsulation(android.net.IpSecManager.UdpEncapsulationSocket, int);
+    method public android.net.IpSecTransform.Builder setNattKeepalive(int);
+    method public android.net.IpSecTransform.Builder setSpi(int, int);
+    method public android.net.IpSecTransform.Builder setSpi(int, android.net.IpSecManager.SecurityParameterIndex);
+    method public android.net.IpSecTransform.Builder setUnderlyingNetwork(android.net.Network);
+  }
+
   public class LinkAddress implements android.os.Parcelable {
     method public int describeContents();
     method public java.net.InetAddress getAddress();
@@ -26963,6 +27548,13 @@
 
   public class NetworkBadging {
     method public static android.graphics.drawable.Drawable getWifiIcon(int, int, android.content.res.Resources.Theme);
+    field public static final int BADGING_4K = 30; // 0x1e
+    field public static final int BADGING_HD = 20; // 0x14
+    field public static final int BADGING_NONE = 0; // 0x0
+    field public static final int BADGING_SD = 10; // 0xa
+  }
+
+  public static abstract class NetworkBadging.Badging implements java.lang.annotation.Annotation {
   }
 
   public final class NetworkCapabilities implements android.os.Parcelable {
@@ -27059,7 +27651,8 @@
   }
 
   public abstract class NetworkRecommendationProvider {
-    ctor public NetworkRecommendationProvider(android.os.Handler);
+    ctor public deprecated NetworkRecommendationProvider(android.os.Handler);
+    ctor public NetworkRecommendationProvider(android.content.Context, java.util.concurrent.Executor);
     method public final android.os.IBinder getBinder();
     method public abstract void onRequestRecommendation(android.net.RecommendationRequest, android.net.NetworkRecommendationProvider.ResultCallback);
     method public abstract void onRequestScores(android.net.NetworkKey[]);
@@ -27226,10 +27819,10 @@
     field public static final java.lang.String ATTRIBUTES_KEY_BADGING_CURVE = "android.net.attributes.key.BADGING_CURVE";
     field public static final java.lang.String ATTRIBUTES_KEY_HAS_CAPTIVE_PORTAL = "android.net.attributes.key.HAS_CAPTIVE_PORTAL";
     field public static final java.lang.String ATTRIBUTES_KEY_RANKING_SCORE_OFFSET = "android.net.attributes.key.RANKING_SCORE_OFFSET";
-    field public static final int BADGING_4K = 30; // 0x1e
-    field public static final int BADGING_HD = 20; // 0x14
-    field public static final int BADGING_NONE = 0; // 0x0
-    field public static final int BADGING_SD = 10; // 0xa
+    field public static final deprecated int BADGING_4K = 30; // 0x1e
+    field public static final deprecated int BADGING_HD = 20; // 0x14
+    field public static final deprecated int BADGING_NONE = 0; // 0x0
+    field public static final deprecated int BADGING_SD = 10; // 0xa
     field public static final android.os.Parcelable.Creator<android.net.ScoredNetwork> CREATOR;
     field public final android.os.Bundle attributes;
     field public final boolean meteredHint;
@@ -27237,7 +27830,7 @@
     field public final android.net.RssiCurve rssiCurve;
   }
 
-  public static abstract class ScoredNetwork.Badging implements java.lang.annotation.Annotation {
+  public static abstract deprecated class ScoredNetwork.Badging implements java.lang.annotation.Annotation {
   }
 
   public class TrafficStats {
@@ -27530,175 +28123,6 @@
 
 }
 
-package android.net.metrics {
-
-  public final class ApfProgramEvent implements android.os.Parcelable {
-    method public int describeContents();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.net.metrics.ApfProgramEvent> CREATOR;
-    field public static final int FLAG_HAS_IPV4_ADDRESS = 1; // 0x1
-    field public static final int FLAG_MULTICAST_FILTER_ON = 0; // 0x0
-    field public final int currentRas;
-    field public final int filteredRas;
-    field public final int flags;
-    field public final long lifetime;
-    field public final int programLength;
-  }
-
-  public final class ApfStats implements android.os.Parcelable {
-    method public int describeContents();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.net.metrics.ApfStats> CREATOR;
-    field public final int droppedRas;
-    field public final long durationMs;
-    field public final int matchingRas;
-    field public final int maxProgramSize;
-    field public final int parseErrors;
-    field public final int programUpdates;
-    field public final int receivedRas;
-    field public final int zeroLifetimeRas;
-  }
-
-  public final class DefaultNetworkEvent implements android.os.Parcelable {
-    method public int describeContents();
-    method public static void logEvent(int, int[], int, boolean, boolean);
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.net.metrics.DefaultNetworkEvent> CREATOR;
-    field public final int netId;
-    field public final boolean prevIPv4;
-    field public final boolean prevIPv6;
-    field public final int prevNetId;
-    field public final int[] transportTypes;
-  }
-
-  public final class DhcpClientEvent implements android.os.Parcelable {
-    method public int describeContents();
-    method public static void logStateEvent(java.lang.String, java.lang.String);
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.net.metrics.DhcpClientEvent> CREATOR;
-    field public final int durationMs;
-    field public final java.lang.String ifName;
-    field public final java.lang.String msg;
-  }
-
-  public final class DhcpErrorEvent implements android.os.Parcelable {
-    method public int describeContents();
-    method public static int errorCodeWithOption(int, int);
-    method public static void logParseError(java.lang.String, int);
-    method public static void logReceiveError(java.lang.String);
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final int BOOTP_TOO_SHORT;
-    field public static final int BUFFER_UNDERFLOW;
-    field public static final android.os.Parcelable.Creator<android.net.metrics.DhcpErrorEvent> CREATOR;
-    field public static final int DHCP_BAD_MAGIC_COOKIE;
-    field public static final int DHCP_ERROR = 4; // 0x4
-    field public static final int DHCP_INVALID_OPTION_LENGTH;
-    field public static final int DHCP_NO_MSG_TYPE;
-    field public static final int DHCP_UNKNOWN_MSG_TYPE;
-    field public static final int L2_ERROR = 1; // 0x1
-    field public static final int L2_TOO_SHORT;
-    field public static final int L2_WRONG_ETH_TYPE;
-    field public static final int L3_ERROR = 2; // 0x2
-    field public static final int L3_INVALID_IP;
-    field public static final int L3_NOT_IPV4;
-    field public static final int L3_TOO_SHORT;
-    field public static final int L4_ERROR = 3; // 0x3
-    field public static final int L4_NOT_UDP;
-    field public static final int L4_WRONG_PORT;
-    field public static final int MISC_ERROR = 5; // 0x5
-    field public static final int RECEIVE_ERROR;
-    field public final int errorCode;
-    field public final java.lang.String ifName;
-  }
-
-  public final class DnsEvent implements android.os.Parcelable {
-    method public int describeContents();
-    method public static void logEvent(int, byte[], byte[], int[]);
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.net.metrics.DnsEvent> CREATOR;
-    field public final byte[] eventTypes;
-    field public final int[] latenciesMs;
-    field public final int netId;
-    field public final byte[] returnCodes;
-  }
-
-  public final class IpManagerEvent implements android.os.Parcelable {
-    method public int describeContents();
-    method public static void logEvent(int, java.lang.String, long);
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final int COMPLETE_LIFECYCLE = 3; // 0x3
-    field public static final android.os.Parcelable.Creator<android.net.metrics.IpManagerEvent> CREATOR;
-    field public static final int PROVISIONING_FAIL = 2; // 0x2
-    field public static final int PROVISIONING_OK = 1; // 0x1
-    field public final long durationMs;
-    field public final int eventType;
-    field public final java.lang.String ifName;
-  }
-
-  public final class IpReachabilityEvent implements android.os.Parcelable {
-    method public int describeContents();
-    method public static void logNudFailed(java.lang.String);
-    method public static void logProbeEvent(java.lang.String, int);
-    method public static void logProvisioningLost(java.lang.String);
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.net.metrics.IpReachabilityEvent> CREATOR;
-    field public static final int NUD_FAILED = 512; // 0x200
-    field public static final int PROBE = 256; // 0x100
-    field public static final int PROVISIONING_LOST = 768; // 0x300
-    field public final int eventType;
-    field public final java.lang.String ifName;
-  }
-
-  public final class NetworkEvent implements android.os.Parcelable {
-    method public int describeContents();
-    method public static void logCaptivePortalFound(int, long);
-    method public static void logEvent(int, int);
-    method public static void logValidated(int, long);
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.net.metrics.NetworkEvent> CREATOR;
-    field public static final int NETWORK_CAPTIVE_PORTAL_FOUND = 4; // 0x4
-    field public static final int NETWORK_CONNECTED = 1; // 0x1
-    field public static final int NETWORK_DISCONNECTED = 7; // 0x7
-    field public static final int NETWORK_LINGER = 5; // 0x5
-    field public static final int NETWORK_UNLINGER = 6; // 0x6
-    field public static final int NETWORK_VALIDATED = 2; // 0x2
-    field public static final int NETWORK_VALIDATION_FAILED = 3; // 0x3
-    field public final long durationMs;
-    field public final int eventType;
-    field public final int netId;
-  }
-
-  public final class RaEvent implements android.os.Parcelable {
-    method public int describeContents();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.net.metrics.RaEvent> CREATOR;
-    field public final long dnsslLifetime;
-    field public final long prefixPreferredLifetime;
-    field public final long prefixValidLifetime;
-    field public final long rdnssLifetime;
-    field public final long routeInfoLifetime;
-    field public final long routerLifetime;
-  }
-
-  public final class ValidationProbeEvent implements android.os.Parcelable {
-    method public int describeContents();
-    method public static void logEvent(int, long, int, int);
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.net.metrics.ValidationProbeEvent> CREATOR;
-    field public static final int DNS_FAILURE = 0; // 0x0
-    field public static final int DNS_SUCCESS = 1; // 0x1
-    field public static final int PROBE_DNS = 0; // 0x0
-    field public static final int PROBE_HTTP = 1; // 0x1
-    field public static final int PROBE_HTTPS = 2; // 0x2
-    field public static final int PROBE_PAC = 3; // 0x3
-    field public final long durationMs;
-    field public final int netId;
-    field public final int probeType;
-    field public final int returnCode;
-  }
-
-}
-
 package android.net.nsd {
 
   public final class NsdManager {
@@ -28757,8 +29181,6 @@
   public class DiscoverySession {
     method public java.lang.String createNetworkSpecifier(android.net.wifi.aware.PeerHandle, byte[]);
     method public void destroy();
-    method public static int getMaxSendRetryCount();
-    method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[], int);
     method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[]);
   }
 
@@ -32642,12 +33064,12 @@
     field public static final int BATTERY_PLUGGED_AC = 1; // 0x1
     field public static final int BATTERY_PLUGGED_USB = 2; // 0x2
     field public static final int BATTERY_PLUGGED_WIRELESS = 4; // 0x4
-    field public static final int BATTERY_PROPERTY_BATTERY_STATUS = 6; // 0x6
     field public static final int BATTERY_PROPERTY_CAPACITY = 4; // 0x4
     field public static final int BATTERY_PROPERTY_CHARGE_COUNTER = 1; // 0x1
     field public static final int BATTERY_PROPERTY_CURRENT_AVERAGE = 3; // 0x3
     field public static final int BATTERY_PROPERTY_CURRENT_NOW = 2; // 0x2
     field public static final int BATTERY_PROPERTY_ENERGY_COUNTER = 5; // 0x5
+    field public static final int BATTERY_PROPERTY_STATUS = 6; // 0x6
     field public static final int BATTERY_STATUS_CHARGING = 2; // 0x2
     field public static final int BATTERY_STATUS_DISCHARGING = 3; // 0x3
     field public static final int BATTERY_STATUS_FULL = 5; // 0x5
@@ -32769,7 +33191,7 @@
     ctor public Bundle(android.os.Bundle);
     ctor public Bundle(android.os.PersistableBundle);
     method public java.lang.Object clone();
-    method public android.os.Bundle deepcopy();
+    method public android.os.Bundle deepCopy();
     method public int describeContents();
     method public android.os.IBinder getBinder(java.lang.String);
     method public android.os.Bundle getBundle(java.lang.String);
@@ -33515,6 +33937,7 @@
     method public boolean match(java.lang.String);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.os.PatternMatcher> CREATOR;
+    field public static final int PATTERN_ADVANCED_GLOB = 3; // 0x3
     field public static final int PATTERN_LITERAL = 0; // 0x0
     field public static final int PATTERN_PREFIX = 1; // 0x1
     field public static final int PATTERN_SIMPLE_GLOB = 2; // 0x2
@@ -33525,7 +33948,7 @@
     ctor public PersistableBundle(int);
     ctor public PersistableBundle(android.os.PersistableBundle);
     method public java.lang.Object clone();
-    method public android.os.PersistableBundle deepcopy();
+    method public android.os.PersistableBundle deepCopy();
     method public int describeContents();
     method public android.os.PersistableBundle getPersistableBundle(java.lang.String);
     method public void putPersistableBundle(java.lang.String, android.os.PersistableBundle);
@@ -33661,6 +34084,7 @@
     method public E getBroadcastItem(int);
     method public java.lang.Object getRegisteredCallbackCookie(int);
     method public int getRegisteredCallbackCount();
+    method public E getRegisteredCallbackItem(int);
     method public void kill();
     method public void onCallbackDied(E);
     method public void onCallbackDied(E, java.lang.Object);
@@ -34132,10 +34556,8 @@
     method public void allocateBytes(java.io.File, long, int) throws java.io.IOException;
     method public void allocateBytes(java.io.FileDescriptor, long, int) throws java.io.IOException;
     method public long getAllocatableBytes(java.io.File, int) throws java.io.IOException;
-    method public long getCacheQuotaBytes();
-    method public long getCacheSizeBytes();
-    method public long getExternalCacheQuotaBytes();
-    method public long getExternalCacheSizeBytes();
+    method public long getCacheQuotaBytes(java.io.File);
+    method public long getCacheSizeBytes(java.io.File);
     method public java.lang.String getMountedObbPath(java.lang.String);
     method public android.os.storage.StorageVolume getPrimaryStorageVolume();
     method public android.os.storage.StorageVolume getStorageVolume(java.io.File);
@@ -36646,6 +37068,7 @@
     field public static final int FLAG_SUPPORTS_IS_CHILD = 16; // 0x10
     field public static final int FLAG_SUPPORTS_RECENTS = 4; // 0x4
     field public static final int FLAG_SUPPORTS_SEARCH = 8; // 0x8
+    field public static final java.lang.String MIME_TYPE_ITEM = "vnd.android.document/root";
   }
 
   public abstract class DocumentsProvider extends android.content.ContentProvider {
@@ -37327,7 +37750,7 @@
     method public static final deprecated void setLocationProviderEnabled(android.content.ContentResolver, java.lang.String, boolean);
     field public static final java.lang.String ACCESSIBILITY_DISPLAY_INVERSION_ENABLED = "accessibility_display_inversion_enabled";
     field public static final java.lang.String ACCESSIBILITY_ENABLED = "accessibility_enabled";
-    field public static final java.lang.String ACCESSIBILITY_SPEAK_PASSWORD = "speak_password";
+    field public static final deprecated java.lang.String ACCESSIBILITY_SPEAK_PASSWORD = "speak_password";
     field public static final deprecated java.lang.String ADB_ENABLED = "adb_enabled";
     field public static final java.lang.String ALLOWED_GEOLOCATION_ORIGINS = "allowed_geolocation_origins";
     field public static final deprecated java.lang.String ALLOW_MOCK_LOCATION = "mock_location";
@@ -39251,7 +39674,6 @@
     field public static final int PURPOSE_ENCRYPT = 1; // 0x1
     field public static final int PURPOSE_SIGN = 4; // 0x4
     field public static final int PURPOSE_VERIFY = 8; // 0x8
-    field public static final int PURPOSE_WRAP_KEY = 16; // 0x10
     field public static final java.lang.String SIGNATURE_PADDING_RSA_PKCS1 = "PKCS1";
     field public static final java.lang.String SIGNATURE_PADDING_RSA_PSS = "PSS";
   }
@@ -39303,6 +39725,7 @@
 
   public abstract class AutoFillService extends android.app.Service {
     ctor public AutoFillService();
+    method public final void disableSelf();
     method public final android.os.IBinder onBind(android.content.Intent);
     method public void onConnected();
     method public void onDisconnected();
@@ -39319,7 +39742,7 @@
   }
 
   public static final class Dataset.Builder {
-    ctor public Dataset.Builder(java.lang.CharSequence);
+    ctor public Dataset.Builder(android.widget.RemoteViews);
     method public android.service.autofill.Dataset build();
     method public android.service.autofill.Dataset.Builder setAuthentication(android.content.IntentSender);
     method public android.service.autofill.Dataset.Builder setValue(android.view.autofill.AutoFillId, android.view.autofill.AutoFillValue);
@@ -39339,10 +39762,10 @@
   public static final class FillResponse.Builder {
     ctor public FillResponse.Builder();
     method public android.service.autofill.FillResponse.Builder addDataset(android.service.autofill.Dataset);
-    method public android.service.autofill.FillResponse.Builder addSavableFields(android.view.autofill.AutoFillId...);
     method public android.service.autofill.FillResponse build();
-    method public android.service.autofill.FillResponse.Builder setAuthentication(android.content.IntentSender);
+    method public android.service.autofill.FillResponse.Builder setAuthentication(android.content.IntentSender, android.widget.RemoteViews);
     method public android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
+    method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo);
   }
 
   public final class SaveCallback {
@@ -39350,6 +39773,24 @@
     method public void onSuccess();
   }
 
+  public final class SaveInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.SaveInfo> CREATOR;
+    field public static final int SAVE_DATA_TYPE_ADDRESS = 2; // 0x2
+    field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 3; // 0x3
+    field public static final int SAVE_DATA_TYPE_GENERIC = 0; // 0x0
+    field public static final int SAVE_DATA_TYPE_PASSWORD = 1; // 0x1
+  }
+
+  public static final class SaveInfo.Builder {
+    ctor public SaveInfo.Builder(int);
+    method public android.service.autofill.SaveInfo.Builder addSavableIds(android.view.autofill.AutoFillId...);
+    method public android.service.autofill.SaveInfo build();
+    method public android.service.autofill.SaveInfo.Builder setDescription(java.lang.CharSequence);
+    method public android.service.autofill.SaveInfo.Builder setNegativeAction(java.lang.CharSequence, android.content.IntentSender);
+  }
+
 }
 
 package android.service.carrier {
@@ -39819,6 +40260,7 @@
     method public final void unlockAndRun(java.lang.Runnable);
     field public static final java.lang.String ACTION_QS_TILE = "android.service.quicksettings.action.QS_TILE";
     field public static final java.lang.String ACTION_QS_TILE_PREFERENCES = "android.service.quicksettings.action.QS_TILE_PREFERENCES";
+    field public static final java.lang.String EXTRA_COMPONENT = "android.service.quicksettings.extra.COMPONENT";
     field public static final java.lang.String META_DATA_ACTIVE_TILE = "android.service.quicksettings.ACTIVE_TILE";
   }
 
@@ -39861,20 +40303,29 @@
 
   public class TrustAgentService extends android.app.Service {
     ctor public TrustAgentService();
+    method public final void addEscrowToken(byte[], android.os.UserHandle);
     method public final deprecated void grantTrust(java.lang.CharSequence, long, boolean);
     method public final void grantTrust(java.lang.CharSequence, long, int);
+    method public final void isEscrowTokenActive(long, android.os.UserHandle);
     method public final android.os.IBinder onBind(android.content.Intent);
     method public boolean onConfigure(java.util.List<android.os.PersistableBundle>);
     method public void onDeviceLocked();
     method public void onDeviceUnlockLockout(long);
     method public void onDeviceUnlocked();
+    method public void onEscrowTokenAdded(byte[], long, android.os.UserHandle);
+    method public void onEscrowTokenRemoved(long, boolean);
+    method public void onEscrowTokenStateReceived(long, int);
     method public void onTrustTimeout();
     method public void onUnlockAttempt(boolean);
+    method public final void removeEscrowToken(long, android.os.UserHandle);
     method public final void revokeTrust();
     method public final void setManagingTrust(boolean);
+    method public final void unlockUserWithToken(long, byte[], android.os.UserHandle);
     field public static final int FLAG_GRANT_TRUST_DISMISS_KEYGUARD = 2; // 0x2
     field public static final int FLAG_GRANT_TRUST_INITIATED_BY_USER = 1; // 0x1
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.trust.TrustAgentService";
+    field public static final int TOKEN_STATE_ACTIVE = 1; // 0x1
+    field public static final int TOKEN_STATE_INACTIVE = 0; // 0x0
     field public static final java.lang.String TRUST_AGENT_META_DATA = "android.service.trust.trustagent";
   }
 
@@ -41068,9 +41519,11 @@
     method public android.telecom.Call.Details getDetails();
     method public android.telecom.Call getParent();
     method public java.lang.String getRemainingPostDialSequence();
+    method public android.telecom.Call.RttCall getRttCall();
     method public int getState();
     method public android.telecom.InCallService.VideoCall getVideoCall();
     method public void hold();
+    method public boolean isRttActive();
     method public void mergeConference();
     method public void phoneAccountSelected(android.telecom.PhoneAccountHandle, boolean);
     method public void playDtmfTone(char);
@@ -41083,9 +41536,12 @@
     method public final void removeExtras(java.util.List<java.lang.String>);
     method public final void removeExtras(java.lang.String...);
     method public deprecated void removeListener(android.telecom.Call.Listener);
+    method public void respondToRttRequest(int, boolean);
     method public void sendCallEvent(java.lang.String, android.os.Bundle);
+    method public void sendRttRequest();
     method public void splitFromConference();
     method public void stopDtmfTone();
+    method public void stopRtt();
     method public void swapConference();
     method public void unhold();
     method public void unregisterCallback(android.telecom.Call.Callback);
@@ -41114,6 +41570,10 @@
     method public void onDetailsChanged(android.telecom.Call, android.telecom.Call.Details);
     method public void onParentChanged(android.telecom.Call, android.telecom.Call);
     method public void onPostDialWait(android.telecom.Call, java.lang.String);
+    method public void onRttInitiationFailure(android.telecom.Call, int);
+    method public void onRttModeChanged(android.telecom.Call, int);
+    method public void onRttRequest(android.telecom.Call, int);
+    method public void onRttStatusChanged(android.telecom.Call, boolean, android.telecom.Call.RttCall);
     method public void onStateChanged(android.telecom.Call, int);
     method public void onVideoCallChanged(android.telecom.Call, android.telecom.InCallService.VideoCall);
   }
@@ -41164,6 +41624,7 @@
     field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 128; // 0x80
     field public static final int PROPERTY_HIGH_DEF_AUDIO = 16; // 0x10
     field public static final int PROPERTY_IS_EXTERNAL_CALL = 64; // 0x40
+    field public static final int PROPERTY_SELF_MANAGED = 256; // 0x100
     field public static final int PROPERTY_WIFI = 8; // 0x8
   }
 
@@ -41171,6 +41632,16 @@
     ctor public Call.Listener();
   }
 
+  public static final class Call.RttCall {
+    method public int getRttAudioMode();
+    method public java.lang.String read();
+    method public void setRttMode(int);
+    method public void write(java.lang.String) throws java.io.IOException;
+    field public static final int RTT_MODE_FULL = 1; // 0x1
+    field public static final int RTT_MODE_HCO = 2; // 0x2
+    field public static final int RTT_MODE_VCO = 3; // 0x3
+  }
+
   public final class CallAudioState implements android.os.Parcelable {
     ctor public CallAudioState(boolean, int, int);
     method public static java.lang.String audioRouteToString(int);
@@ -41377,6 +41848,15 @@
     field public static final int STATE_RINGING = 2; // 0x2
   }
 
+  public static final class Connection.RttModifyStatus {
+    ctor public Connection.RttModifyStatus();
+    field public static final int SESSION_MODIFY_REQUEST_FAIL = 2; // 0x2
+    field public static final int SESSION_MODIFY_REQUEST_INVALID = 3; // 0x3
+    field public static final int SESSION_MODIFY_REQUEST_REJECTED_BY_REMOTE = 5; // 0x5
+    field public static final int SESSION_MODIFY_REQUEST_SUCCESS = 1; // 0x1
+    field public static final int SESSION_MODIFY_REQUEST_TIMED_OUT = 4; // 0x4
+  }
+
   public static abstract class Connection.VideoProvider {
     ctor public Connection.VideoProvider();
     method public void changeCameraCapabilities(android.telecom.VideoProfile.CameraCapabilities);
@@ -41434,9 +41914,9 @@
     method public final android.os.IBinder onBind(android.content.Intent);
     method public void onConference(android.telecom.Connection, android.telecom.Connection);
     method public android.telecom.Connection onCreateIncomingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
-    method public void onCreateIncomingConnectionFailed(android.telecom.ConnectionRequest);
+    method public void onCreateIncomingConnectionFailed(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
     method public android.telecom.Connection onCreateOutgoingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
-    method public void onCreateOutgoingConnectionFailed(android.telecom.ConnectionRequest);
+    method public void onCreateOutgoingConnectionFailed(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
     method public void onRemoteConferenceAdded(android.telecom.RemoteConference);
     method public void onRemoteExistingConnectionAdded(android.telecom.RemoteConnection);
     field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.ConnectionService";
@@ -41673,6 +42153,7 @@
     field public static final int CAPABILITY_CONNECTION_MANAGER = 1; // 0x1
     field public static final int CAPABILITY_MULTI_USER = 32; // 0x20
     field public static final int CAPABILITY_PLACE_EMERGENCY_CALLS = 16; // 0x10
+    field public static final int CAPABILITY_RTT = 4096; // 0x1000
     field public static final int CAPABILITY_SELF_MANAGED = 2048; // 0x800
     field public static final int CAPABILITY_SIM_SUBSCRIPTION = 4; // 0x4
     field public static final int CAPABILITY_SUPPORTS_VIDEO_CALLING = 1024; // 0x400
@@ -41912,6 +42393,7 @@
     method public boolean handleMmi(java.lang.String);
     method public boolean handleMmi(java.lang.String, android.telecom.PhoneAccountHandle);
     method public boolean isInCall();
+    method public boolean isInManagedCall();
     method public boolean isIncomingCallPermitted(android.telecom.PhoneAccountHandle);
     method public boolean isOutgoingCallPermitted(android.telecom.PhoneAccountHandle);
     method public boolean isRinging();
@@ -41949,11 +42431,13 @@
     field public static final java.lang.String EXTRA_NOTIFICATION_PHONE_NUMBER = "android.telecom.extra.NOTIFICATION_PHONE_NUMBER";
     field public static final java.lang.String EXTRA_OUTGOING_CALL_EXTRAS = "android.telecom.extra.OUTGOING_CALL_EXTRAS";
     field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.telecom.extra.PHONE_ACCOUNT_HANDLE";
+    field public static final java.lang.String EXTRA_START_CALL_WITH_RTT = "android.telecom.extra.START_CALL_WITH_RTT";
     field public static final java.lang.String EXTRA_START_CALL_WITH_SPEAKERPHONE = "android.telecom.extra.START_CALL_WITH_SPEAKERPHONE";
     field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE";
     field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS";
     field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE";
     field public static final java.lang.String METADATA_INCLUDE_EXTERNAL_CALLS = "android.telecom.INCLUDE_EXTERNAL_CALLS";
+    field public static final java.lang.String METADATA_INCLUDE_SELF_MANAGED_CALLS = "android.telecom.INCLUDE_SELF_MANAGED_CALLS";
     field public static final java.lang.String METADATA_IN_CALL_SERVICE_RINGING = "android.telecom.IN_CALL_SERVICE_RINGING";
     field public static final java.lang.String METADATA_IN_CALL_SERVICE_UI = "android.telecom.IN_CALL_SERVICE_UI";
     field public static final int PRESENTATION_ALLOWED = 1; // 0x1
@@ -42474,7 +42958,9 @@
     method public void sendDataMessage(java.lang.String, java.lang.String, short, byte[], android.app.PendingIntent, android.app.PendingIntent);
     method public void sendMultimediaMessage(android.content.Context, android.net.Uri, java.lang.String, android.os.Bundle, android.app.PendingIntent);
     method public void sendMultipartTextMessage(java.lang.String, java.lang.String, java.util.ArrayList<java.lang.String>, java.util.ArrayList<android.app.PendingIntent>, java.util.ArrayList<android.app.PendingIntent>);
+    method public void sendMultipartTextMessageWithoutPersisting(java.lang.String, java.lang.String, java.util.List<java.lang.String>, java.util.List<android.app.PendingIntent>, java.util.List<android.app.PendingIntent>);
     method public void sendTextMessage(java.lang.String, java.lang.String, java.lang.String, android.app.PendingIntent, android.app.PendingIntent);
+    method public void sendTextMessageWithoutPersisting(java.lang.String, java.lang.String, java.lang.String, android.app.PendingIntent, android.app.PendingIntent);
     field public static final java.lang.String EXTRA_MMS_DATA = "android.telephony.extra.MMS_DATA";
     field public static final java.lang.String EXTRA_MMS_HTTP_STATUS = "android.telephony.extra.MMS_HTTP_STATUS";
     field public static final java.lang.String MMS_CONFIG_ALIAS_ENABLED = "aliasEnabled";
@@ -42682,6 +43168,7 @@
     method public java.lang.String getDeviceId();
     method public java.lang.String getDeviceId(int);
     method public java.lang.String getDeviceSoftwareVersion();
+    method public java.lang.String[] getForbiddenPlmns();
     method public java.lang.String getGroupIdLevel1();
     method public java.lang.String getIccAuthentication(int, int, java.lang.String);
     method public java.lang.String getImei();
@@ -42792,6 +43279,7 @@
     field public static final java.lang.String EXTRA_INCOMING_NUMBER = "incoming_number";
     field public static final java.lang.String EXTRA_LAUNCH_VOICEMAIL_SETTINGS_INTENT = "android.telephony.extra.LAUNCH_VOICEMAIL_SETTINGS_INTENT";
     field public static final java.lang.String EXTRA_NOTIFICATION_COUNT = "android.telephony.extra.NOTIFICATION_COUNT";
+    field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.telephony.extra.PHONE_ACCOUNT_HANDLE";
     field public static final java.lang.String EXTRA_STATE = "state";
     field public static final java.lang.String EXTRA_STATE_IDLE;
     field public static final java.lang.String EXTRA_STATE_OFFHOOK;
@@ -43544,6 +44032,8 @@
     method public java.lang.String getInstallerPackageName(java.lang.String);
     method public byte[] getInstantAppCookie();
     method public int getInstantAppCookieMaxSize();
+    method public android.graphics.drawable.Drawable getInstantAppIcon(java.lang.String);
+    method public java.util.List<android.content.pm.InstantAppInfo> getInstantApps();
     method public android.content.pm.InstrumentationInfo getInstrumentationInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public java.util.List<android.content.pm.IntentFilterVerificationInfo> getIntentFilterVerifications(java.lang.String);
     method public int getIntentVerificationStatusAsUser(java.lang.String, int);
@@ -43581,6 +44071,7 @@
     method public boolean hasSystemFeature(java.lang.String);
     method public boolean hasSystemFeature(java.lang.String, int);
     method public boolean isInstantApp();
+    method public boolean isInstantApp(java.lang.String);
     method public boolean isPermissionRevokedByPolicy(java.lang.String, java.lang.String);
     method public boolean isSafeMode();
     method public java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(android.content.Intent, int);
@@ -43618,7 +44109,7 @@
 
 package android.test.suitebuilder {
 
-  public class TestMethod {
+  public deprecated class TestMethod {
     ctor public TestMethod(java.lang.reflect.Method, java.lang.Class<? extends junit.framework.TestCase>);
     ctor public TestMethod(java.lang.String, java.lang.Class<? extends junit.framework.TestCase>);
     ctor public TestMethod(junit.framework.TestCase);
@@ -43629,7 +44120,7 @@
     method public java.lang.String getName();
   }
 
-  public class TestSuiteBuilder {
+  public deprecated class TestSuiteBuilder {
     ctor public TestSuiteBuilder(java.lang.Class);
     ctor public TestSuiteBuilder(java.lang.String, java.lang.ClassLoader);
     method public android.test.suitebuilder.TestSuiteBuilder addRequirements(java.util.List<com.android.internal.util.Predicate<android.test.suitebuilder.TestMethod>>);
@@ -43642,7 +44133,7 @@
     method public android.test.suitebuilder.TestSuiteBuilder named(java.lang.String);
   }
 
-  public static class TestSuiteBuilder.FailedToCreateTests extends junit.framework.TestCase {
+  public static deprecated class TestSuiteBuilder.FailedToCreateTests extends junit.framework.TestCase {
     ctor public TestSuiteBuilder.FailedToCreateTests(java.lang.Exception);
     method public void testSuiteConstructionFailed();
   }
@@ -45858,30 +46349,51 @@
     method public abstract void setValue(T, float);
   }
 
-  public final class Half {
+  public final class Half extends java.lang.Number implements java.lang.Comparable {
+    ctor public Half(short);
+    ctor public Half(float);
+    ctor public Half(double);
+    ctor public Half(java.lang.String) throws java.lang.NumberFormatException;
     method public static short abs(short);
     method public static short ceil(short);
+    method public static int compare(short, short);
+    method public int compareTo(android.util.Half);
     method public static short copySign(short, short);
+    method public double doubleValue();
     method public static boolean equals(short, short);
+    method public float floatValue();
     method public static short floor(short);
     method public static int getExponent(short);
     method public static int getSign(short);
     method public static int getSignificand(short);
     method public static boolean greater(short, short);
     method public static boolean greaterEquals(short, short);
+    method public static int halfToIntBits(short);
+    method public static int halfToRawIntBits(short);
+    method public static short halfToShortBits(short);
+    method public short halfValue();
+    method public static int hashCode(short);
+    method public static short intBitsToHalf(int);
+    method public int intValue();
     method public static boolean isInfinite(short);
+    method public boolean isNaN();
     method public static boolean isNaN(short);
     method public static boolean isNormalized(short);
     method public static boolean less(short, short);
     method public static boolean lessEquals(short, short);
+    method public long longValue();
     method public static short max(short, short);
     method public static short min(short, short);
+    method public static short parseHalf(java.lang.String) throws java.lang.NumberFormatException;
     method public static short round(short);
     method public static float toFloat(short);
+    method public static short toHalf(float);
     method public static java.lang.String toHexString(short);
     method public static java.lang.String toString(short);
     method public static short trunc(short);
-    method public static short valueOf(float);
+    method public static android.util.Half valueOf(short);
+    method public static android.util.Half valueOf(float);
+    method public static android.util.Half valueOf(java.lang.String);
     field public static final short EPSILON = 5120; // 0x1400
     field public static final short LOWEST_VALUE = -1025; // 0xfffffbff
     field public static final int MAX_EXPONENT = 15; // 0xf
@@ -46538,6 +47050,7 @@
     field public static final int STATE_OFF = 1; // 0x1
     field public static final int STATE_ON = 2; // 0x2
     field public static final int STATE_UNKNOWN = 0; // 0x0
+    field public static final int STATE_VR = 5; // 0x5
   }
 
   public static final class Display.HdrCapabilities implements android.os.Parcelable {
@@ -46606,11 +47119,13 @@
     field public static final int DRAW_DURATION = 4; // 0x4
     field public static final int FIRST_DRAW_FRAME = 9; // 0x9
     field public static final int INPUT_HANDLING_DURATION = 1; // 0x1
+    field public static final int INTENDED_VSYNC_TIMESTAMP = 10; // 0xa
     field public static final int LAYOUT_MEASURE_DURATION = 3; // 0x3
     field public static final int SWAP_BUFFERS_DURATION = 7; // 0x7
     field public static final int SYNC_DURATION = 5; // 0x5
     field public static final int TOTAL_DURATION = 8; // 0x8
     field public static final int UNKNOWN_DELAY_DURATION = 0; // 0x0
+    field public static final int VSYNC_TIMESTAMP = 11; // 0xb
   }
 
   public abstract class FrameStats {
@@ -47983,8 +48498,8 @@
     method public void drawableHotspotChanged(float, float);
     method protected void drawableStateChanged();
     method public android.view.View findFocus();
-    method public final android.view.View findViewById(int);
-    method public final android.view.View findViewWithTag(java.lang.Object);
+    method public final <T extends android.view.View> T findViewById(int);
+    method public final <T extends android.view.View> T findViewWithTag(java.lang.Object);
     method public void findViewsWithText(java.util.ArrayList<android.view.View>, java.lang.CharSequence, int);
     method protected deprecated boolean fitSystemWindows(android.graphics.Rect);
     method public android.view.View focusSearch(int);
@@ -47999,9 +48514,11 @@
     method public float getAlpha();
     method public android.view.animation.Animation getAnimation();
     method public android.os.IBinder getApplicationWindowToken();
+    method public int getAutoFillHint();
     method public int getAutoFillMode();
-    method public android.view.autofill.AutoFillType getAutoFillType();
+    method public final deprecated android.view.autofill.AutoFillType getAutoFillType();
     method public android.view.autofill.AutoFillValue getAutoFillValue();
+    method public int getAutofillType();
     method public android.graphics.drawable.Drawable getBackground();
     method public android.content.res.ColorStateList getBackgroundTintList();
     method public android.graphics.PorterDuff.Mode getBackgroundTintMode();
@@ -48045,6 +48562,7 @@
     method protected int getHorizontalScrollbarHeight();
     method public int getId();
     method public int getImportantForAccessibility();
+    method public int getImportantForAutofill();
     method public boolean getKeepScreenOn();
     method public android.view.KeyEvent.DispatcherState getKeyDispatcherState();
     method public int getLabelFor();
@@ -48086,6 +48604,7 @@
     method public float getPivotX();
     method public float getPivotY();
     method public android.view.PointerIcon getPointerIcon();
+    method public int getResolvedAutoFillMode();
     method public android.content.res.Resources getResources();
     method public final boolean getRevealOnFocusHint();
     method public final int getRight();
@@ -48173,6 +48692,7 @@
     method public boolean isHorizontalScrollBarEnabled();
     method public boolean isHovered();
     method public boolean isImportantForAccessibility();
+    method public final boolean isImportantForAutofill();
     method public boolean isInEditMode();
     method public boolean isInLayout();
     method public boolean isInTouchMode();
@@ -48316,6 +48836,7 @@
     method public void setActivated(boolean);
     method public void setAlpha(float);
     method public void setAnimation(android.view.animation.Animation);
+    method public void setAutoFillHint(int);
     method public void setAutoFillMode(int);
     method public void setBackground(android.graphics.drawable.Drawable);
     method public void setBackgroundColor(int);
@@ -48354,6 +48875,7 @@
     method public void setHovered(boolean);
     method public void setId(int);
     method public void setImportantForAccessibility(int);
+    method public void setImportantForAutofill(int);
     method public void setKeepScreenOn(boolean);
     method public void setKeyboardNavigationCluster(boolean);
     method public void setLabelFor(int);
@@ -48457,6 +48979,25 @@
     field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
     field public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 1; // 0x1
     field public static final android.util.Property<android.view.View, java.lang.Float> ALPHA;
+    field public static final int AUTOFILL_TYPE_DATE = 4; // 0x4
+    field public static final int AUTOFILL_TYPE_LIST = 3; // 0x3
+    field public static final int AUTOFILL_TYPE_NONE = 0; // 0x0
+    field public static final int AUTOFILL_TYPE_TEXT = 1; // 0x1
+    field public static final int AUTOFILL_TYPE_TOGGLE = 2; // 0x2
+    field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_DATE = 512; // 0x200
+    field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_DAY = 4096; // 0x1000
+    field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_MONTH = 1024; // 0x400
+    field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_YEAR = 2048; // 0x800
+    field public static final int AUTO_FILL_HINT_CREDIT_CARD_NUMBER = 128; // 0x80
+    field public static final int AUTO_FILL_HINT_CREDIT_CARD_SECURITY_CODE = 256; // 0x100
+    field public static final int AUTO_FILL_HINT_EMAIL_ADDRESS = 1; // 0x1
+    field public static final int AUTO_FILL_HINT_NAME = 2; // 0x2
+    field public static final int AUTO_FILL_HINT_NONE = 0; // 0x0
+    field public static final int AUTO_FILL_HINT_PASSWORD = 8; // 0x8
+    field public static final int AUTO_FILL_HINT_PHONE = 16; // 0x10
+    field public static final int AUTO_FILL_HINT_POSTAL_ADDRESS = 32; // 0x20
+    field public static final int AUTO_FILL_HINT_POSTAL_CODE = 64; // 0x40
+    field public static final int AUTO_FILL_HINT_USERNAME = 4; // 0x4
     field public static final int AUTO_FILL_MODE_AUTO = 1; // 0x1
     field public static final int AUTO_FILL_MODE_INHERIT = 0; // 0x0
     field public static final int AUTO_FILL_MODE_MANUAL = 2; // 0x2
@@ -48500,6 +49041,9 @@
     field public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 2; // 0x2
     field public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 4; // 0x4
     field public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 1; // 0x1
+    field public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0; // 0x0
+    field public static final int IMPORTANT_FOR_AUTOFILL_NO = 2; // 0x2
+    field public static final int IMPORTANT_FOR_AUTOFILL_YES = 1; // 0x1
     field public static final int INVISIBLE = 4; // 0x4
     field public static final int KEEP_SCREEN_ON = 67108864; // 0x4000000
     field public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
@@ -49018,6 +49562,7 @@
     method public abstract int getLayoutDirection();
     method public abstract android.view.ViewParent getParent();
     method public abstract android.view.ViewParent getParentForAccessibility();
+    method public default int getResolvedAutoFillMode();
     method public abstract int getTextAlignment();
     method public abstract int getTextDirection();
     method public abstract deprecated void invalidateChild(android.view.View, android.graphics.Rect);
@@ -49096,7 +49641,7 @@
     method public abstract int addChildCount(int);
     method public abstract void asyncCommit();
     method public abstract android.view.ViewStructure asyncNewChild(int);
-    method public abstract android.view.ViewStructure asyncNewChild(int, int, int);
+    method public abstract android.view.ViewStructure asyncNewChildForAutoFill(int, int, int);
     method public abstract int getChildCount();
     method public abstract android.os.Bundle getExtras();
     method public abstract java.lang.CharSequence getHint();
@@ -49105,12 +49650,15 @@
     method public abstract int getTextSelectionStart();
     method public abstract boolean hasExtras();
     method public abstract android.view.ViewStructure newChild(int);
-    method public abstract android.view.ViewStructure newChild(int, int, int);
+    method public abstract android.view.ViewStructure newChildForAutoFill(int, int, int);
     method public abstract void setAccessibilityFocused(boolean);
     method public abstract void setActivated(boolean);
     method public abstract void setAlpha(float);
-    method public abstract void setAutoFillType(android.view.autofill.AutoFillType);
+    method public abstract void setAutoFillHint(int);
+    method public abstract void setAutoFillOptions(java.lang.String[]);
+    method public abstract deprecated void setAutoFillType(android.view.autofill.AutoFillType);
     method public abstract void setAutoFillValue(android.view.autofill.AutoFillValue);
+    method public abstract void setAutofillType(int);
     method public abstract void setCheckable(boolean);
     method public abstract void setChecked(boolean);
     method public abstract void setChildCount(int);
@@ -49125,7 +49673,9 @@
     method public abstract void setFocused(boolean);
     method public abstract void setHint(java.lang.CharSequence);
     method public abstract void setId(int, java.lang.String, java.lang.String, java.lang.String);
+    method public abstract void setInputType(int);
     method public abstract void setLongClickable(boolean);
+    method public abstract void setSanitized(boolean);
     method public abstract void setSelected(boolean);
     method public abstract void setText(java.lang.CharSequence);
     method public abstract void setText(java.lang.CharSequence, int, int);
@@ -49134,7 +49684,6 @@
     method public abstract void setTransformation(android.graphics.Matrix);
     method public abstract void setUrl(java.lang.String);
     method public abstract void setVisibility(int);
-    field public static final int AUTO_FILL_FLAG_SANITIZED = 1; // 0x1
   }
 
   public final class ViewStub extends android.view.View {
@@ -50368,21 +50917,34 @@
   }
 
   public final class AutoFillManager {
-    method public void focusChanged(android.view.View, boolean);
+    method public void registerCallback(android.view.autofill.AutoFillManager.AutofillCallback);
     method public void reset();
+    method public void startAutoFillRequest(android.view.View);
+    method public void startAutoFillRequestOnVirtualView(android.view.View, int, android.graphics.Rect);
+    method public void stopAutoFillRequest(android.view.View);
+    method public void stopAutoFillRequestOnVirtualView(android.view.View, int);
+    method public void unregisterCallback(android.view.autofill.AutoFillManager.AutofillCallback);
     method public void valueChanged(android.view.View);
-    method public void virtualFocusChanged(android.view.View, int, android.graphics.Rect, boolean);
     method public void virtualValueChanged(android.view.View, int, android.view.autofill.AutoFillValue);
     field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE";
     field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT";
   }
 
+  public static abstract class AutoFillManager.AutofillCallback {
+    ctor public AutoFillManager.AutofillCallback();
+    method public void onAutofillEvent(android.view.View, int);
+    method public void onAutofillEventVirtual(android.view.View, int, int);
+    field public static final int EVENT_INPUT_HIDDEN = 2; // 0x2
+    field public static final int EVENT_INPUT_SHOWN = 1; // 0x1
+  }
+
   public final class AutoFillType implements android.os.Parcelable {
     method public int describeContents();
+    method public static android.view.autofill.AutoFillType forDate();
     method public static android.view.autofill.AutoFillType forList();
-    method public static android.view.autofill.AutoFillType forText(int);
+    method public static android.view.autofill.AutoFillType forText();
     method public static android.view.autofill.AutoFillType forToggle();
-    method public int getSubType();
+    method public boolean isDate();
     method public boolean isList();
     method public boolean isText();
     method public boolean isToggle();
@@ -50392,9 +50954,11 @@
 
   public final class AutoFillValue implements android.os.Parcelable {
     method public int describeContents();
+    method public static android.view.autofill.AutoFillValue forDate(long);
     method public static android.view.autofill.AutoFillValue forList(int);
     method public static android.view.autofill.AutoFillValue forText(java.lang.CharSequence);
     method public static android.view.autofill.AutoFillValue forToggle(boolean);
+    method public long getDateValue();
     method public int getListValue();
     method public java.lang.CharSequence getTextValue();
     method public boolean getToggleValue();
@@ -50838,9 +51402,9 @@
   }
 
   public abstract interface TextClassifier {
-    method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int);
-    method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int);
-    method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int);
+    method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int, android.os.LocaleList);
+    method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int, android.os.LocaleList);
+    method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int, android.os.LocaleList);
     field public static final android.view.textclassifier.TextClassifier NO_OP;
     field public static final java.lang.String TYPE_ADDRESS = "address";
     field public static final java.lang.String TYPE_EMAIL = "email";
@@ -54370,11 +54934,9 @@
     method public void removeTextChangedListener(android.text.TextWatcher);
     method public void setAllCaps(boolean);
     method public final void setAutoLinkMask(int);
-    method public void setAutoSizeMaxTextSize(int, float);
-    method public void setAutoSizeMinTextSize(int, float);
-    method public void setAutoSizeStepGranularity(int, float);
-    method public void setAutoSizeTextPresetSizes(int[]);
-    method public void setAutoSizeTextType(int);
+    method public void setAutoSizeTextTypeUniformWithConfiguration(int, int, int, int) throws java.lang.IllegalArgumentException;
+    method public void setAutoSizeTextTypeUniformWithPresetSizes(int[], int) throws java.lang.IllegalArgumentException;
+    method public void setAutoSizeTextTypeWithDefaults(int);
     method public void setBreakStrategy(int);
     method public void setCompoundDrawablePadding(int);
     method public void setCompoundDrawableTintList(android.content.res.ColorStateList);
@@ -54657,6 +55219,8 @@
     method public int resolveAdjustedSize(int, int);
     method public void resume();
     method public void seekTo(int);
+    method public void setAudioAttributes(android.media.AudioAttributes);
+    method public void setAudioFocusRequest(int);
     method public void setMediaController(android.widget.MediaController);
     method public void setOnCompletionListener(android.media.MediaPlayer.OnCompletionListener);
     method public void setOnErrorListener(android.media.MediaPlayer.OnErrorListener);
@@ -54761,7 +55325,7 @@
 
 package com.android.internal.util {
 
-  public abstract interface Predicate<T> {
+  public abstract deprecated interface Predicate<T> {
     method public abstract boolean apply(T);
   }
 
@@ -55091,7 +55655,7 @@
     method public static dalvik.system.DexFile loadDex(java.lang.String, java.lang.String, int) throws java.io.IOException;
   }
 
-  public final class InMemoryDexClassLoader extends java.lang.ClassLoader {
+  public final class InMemoryDexClassLoader extends dalvik.system.BaseDexClassLoader {
     ctor public InMemoryDexClassLoader(java.nio.ByteBuffer, java.lang.ClassLoader);
   }
 
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 1ba26f5..bd535d2 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -18,25 +18,14 @@
 package android.content {
 
   public abstract class Context {
-    method public deprecated android.content.Context createCredentialEncryptedStorageContext();
-    method public deprecated android.content.Context createDeviceEncryptedStorageContext();
     method public abstract android.content.SharedPreferences getSharedPreferences(java.io.File, int);
     method public abstract java.io.File getSharedPreferencesPath(java.lang.String);
-    method public deprecated boolean isCredentialEncryptedStorage();
-    method public deprecated boolean isDeviceEncryptedStorage();
-    method public deprecated boolean migrateDatabaseFrom(android.content.Context, java.lang.String);
-    method public deprecated boolean migrateSharedPreferencesFrom(android.content.Context, java.lang.String);
   }
 
 }
 
 package android.content.pm {
 
-  public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
-    field public deprecated java.lang.String credentialEncryptedDataDir;
-    field public deprecated java.lang.String deviceEncryptedDataDir;
-  }
-
   public class ComponentInfo extends android.content.pm.PackageItemInfo {
     field public deprecated boolean encryptionAware;
   }
@@ -45,12 +34,6 @@
     field public static final int REQUESTED_PERMISSION_REQUIRED = 1; // 0x1
   }
 
-  public abstract class PackageManager {
-    field public static final deprecated int MATCH_ENCRYPTION_AWARE = 524288; // 0x80000
-    field public static final deprecated int MATCH_ENCRYPTION_AWARE_AND_UNAWARE = 786432; // 0xc0000
-    field public static final deprecated int MATCH_ENCRYPTION_UNAWARE = 262144; // 0x40000
-  }
-
 }
 
 package android.database {
@@ -163,10 +146,6 @@
     method public android.graphics.drawable.Drawable getBadgedDrawableForUser(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int);
     method public android.graphics.drawable.Drawable getBadgedIconForUser(android.graphics.drawable.Drawable, android.os.UserHandle);
     method public java.lang.CharSequence getBadgedLabelForUser(java.lang.CharSequence, android.os.UserHandle);
-    method public deprecated boolean isUserRunningAndLocked();
-    method public deprecated boolean isUserRunningAndLocked(android.os.UserHandle);
-    method public deprecated boolean isUserRunningAndUnlocked();
-    method public deprecated boolean isUserRunningAndUnlocked(android.os.UserHandle);
   }
 
 }
@@ -174,21 +153,16 @@
 package android.os.storage {
 
   public class StorageManager {
+    method public deprecated long getCacheQuotaBytes();
+    method public deprecated long getCacheSizeBytes();
+    method public deprecated long getExternalCacheQuotaBytes();
+    method public deprecated long getExternalCacheSizeBytes();
     method public android.os.storage.StorageVolume getPrimaryVolume();
     method public android.os.storage.StorageVolume[] getVolumeList();
   }
 
 }
 
-package android.preference {
-
-  public class PreferenceManager {
-    method public deprecated void setStorageCredentialEncrypted();
-    method public deprecated void setStorageDeviceEncrypted();
-  }
-
-}
-
 package android.provider {
 
   public class Browser {
@@ -389,6 +363,16 @@
 
 }
 
+package android.view.textclassifier {
+
+  public abstract interface TextClassifier {
+    method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int);
+    method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int);
+    method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int);
+  }
+
+}
+
 package android.webkit {
 
   public class WebViewClient {
diff --git a/api/test-current.txt b/api/test-current.txt
index 22a3c0f..fc96532 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -16,6 +16,7 @@
     field public static final java.lang.String ACCOUNT_MANAGER = "android.permission.ACCOUNT_MANAGER";
     field public static final java.lang.String ADD_VOICEMAIL = "com.android.voicemail.permission.ADD_VOICEMAIL";
     field public static final java.lang.String ALLOCATE_AGGRESSIVE = "android.permission.ALLOCATE_AGGRESSIVE";
+    field public static final java.lang.String ANSWER_PHONE_CALLS = "android.permission.ANSWER_PHONE_CALLS";
     field public static final java.lang.String BATTERY_STATS = "android.permission.BATTERY_STATS";
     field public static final java.lang.String BIND_ACCESSIBILITY_SERVICE = "android.permission.BIND_ACCESSIBILITY_SERVICE";
     field public static final java.lang.String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET";
@@ -297,6 +298,7 @@
     field public static final int authorities = 16842776; // 0x1010018
     field public static final int autoAdvanceViewId = 16843535; // 0x101030f
     field public static final int autoCompleteTextViewStyle = 16842859; // 0x101006b
+    field public static final int autoFillHint = 16844121; // 0x1010559
     field public static final int autoFillMode = 16844116; // 0x1010554
     field public static final int autoLink = 16842928; // 0x10100b0
     field public static final int autoMirrored = 16843754; // 0x10103ea
@@ -305,7 +307,7 @@
     field public static final int autoSizeMinTextSize = 16844088; // 0x1010538
     field public static final int autoSizePresetSizes = 16844087; // 0x1010537
     field public static final int autoSizeStepGranularity = 16844086; // 0x1010536
-    field public static final int autoSizeText = 16844085; // 0x1010535
+    field public static final int autoSizeTextType = 16844085; // 0x1010535
     field public static final int autoStart = 16843445; // 0x10102b5
     field public static final deprecated int autoText = 16843114; // 0x101016a
     field public static final int autoUrlDetect = 16843404; // 0x101028c
@@ -410,6 +412,7 @@
     field public static final int colorControlHighlight = 16843820; // 0x101042c
     field public static final int colorControlNormal = 16843817; // 0x1010429
     field public static final int colorEdgeEffect = 16843982; // 0x10104ce
+    field public static final int colorError = 16844100; // 0x1010544
     field public static final int colorFocusedHighlight = 16843663; // 0x101038f
     field public static final int colorForeground = 16842800; // 0x1010030
     field public static final int colorForegroundInverse = 16843270; // 0x1010206
@@ -604,8 +607,9 @@
     field public static final int fontFamily = 16843692; // 0x10103ac
     field public static final int fontFeatureSettings = 16843959; // 0x10104b7
     field public static final int fontProviderAuthority = 16844114; // 0x1010552
+    field public static final int fontProviderPackage = 16844122; // 0x101055a
     field public static final int fontProviderQuery = 16844115; // 0x1010553
-    field public static final int fontStyle = 16844081; // 0x1010531
+    field public static final int fontStyle = 16844095; // 0x101053f
     field public static final int fontWeight = 16844083; // 0x1010533
     field public static final int footerDividersEnabled = 16843311; // 0x101022f
     field public static final int forceHasOverlappingRendering = 16844065; // 0x1010521
@@ -706,6 +710,7 @@
     field public static final int imeSubtypeMode = 16843501; // 0x10102ed
     field public static final int immersive = 16843456; // 0x10102c0
     field public static final int importantForAccessibility = 16843690; // 0x10103aa
+    field public static final int importantForAutofill = 16844123; // 0x101055b
     field public static final int inAnimation = 16843127; // 0x1010177
     field public static final int includeFontPadding = 16843103; // 0x101015f
     field public static final int includeInGlobalSearch = 16843374; // 0x101026e
@@ -1003,7 +1008,7 @@
     field public static final int preferenceStyle = 16842894; // 0x101008e
     field public static final int presentationTheme = 16843712; // 0x10103c0
     field public static final int previewImage = 16843482; // 0x10102da
-    field public static final int primaryContentAlpha = 16843367; // 0x1010267
+    field public static final int primaryContentAlpha = 16844117; // 0x1010555
     field public static final int priority = 16842780; // 0x101001c
     field public static final int privateImeOptions = 16843299; // 0x1010223
     field public static final int process = 16842769; // 0x1010011
@@ -1059,7 +1064,9 @@
     field public static final int requireDeviceUnlock = 16843756; // 0x10103ec
     field public static final int required = 16843406; // 0x101028e
     field public static final int requiredAccountType = 16843734; // 0x10103d6
+    field public static final int requiredFeature = 16844119; // 0x1010557
     field public static final int requiredForAllUsers = 16843728; // 0x10103d0
+    field public static final int requiredNotFeature = 16844120; // 0x1010558
     field public static final int requiresFadingEdge = 16843685; // 0x10103a5
     field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364
     field public static final int resizeClip = 16843983; // 0x10104cf
@@ -1128,7 +1135,7 @@
     field public static final int searchSuggestSelection = 16843224; // 0x10101d8
     field public static final int searchSuggestThreshold = 16843373; // 0x101026d
     field public static final int searchViewStyle = 16843904; // 0x1010480
-    field public static final int secondaryContentAlpha = 16843688; // 0x10103a8
+    field public static final int secondaryContentAlpha = 16844118; // 0x1010556
     field public static final int secondaryProgress = 16843064; // 0x1010138
     field public static final int secondaryProgressTint = 16843879; // 0x1010467
     field public static final int secondaryProgressTintMode = 16843880; // 0x1010468
@@ -1316,7 +1323,6 @@
     field public static final int textCheckMarkInverse = 16842823; // 0x1010047
     field public static final int textColor = 16842904; // 0x1010098
     field public static final int textColorAlertDialogListItem = 16843526; // 0x1010306
-    field public static final int textColorError = 16844100; // 0x1010544
     field public static final int textColorHighlight = 16842905; // 0x1010099
     field public static final int textColorHighlightInverse = 16843599; // 0x101034f
     field public static final int textColorHint = 16842906; // 0x101009a
@@ -1455,7 +1461,7 @@
     field public static final int viewportWidth = 16843778; // 0x1010402
     field public static final int visibility = 16842972; // 0x10100dc
     field public static final int visible = 16843156; // 0x1010194
-    field public static final int visibleToInstantApps = 16844095; // 0x101053f
+    field public static final int visibleToInstantApps = 16844081; // 0x1010531
     field public static final int vmSafeMode = 16843448; // 0x10102b8
     field public static final int voiceIcon = 16843908; // 0x1010484
     field public static final int voiceLanguage = 16843349; // 0x1010255
@@ -2807,6 +2813,7 @@
     method public android.content.pm.ResolveInfo getResolveInfo();
     method public java.lang.String getSettingsActivityName();
     method public java.lang.String loadDescription(android.content.pm.PackageManager);
+    method public java.lang.String loadSummary(android.content.pm.PackageManager);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int CAPABILITY_CAN_CAPTURE_FINGERPRINT_GESTURES = 64; // 0x40
     field public static final int CAPABILITY_CAN_CONTROL_MAGNIFICATION = 16; // 0x10
@@ -3917,8 +3924,9 @@
     method public void readFromParcel(android.os.Parcel);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.app.ActivityManager.RunningAppProcessInfo> CREATOR;
-    field public static final int IMPORTANCE_BACKGROUND = 400; // 0x190
-    field public static final int IMPORTANCE_EMPTY = 500; // 0x1f4
+    field public static final deprecated int IMPORTANCE_BACKGROUND = 400; // 0x190
+    field public static final int IMPORTANCE_CACHED = 400; // 0x190
+    field public static final deprecated int IMPORTANCE_EMPTY = 500; // 0x1f4
     field public static final int IMPORTANCE_FOREGROUND = 100; // 0x64
     field public static final int IMPORTANCE_FOREGROUND_SERVICE = 125; // 0x7d
     field public static final int IMPORTANCE_GONE = 1000; // 0x3e8
@@ -4153,6 +4161,7 @@
     field public static final int MODE_ERRORED = 2; // 0x2
     field public static final int MODE_IGNORED = 1; // 0x1
     field public static final java.lang.String OPSTR_ADD_VOICEMAIL = "android:add_voicemail";
+    field public static final java.lang.String OPSTR_ANSWER_PHONE_CALLS = "android:answer_phone_calls";
     field public static final java.lang.String OPSTR_BODY_SENSORS = "android:body_sensors";
     field public static final java.lang.String OPSTR_CALL_PHONE = "android:call_phone";
     field public static final java.lang.String OPSTR_CAMERA = "android:camera";
@@ -4747,6 +4756,7 @@
     method public abstract android.app.Fragment getPrimaryNavigationFragment();
     method public void invalidateOptionsMenu();
     method public abstract boolean isDestroyed();
+    method public abstract boolean isStateSaved();
     method public abstract void popBackStack();
     method public abstract void popBackStack(java.lang.String, int);
     method public abstract void popBackStack(int, int);
@@ -5489,6 +5499,7 @@
 
   public final class NotificationChannel implements android.os.Parcelable {
     ctor public NotificationChannel(java.lang.String, java.lang.CharSequence, int);
+    ctor public NotificationChannel(java.lang.String, int, int);
     ctor protected NotificationChannel(android.os.Parcel);
     method public boolean canBypassDnd();
     method public boolean canShowBadge();
@@ -5502,6 +5513,7 @@
     method public int getLightColor();
     method public int getLockscreenVisibility();
     method public java.lang.CharSequence getName();
+    method public int getNameResId();
     method public android.net.Uri getSound();
     method public long[] getVibrationPattern();
     method public void setBypassDnd(boolean);
@@ -5521,12 +5533,14 @@
 
   public final class NotificationChannelGroup implements android.os.Parcelable {
     ctor public NotificationChannelGroup(java.lang.String, java.lang.CharSequence);
+    ctor public NotificationChannelGroup(java.lang.String, int);
     ctor protected NotificationChannelGroup(android.os.Parcel);
     method public android.app.NotificationChannelGroup clone();
     method public int describeContents();
     method public java.util.List<android.app.NotificationChannel> getChannels();
     method public java.lang.String getId();
     method public java.lang.CharSequence getName();
+    method public int getNameResId();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.app.NotificationChannelGroup> CREATOR;
   }
@@ -6256,6 +6270,7 @@
     method public long getMaximumTimeToLock(android.content.ComponentName);
     method public int getOrganizationColor(android.content.ComponentName);
     method public java.lang.CharSequence getOrganizationName(android.content.ComponentName);
+    method public java.util.List<java.lang.String> getOwnerInstalledCaCerts(android.os.UserHandle);
     method public android.app.admin.DevicePolicyManager getParentProfileInstance(android.content.ComponentName);
     method public long getPasswordExpiration(android.content.ComponentName);
     method public long getPasswordExpirationTimeout(android.content.ComponentName);
@@ -6293,7 +6308,7 @@
     method public boolean isApplicationHidden(android.content.ComponentName, java.lang.String);
     method public boolean isBackupServiceEnabled(android.content.ComponentName);
     method public deprecated boolean isCallerApplicationRestrictionsManagingPackage();
-    method public boolean isDefaultInputMethodSetByOwner(android.os.UserHandle);
+    method public boolean isCurrentInputMethodSetByOwner();
     method public boolean isDeviceManaged();
     method public boolean isDeviceOwnerApp(java.lang.String);
     method public boolean isLockTaskPermitted(java.lang.String);
@@ -6572,9 +6587,12 @@
 
   public static class AssistStructure.ViewNode {
     method public float getAlpha();
+    method public int getAutoFillHint();
     method public android.view.autofill.AutoFillId getAutoFillId();
-    method public android.view.autofill.AutoFillType getAutoFillType();
+    method public java.lang.String[] getAutoFillOptions();
+    method public deprecated android.view.autofill.AutoFillType getAutoFillType();
     method public android.view.autofill.AutoFillValue getAutoFillValue();
+    method public int getAutofillType();
     method public android.app.assist.AssistStructure.ViewNode getChildAt(int);
     method public int getChildCount();
     method public java.lang.String getClassName();
@@ -6587,6 +6605,7 @@
     method public java.lang.String getIdEntry();
     method public java.lang.String getIdPackage();
     method public java.lang.String getIdType();
+    method public int getInputType();
     method public int getLeft();
     method public int getScrollX();
     method public int getScrollY();
@@ -6742,6 +6761,7 @@
     method public android.app.job.JobInfo.TriggerContentUri[] getTriggerContentUris();
     method public boolean isPeriodic();
     method public boolean isPersisted();
+    method public boolean isRequireBatteryNotLow();
     method public boolean isRequireCharging();
     method public boolean isRequireDeviceIdle();
     method public void writeToParcel(android.os.Parcel, int);
@@ -6768,6 +6788,7 @@
     method public android.app.job.JobInfo.Builder setPeriodic(long, long);
     method public android.app.job.JobInfo.Builder setPersisted(boolean);
     method public android.app.job.JobInfo.Builder setRequiredNetworkType(int);
+    method public android.app.job.JobInfo.Builder setRequiresBatteryNotLow(boolean);
     method public android.app.job.JobInfo.Builder setRequiresCharging(boolean);
     method public android.app.job.JobInfo.Builder setRequiresDeviceIdle(boolean);
     method public android.app.job.JobInfo.Builder setTransientExtras(android.os.Bundle);
@@ -6908,6 +6929,7 @@
     method public long getFreeBytes(java.lang.String);
     method public long getTotalBytes(java.lang.String);
     method public android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.lang.String, android.os.UserHandle);
+    method public android.app.usage.StorageStats queryStatsForPackage(java.lang.String, java.lang.String, android.os.UserHandle);
     method public android.app.usage.StorageStats queryStatsForUid(java.lang.String, int);
     method public android.app.usage.StorageStats queryStatsForUser(java.lang.String, android.os.UserHandle);
   }
@@ -7013,7 +7035,7 @@
     method public void notifyAppWidgetViewDataChanged(int, int);
     method public void partiallyUpdateAppWidget(int[], android.widget.RemoteViews);
     method public void partiallyUpdateAppWidget(int, android.widget.RemoteViews);
-    method public boolean requestPinAppWidget(android.content.ComponentName, android.app.PendingIntent);
+    method public boolean requestPinAppWidget(android.content.ComponentName, android.os.Bundle, android.app.PendingIntent);
     method public void updateAppWidget(int[], android.widget.RemoteViews);
     method public void updateAppWidget(int, android.widget.RemoteViews);
     method public void updateAppWidget(android.content.ComponentName, android.widget.RemoteViews);
@@ -7032,6 +7054,7 @@
     field public static final java.lang.String EXTRA_APPWIDGET_IDS = "appWidgetIds";
     field public static final java.lang.String EXTRA_APPWIDGET_OLD_IDS = "appWidgetOldIds";
     field public static final java.lang.String EXTRA_APPWIDGET_OPTIONS = "appWidgetOptions";
+    field public static final java.lang.String EXTRA_APPWIDGET_PREVIEW = "appWidgetPreview";
     field public static final java.lang.String EXTRA_APPWIDGET_PROVIDER = "appWidgetProvider";
     field public static final java.lang.String EXTRA_APPWIDGET_PROVIDER_PROFILE = "appWidgetProviderProfile";
     field public static final java.lang.String EXTRA_CUSTOM_EXTRAS = "customExtras";
@@ -7120,6 +7143,7 @@
     method public java.util.Set<android.bluetooth.BluetoothDevice> getBondedDevices();
     method public static synchronized android.bluetooth.BluetoothAdapter getDefaultAdapter();
     method public java.lang.String getName();
+    method public android.bluetooth.le.PeriodicAdvertisingManager getPeriodicAdvertisingManager();
     method public int getProfileConnectionState(int);
     method public boolean getProfileProxy(android.content.Context, android.bluetooth.BluetoothProfile.ServiceListener, int);
     method public android.bluetooth.BluetoothDevice getRemoteDevice(java.lang.String);
@@ -7128,6 +7152,10 @@
     method public int getState();
     method public boolean isDiscovering();
     method public boolean isEnabled();
+    method public boolean isLe2MPhySupported();
+    method public boolean isLeCodedPhySupported();
+    method public boolean isLeExtendedAdvertisingSupported();
+    method public boolean isLePeriodicAdvertisingSupported();
     method public boolean isMultipleAdvertisementSupported();
     method public boolean isOffloadedFilteringSupported();
     method public boolean isOffloadedScanBatchingSupported();
@@ -7496,6 +7524,9 @@
   public final class BluetoothDevice implements android.os.Parcelable {
     method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback);
     method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int);
+    method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallbackExt);
+    method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallbackExt, int);
+    method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallbackExt, int, int);
     method public boolean createBond();
     method public android.bluetooth.BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
     method public android.bluetooth.BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
@@ -7539,6 +7570,13 @@
     field public static final java.lang.String EXTRA_UUID = "android.bluetooth.device.extra.UUID";
     field public static final int PAIRING_VARIANT_PASSKEY_CONFIRMATION = 2; // 0x2
     field public static final int PAIRING_VARIANT_PIN = 0; // 0x0
+    field public static final int PHY_LE_1M = 1; // 0x1
+    field public static final int PHY_LE_2M = 2; // 0x2
+    field public static final int PHY_LE_ANY = 7; // 0x7
+    field public static final int PHY_LE_CODED = 4; // 0x4
+    field public static final int PHY_OPTION_NO_PREFERRED = 0; // 0x0
+    field public static final int PHY_OPTION_S2 = 1; // 0x1
+    field public static final int PHY_OPTION_S8 = 2; // 0x2
     field public static final int TRANSPORT_AUTO = 0; // 0x0
     field public static final int TRANSPORT_BREDR = 1; // 0x1
     field public static final int TRANSPORT_LE = 2; // 0x2
@@ -7561,10 +7599,12 @@
     method public java.util.List<android.bluetooth.BluetoothGattService> getServices();
     method public boolean readCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
     method public boolean readDescriptor(android.bluetooth.BluetoothGattDescriptor);
+    method public void readPhy();
     method public boolean readRemoteRssi();
     method public boolean requestConnectionPriority(int);
     method public boolean requestMtu(int);
     method public boolean setCharacteristicNotification(android.bluetooth.BluetoothGattCharacteristic, boolean);
+    method public void setPreferredPhy(int, int, int);
     method public boolean writeCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
     method public boolean writeDescriptor(android.bluetooth.BluetoothGattDescriptor);
     field public static final int CONNECTION_PRIORITY_BALANCED = 0; // 0x0
@@ -7582,8 +7622,12 @@
     field public static final int GATT_WRITE_NOT_PERMITTED = 3; // 0x3
   }
 
-  public abstract class BluetoothGattCallback {
+  public abstract deprecated class BluetoothGattCallback extends android.bluetooth.BluetoothGattCallbackExt {
     ctor public BluetoothGattCallback();
+  }
+
+  public abstract class BluetoothGattCallbackExt {
+    ctor public BluetoothGattCallbackExt();
     method public void onCharacteristicChanged(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic);
     method public void onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
     method public void onCharacteristicWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
@@ -7591,6 +7635,8 @@
     method public void onDescriptorRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattDescriptor, int);
     method public void onDescriptorWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattDescriptor, int);
     method public void onMtuChanged(android.bluetooth.BluetoothGatt, int, int);
+    method public void onPhyRead(android.bluetooth.BluetoothGatt, int, int, int);
+    method public void onPhyUpdate(android.bluetooth.BluetoothGatt, int, int, int);
     method public void onReadRemoteRssi(android.bluetooth.BluetoothGatt, int, int);
     method public void onReliableWriteCompleted(android.bluetooth.BluetoothGatt, int);
     method public void onServicesDiscovered(android.bluetooth.BluetoothGatt, int);
@@ -7684,12 +7730,18 @@
     method public android.bluetooth.BluetoothGattService getService(java.util.UUID);
     method public java.util.List<android.bluetooth.BluetoothGattService> getServices();
     method public boolean notifyCharacteristicChanged(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothGattCharacteristic, boolean);
+    method public void readPhy(android.bluetooth.BluetoothDevice);
     method public boolean removeService(android.bluetooth.BluetoothGattService);
     method public boolean sendResponse(android.bluetooth.BluetoothDevice, int, int, int, byte[]);
+    method public void setPreferredPhy(android.bluetooth.BluetoothDevice, int, int, int);
   }
 
-  public abstract class BluetoothGattServerCallback {
+  public abstract deprecated class BluetoothGattServerCallback extends android.bluetooth.BluetoothGattServerCallbackExt {
     ctor public BluetoothGattServerCallback();
+  }
+
+  public abstract class BluetoothGattServerCallbackExt {
+    ctor public BluetoothGattServerCallbackExt();
     method public void onCharacteristicReadRequest(android.bluetooth.BluetoothDevice, int, int, android.bluetooth.BluetoothGattCharacteristic);
     method public void onCharacteristicWriteRequest(android.bluetooth.BluetoothDevice, int, android.bluetooth.BluetoothGattCharacteristic, boolean, boolean, int, byte[]);
     method public void onConnectionStateChange(android.bluetooth.BluetoothDevice, int, int);
@@ -7698,6 +7750,8 @@
     method public void onExecuteWrite(android.bluetooth.BluetoothDevice, int, boolean);
     method public void onMtuChanged(android.bluetooth.BluetoothDevice, int);
     method public void onNotificationSent(android.bluetooth.BluetoothDevice, int);
+    method public void onPhyRead(android.bluetooth.BluetoothDevice, int, int, int);
+    method public void onPhyUpdate(android.bluetooth.BluetoothDevice, int, int, int);
     method public void onServiceAdded(int, android.bluetooth.BluetoothGattService);
   }
 
@@ -7898,10 +7952,85 @@
     method public android.bluetooth.le.AdvertiseSettings.Builder setTxPowerLevel(int);
   }
 
+  public final class AdvertisingSet {
+    method public void enableAdvertising(boolean);
+    method public void periodicAdvertisingEnable(boolean);
+    method public void setAdvertisingData(android.bluetooth.le.AdvertiseData);
+    method public void setAdvertisingParameters(android.bluetooth.le.AdvertisingSetParameters);
+    method public void setPeriodicAdvertisingData(android.bluetooth.le.AdvertiseData);
+    method public void setPeriodicAdvertisingParameters(android.bluetooth.le.PeriodicAdvertisingParameters);
+    method public void setScanResponseData(android.bluetooth.le.AdvertiseData);
+  }
+
+  public abstract class AdvertisingSetCallback {
+    ctor public AdvertisingSetCallback();
+    method public void onAdvertisingDataSet(android.bluetooth.le.AdvertisingSet, int);
+    method public void onAdvertisingEnabled(android.bluetooth.le.AdvertisingSet, boolean, int);
+    method public void onAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int);
+    method public void onAdvertisingSetStarted(android.bluetooth.le.AdvertisingSet, int);
+    method public void onAdvertisingSetStopped(android.bluetooth.le.AdvertisingSet);
+    method public void onPeriodicAdvertisingDataSet(android.bluetooth.le.AdvertisingSet, int);
+    method public void onPeriodicAdvertisingEnable(android.bluetooth.le.AdvertisingSet, boolean, int);
+    method public void onPeriodicAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int);
+    method public void onScanResponseDataSet(android.bluetooth.le.AdvertisingSet, int);
+    field public static final int ADVERTISE_FAILED_ALREADY_STARTED = 3; // 0x3
+    field public static final int ADVERTISE_FAILED_DATA_TOO_LARGE = 1; // 0x1
+    field public static final int ADVERTISE_FAILED_FEATURE_UNSUPPORTED = 5; // 0x5
+    field public static final int ADVERTISE_FAILED_INTERNAL_ERROR = 4; // 0x4
+    field public static final int ADVERTISE_FAILED_TOO_MANY_ADVERTISERS = 2; // 0x2
+    field public static final int ADVERTISE_SUCCESS = 0; // 0x0
+  }
+
+  public final class AdvertisingSetParameters implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getInterval();
+    method public int getPrimaryPhy();
+    method public int getSecondaryPhy();
+    method public int getTimeout();
+    method public int getTxPowerLevel();
+    method public boolean includeTxPower();
+    method public boolean isAnonymous();
+    method public boolean isConnectable();
+    method public boolean isLegacy();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.bluetooth.le.AdvertisingSetParameters> CREATOR;
+    field public static final int INTERVAL_HIGH = 160; // 0xa0
+    field public static final int INTERVAL_LOW = 1600; // 0x640
+    field public static final int INTERVAL_MAX = 16777215; // 0xffffff
+    field public static final int INTERVAL_MEDIUM = 400; // 0x190
+    field public static final int INTERVAL_MIN = 160; // 0xa0
+    field public static final int PHY_LE_1M = 1; // 0x1
+    field public static final int PHY_LE_2M = 2; // 0x2
+    field public static final int PHY_LE_CODED = 3; // 0x3
+    field public static final int TX_POWER_HIGH = 1; // 0x1
+    field public static final int TX_POWER_LOW = -15; // 0xfffffff1
+    field public static final int TX_POWER_MAX = 1; // 0x1
+    field public static final int TX_POWER_MEDIUM = -7; // 0xfffffff9
+    field public static final int TX_POWER_MIN = -127; // 0xffffff81
+    field public static final int TX_POWER_ULTRA_LOW = -21; // 0xffffffeb
+  }
+
+  public static final class AdvertisingSetParameters.Builder {
+    ctor public AdvertisingSetParameters.Builder();
+    method public android.bluetooth.le.AdvertisingSetParameters build();
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setAnonymouus(boolean);
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setConnectable(boolean);
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setIncludeTxPower(boolean);
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setInterval(int);
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setLegacyMode(boolean);
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setPrimaryPhy(int);
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setSecondaryPhy(int);
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setTimeout(int);
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setTxPowerLevel(int);
+  }
+
   public final class BluetoothLeAdvertiser {
     method public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback);
     method public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback);
+    method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback);
+    method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
     method public void stopAdvertising(android.bluetooth.le.AdvertiseCallback);
+    method public void stopAdvertisingSet(android.bluetooth.le.AdvertisingSetCallback);
   }
 
   public final class BluetoothLeScanner {
@@ -7911,6 +8040,53 @@
     method public void stopScan(android.bluetooth.le.ScanCallback);
   }
 
+  public abstract class PeriodicAdvertisingCallback {
+    ctor public PeriodicAdvertisingCallback();
+    method public void onPeriodicAdvertisingReport(android.bluetooth.le.PeriodicAdvertisingReport);
+    method public void onSyncEstablished(int, android.bluetooth.BluetoothDevice, int, int, int, int);
+    method public void onSyncLost(int);
+    field public static final int SYNC_NO_RESOURCES = 2; // 0x2
+    field public static final int SYNC_NO_RESPONSE = 1; // 0x1
+  }
+
+  public final class PeriodicAdvertisingManager {
+    method public void registerSync(android.bluetooth.le.ScanResult, int, int, android.bluetooth.le.PeriodicAdvertisingCallback);
+    method public void registerSync(android.bluetooth.le.ScanResult, int, int, android.bluetooth.le.PeriodicAdvertisingCallback, android.os.Handler);
+    method public void unregisterSync(android.bluetooth.le.PeriodicAdvertisingCallback);
+  }
+
+  public final class PeriodicAdvertisingParameters implements android.os.Parcelable {
+    method public int describeContents();
+    method public boolean getEnable();
+    method public boolean getIncludeTxPower();
+    method public int getInterval();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.bluetooth.le.PeriodicAdvertisingParameters> CREATOR;
+  }
+
+  public static final class PeriodicAdvertisingParameters.Builder {
+    ctor public PeriodicAdvertisingParameters.Builder();
+    method public android.bluetooth.le.PeriodicAdvertisingParameters build();
+    method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setEnable(boolean);
+    method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setIncludeTxPower(boolean);
+    method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setInterval(int);
+  }
+
+  public final class PeriodicAdvertisingReport implements android.os.Parcelable {
+    ctor public PeriodicAdvertisingReport(int, int, int, int, android.bluetooth.le.ScanRecord);
+    method public int describeContents();
+    method public android.bluetooth.le.ScanRecord getData();
+    method public int getDataStatus();
+    method public int getRssi();
+    method public int getSyncHandle();
+    method public long getTimestampNanos();
+    method public int getTxPower();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.bluetooth.le.PeriodicAdvertisingReport> CREATOR;
+    field public static final int DATA_COMPLETE = 0; // 0x0
+    field public static final int DATA_INCOMPLETE_TRUNCATED = 2; // 0x2
+  }
+
   public abstract class ScanCallback {
     ctor public ScanCallback();
     method public void onBatchScanResults(java.util.List<android.bluetooth.le.ScanResult>);
@@ -7965,19 +8141,37 @@
   }
 
   public final class ScanResult implements android.os.Parcelable {
-    ctor public ScanResult(android.bluetooth.BluetoothDevice, android.bluetooth.le.ScanRecord, int, long);
+    ctor public deprecated ScanResult(android.bluetooth.BluetoothDevice, android.bluetooth.le.ScanRecord, int, long);
+    ctor public ScanResult(android.bluetooth.BluetoothDevice, int, int, int, int, int, int, int, android.bluetooth.le.ScanRecord, long);
     method public int describeContents();
+    method public int getAdvertisingSid();
+    method public int getDataStatus();
     method public android.bluetooth.BluetoothDevice getDevice();
+    method public int getPeriodicAdvertisingInterval();
+    method public int getPrimaryPhy();
     method public int getRssi();
     method public android.bluetooth.le.ScanRecord getScanRecord();
+    method public int getSecondaryPhy();
     method public long getTimestampNanos();
+    method public int getTxPower();
+    method public boolean isConnectable();
+    method public boolean isLegacy();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.bluetooth.le.ScanResult> CREATOR;
+    field public static final int DATA_COMPLETE = 0; // 0x0
+    field public static final int DATA_TRUNCATED = 2; // 0x2
+    field public static final int PHY_LE_1M = 1; // 0x1
+    field public static final int PHY_LE_2M = 2; // 0x2
+    field public static final int PHY_LE_CODED = 3; // 0x3
+    field public static final int PHY_UNUSED = 0; // 0x0
+    field public static final int SID_NOT_PRESENT = 255; // 0xff
   }
 
   public final class ScanSettings implements android.os.Parcelable {
     method public int describeContents();
     method public int getCallbackType();
+    method public boolean getLegacy();
+    method public int getPhy();
     method public long getReportDelayMillis();
     method public int getScanMode();
     method public int getScanResultType();
@@ -7991,6 +8185,9 @@
     field public static final int MATCH_NUM_FEW_ADVERTISEMENT = 2; // 0x2
     field public static final int MATCH_NUM_MAX_ADVERTISEMENT = 3; // 0x3
     field public static final int MATCH_NUM_ONE_ADVERTISEMENT = 1; // 0x1
+    field public static final int PHY_LE_1M = 1; // 0x1
+    field public static final int PHY_LE_ALL_SUPPORTED = 255; // 0xff
+    field public static final int PHY_LE_CODED = 3; // 0x3
     field public static final int SCAN_MODE_BALANCED = 1; // 0x1
     field public static final int SCAN_MODE_LOW_LATENCY = 2; // 0x2
     field public static final int SCAN_MODE_LOW_POWER = 0; // 0x0
@@ -8001,8 +8198,10 @@
     ctor public ScanSettings.Builder();
     method public android.bluetooth.le.ScanSettings build();
     method public android.bluetooth.le.ScanSettings.Builder setCallbackType(int);
+    method public android.bluetooth.le.ScanSettings.Builder setLegacy(boolean);
     method public android.bluetooth.le.ScanSettings.Builder setMatchMode(int);
     method public android.bluetooth.le.ScanSettings.Builder setNumOfMatches(int);
+    method public android.bluetooth.le.ScanSettings.Builder setPhy(int);
     method public android.bluetooth.le.ScanSettings.Builder setReportDelay(long);
     method public android.bluetooth.le.ScanSettings.Builder setScanMode(int);
   }
@@ -8054,6 +8253,8 @@
 
   public final class CompanionDeviceManager {
     method public void associate(android.companion.AssociationRequest<?>, android.companion.CompanionDeviceManager.Callback, android.os.Handler);
+    method public void disassociate(java.lang.String);
+    method public java.util.List<java.lang.String> getAssociations();
     field public static final java.lang.String EXTRA_DEVICE = "android.companion.extra.DEVICE";
   }
 
@@ -8465,8 +8666,10 @@
     field public static final java.lang.String ANY_CURSOR_ITEM_TYPE = "vnd.android.cursor.item/*";
     field public static final java.lang.String CURSOR_DIR_BASE_TYPE = "vnd.android.cursor.dir";
     field public static final java.lang.String CURSOR_ITEM_BASE_TYPE = "vnd.android.cursor.item";
+    field public static final java.lang.String EXTRA_HONORED_ARGS = "android.content.extra.HONORED_ARGS";
     field public static final java.lang.String EXTRA_REFRESH_SUPPORTED = "android.content.extra.REFRESH_SUPPORTED";
     field public static final java.lang.String EXTRA_SIZE = "android.content.extra.SIZE";
+    field public static final java.lang.String EXTRA_TOTAL_SIZE = "android.content.extra.TOTAL_SIZE";
     field public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 2; // 0x2
     field public static final int NOTIFY_SYNC_TO_NETWORK = 1; // 0x1
     field public static final java.lang.String QUERY_ARG_LIMIT = "android:query-page-limit";
@@ -8477,7 +8680,6 @@
     field public static final java.lang.String QUERY_ARG_SQL_SELECTION = "android:query-sql-selection";
     field public static final java.lang.String QUERY_ARG_SQL_SELECTION_ARGS = "android:query-sql-selection-args";
     field public static final java.lang.String QUERY_ARG_SQL_SORT_ORDER = "android:query-sql-sort-order";
-    field public static final java.lang.String QUERY_RESULT_SIZE = "android:query-result-size";
     field public static final int QUERY_SORT_DIRECTION_ASCENDING = 0; // 0x0
     field public static final int QUERY_SORT_DIRECTION_DESCENDING = 1; // 0x1
     field public static final java.lang.String SCHEME_ANDROID_RESOURCE = "android.resource";
@@ -8697,6 +8899,7 @@
     field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardware_properties";
     field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method";
     field public static final java.lang.String INPUT_SERVICE = "input";
+    field public static final java.lang.String IPSEC_SERVICE = "ipsec";
     field public static final java.lang.String JOB_SCHEDULER_SERVICE = "jobscheduler";
     field public static final java.lang.String KEYGUARD_SERVICE = "keyguard";
     field public static final java.lang.String LAUNCHER_APPS_SERVICE = "launcherapps";
@@ -9067,6 +9270,7 @@
     field public static final java.lang.String ACTION_CALL = "android.intent.action.CALL";
     field public static final java.lang.String ACTION_CALL_BUTTON = "android.intent.action.CALL_BUTTON";
     field public static final java.lang.String ACTION_CAMERA_BUTTON = "android.intent.action.CAMERA_BUTTON";
+    field public static final java.lang.String ACTION_CARRIER_SETUP = "android.intent.action.CARRIER_SETUP";
     field public static final java.lang.String ACTION_CHOOSER = "android.intent.action.CHOOSER";
     field public static final java.lang.String ACTION_CLEAR_PACKAGE = "android.intent.action.CLEAR_PACKAGE";
     field public static final java.lang.String ACTION_CLOSE_SYSTEM_DIALOGS = "android.intent.action.CLOSE_SYSTEM_DIALOGS";
@@ -10118,6 +10322,7 @@
     method public boolean accept();
     method public int describeContents();
     method public android.appwidget.AppWidgetProviderInfo getAppWidgetProviderInfo(android.content.Context);
+    method public android.os.Bundle getExtras();
     method public int getRequestType();
     method public android.content.pm.ShortcutInfo getShortcutInfo();
     method public boolean isValid();
@@ -10131,10 +10336,12 @@
     ctor public LauncherApps.ShortcutQuery();
     method public android.content.pm.LauncherApps.ShortcutQuery setActivity(android.content.ComponentName);
     method public android.content.pm.LauncherApps.ShortcutQuery setChangedSince(long);
+    method public android.content.pm.LauncherApps.ShortcutQuery setIntent(android.content.Intent);
     method public android.content.pm.LauncherApps.ShortcutQuery setPackage(java.lang.String);
     method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int);
     method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(java.util.List<java.lang.String>);
     field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
+    field public static final int FLAG_MATCH_CHOOSER = 16; // 0x10
     field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1
     field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8
     field public static final int FLAG_MATCH_PINNED = 2; // 0x2
@@ -10190,9 +10397,11 @@
     method public void unregisterSessionCallback(android.content.pm.PackageInstaller.SessionCallback);
     method public void updateSessionAppIcon(int, android.graphics.Bitmap);
     method public void updateSessionAppLabel(int, java.lang.CharSequence);
+    field public static final java.lang.String ACTION_SESSION_COMMITTED = "android.content.pm.action.SESSION_COMMITTED";
     field public static final java.lang.String ACTION_SESSION_DETAILS = "android.content.pm.action.SESSION_DETAILS";
     field public static final java.lang.String EXTRA_OTHER_PACKAGE_NAME = "android.content.pm.extra.OTHER_PACKAGE_NAME";
     field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.content.pm.extra.PACKAGE_NAME";
+    field public static final java.lang.String EXTRA_SESSION = "android.content.pm.extra.SESSION";
     field public static final java.lang.String EXTRA_SESSION_ID = "android.content.pm.extra.SESSION_ID";
     field public static final java.lang.String EXTRA_STATUS = "android.content.pm.extra.STATUS";
     field public static final java.lang.String EXTRA_STATUS_MESSAGE = "android.content.pm.extra.STATUS_MESSAGE";
@@ -10235,10 +10444,12 @@
     method public android.graphics.Bitmap getAppIcon();
     method public java.lang.CharSequence getAppLabel();
     method public java.lang.String getAppPackageName();
+    method public int getInstallReason();
     method public java.lang.String getInstallerPackageName();
     method public float getProgress();
     method public int getSessionId();
     method public boolean isActive();
+    method public boolean isSealed();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.content.pm.PackageInstaller.SessionInfo> CREATOR;
   }
@@ -10365,6 +10576,7 @@
     method public abstract boolean hasSystemFeature(java.lang.String);
     method public abstract boolean hasSystemFeature(java.lang.String, int);
     method public abstract boolean isInstantApp();
+    method public abstract boolean isInstantApp(java.lang.String);
     method public abstract boolean isPermissionReviewModeEnabled();
     method public abstract boolean isPermissionRevokedByPolicy(java.lang.String, java.lang.String);
     method public abstract boolean isSafeMode();
@@ -10497,8 +10709,11 @@
     field public static final int GET_SIGNATURES = 64; // 0x40
     field public static final deprecated int GET_UNINSTALLED_PACKAGES = 8192; // 0x2000
     field public static final int GET_URI_PERMISSION_PATTERNS = 2048; // 0x800
+    field public static final int INSTALL_REASON_DEVICE_RESTORE = 2; // 0x2
+    field public static final int INSTALL_REASON_DEVICE_SETUP = 3; // 0x3
     field public static final int INSTALL_REASON_POLICY = 1; // 0x1
     field public static final int INSTALL_REASON_UNKNOWN = 0; // 0x0
+    field public static final int INSTALL_REASON_USER = 4; // 0x4
     field public static final int MATCH_ALL = 131072; // 0x20000
     field public static final int MATCH_DEFAULT_ONLY = 65536; // 0x10000
     field public static final int MATCH_DIRECT_BOOT_AWARE = 524288; // 0x80000
@@ -10526,7 +10741,7 @@
     ctor public PackageManager.NameNotFoundException(java.lang.String);
   }
 
-  public class PackageStats implements android.os.Parcelable {
+  public deprecated class PackageStats implements android.os.Parcelable {
     ctor public PackageStats(java.lang.String);
     ctor public PackageStats(android.os.Parcel);
     ctor public PackageStats(android.content.pm.PackageStats);
@@ -10628,6 +10843,7 @@
     field public android.content.pm.ActivityInfo activityInfo;
     field public android.content.IntentFilter filter;
     field public int icon;
+    field public boolean instantAppAvailable;
     field public boolean isDefault;
     field public int labelRes;
     field public int match;
@@ -10677,6 +10893,9 @@
     method public int describeContents();
     method public android.content.ComponentName getActivity();
     method public java.util.Set<java.lang.String> getCategories();
+    method public android.content.ComponentName[] getChooserComponentNames();
+    method public android.os.PersistableBundle getChooserExtras();
+    method public android.content.IntentFilter[] getChooserIntentFilters();
     method public java.lang.CharSequence getDisabledMessage();
     method public android.os.PersistableBundle getExtras();
     method public java.lang.String getId();
@@ -10689,6 +10908,7 @@
     method public java.lang.CharSequence getShortLabel();
     method public android.os.UserHandle getUserHandle();
     method public boolean hasKeyFieldsOnly();
+    method public boolean isChooser();
     method public boolean isDeclaredInManifest();
     method public boolean isDynamic();
     method public boolean isEnabled();
@@ -10701,9 +10921,11 @@
 
   public static class ShortcutInfo.Builder {
     ctor public ShortcutInfo.Builder(android.content.Context, java.lang.String);
+    method public android.content.pm.ShortcutInfo.Builder addChooserIntentFilter(android.content.IntentFilter, android.content.ComponentName);
     method public android.content.pm.ShortcutInfo build();
     method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName);
     method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>);
+    method public android.content.pm.ShortcutInfo.Builder setChooserExtras(android.os.PersistableBundle);
     method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence);
     method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
     method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
@@ -12208,6 +12430,7 @@
     method public android.graphics.Bitmap extractAlpha(android.graphics.Paint, int[]);
     method public final int getAllocationByteCount();
     method public final int getByteCount();
+    method public final android.graphics.ColorSpace getColorSpace();
     method public final android.graphics.Bitmap.Config getConfig();
     method public int getDensity();
     method public int getGenerationId();
@@ -12590,6 +12813,7 @@
     method public java.lang.String getName();
     method public boolean isSrgb();
     method public abstract boolean isWideGamut();
+    method public static android.graphics.ColorSpace match(float[], android.graphics.ColorSpace.Rgb.TransferParameters);
     method public float[] toXyz(float, float, float);
     method public abstract float[] toXyz(float[]);
     field public static final float[] ILLUMINANT_A;
@@ -12609,6 +12833,7 @@
     method public static android.graphics.ColorSpace.Adaptation valueOf(java.lang.String);
     method public static final android.graphics.ColorSpace.Adaptation[] values();
     enum_constant public static final android.graphics.ColorSpace.Adaptation BRADFORD;
+    enum_constant public static final android.graphics.ColorSpace.Adaptation CIECAT02;
     enum_constant public static final android.graphics.ColorSpace.Adaptation VON_KRIES;
   }
 
@@ -12673,6 +12898,10 @@
   public static class ColorSpace.Rgb extends android.graphics.ColorSpace {
     ctor public ColorSpace.Rgb(java.lang.String, float[], java.util.function.DoubleUnaryOperator, java.util.function.DoubleUnaryOperator);
     ctor public ColorSpace.Rgb(java.lang.String, float[], float[], java.util.function.DoubleUnaryOperator, java.util.function.DoubleUnaryOperator, float, float);
+    ctor public ColorSpace.Rgb(java.lang.String, float[], android.graphics.ColorSpace.Rgb.TransferParameters);
+    ctor public ColorSpace.Rgb(java.lang.String, float[], float[], android.graphics.ColorSpace.Rgb.TransferParameters);
+    ctor public ColorSpace.Rgb(java.lang.String, float[], double);
+    ctor public ColorSpace.Rgb(java.lang.String, float[], float[], double);
     method public float[] fromLinear(float, float, float);
     method public float[] fromLinear(float[]);
     method public float[] fromXyz(float[]);
@@ -12684,6 +12913,7 @@
     method public java.util.function.DoubleUnaryOperator getOetf();
     method public float[] getPrimaries(float[]);
     method public float[] getPrimaries();
+    method public android.graphics.ColorSpace.Rgb.TransferParameters getTransferParameters();
     method public float[] getTransform(float[]);
     method public float[] getTransform();
     method public float[] getWhitePoint(float[]);
@@ -12694,6 +12924,18 @@
     method public float[] toXyz(float[]);
   }
 
+  public static class ColorSpace.Rgb.TransferParameters {
+    ctor public ColorSpace.Rgb.TransferParameters(double, double, double, double, double);
+    ctor public ColorSpace.Rgb.TransferParameters(double, double, double, double, double, double, double);
+    field public final double a;
+    field public final double b;
+    field public final double c;
+    field public final double d;
+    field public final double e;
+    field public final double f;
+    field public final double g;
+  }
+
   public class ComposePathEffect extends android.graphics.PathEffect {
     ctor public ComposePathEffect(android.graphics.PathEffect, android.graphics.PathEffect);
   }
@@ -13528,6 +13770,22 @@
 
 package android.graphics.drawable {
 
+  public class AdaptiveIconDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
+    method public void draw(android.graphics.Canvas);
+    method public android.graphics.drawable.Drawable getBackground();
+    method public static float getExtraInsetPercentage();
+    method public android.graphics.drawable.Drawable getForeground();
+    method public android.graphics.Path getIconMask();
+    method public int getOpacity();
+    method public android.graphics.Region getSafeZone();
+    method public void invalidateDrawable(android.graphics.drawable.Drawable);
+    method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
+    method public void setAlpha(int);
+    method public void setColorFilter(android.graphics.ColorFilter);
+    method public void setOpacity(int);
+    method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
+  }
+
   public abstract interface Animatable {
     method public abstract boolean isRunning();
     method public abstract void start();
@@ -13829,12 +14087,12 @@
   }
 
   public final class Icon implements android.os.Parcelable {
+    method public static android.graphics.drawable.Icon createWithAdaptiveBitmap(android.graphics.Bitmap);
     method public static android.graphics.drawable.Icon createWithBitmap(android.graphics.Bitmap);
     method public static android.graphics.drawable.Icon createWithContentUri(java.lang.String);
     method public static android.graphics.drawable.Icon createWithContentUri(android.net.Uri);
     method public static android.graphics.drawable.Icon createWithData(byte[], int, int);
     method public static android.graphics.drawable.Icon createWithFilePath(java.lang.String);
-    method public static android.graphics.drawable.Icon createWithMaskableBitmap(android.graphics.Bitmap);
     method public static android.graphics.drawable.Icon createWithResource(android.content.Context, int);
     method public static android.graphics.drawable.Icon createWithResource(java.lang.String, int);
     method public int describeContents();
@@ -13917,22 +14175,6 @@
     method public void addLevel(int, int, android.graphics.drawable.Drawable);
   }
 
-  public class MaskableIconDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
-    method public void draw(android.graphics.Canvas);
-    method public android.graphics.drawable.Drawable getBackground();
-    method public static float getExtraInsetPercentage();
-    method public android.graphics.drawable.Drawable getForeground();
-    method public android.graphics.Path getIconMask();
-    method public int getOpacity();
-    method public android.graphics.Region getSafeZone();
-    method public void invalidateDrawable(android.graphics.drawable.Drawable);
-    method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
-    method public void setAlpha(int);
-    method public void setColorFilter(android.graphics.ColorFilter);
-    method public void setOpacity(int);
-    method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
-  }
-
   public class NinePatchDrawable extends android.graphics.drawable.Drawable {
     ctor public deprecated NinePatchDrawable(android.graphics.Bitmap, byte[], android.graphics.Rect, java.lang.String);
     ctor public NinePatchDrawable(android.content.res.Resources, android.graphics.Bitmap, byte[], android.graphics.Rect, java.lang.String);
@@ -14046,6 +14288,8 @@
 
   public class ArcShape extends android.graphics.drawable.shapes.RectShape {
     ctor public ArcShape(float, float);
+    method public final float getStartAngle();
+    method public final float getSweepAngle();
   }
 
   public class OvalShape extends android.graphics.drawable.shapes.RectShape {
@@ -14084,9 +14328,12 @@
 package android.graphics.fonts {
 
   public final class FontRequest implements android.os.Parcelable {
-    ctor public FontRequest(java.lang.String, java.lang.String);
+    ctor public FontRequest(java.lang.String, java.lang.String, java.lang.String);
+    ctor public FontRequest(java.lang.String, java.lang.String, java.lang.String, java.util.List<java.util.List<byte[]>>);
     method public int describeContents();
+    method public java.util.List<java.util.List<byte[]>> getCertificates();
     method public java.lang.String getProviderAuthority();
+    method public java.lang.String getProviderPackage();
     method public java.lang.String getQuery();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.graphics.fonts.FontRequest> CREATOR;
@@ -14860,10 +15107,14 @@
     method public abstract void createCaptureSession(java.util.List<android.view.Surface>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
     method public abstract void createCaptureSessionByOutputConfigurations(java.util.List<android.hardware.camera2.params.OutputConfiguration>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
     method public abstract void createConstrainedHighSpeedCaptureSession(java.util.List<android.view.Surface>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
+    method public abstract void createCustomCaptureSession(android.hardware.camera2.params.InputConfiguration, java.util.List<android.hardware.camera2.params.OutputConfiguration>, int, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
     method public abstract android.hardware.camera2.CaptureRequest.Builder createReprocessCaptureRequest(android.hardware.camera2.TotalCaptureResult) throws android.hardware.camera2.CameraAccessException;
     method public abstract void createReprocessableCaptureSession(android.hardware.camera2.params.InputConfiguration, java.util.List<android.view.Surface>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
     method public abstract void createReprocessableCaptureSessionByConfigurations(android.hardware.camera2.params.InputConfiguration, java.util.List<android.hardware.camera2.params.OutputConfiguration>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
     method public abstract java.lang.String getId();
+    field public static final int SESSION_OPERATION_MODE_CONSTRAINED_HIGH_SPEED = 1; // 0x1
+    field public static final int SESSION_OPERATION_MODE_NORMAL = 0; // 0x0
+    field public static final int SESSION_OPERATION_MODE_VENDOR_START = 32768; // 0x8000
     field public static final int TEMPLATE_MANUAL = 6; // 0x6
     field public static final int TEMPLATE_PREVIEW = 1; // 0x1
     field public static final int TEMPLATE_RECORD = 3; // 0x3
@@ -19630,6 +19881,8 @@
     field public static final int SHORT_COMMONLY_USED = 6; // 0x6
     field public static final int SHORT_GENERIC = 2; // 0x2
     field public static final int SHORT_GMT = 4; // 0x4
+    field public static final int TIMEZONE_ICU = 0; // 0x0
+    field public static final int TIMEZONE_JDK = 1; // 0x1
     field public static final android.icu.util.TimeZone UNKNOWN_ZONE;
     field public static final java.lang.String UNKNOWN_ZONE_ID = "Etc/Unknown";
   }
@@ -20739,6 +20992,26 @@
     field public static final int TYPE_WIRED_HEADSET = 3; // 0x3
   }
 
+  public final class AudioFocusRequest {
+    method public boolean acceptsDelayedFocusGain();
+    method public android.media.AudioAttributes getAudioAttributes();
+    method public int getFocusGain();
+    method public android.media.AudioManager.OnAudioFocusChangeListener getOnAudioFocusChangeListener();
+    method public android.os.Handler getOnAudioFocusChangeListenerHandler();
+    method public boolean willPauseWhenDucked();
+  }
+
+  public static final class AudioFocusRequest.Builder {
+    ctor public AudioFocusRequest.Builder(int);
+    ctor public AudioFocusRequest.Builder(android.media.AudioFocusRequest);
+    method public android.media.AudioFocusRequest build();
+    method public android.media.AudioFocusRequest.Builder setAcceptsDelayedFocusGain(boolean);
+    method public android.media.AudioFocusRequest.Builder setAudioAttributes(android.media.AudioAttributes);
+    method public android.media.AudioFocusRequest.Builder setFocusGain(int);
+    method public android.media.AudioFocusRequest.Builder setOnAudioFocusChangeListener(android.media.AudioManager.OnAudioFocusChangeListener, android.os.Handler);
+    method public android.media.AudioFocusRequest.Builder setWillPauseWhenDucked(boolean);
+  }
+
   public final class AudioFormat implements android.os.Parcelable {
     method public int describeContents();
     method public int getChannelCount();
@@ -20815,6 +21088,7 @@
 
   public class AudioManager {
     method public int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener);
+    method public int abandonAudioFocusRequest(android.media.AudioFocusRequest);
     method public void adjustStreamVolume(int, int, int);
     method public void adjustSuggestedStreamVolume(int, int, int);
     method public void adjustVolume(int, int);
@@ -20851,6 +21125,7 @@
     method public deprecated void registerRemoteControlClient(android.media.RemoteControlClient);
     method public deprecated boolean registerRemoteController(android.media.RemoteController);
     method public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int);
+    method public int requestAudioFocus(android.media.AudioFocusRequest);
     method public deprecated void setBluetoothA2dpOn(boolean);
     method public void setBluetoothScoOn(boolean);
     method public void setMicrophoneMute(boolean);
@@ -20893,6 +21168,8 @@
     field public static final int AUDIOFOCUS_LOSS = -1; // 0xffffffff
     field public static final int AUDIOFOCUS_LOSS_TRANSIENT = -2; // 0xfffffffe
     field public static final int AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK = -3; // 0xfffffffd
+    field public static final int AUDIOFOCUS_NONE = 0; // 0x0
+    field public static final int AUDIOFOCUS_REQUEST_DELAYED = 2; // 0x2
     field public static final int AUDIOFOCUS_REQUEST_FAILED = 0; // 0x0
     field public static final int AUDIOFOCUS_REQUEST_GRANTED = 1; // 0x1
     field public static final int AUDIO_SESSION_ID_GENERATE = 0; // 0x0
@@ -21089,13 +21366,14 @@
     field public long nanoTime;
   }
 
-  public class AudioTrack implements android.media.AudioRouting {
+  public class AudioTrack implements android.media.AudioRouting android.media.VolumeAutomation {
     ctor public deprecated AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
     ctor public deprecated AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
     ctor public AudioTrack(android.media.AudioAttributes, android.media.AudioFormat, int, int, int) throws java.lang.IllegalArgumentException;
     method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
     method public deprecated void addOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener, android.os.Handler);
     method public int attachAuxEffect(int);
+    method public android.media.VolumeShaper createVolumeShaper(android.media.VolumeShaper.Configuration);
     method public void flush();
     method public int getAudioFormat();
     method public int getAudioSessionId();
@@ -21563,8 +21841,42 @@
     field public static final int STOP_VIDEO_RECORDING = 3; // 0x3
   }
 
+  public final class MediaCas {
+    ctor public MediaCas(int) throws android.media.UnsupportedCasException;
+    method public void closeSession(byte[]);
+    method public static android.media.MediaCas.PluginDescriptor[] enumeratePlugins();
+    method public static boolean isSystemIdSupported(int);
+    method public byte[] openSession(int);
+    method public byte[] openSession(int, int);
+    method public void processEcm(byte[], byte[], int, int);
+    method public void processEcm(byte[], byte[]);
+    method public void processEmm(byte[], int, int);
+    method public void processEmm(byte[]);
+    method public void provision(java.lang.String);
+    method public void refreshEntitlements(int, byte[]);
+    method public void release();
+    method public void sendEvent(int, int, byte[]);
+    method public void setEventListener(android.media.MediaCas.EventListener, android.os.Handler);
+    method public void setPrivateData(byte[]);
+    method public void setSessionPrivateData(byte[], byte[]);
+  }
+
+  public static abstract interface MediaCas.EventListener {
+    method public abstract void onEvent(android.media.MediaCas, int, int, byte[]);
+  }
+
+  public static class MediaCas.PluginDescriptor {
+    method public java.lang.String getName();
+    method public int getSystemId();
+  }
+
+  public class MediaCasException extends java.lang.Exception {
+    ctor public MediaCasException(java.lang.String);
+  }
+
   public final class MediaCodec {
     method public void configure(android.media.MediaFormat, android.view.Surface, android.media.MediaCrypto, int);
+    method public void configure(android.media.MediaFormat, android.view.Surface, int, android.media.MediaDescrambler);
     method public static android.media.MediaCodec createByCodecName(java.lang.String) throws java.io.IOException;
     method public static android.media.MediaCodec createDecoderByType(java.lang.String) throws java.io.IOException;
     method public static android.media.MediaCodec createEncoderByType(java.lang.String) throws java.io.IOException;
@@ -21604,6 +21916,7 @@
     field public static final int BUFFER_FLAG_CODEC_CONFIG = 2; // 0x2
     field public static final int BUFFER_FLAG_END_OF_STREAM = 4; // 0x4
     field public static final int BUFFER_FLAG_KEY_FRAME = 1; // 0x1
+    field public static final int BUFFER_FLAG_PARTIAL_FRAME = 8; // 0x8
     field public static final deprecated int BUFFER_FLAG_SYNC_FRAME = 1; // 0x1
     field public static final int CONFIGURE_FLAG_ENCODE = 1; // 0x1
     field public static final int CRYPTO_MODE_AES_CBC = 2; // 0x2
@@ -21760,6 +22073,7 @@
     field public static final deprecated int COLOR_TI_FormatYUV420PackedSemiPlanar = 2130706688; // 0x7f000100
     field public static final java.lang.String FEATURE_AdaptivePlayback = "adaptive-playback";
     field public static final java.lang.String FEATURE_IntraRefresh = "intra-refresh";
+    field public static final java.lang.String FEATURE_PartialFrame = "partial-frame";
     field public static final java.lang.String FEATURE_SecurePlayback = "secure-playback";
     field public static final java.lang.String FEATURE_TunneledPlayback = "tunneled-playback";
     field public int[] colorFormats;
@@ -21984,6 +22298,14 @@
     method public abstract int readAt(long, byte[], int, int) throws java.io.IOException;
   }
 
+  public final class MediaDescrambler {
+    ctor public MediaDescrambler(int) throws android.media.UnsupportedCasException;
+    method public final int descramble(java.nio.ByteBuffer, int, java.nio.ByteBuffer, int, android.media.MediaCodec.CryptoInfo);
+    method public final void release();
+    method public final boolean requiresSecureDecoderComponent(java.lang.String);
+    method public final void setMediaCasSession(byte[]);
+  }
+
   public class MediaDescription implements android.os.Parcelable {
     method public int describeContents();
     method public java.lang.CharSequence getDescription();
@@ -22140,8 +22462,10 @@
     method public final void setDataSource(android.content.res.AssetFileDescriptor) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
     method public final void setDataSource(java.io.FileDescriptor) throws java.io.IOException;
     method public final void setDataSource(java.io.FileDescriptor, long, long) throws java.io.IOException;
+    method public final void setMediaCas(android.media.MediaCas);
     method public void unselectTrack(int);
     field public static final int SAMPLE_FLAG_ENCRYPTED = 2; // 0x2
+    field public static final int SAMPLE_FLAG_PARTIAL_FRAME = 4; // 0x4
     field public static final int SAMPLE_FLAG_SYNC = 1; // 0x1
     field public static final int SEEK_TO_CLOSEST_SYNC = 2; // 0x2
     field public static final int SEEK_TO_NEXT_SYNC = 1; // 0x1
@@ -22207,6 +22531,7 @@
     field public static final java.lang.String KEY_IS_FORCED_SUBTITLE = "is-forced-subtitle";
     field public static final java.lang.String KEY_I_FRAME_INTERVAL = "i-frame-interval";
     field public static final java.lang.String KEY_LANGUAGE = "language";
+    field public static final java.lang.String KEY_LATENCY = "latency";
     field public static final java.lang.String KEY_LEVEL = "level";
     field public static final java.lang.String KEY_MAX_HEIGHT = "max-height";
     field public static final java.lang.String KEY_MAX_INPUT_SIZE = "max-input-size";
@@ -22238,6 +22563,7 @@
     field public static final java.lang.String MIMETYPE_AUDIO_OPUS = "audio/opus";
     field public static final java.lang.String MIMETYPE_AUDIO_QCELP = "audio/qcelp";
     field public static final java.lang.String MIMETYPE_AUDIO_RAW = "audio/raw";
+    field public static final java.lang.String MIMETYPE_AUDIO_SCRAMBLED = "audio/scrambled";
     field public static final java.lang.String MIMETYPE_AUDIO_VORBIS = "audio/vorbis";
     field public static final java.lang.String MIMETYPE_TEXT_CEA_608 = "text/cea-608";
     field public static final java.lang.String MIMETYPE_TEXT_VTT = "text/vtt";
@@ -22248,6 +22574,7 @@
     field public static final java.lang.String MIMETYPE_VIDEO_MPEG2 = "video/mpeg2";
     field public static final java.lang.String MIMETYPE_VIDEO_MPEG4 = "video/mp4v-es";
     field public static final java.lang.String MIMETYPE_VIDEO_RAW = "video/raw";
+    field public static final java.lang.String MIMETYPE_VIDEO_SCRAMBLED = "video/scrambled";
     field public static final java.lang.String MIMETYPE_VIDEO_VP8 = "video/x-vnd.on2.vp8";
     field public static final java.lang.String MIMETYPE_VIDEO_VP9 = "video/x-vnd.on2.vp9";
   }
@@ -22388,7 +22715,7 @@
     field public static final int MUXER_OUTPUT_WEBM = 1; // 0x1
   }
 
-  public class MediaPlayer {
+  public class MediaPlayer implements android.media.VolumeAutomation {
     ctor public MediaPlayer();
     method public void addTimedTextSource(java.lang.String, java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
     method public void addTimedTextSource(android.content.Context, android.net.Uri, java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
@@ -22400,6 +22727,7 @@
     method public static android.media.MediaPlayer create(android.content.Context, android.net.Uri, android.view.SurfaceHolder, android.media.AudioAttributes, int);
     method public static android.media.MediaPlayer create(android.content.Context, int);
     method public static android.media.MediaPlayer create(android.content.Context, int, android.media.AudioAttributes, int);
+    method public android.media.VolumeShaper createVolumeShaper(android.media.VolumeShaper.Configuration);
     method public void deselectTrack(int) throws java.lang.IllegalStateException;
     method public int getAudioSessionId();
     method public android.media.BufferingParams getBufferingParams();
@@ -23219,10 +23547,18 @@
     field public static final int TONE_SUP_RINGTONE = 23; // 0x17
   }
 
+  public final class UnsupportedCasException extends android.media.MediaCasException {
+    ctor public UnsupportedCasException(java.lang.String);
+  }
+
   public final class UnsupportedSchemeException extends android.media.MediaDrmException {
     ctor public UnsupportedSchemeException(java.lang.String);
   }
 
+  public abstract interface VolumeAutomation {
+    method public abstract android.media.VolumeShaper createVolumeShaper(android.media.VolumeShaper.Configuration);
+  }
+
   public abstract class VolumeProvider {
     ctor public VolumeProvider(int, int, int);
     method public final int getCurrentVolume();
@@ -23236,6 +23572,53 @@
     field public static final int VOLUME_CONTROL_RELATIVE = 1; // 0x1
   }
 
+  public final class VolumeShaper implements java.lang.AutoCloseable {
+    method public void apply(android.media.VolumeShaper.Operation);
+    method public void close();
+    method public float getVolume();
+    method public void replace(android.media.VolumeShaper.Configuration, android.media.VolumeShaper.Operation, boolean);
+  }
+
+  public static final class VolumeShaper.Configuration implements android.os.Parcelable {
+    method public int describeContents();
+    method public double getDurationMs();
+    method public int getInterpolatorType();
+    method public static int getMaximumCurvePoints();
+    method public float[] getTimes();
+    method public float[] getVolumes();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.media.VolumeShaper.Configuration> CREATOR;
+    field public static final android.media.VolumeShaper.Configuration CUBIC_RAMP;
+    field public static final int INTERPOLATOR_TYPE_CUBIC = 2; // 0x2
+    field public static final int INTERPOLATOR_TYPE_CUBIC_MONOTONIC = 3; // 0x3
+    field public static final int INTERPOLATOR_TYPE_LINEAR = 1; // 0x1
+    field public static final int INTERPOLATOR_TYPE_STEP = 0; // 0x0
+    field public static final android.media.VolumeShaper.Configuration LINEAR_RAMP;
+    field public static final android.media.VolumeShaper.Configuration SCURVE_RAMP;
+    field public static final android.media.VolumeShaper.Configuration SINE_RAMP;
+  }
+
+  public static final class VolumeShaper.Configuration.Builder {
+    ctor public VolumeShaper.Configuration.Builder();
+    ctor public VolumeShaper.Configuration.Builder(android.media.VolumeShaper.Configuration);
+    method public android.media.VolumeShaper.Configuration build();
+    method public android.media.VolumeShaper.Configuration.Builder invertVolumes();
+    method public android.media.VolumeShaper.Configuration.Builder reflectTimes();
+    method public android.media.VolumeShaper.Configuration.Builder scaleToEndVolume(float);
+    method public android.media.VolumeShaper.Configuration.Builder scaleToStartVolume(float);
+    method public android.media.VolumeShaper.Configuration.Builder setCurve(float[], float[]);
+    method public android.media.VolumeShaper.Configuration.Builder setDurationMs(double);
+    method public android.media.VolumeShaper.Configuration.Builder setInterpolatorType(int);
+  }
+
+  public static final class VolumeShaper.Operation implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.media.VolumeShaper.Operation> CREATOR;
+    field public static final android.media.VolumeShaper.Operation PLAY;
+    field public static final android.media.VolumeShaper.Operation REVERSE;
+  }
+
 }
 
 package android.media.audiofx {
@@ -24081,17 +24464,79 @@
     method public static final android.net.Uri buildProgramsUriForChannel(long, long, long);
     method public static final android.net.Uri buildProgramsUriForChannel(android.net.Uri, long, long);
     method public static final android.net.Uri buildRecordedProgramUri(long);
+    method public static final android.net.Uri buildWatchNextProgramUri(long);
     method public static final boolean isChannelUri(android.net.Uri);
     method public static final boolean isChannelUriForPassthroughInput(android.net.Uri);
     method public static final boolean isChannelUriForTunerInput(android.net.Uri);
     method public static final boolean isProgramUri(android.net.Uri);
+    field public static final java.lang.String ACTION_MAKE_CHANNEL_BROWSABLE = "android.media.tv.action.MAKE_CHANNEL_BROWSABLE";
+    field public static final java.lang.String ACTION_PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT = "android.media.tv.action.PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT";
+    field public static final java.lang.String ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED = "android.media.tv.action.PREVIEW_PROGRAM_BROWSABLE_DISABLED";
+    field public static final java.lang.String ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED = "android.media.tv.action.WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED";
     field public static final java.lang.String AUTHORITY = "android.media.tv";
+    field public static final java.lang.String EXTRA_CHANNEL_ID = "android.media.tv.extra.CHANNEL_ID";
+    field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.media.tv.extra.PACKAGE_NAME";
+    field public static final java.lang.String EXTRA_PREVIEW_PROGRAM_ID = "android.media.tv.extra.PREVIEW_PROGRAM_ID";
+    field public static final java.lang.String EXTRA_WATCH_NEXT_PROGRAM_ID = "android.media.tv.extra.WATCH_NEXT_PROGRAM_ID";
+  }
+
+  public static abstract interface TvContract.BasePreviewProgramColumns implements android.media.tv.TvContract.BaseProgramColumns {
+    field public static final java.lang.String ASPECT_RATIO_16_9 = "ASPECT_RATIO_16_9";
+    field public static final java.lang.String ASPECT_RATIO_1_1 = "ASPECT_RATIO_1_1";
+    field public static final java.lang.String ASPECT_RATIO_2_3 = "ASPECT_RATIO_2_3";
+    field public static final java.lang.String ASPECT_RATIO_3_2 = "ASPECT_RATIO_3_2";
+    field public static final java.lang.String AVAILABILITY_AVAILABLE = "AVAILABILITY_AVAILABLE";
+    field public static final java.lang.String AVAILABILITY_FREE_WITH_SUBSCRIPTION = "AVAILABILITY_FREE_WITH_SUBSCRIPTION";
+    field public static final java.lang.String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT";
+    field public static final java.lang.String COLUMN_APP_LINK_INTENT_URI = "app_link_intent_uri";
+    field public static final java.lang.String COLUMN_AUTHOR = "author";
+    field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
+    field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
+    field public static final java.lang.String COLUMN_CONTENT_ID = "content_id";
+    field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
+    field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count";
+    field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
+    field public static final java.lang.String COLUMN_ITEM_COUNT = "item_count";
+    field public static final java.lang.String COLUMN_LAST_PLAYBACK_POSITION_MILLIS = "last_playback_position_millis";
+    field public static final java.lang.String COLUMN_LIVE = "live";
+    field public static final java.lang.String COLUMN_LOGO_URI = "logo_uri";
+    field public static final java.lang.String COLUMN_OFFER_PRICE = "offer_price";
+    field public static final java.lang.String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
+    field public static final java.lang.String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri";
+    field public static final java.lang.String COLUMN_RELEASE_DATE = "release_date";
+    field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating";
+    field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
+    field public static final java.lang.String COLUMN_STARTING_PRICE = "starting_price";
+    field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
+    field public static final java.lang.String COLUMN_TYPE = "type";
+    field public static final java.lang.String INTERACTION_TYPE_FANS = "INTERACTION_TYPE_FANS";
+    field public static final java.lang.String INTERACTION_TYPE_FOLLOWERS = "INTERACTION_TYPE_FOLLOWERS";
+    field public static final java.lang.String INTERACTION_TYPE_LIKES = "INTERACTION_TYPE_LIKES";
+    field public static final java.lang.String INTERACTION_TYPE_LISTENS = "INTERACTION_TYPE_LISTENS";
+    field public static final java.lang.String INTERACTION_TYPE_THUMBS = "INTERACTION_TYPE_THUMBS";
+    field public static final java.lang.String INTERACTION_TYPE_VIEWERS = "INTERACTION_TYPE_VIEWERS";
+    field public static final java.lang.String INTERACTION_TYPE_VIEWS = "INTERACTION_TYPE_VIEWS";
+    field public static final java.lang.String REVIEW_RATING_STYLE_PERCENTAGE = "REVIEW_RATING_STYLE_PERCENTAGE";
+    field public static final java.lang.String REVIEW_RATING_STYLE_STARS = "REVIEW_RATING_STYLE_STARS";
+    field public static final java.lang.String REVIEW_RATING_STYLE_THUMBS_UP_DOWN = "REVIEW_RATING_STYLE_THUMBS_UP_DOWN";
+    field public static final java.lang.String TYPE_ALBUM = "TYPE_ALBUM";
+    field public static final java.lang.String TYPE_ARTIST = "TYPE_ARTIST";
+    field public static final java.lang.String TYPE_CHANNEL = "TYPE_CHANNEL";
+    field public static final java.lang.String TYPE_CLIP = "TYPE_CLIP";
+    field public static final java.lang.String TYPE_EVENT = "TYPE_EVENT";
+    field public static final java.lang.String TYPE_MOVIE = "TYPE_MOVIE";
+    field public static final java.lang.String TYPE_PLAYLIST = "TYPE_PLAYLIST";
+    field public static final java.lang.String TYPE_STATION = "TYPE_STATION";
+    field public static final java.lang.String TYPE_TRACK = "TYPE_TRACK";
+    field public static final java.lang.String TYPE_TV_EPISODE = "TYPE_TV_EPISODE";
+    field public static final java.lang.String TYPE_TV_SEASON = "TYPE_TV_SEASON";
+    field public static final java.lang.String TYPE_TV_SERIES = "TYPE_TV_SERIES";
   }
 
   public static abstract interface TvContract.BaseProgramColumns implements android.media.tv.TvContract.BaseTvColumns {
     field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
     field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
-    field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
     field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
     field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
     field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
@@ -24124,6 +24569,7 @@
     field public static final java.lang.String COLUMN_APP_LINK_INTENT_URI = "app_link_intent_uri";
     field public static final java.lang.String COLUMN_APP_LINK_POSTER_ART_URI = "app_link_poster_art_uri";
     field public static final java.lang.String COLUMN_APP_LINK_TEXT = "app_link_text";
+    field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
     field public static final java.lang.String COLUMN_DESCRIPTION = "description";
     field public static final java.lang.String COLUMN_DISPLAY_NAME = "display_name";
     field public static final java.lang.String COLUMN_DISPLAY_NUMBER = "display_number";
@@ -24196,69 +24642,17 @@
     field public static final java.lang.String CONTENT_DIRECTORY = "logo";
   }
 
-  public static final class TvContract.PreviewPrograms implements android.media.tv.TvContract.BaseProgramColumns {
-    field public static final java.lang.String ASPECT_RATIO_16_9 = "ASPECT_RATIO_16_9";
-    field public static final java.lang.String ASPECT_RATIO_1_1 = "ASPECT_RATIO_1_1";
-    field public static final java.lang.String ASPECT_RATIO_2_3 = "ASPECT_RATIO_2_3";
-    field public static final java.lang.String ASPECT_RATIO_3_2 = "ASPECT_RATIO_3_2";
-    field public static final java.lang.String AVAILABILITY_AVAILABLE = "AVAILABILITY_AVAILABLE";
-    field public static final java.lang.String AVAILABILITY_FREE_WITH_SUBSCRIPTION = "AVAILABILITY_FREE_WITH_SUBSCRIPTION";
-    field public static final java.lang.String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT";
-    field public static final java.lang.String COLUMN_APP_LINK_INTENT_URI = "app_link_intent_uri";
-    field public static final java.lang.String COLUMN_AUTHOR = "author";
-    field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
-    field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
-    field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
-    field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count";
-    field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type";
-    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
-    field public static final java.lang.String COLUMN_ITEM_COUNT = "item_count";
-    field public static final java.lang.String COLUMN_LAST_PLAYBACK_POSITION_MILLIS = "last_playback_position_millis";
-    field public static final java.lang.String COLUMN_LIVE = "live";
-    field public static final java.lang.String COLUMN_LOGO_URI = "logo_uri";
-    field public static final java.lang.String COLUMN_OFFER_PRICE = "offer_price";
-    field public static final java.lang.String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
-    field public static final java.lang.String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri";
-    field public static final java.lang.String COLUMN_RELEASE_DATE = "release_date";
-    field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating";
-    field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
-    field public static final java.lang.String COLUMN_STARTING_PRICE = "starting_price";
-    field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
-    field public static final java.lang.String COLUMN_TYPE = "type";
-    field public static final java.lang.String COLUMN_WATCH_NEXT_TYPE = "watch_next_type";
+  public static final class TvContract.PreviewPrograms implements android.media.tv.TvContract.BasePreviewProgramColumns {
+    field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
     field public static final java.lang.String COLUMN_WEIGHT = "weight";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/preview_program";
     field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/preview_program";
     field public static final android.net.Uri CONTENT_URI;
-    field public static final java.lang.String INTERACTION_TYPE_FANS = "INTERACTION_TYPE_FANS";
-    field public static final java.lang.String INTERACTION_TYPE_FOLLOWERS = "INTERACTION_TYPE_FOLLOWERS";
-    field public static final java.lang.String INTERACTION_TYPE_LIKES = "INTERACTION_TYPE_LIKES";
-    field public static final java.lang.String INTERACTION_TYPE_LISTENS = "INTERACTION_TYPE_LISTENS";
-    field public static final java.lang.String INTERACTION_TYPE_THUMBS = "INTERACTION_TYPE_THUMBS";
-    field public static final java.lang.String INTERACTION_TYPE_VIEWERS = "INTERACTION_TYPE_VIEWERS";
-    field public static final java.lang.String INTERACTION_TYPE_VIEWS = "INTERACTION_TYPE_VIEWS";
-    field public static final java.lang.String REVIEW_RATING_STYLE_PERCENTAGE = "REVIEW_RATING_STYLE_PERCENTAGE";
-    field public static final java.lang.String REVIEW_RATING_STYLE_STARS = "REVIEW_RATING_STYLE_STARS";
-    field public static final java.lang.String REVIEW_RATING_STYLE_THUMBS_UP_DOWN = "REVIEW_RATING_STYLE_THUMBS_UP_DOWN";
-    field public static final java.lang.String TYPE_ALBUM = "TYPE_ALBUM";
-    field public static final java.lang.String TYPE_ARTIST = "TYPE_ARTIST";
-    field public static final java.lang.String TYPE_CHANNEL = "TYPE_CHANNEL";
-    field public static final java.lang.String TYPE_CLIP = "TYPE_CLIP";
-    field public static final java.lang.String TYPE_EVENT = "TYPE_EVENT";
-    field public static final java.lang.String TYPE_MOVIE = "TYPE_MOVIE";
-    field public static final java.lang.String TYPE_PLAYLIST = "TYPE_PLAYLIST";
-    field public static final java.lang.String TYPE_STATION = "TYPE_STATION";
-    field public static final java.lang.String TYPE_TRACK = "TYPE_TRACK";
-    field public static final java.lang.String TYPE_TV_EPISODE = "TYPE_TV_EPISODE";
-    field public static final java.lang.String TYPE_TV_SEASON = "TYPE_TV_SEASON";
-    field public static final java.lang.String TYPE_TV_SERIES = "TYPE_TV_SERIES";
-    field public static final java.lang.String WATCH_NEXT_TYPE_CONTINUE = "WATCH_NEXT_TYPE_CONTINUE";
-    field public static final java.lang.String WATCH_NEXT_TYPE_NEW = "WATCH_NEXT_TYPE_NEW";
-    field public static final java.lang.String WATCH_NEXT_TYPE_NEXT = "WATCH_NEXT_TYPE_NEXT";
   }
 
   public static final class TvContract.Programs implements android.media.tv.TvContract.BaseProgramColumns {
     field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre";
+    field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
     field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
     field public static final deprecated java.lang.String COLUMN_EPISODE_NUMBER = "episode_number";
     field public static final java.lang.String COLUMN_RECORDING_PROHIBITED = "recording_prohibited";
@@ -24294,6 +24688,7 @@
 
   public static final class TvContract.RecordedPrograms implements android.media.tv.TvContract.BaseProgramColumns {
     field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre";
+    field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
     field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
     field public static final java.lang.String COLUMN_INPUT_ID = "input_id";
     field public static final java.lang.String COLUMN_RECORDING_DATA_BYTES = "recording_data_bytes";
@@ -24306,6 +24701,19 @@
     field public static final android.net.Uri CONTENT_URI;
   }
 
+  public static final class TvContract.WatchNextPrograms implements android.media.tv.TvContract.BasePreviewProgramColumns {
+    ctor public TvContract.WatchNextPrograms();
+    field public static final java.lang.String COLUMN_LAST_ENGAGEMENT_TIME_UTC_MILLIS = "last_engagement_time_utc_millis";
+    field public static final java.lang.String COLUMN_WATCH_NEXT_TYPE = "watch_next_type";
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/watch_next_program";
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/watch_next_program";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String WATCH_NEXT_TYPE_CONTINUE = "WATCH_NEXT_TYPE_CONTINUE";
+    field public static final java.lang.String WATCH_NEXT_TYPE_NEW = "WATCH_NEXT_TYPE_NEW";
+    field public static final java.lang.String WATCH_NEXT_TYPE_NEXT = "WATCH_NEXT_TYPE_NEXT";
+    field public static final java.lang.String WATCH_NEXT_TYPE_WATCHLIST = "WATCH_NEXT_TYPE_WATCHLIST";
+  }
+
   public final class TvInputInfo implements android.os.Parcelable {
     method public boolean canRecord();
     method public android.content.Intent createSettingsIntent();
@@ -24355,15 +24763,10 @@
     method public void unregisterCallback(android.media.tv.TvInputManager.TvInputCallback);
     method public void updateTvInputInfo(android.media.tv.TvInputInfo);
     field public static final java.lang.String ACTION_BLOCKED_RATINGS_CHANGED = "android.media.tv.action.BLOCKED_RATINGS_CHANGED";
-    field public static final java.lang.String ACTION_MAKE_CHANNEL_BROWSABLE = "android.media.tv.action.MAKE_CHANNEL_BROWSABLE";
     field public static final java.lang.String ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED = "android.media.tv.action.PARENTAL_CONTROLS_ENABLED_CHANGED";
-    field public static final java.lang.String ACTION_PROGRAM_BROWSABLE_DISABLED = "android.media.tv.action.PROGRAM_BROWSABLE_DISABLED";
     field public static final java.lang.String ACTION_QUERY_CONTENT_RATING_SYSTEMS = "android.media.tv.action.QUERY_CONTENT_RATING_SYSTEMS";
     field public static final java.lang.String ACTION_SETUP_INPUTS = "android.media.tv.action.SETUP_INPUTS";
     field public static final java.lang.String ACTION_VIEW_RECORDING_SCHEDULES = "android.media.tv.action.VIEW_RECORDING_SCHEDULES";
-    field public static final java.lang.String EXTRA_CHANNEL_ID = "android.media.tv.extra.CHANNEL_ID";
-    field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.media.tv.extra.PACKAGE_NAME";
-    field public static final java.lang.String EXTRA_PROGRAM_ID = "android.media.tv.extra.PROGRAM_ID";
     field public static final int INPUT_STATE_CONNECTED = 0; // 0x0
     field public static final int INPUT_STATE_CONNECTED_STANDBY = 1; // 0x1
     field public static final int INPUT_STATE_DISCONNECTED = 2; // 0x2
@@ -24852,6 +25255,7 @@
     method public void reportNetworkConnectivity(android.net.Network, boolean);
     method public boolean requestBandwidthUpdate(android.net.Network);
     method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
+    method public void requestNetwork(android.net.NetworkRequest, int, android.net.ConnectivityManager.NetworkCallback);
     method public void requestNetwork(android.net.NetworkRequest, android.app.PendingIntent);
     method public deprecated void setNetworkPreference(int);
     method public static deprecated boolean setProcessDefaultNetwork(android.net.Network);
@@ -24899,6 +25303,7 @@
     method public void onLinkPropertiesChanged(android.net.Network, android.net.LinkProperties);
     method public void onLosing(android.net.Network, int);
     method public void onLost(android.net.Network);
+    method public void onUnavailable();
   }
 
   public static abstract interface ConnectivityManager.OnNetworkActiveListener {
@@ -24935,6 +25340,68 @@
     field public static final android.os.Parcelable.Creator<android.net.IpPrefix> CREATOR;
   }
 
+  public final class IpSecAlgorithm implements android.os.Parcelable {
+    ctor public IpSecAlgorithm(java.lang.String, byte[]);
+    ctor public IpSecAlgorithm(java.lang.String, byte[], int);
+    method public int describeContents();
+    method public byte[] getKey();
+    method public java.lang.String getName();
+    method public int getTruncationLengthBits();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final java.lang.String ALGO_AUTH_HMAC_MD5 = "hmac(md5)";
+    field public static final java.lang.String ALGO_AUTH_HMAC_SHA1 = "hmac(sha1)";
+    field public static final java.lang.String ALGO_AUTH_HMAC_SHA256 = "hmac(sha256)";
+    field public static final java.lang.String ALGO_AUTH_HMAC_SHA384 = "hmac(sha384)";
+    field public static final java.lang.String ALGO_AUTH_HMAC_SHA512 = "hmac(sha512)";
+    field public static final java.lang.String ALGO_CRYPT_AES_CBC = "cbc(aes)";
+    field public static final android.os.Parcelable.Creator<android.net.IpSecAlgorithm> CREATOR;
+  }
+
+  public final class IpSecManager {
+    method public void applyTransportModeTransform(java.net.Socket, android.net.IpSecTransform) throws java.io.IOException;
+    method public void applyTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform) throws java.io.IOException;
+    method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket(int) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
+    method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket() throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
+    method public void removeTransportModeTransform(java.net.Socket, android.net.IpSecTransform);
+    method public void removeTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform);
+    method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(java.net.InetAddress, int) throws android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
+    field public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; // 0x0
+  }
+
+  public static final class IpSecManager.ResourceUnavailableException extends android.util.AndroidException {
+  }
+
+  public static final class IpSecManager.SecurityParameterIndex implements java.lang.AutoCloseable {
+    method public void close();
+    method public int getSpi();
+  }
+
+  public static final class IpSecManager.SpiUnavailableException extends android.util.AndroidException {
+    method public int getSpi();
+  }
+
+  public static final class IpSecManager.UdpEncapsulationSocket implements java.lang.AutoCloseable {
+    method public void close();
+    method public int getPort();
+    method public java.io.FileDescriptor getSocket();
+  }
+
+  public final class IpSecTransform implements java.lang.AutoCloseable {
+    method public void close();
+    field public static final int DIRECTION_IN = 0; // 0x0
+    field public static final int DIRECTION_OUT = 1; // 0x1
+  }
+
+  public static class IpSecTransform.Builder {
+    ctor public IpSecTransform.Builder(android.content.Context);
+    method public android.net.IpSecTransform buildTransportModeTransform(java.net.InetAddress) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
+    method public android.net.IpSecTransform.Builder setAuthentication(int, android.net.IpSecAlgorithm);
+    method public android.net.IpSecTransform.Builder setEncryption(int, android.net.IpSecAlgorithm);
+    method public android.net.IpSecTransform.Builder setIpv4Encapsulation(android.net.IpSecManager.UdpEncapsulationSocket, int);
+    method public android.net.IpSecTransform.Builder setSpi(int, int);
+    method public android.net.IpSecTransform.Builder setSpi(int, android.net.IpSecManager.SecurityParameterIndex);
+  }
+
   public class LinkAddress implements android.os.Parcelable {
     method public int describeContents();
     method public java.net.InetAddress getAddress();
@@ -26115,8 +26582,6 @@
   public class DiscoverySession {
     method public java.lang.String createNetworkSpecifier(android.net.wifi.aware.PeerHandle, byte[]);
     method public void destroy();
-    method public static int getMaxSendRetryCount();
-    method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[], int);
     method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[]);
   }
 
@@ -29987,12 +30452,12 @@
     field public static final int BATTERY_PLUGGED_AC = 1; // 0x1
     field public static final int BATTERY_PLUGGED_USB = 2; // 0x2
     field public static final int BATTERY_PLUGGED_WIRELESS = 4; // 0x4
-    field public static final int BATTERY_PROPERTY_BATTERY_STATUS = 6; // 0x6
     field public static final int BATTERY_PROPERTY_CAPACITY = 4; // 0x4
     field public static final int BATTERY_PROPERTY_CHARGE_COUNTER = 1; // 0x1
     field public static final int BATTERY_PROPERTY_CURRENT_AVERAGE = 3; // 0x3
     field public static final int BATTERY_PROPERTY_CURRENT_NOW = 2; // 0x2
     field public static final int BATTERY_PROPERTY_ENERGY_COUNTER = 5; // 0x5
+    field public static final int BATTERY_PROPERTY_STATUS = 6; // 0x6
     field public static final int BATTERY_STATUS_CHARGING = 2; // 0x2
     field public static final int BATTERY_STATUS_DISCHARGING = 3; // 0x3
     field public static final int BATTERY_STATUS_FULL = 5; // 0x5
@@ -30113,7 +30578,7 @@
     ctor public Bundle(android.os.Bundle);
     ctor public Bundle(android.os.PersistableBundle);
     method public java.lang.Object clone();
-    method public android.os.Bundle deepcopy();
+    method public android.os.Bundle deepCopy();
     method public int describeContents();
     method public android.os.IBinder getBinder(java.lang.String);
     method public android.os.Bundle getBundle(java.lang.String);
@@ -30859,6 +31324,7 @@
     method public boolean match(java.lang.String);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.os.PatternMatcher> CREATOR;
+    field public static final int PATTERN_ADVANCED_GLOB = 3; // 0x3
     field public static final int PATTERN_LITERAL = 0; // 0x0
     field public static final int PATTERN_PREFIX = 1; // 0x1
     field public static final int PATTERN_SIMPLE_GLOB = 2; // 0x2
@@ -30869,7 +31335,7 @@
     ctor public PersistableBundle(int);
     ctor public PersistableBundle(android.os.PersistableBundle);
     method public java.lang.Object clone();
-    method public android.os.PersistableBundle deepcopy();
+    method public android.os.PersistableBundle deepCopy();
     method public int describeContents();
     method public android.os.PersistableBundle getPersistableBundle(java.lang.String);
     method public void putPersistableBundle(java.lang.String, android.os.PersistableBundle);
@@ -30978,6 +31444,7 @@
     method public E getBroadcastItem(int);
     method public java.lang.Object getRegisteredCallbackCookie(int);
     method public int getRegisteredCallbackCount();
+    method public E getRegisteredCallbackItem(int);
     method public void kill();
     method public void onCallbackDied(E);
     method public void onCallbackDied(E, java.lang.Object);
@@ -31374,10 +31841,8 @@
     method public void allocateBytes(java.io.File, long, int) throws java.io.IOException;
     method public void allocateBytes(java.io.FileDescriptor, long, int) throws java.io.IOException;
     method public long getAllocatableBytes(java.io.File, int) throws java.io.IOException;
-    method public long getCacheQuotaBytes();
-    method public long getCacheSizeBytes();
-    method public long getExternalCacheQuotaBytes();
-    method public long getExternalCacheSizeBytes();
+    method public long getCacheQuotaBytes(java.io.File);
+    method public long getCacheSizeBytes(java.io.File);
     method public java.lang.String getMountedObbPath(java.lang.String);
     method public android.os.storage.StorageVolume getPrimaryStorageVolume();
     method public android.os.storage.StorageVolume getStorageVolume(java.io.File);
@@ -33823,6 +34288,7 @@
     field public static final int FLAG_SUPPORTS_IS_CHILD = 16; // 0x10
     field public static final int FLAG_SUPPORTS_RECENTS = 4; // 0x4
     field public static final int FLAG_SUPPORTS_SEARCH = 8; // 0x8
+    field public static final java.lang.String MIME_TYPE_ITEM = "vnd.android.document/root";
   }
 
   public abstract class DocumentsProvider extends android.content.ContentProvider {
@@ -34389,7 +34855,7 @@
     method public static final deprecated void setLocationProviderEnabled(android.content.ContentResolver, java.lang.String, boolean);
     field public static final java.lang.String ACCESSIBILITY_DISPLAY_INVERSION_ENABLED = "accessibility_display_inversion_enabled";
     field public static final java.lang.String ACCESSIBILITY_ENABLED = "accessibility_enabled";
-    field public static final java.lang.String ACCESSIBILITY_SPEAK_PASSWORD = "speak_password";
+    field public static final deprecated java.lang.String ACCESSIBILITY_SPEAK_PASSWORD = "speak_password";
     field public static final deprecated java.lang.String ADB_ENABLED = "adb_enabled";
     field public static final java.lang.String ALLOWED_GEOLOCATION_ORIGINS = "allowed_geolocation_origins";
     field public static final deprecated java.lang.String ALLOW_MOCK_LOCATION = "mock_location";
@@ -36317,7 +36783,6 @@
     field public static final int PURPOSE_ENCRYPT = 1; // 0x1
     field public static final int PURPOSE_SIGN = 4; // 0x4
     field public static final int PURPOSE_VERIFY = 8; // 0x8
-    field public static final int PURPOSE_WRAP_KEY = 16; // 0x10
     field public static final java.lang.String SIGNATURE_PADDING_RSA_PKCS1 = "PKCS1";
     field public static final java.lang.String SIGNATURE_PADDING_RSA_PSS = "PSS";
   }
@@ -36369,6 +36834,7 @@
 
   public abstract class AutoFillService extends android.app.Service {
     ctor public AutoFillService();
+    method public final void disableSelf();
     method public final android.os.IBinder onBind(android.content.Intent);
     method public void onConnected();
     method public void onDisconnected();
@@ -36385,7 +36851,7 @@
   }
 
   public static final class Dataset.Builder {
-    ctor public Dataset.Builder(java.lang.CharSequence);
+    ctor public Dataset.Builder(android.widget.RemoteViews);
     method public android.service.autofill.Dataset build();
     method public android.service.autofill.Dataset.Builder setAuthentication(android.content.IntentSender);
     method public android.service.autofill.Dataset.Builder setValue(android.view.autofill.AutoFillId, android.view.autofill.AutoFillValue);
@@ -36405,10 +36871,10 @@
   public static final class FillResponse.Builder {
     ctor public FillResponse.Builder();
     method public android.service.autofill.FillResponse.Builder addDataset(android.service.autofill.Dataset);
-    method public android.service.autofill.FillResponse.Builder addSavableFields(android.view.autofill.AutoFillId...);
     method public android.service.autofill.FillResponse build();
-    method public android.service.autofill.FillResponse.Builder setAuthentication(android.content.IntentSender);
+    method public android.service.autofill.FillResponse.Builder setAuthentication(android.content.IntentSender, android.widget.RemoteViews);
     method public android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
+    method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo);
   }
 
   public final class SaveCallback {
@@ -36416,6 +36882,24 @@
     method public void onSuccess();
   }
 
+  public final class SaveInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.SaveInfo> CREATOR;
+    field public static final int SAVE_DATA_TYPE_ADDRESS = 2; // 0x2
+    field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 3; // 0x3
+    field public static final int SAVE_DATA_TYPE_GENERIC = 0; // 0x0
+    field public static final int SAVE_DATA_TYPE_PASSWORD = 1; // 0x1
+  }
+
+  public static final class SaveInfo.Builder {
+    ctor public SaveInfo.Builder(int);
+    method public android.service.autofill.SaveInfo.Builder addSavableIds(android.view.autofill.AutoFillId...);
+    method public android.service.autofill.SaveInfo build();
+    method public android.service.autofill.SaveInfo.Builder setDescription(java.lang.CharSequence);
+    method public android.service.autofill.SaveInfo.Builder setNegativeAction(java.lang.CharSequence, android.content.IntentSender);
+  }
+
 }
 
 package android.service.carrier {
@@ -36856,6 +37340,7 @@
     method public final void unlockAndRun(java.lang.Runnable);
     field public static final java.lang.String ACTION_QS_TILE = "android.service.quicksettings.action.QS_TILE";
     field public static final java.lang.String ACTION_QS_TILE_PREFERENCES = "android.service.quicksettings.action.QS_TILE_PREFERENCES";
+    field public static final java.lang.String EXTRA_COMPONENT = "android.service.quicksettings.extra.COMPONENT";
     field public static final java.lang.String META_DATA_ACTIVE_TILE = "android.service.quicksettings.ACTIVE_TILE";
   }
 
@@ -38063,9 +38548,11 @@
     method public android.telecom.Call.Details getDetails();
     method public android.telecom.Call getParent();
     method public java.lang.String getRemainingPostDialSequence();
+    method public android.telecom.Call.RttCall getRttCall();
     method public int getState();
     method public android.telecom.InCallService.VideoCall getVideoCall();
     method public void hold();
+    method public boolean isRttActive();
     method public void mergeConference();
     method public void phoneAccountSelected(android.telecom.PhoneAccountHandle, boolean);
     method public void playDtmfTone(char);
@@ -38077,9 +38564,12 @@
     method public void reject(boolean, java.lang.String);
     method public final void removeExtras(java.util.List<java.lang.String>);
     method public final void removeExtras(java.lang.String...);
+    method public void respondToRttRequest(int, boolean);
     method public void sendCallEvent(java.lang.String, android.os.Bundle);
+    method public void sendRttRequest();
     method public void splitFromConference();
     method public void stopDtmfTone();
+    method public void stopRtt();
     method public void swapConference();
     method public void unhold();
     method public void unregisterCallback(android.telecom.Call.Callback);
@@ -38107,6 +38597,10 @@
     method public void onDetailsChanged(android.telecom.Call, android.telecom.Call.Details);
     method public void onParentChanged(android.telecom.Call, android.telecom.Call);
     method public void onPostDialWait(android.telecom.Call, java.lang.String);
+    method public void onRttInitiationFailure(android.telecom.Call, int);
+    method public void onRttModeChanged(android.telecom.Call, int);
+    method public void onRttRequest(android.telecom.Call, int);
+    method public void onRttStatusChanged(android.telecom.Call, boolean, android.telecom.Call.RttCall);
     method public void onStateChanged(android.telecom.Call, int);
     method public void onVideoCallChanged(android.telecom.Call, android.telecom.InCallService.VideoCall);
   }
@@ -38157,9 +38651,20 @@
     field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 128; // 0x80
     field public static final int PROPERTY_HIGH_DEF_AUDIO = 16; // 0x10
     field public static final int PROPERTY_IS_EXTERNAL_CALL = 64; // 0x40
+    field public static final int PROPERTY_SELF_MANAGED = 256; // 0x100
     field public static final int PROPERTY_WIFI = 8; // 0x8
   }
 
+  public static final class Call.RttCall {
+    method public int getRttAudioMode();
+    method public java.lang.String read();
+    method public void setRttMode(int);
+    method public void write(java.lang.String) throws java.io.IOException;
+    field public static final int RTT_MODE_FULL = 1; // 0x1
+    field public static final int RTT_MODE_HCO = 2; // 0x2
+    field public static final int RTT_MODE_VCO = 3; // 0x3
+  }
+
   public final class CallAudioState implements android.os.Parcelable {
     ctor public CallAudioState(boolean, int, int);
     method public static java.lang.String audioRouteToString(int);
@@ -38359,6 +38864,15 @@
     field public static final int STATE_RINGING = 2; // 0x2
   }
 
+  public static final class Connection.RttModifyStatus {
+    ctor public Connection.RttModifyStatus();
+    field public static final int SESSION_MODIFY_REQUEST_FAIL = 2; // 0x2
+    field public static final int SESSION_MODIFY_REQUEST_INVALID = 3; // 0x3
+    field public static final int SESSION_MODIFY_REQUEST_REJECTED_BY_REMOTE = 5; // 0x5
+    field public static final int SESSION_MODIFY_REQUEST_SUCCESS = 1; // 0x1
+    field public static final int SESSION_MODIFY_REQUEST_TIMED_OUT = 4; // 0x4
+  }
+
   public static abstract class Connection.VideoProvider {
     ctor public Connection.VideoProvider();
     method public void changeCameraCapabilities(android.telecom.VideoProfile.CameraCapabilities);
@@ -38416,9 +38930,9 @@
     method public final android.os.IBinder onBind(android.content.Intent);
     method public void onConference(android.telecom.Connection, android.telecom.Connection);
     method public android.telecom.Connection onCreateIncomingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
-    method public void onCreateIncomingConnectionFailed(android.telecom.ConnectionRequest);
+    method public void onCreateIncomingConnectionFailed(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
     method public android.telecom.Connection onCreateOutgoingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
-    method public void onCreateOutgoingConnectionFailed(android.telecom.ConnectionRequest);
+    method public void onCreateOutgoingConnectionFailed(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
     method public void onRemoteConferenceAdded(android.telecom.RemoteConference);
     method public void onRemoteExistingConnectionAdded(android.telecom.RemoteConnection);
     field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.ConnectionService";
@@ -38531,6 +39045,7 @@
     field public static final int CAPABILITY_CALL_SUBJECT = 64; // 0x40
     field public static final int CAPABILITY_CONNECTION_MANAGER = 1; // 0x1
     field public static final int CAPABILITY_PLACE_EMERGENCY_CALLS = 16; // 0x10
+    field public static final int CAPABILITY_RTT = 4096; // 0x1000
     field public static final int CAPABILITY_SELF_MANAGED = 2048; // 0x800
     field public static final int CAPABILITY_SIM_SUBSCRIPTION = 4; // 0x4
     field public static final int CAPABILITY_SUPPORTS_VIDEO_CALLING = 1024; // 0x400
@@ -38699,6 +39214,8 @@
   }
 
   public class TelecomManager {
+    method public void acceptRingingCall();
+    method public void acceptRingingCall(int);
     method public void addNewIncomingCall(android.telecom.PhoneAccountHandle, android.os.Bundle);
     method public void cancelMissedCallsNotification();
     method public android.content.Intent createManageBlockedNumbersIntent();
@@ -38713,6 +39230,7 @@
     method public boolean handleMmi(java.lang.String);
     method public boolean handleMmi(java.lang.String, android.telecom.PhoneAccountHandle);
     method public boolean isInCall();
+    method public boolean isInManagedCall();
     method public boolean isIncomingCallPermitted(android.telecom.PhoneAccountHandle);
     method public boolean isOutgoingCallPermitted(android.telecom.PhoneAccountHandle);
     method public boolean isVoiceMailNumber(android.telecom.PhoneAccountHandle, java.lang.String);
@@ -38743,11 +39261,13 @@
     field public static final java.lang.String EXTRA_NOTIFICATION_PHONE_NUMBER = "android.telecom.extra.NOTIFICATION_PHONE_NUMBER";
     field public static final java.lang.String EXTRA_OUTGOING_CALL_EXTRAS = "android.telecom.extra.OUTGOING_CALL_EXTRAS";
     field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.telecom.extra.PHONE_ACCOUNT_HANDLE";
+    field public static final java.lang.String EXTRA_START_CALL_WITH_RTT = "android.telecom.extra.START_CALL_WITH_RTT";
     field public static final java.lang.String EXTRA_START_CALL_WITH_SPEAKERPHONE = "android.telecom.extra.START_CALL_WITH_SPEAKERPHONE";
     field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE";
     field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS";
     field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE";
     field public static final java.lang.String METADATA_INCLUDE_EXTERNAL_CALLS = "android.telecom.INCLUDE_EXTERNAL_CALLS";
+    field public static final java.lang.String METADATA_INCLUDE_SELF_MANAGED_CALLS = "android.telecom.INCLUDE_SELF_MANAGED_CALLS";
     field public static final java.lang.String METADATA_IN_CALL_SERVICE_RINGING = "android.telecom.IN_CALL_SERVICE_RINGING";
     field public static final java.lang.String METADATA_IN_CALL_SERVICE_UI = "android.telecom.IN_CALL_SERVICE_UI";
     field public static final int PRESENTATION_ALLOWED = 1; // 0x1
@@ -39435,6 +39955,7 @@
     method public java.lang.String getDeviceId();
     method public java.lang.String getDeviceId(int);
     method public java.lang.String getDeviceSoftwareVersion();
+    method public java.lang.String[] getForbiddenPlmns();
     method public java.lang.String getGroupIdLevel1();
     method public java.lang.String getIccAuthentication(int, int, java.lang.String);
     method public java.lang.String getLine1Number();
@@ -39516,6 +40037,7 @@
     field public static final java.lang.String EXTRA_INCOMING_NUMBER = "incoming_number";
     field public static final java.lang.String EXTRA_LAUNCH_VOICEMAIL_SETTINGS_INTENT = "android.telephony.extra.LAUNCH_VOICEMAIL_SETTINGS_INTENT";
     field public static final java.lang.String EXTRA_NOTIFICATION_COUNT = "android.telephony.extra.NOTIFICATION_COUNT";
+    field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.telephony.extra.PHONE_ACCOUNT_HANDLE";
     field public static final java.lang.String EXTRA_STATE = "state";
     field public static final java.lang.String EXTRA_STATE_IDLE;
     field public static final java.lang.String EXTRA_STATE_OFFHOOK;
@@ -40286,6 +40808,7 @@
     method public boolean hasSystemFeature(java.lang.String);
     method public boolean hasSystemFeature(java.lang.String, int);
     method public boolean isInstantApp();
+    method public boolean isInstantApp(java.lang.String);
     method public boolean isPermissionReviewModeEnabled();
     method public boolean isPermissionRevokedByPolicy(java.lang.String, java.lang.String);
     method public boolean isSafeMode();
@@ -40318,7 +40841,7 @@
 
 package android.test.suitebuilder {
 
-  public class TestMethod {
+  public deprecated class TestMethod {
     ctor public TestMethod(java.lang.reflect.Method, java.lang.Class<? extends junit.framework.TestCase>);
     ctor public TestMethod(java.lang.String, java.lang.Class<? extends junit.framework.TestCase>);
     ctor public TestMethod(junit.framework.TestCase);
@@ -40329,7 +40852,7 @@
     method public java.lang.String getName();
   }
 
-  public class TestSuiteBuilder {
+  public deprecated class TestSuiteBuilder {
     ctor public TestSuiteBuilder(java.lang.Class);
     ctor public TestSuiteBuilder(java.lang.String, java.lang.ClassLoader);
     method public android.test.suitebuilder.TestSuiteBuilder addRequirements(java.util.List<com.android.internal.util.Predicate<android.test.suitebuilder.TestMethod>>);
@@ -40342,7 +40865,7 @@
     method public android.test.suitebuilder.TestSuiteBuilder named(java.lang.String);
   }
 
-  public static class TestSuiteBuilder.FailedToCreateTests extends junit.framework.TestCase {
+  public static deprecated class TestSuiteBuilder.FailedToCreateTests extends junit.framework.TestCase {
     ctor public TestSuiteBuilder.FailedToCreateTests(java.lang.Exception);
     method public void testSuiteConstructionFailed();
   }
@@ -42558,30 +43081,51 @@
     method public abstract void setValue(T, float);
   }
 
-  public final class Half {
+  public final class Half extends java.lang.Number implements java.lang.Comparable {
+    ctor public Half(short);
+    ctor public Half(float);
+    ctor public Half(double);
+    ctor public Half(java.lang.String) throws java.lang.NumberFormatException;
     method public static short abs(short);
     method public static short ceil(short);
+    method public static int compare(short, short);
+    method public int compareTo(android.util.Half);
     method public static short copySign(short, short);
+    method public double doubleValue();
     method public static boolean equals(short, short);
+    method public float floatValue();
     method public static short floor(short);
     method public static int getExponent(short);
     method public static int getSign(short);
     method public static int getSignificand(short);
     method public static boolean greater(short, short);
     method public static boolean greaterEquals(short, short);
+    method public static int halfToIntBits(short);
+    method public static int halfToRawIntBits(short);
+    method public static short halfToShortBits(short);
+    method public short halfValue();
+    method public static int hashCode(short);
+    method public static short intBitsToHalf(int);
+    method public int intValue();
     method public static boolean isInfinite(short);
+    method public boolean isNaN();
     method public static boolean isNaN(short);
     method public static boolean isNormalized(short);
     method public static boolean less(short, short);
     method public static boolean lessEquals(short, short);
+    method public long longValue();
     method public static short max(short, short);
     method public static short min(short, short);
+    method public static short parseHalf(java.lang.String) throws java.lang.NumberFormatException;
     method public static short round(short);
     method public static float toFloat(short);
+    method public static short toHalf(float);
     method public static java.lang.String toHexString(short);
     method public static java.lang.String toString(short);
     method public static short trunc(short);
-    method public static short valueOf(float);
+    method public static android.util.Half valueOf(short);
+    method public static android.util.Half valueOf(float);
+    method public static android.util.Half valueOf(java.lang.String);
     field public static final short EPSILON = 5120; // 0x1400
     field public static final short LOWEST_VALUE = -1025; // 0xfffffbff
     field public static final int MAX_EXPONENT = 15; // 0xf
@@ -43402,6 +43946,7 @@
     field public static final int STATE_OFF = 1; // 0x1
     field public static final int STATE_ON = 2; // 0x2
     field public static final int STATE_UNKNOWN = 0; // 0x0
+    field public static final int STATE_VR = 5; // 0x5
   }
 
   public static final class Display.HdrCapabilities implements android.os.Parcelable {
@@ -43470,11 +44015,13 @@
     field public static final int DRAW_DURATION = 4; // 0x4
     field public static final int FIRST_DRAW_FRAME = 9; // 0x9
     field public static final int INPUT_HANDLING_DURATION = 1; // 0x1
+    field public static final int INTENDED_VSYNC_TIMESTAMP = 10; // 0xa
     field public static final int LAYOUT_MEASURE_DURATION = 3; // 0x3
     field public static final int SWAP_BUFFERS_DURATION = 7; // 0x7
     field public static final int SYNC_DURATION = 5; // 0x5
     field public static final int TOTAL_DURATION = 8; // 0x8
     field public static final int UNKNOWN_DELAY_DURATION = 0; // 0x0
+    field public static final int VSYNC_TIMESTAMP = 11; // 0xb
   }
 
   public abstract class FrameStats {
@@ -44849,8 +45396,8 @@
     method public void drawableHotspotChanged(float, float);
     method protected void drawableStateChanged();
     method public android.view.View findFocus();
-    method public final android.view.View findViewById(int);
-    method public final android.view.View findViewWithTag(java.lang.Object);
+    method public final <T extends android.view.View> T findViewById(int);
+    method public final <T extends android.view.View> T findViewWithTag(java.lang.Object);
     method public void findViewsWithText(java.util.ArrayList<android.view.View>, java.lang.CharSequence, int);
     method protected deprecated boolean fitSystemWindows(android.graphics.Rect);
     method public android.view.View focusSearch(int);
@@ -44865,9 +45412,11 @@
     method public float getAlpha();
     method public android.view.animation.Animation getAnimation();
     method public android.os.IBinder getApplicationWindowToken();
+    method public int getAutoFillHint();
     method public int getAutoFillMode();
-    method public android.view.autofill.AutoFillType getAutoFillType();
+    method public final deprecated android.view.autofill.AutoFillType getAutoFillType();
     method public android.view.autofill.AutoFillValue getAutoFillValue();
+    method public int getAutofillType();
     method public android.graphics.drawable.Drawable getBackground();
     method public android.content.res.ColorStateList getBackgroundTintList();
     method public android.graphics.PorterDuff.Mode getBackgroundTintMode();
@@ -44911,6 +45460,7 @@
     method protected int getHorizontalScrollbarHeight();
     method public int getId();
     method public int getImportantForAccessibility();
+    method public int getImportantForAutofill();
     method public boolean getKeepScreenOn();
     method public android.view.KeyEvent.DispatcherState getKeyDispatcherState();
     method public int getLabelFor();
@@ -44952,6 +45502,7 @@
     method public float getPivotX();
     method public float getPivotY();
     method public android.view.PointerIcon getPointerIcon();
+    method public int getResolvedAutoFillMode();
     method public android.content.res.Resources getResources();
     method public final boolean getRevealOnFocusHint();
     method public final int getRight();
@@ -45040,6 +45591,7 @@
     method public boolean isHorizontalScrollBarEnabled();
     method public boolean isHovered();
     method public boolean isImportantForAccessibility();
+    method public final boolean isImportantForAutofill();
     method public boolean isInEditMode();
     method public boolean isInLayout();
     method public boolean isInTouchMode();
@@ -45185,6 +45737,7 @@
     method public void setActivated(boolean);
     method public void setAlpha(float);
     method public void setAnimation(android.view.animation.Animation);
+    method public void setAutoFillHint(int);
     method public void setAutoFillMode(int);
     method public void setBackground(android.graphics.drawable.Drawable);
     method public void setBackgroundColor(int);
@@ -45223,6 +45776,7 @@
     method public void setHovered(boolean);
     method public void setId(int);
     method public void setImportantForAccessibility(int);
+    method public void setImportantForAutofill(int);
     method public void setKeepScreenOn(boolean);
     method public void setKeyboardNavigationCluster(boolean);
     method public void setLabelFor(int);
@@ -45326,6 +45880,25 @@
     field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
     field public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 1; // 0x1
     field public static final android.util.Property<android.view.View, java.lang.Float> ALPHA;
+    field public static final int AUTOFILL_TYPE_DATE = 4; // 0x4
+    field public static final int AUTOFILL_TYPE_LIST = 3; // 0x3
+    field public static final int AUTOFILL_TYPE_NONE = 0; // 0x0
+    field public static final int AUTOFILL_TYPE_TEXT = 1; // 0x1
+    field public static final int AUTOFILL_TYPE_TOGGLE = 2; // 0x2
+    field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_DATE = 512; // 0x200
+    field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_DAY = 4096; // 0x1000
+    field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_MONTH = 1024; // 0x400
+    field public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_YEAR = 2048; // 0x800
+    field public static final int AUTO_FILL_HINT_CREDIT_CARD_NUMBER = 128; // 0x80
+    field public static final int AUTO_FILL_HINT_CREDIT_CARD_SECURITY_CODE = 256; // 0x100
+    field public static final int AUTO_FILL_HINT_EMAIL_ADDRESS = 1; // 0x1
+    field public static final int AUTO_FILL_HINT_NAME = 2; // 0x2
+    field public static final int AUTO_FILL_HINT_NONE = 0; // 0x0
+    field public static final int AUTO_FILL_HINT_PASSWORD = 8; // 0x8
+    field public static final int AUTO_FILL_HINT_PHONE = 16; // 0x10
+    field public static final int AUTO_FILL_HINT_POSTAL_ADDRESS = 32; // 0x20
+    field public static final int AUTO_FILL_HINT_POSTAL_CODE = 64; // 0x40
+    field public static final int AUTO_FILL_HINT_USERNAME = 4; // 0x4
     field public static final int AUTO_FILL_MODE_AUTO = 1; // 0x1
     field public static final int AUTO_FILL_MODE_INHERIT = 0; // 0x0
     field public static final int AUTO_FILL_MODE_MANUAL = 2; // 0x2
@@ -45369,6 +45942,9 @@
     field public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 2; // 0x2
     field public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 4; // 0x4
     field public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 1; // 0x1
+    field public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0; // 0x0
+    field public static final int IMPORTANT_FOR_AUTOFILL_NO = 2; // 0x2
+    field public static final int IMPORTANT_FOR_AUTOFILL_YES = 1; // 0x1
     field public static final int INVISIBLE = 4; // 0x4
     field public static final int KEEP_SCREEN_ON = 67108864; // 0x4000000
     field public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
@@ -45891,6 +46467,7 @@
     method public abstract int getLayoutDirection();
     method public abstract android.view.ViewParent getParent();
     method public abstract android.view.ViewParent getParentForAccessibility();
+    method public default int getResolvedAutoFillMode();
     method public abstract int getTextAlignment();
     method public abstract int getTextDirection();
     method public abstract deprecated void invalidateChild(android.view.View, android.graphics.Rect);
@@ -45969,7 +46546,7 @@
     method public abstract int addChildCount(int);
     method public abstract void asyncCommit();
     method public abstract android.view.ViewStructure asyncNewChild(int);
-    method public abstract android.view.ViewStructure asyncNewChild(int, int, int);
+    method public abstract android.view.ViewStructure asyncNewChildForAutoFill(int, int, int);
     method public abstract int getChildCount();
     method public abstract android.os.Bundle getExtras();
     method public abstract java.lang.CharSequence getHint();
@@ -45978,12 +46555,15 @@
     method public abstract int getTextSelectionStart();
     method public abstract boolean hasExtras();
     method public abstract android.view.ViewStructure newChild(int);
-    method public abstract android.view.ViewStructure newChild(int, int, int);
+    method public abstract android.view.ViewStructure newChildForAutoFill(int, int, int);
     method public abstract void setAccessibilityFocused(boolean);
     method public abstract void setActivated(boolean);
     method public abstract void setAlpha(float);
-    method public abstract void setAutoFillType(android.view.autofill.AutoFillType);
+    method public abstract void setAutoFillHint(int);
+    method public abstract void setAutoFillOptions(java.lang.String[]);
+    method public abstract deprecated void setAutoFillType(android.view.autofill.AutoFillType);
     method public abstract void setAutoFillValue(android.view.autofill.AutoFillValue);
+    method public abstract void setAutofillType(int);
     method public abstract void setCheckable(boolean);
     method public abstract void setChecked(boolean);
     method public abstract void setChildCount(int);
@@ -45998,7 +46578,9 @@
     method public abstract void setFocused(boolean);
     method public abstract void setHint(java.lang.CharSequence);
     method public abstract void setId(int, java.lang.String, java.lang.String, java.lang.String);
+    method public abstract void setInputType(int);
     method public abstract void setLongClickable(boolean);
+    method public abstract void setSanitized(boolean);
     method public abstract void setSelected(boolean);
     method public abstract void setText(java.lang.CharSequence);
     method public abstract void setText(java.lang.CharSequence, int, int);
@@ -46007,7 +46589,6 @@
     method public abstract void setTransformation(android.graphics.Matrix);
     method public abstract void setUrl(java.lang.String);
     method public abstract void setVisibility(int);
-    field public static final int AUTO_FILL_FLAG_SANITIZED = 1; // 0x1
   }
 
   public final class ViewStub extends android.view.View {
@@ -47240,21 +47821,34 @@
   }
 
   public final class AutoFillManager {
-    method public void focusChanged(android.view.View, boolean);
+    method public void registerCallback(android.view.autofill.AutoFillManager.AutofillCallback);
     method public void reset();
+    method public void startAutoFillRequest(android.view.View);
+    method public void startAutoFillRequestOnVirtualView(android.view.View, int, android.graphics.Rect);
+    method public void stopAutoFillRequest(android.view.View);
+    method public void stopAutoFillRequestOnVirtualView(android.view.View, int);
+    method public void unregisterCallback(android.view.autofill.AutoFillManager.AutofillCallback);
     method public void valueChanged(android.view.View);
-    method public void virtualFocusChanged(android.view.View, int, android.graphics.Rect, boolean);
     method public void virtualValueChanged(android.view.View, int, android.view.autofill.AutoFillValue);
     field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE";
     field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT";
   }
 
+  public static abstract class AutoFillManager.AutofillCallback {
+    ctor public AutoFillManager.AutofillCallback();
+    method public void onAutofillEvent(android.view.View, int);
+    method public void onAutofillEventVirtual(android.view.View, int, int);
+    field public static final int EVENT_INPUT_HIDDEN = 2; // 0x2
+    field public static final int EVENT_INPUT_SHOWN = 1; // 0x1
+  }
+
   public final class AutoFillType implements android.os.Parcelable {
     method public int describeContents();
+    method public static android.view.autofill.AutoFillType forDate();
     method public static android.view.autofill.AutoFillType forList();
-    method public static android.view.autofill.AutoFillType forText(int);
+    method public static android.view.autofill.AutoFillType forText();
     method public static android.view.autofill.AutoFillType forToggle();
-    method public int getSubType();
+    method public boolean isDate();
     method public boolean isList();
     method public boolean isText();
     method public boolean isToggle();
@@ -47264,9 +47858,11 @@
 
   public final class AutoFillValue implements android.os.Parcelable {
     method public int describeContents();
+    method public static android.view.autofill.AutoFillValue forDate(long);
     method public static android.view.autofill.AutoFillValue forList(int);
     method public static android.view.autofill.AutoFillValue forText(java.lang.CharSequence);
     method public static android.view.autofill.AutoFillValue forToggle(boolean);
+    method public long getDateValue();
     method public int getListValue();
     method public java.lang.CharSequence getTextValue();
     method public boolean getToggleValue();
@@ -47710,9 +48306,9 @@
   }
 
   public abstract interface TextClassifier {
-    method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int);
-    method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int);
-    method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int);
+    method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int, android.os.LocaleList);
+    method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int, android.os.LocaleList);
+    method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int, android.os.LocaleList);
     field public static final android.view.textclassifier.TextClassifier NO_OP;
     field public static final java.lang.String TYPE_ADDRESS = "address";
     field public static final java.lang.String TYPE_EMAIL = "email";
@@ -50888,11 +51484,9 @@
     method public void removeTextChangedListener(android.text.TextWatcher);
     method public void setAllCaps(boolean);
     method public final void setAutoLinkMask(int);
-    method public void setAutoSizeMaxTextSize(int, float);
-    method public void setAutoSizeMinTextSize(int, float);
-    method public void setAutoSizeStepGranularity(int, float);
-    method public void setAutoSizeTextPresetSizes(int[]);
-    method public void setAutoSizeTextType(int);
+    method public void setAutoSizeTextTypeUniformWithConfiguration(int, int, int, int) throws java.lang.IllegalArgumentException;
+    method public void setAutoSizeTextTypeUniformWithPresetSizes(int[], int) throws java.lang.IllegalArgumentException;
+    method public void setAutoSizeTextTypeWithDefaults(int);
     method public void setBreakStrategy(int);
     method public void setCompoundDrawablePadding(int);
     method public void setCompoundDrawableTintList(android.content.res.ColorStateList);
@@ -51183,6 +51777,8 @@
     method public int resolveAdjustedSize(int, int);
     method public void resume();
     method public void seekTo(int);
+    method public void setAudioAttributes(android.media.AudioAttributes);
+    method public void setAudioFocusRequest(int);
     method public void setMediaController(android.widget.MediaController);
     method public void setOnCompletionListener(android.media.MediaPlayer.OnCompletionListener);
     method public void setOnErrorListener(android.media.MediaPlayer.OnErrorListener);
@@ -51287,7 +51883,7 @@
 
 package com.android.internal.util {
 
-  public abstract interface Predicate<T> {
+  public abstract deprecated interface Predicate<T> {
     method public abstract boolean apply(T);
   }
 
@@ -51617,7 +52213,7 @@
     method public static dalvik.system.DexFile loadDex(java.lang.String, java.lang.String, int) throws java.io.IOException;
   }
 
-  public final class InMemoryDexClassLoader extends java.lang.ClassLoader {
+  public final class InMemoryDexClassLoader extends dalvik.system.BaseDexClassLoader {
     ctor public InMemoryDexClassLoader(java.nio.ByteBuffer, java.lang.ClassLoader);
   }
 
diff --git a/api/test-removed.txt b/api/test-removed.txt
index ab22b6e..148f3f1 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -20,25 +20,14 @@
 package android.content {
 
   public abstract class Context {
-    method public deprecated android.content.Context createCredentialEncryptedStorageContext();
-    method public deprecated android.content.Context createDeviceEncryptedStorageContext();
     method public abstract android.content.SharedPreferences getSharedPreferences(java.io.File, int);
     method public abstract java.io.File getSharedPreferencesPath(java.lang.String);
-    method public deprecated boolean isCredentialEncryptedStorage();
-    method public deprecated boolean isDeviceEncryptedStorage();
-    method public deprecated boolean migrateDatabaseFrom(android.content.Context, java.lang.String);
-    method public deprecated boolean migrateSharedPreferencesFrom(android.content.Context, java.lang.String);
   }
 
 }
 
 package android.content.pm {
 
-  public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
-    field public deprecated java.lang.String credentialEncryptedDataDir;
-    field public deprecated java.lang.String deviceEncryptedDataDir;
-  }
-
   public class ComponentInfo extends android.content.pm.PackageItemInfo {
     field public deprecated boolean encryptionAware;
   }
@@ -47,12 +36,6 @@
     field public static final int REQUESTED_PERMISSION_REQUIRED = 1; // 0x1
   }
 
-  public abstract class PackageManager {
-    field public static final deprecated int MATCH_ENCRYPTION_AWARE = 524288; // 0x80000
-    field public static final deprecated int MATCH_ENCRYPTION_AWARE_AND_UNAWARE = 786432; // 0xc0000
-    field public static final deprecated int MATCH_ENCRYPTION_UNAWARE = 262144; // 0x40000
-  }
-
 }
 
 package android.database {
@@ -169,10 +152,6 @@
     method public android.graphics.drawable.Drawable getBadgedDrawableForUser(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int);
     method public android.graphics.drawable.Drawable getBadgedIconForUser(android.graphics.drawable.Drawable, android.os.UserHandle);
     method public java.lang.CharSequence getBadgedLabelForUser(java.lang.CharSequence, android.os.UserHandle);
-    method public deprecated boolean isUserRunningAndLocked();
-    method public deprecated boolean isUserRunningAndLocked(android.os.UserHandle);
-    method public deprecated boolean isUserRunningAndUnlocked();
-    method public deprecated boolean isUserRunningAndUnlocked(android.os.UserHandle);
   }
 
 }
@@ -180,21 +159,16 @@
 package android.os.storage {
 
   public class StorageManager {
+    method public deprecated long getCacheQuotaBytes();
+    method public deprecated long getCacheSizeBytes();
+    method public deprecated long getExternalCacheQuotaBytes();
+    method public deprecated long getExternalCacheSizeBytes();
     method public android.os.storage.StorageVolume getPrimaryVolume();
     method public android.os.storage.StorageVolume[] getVolumeList();
   }
 
 }
 
-package android.preference {
-
-  public class PreferenceManager {
-    method public deprecated void setStorageCredentialEncrypted();
-    method public deprecated void setStorageDeviceEncrypted();
-  }
-
-}
-
 package android.provider {
 
   public class Browser {
@@ -395,6 +369,16 @@
 
 }
 
+package android.view.textclassifier {
+
+  public abstract interface TextClassifier {
+    method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int);
+    method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int);
+    method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int);
+  }
+
+}
+
 package android.webkit {
 
   public class WebViewClient {
diff --git a/cmds/idmap/scan.cpp b/cmds/idmap/scan.cpp
index ab6adfb..8122395 100644
--- a/cmds/idmap/scan.cpp
+++ b/cmds/idmap/scan.cpp
@@ -237,3 +237,4 @@
 
     return EXIT_SUCCESS;
 }
+
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 7965fc3..91520f1 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -65,6 +65,7 @@
 import android.text.TextUtils;
 import android.text.format.DateUtils;
 import android.util.Log;
+import android.util.Pair;
 
 import com.android.internal.content.PackageHelper;
 import com.android.internal.util.ArrayUtils;
@@ -402,6 +403,7 @@
      * The use of "adb install" or "cmd package install" over "pm install" is highly encouraged.
      */
     private int runInstall() throws RemoteException {
+        long startedTime = SystemClock.elapsedRealtime();
         final InstallParams params = makeInstallParams();
         final String inPath = nextArg();
         if (params.sessionParams.sizeBytes == -1 && !STDIN_PATH.equals(inPath)) {
@@ -435,10 +437,12 @@
                     false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
                 return 1;
             }
-            if (doCommitSession(sessionId, false /*logSuccess*/)
-                    != PackageInstaller.STATUS_SUCCESS) {
+            Pair<String, Integer> status = doCommitSession(sessionId, false /*logSuccess*/);
+            if (status.second != PackageInstaller.STATUS_SUCCESS) {
                 return 1;
             }
+            Log.i(TAG, "Package " + status.first + " installed in " + (SystemClock.elapsedRealtime()
+                    - startedTime) + " ms");
             System.out.println("Success");
             return 0;
         } finally {
@@ -456,7 +460,7 @@
 
     private int runInstallCommit() throws RemoteException {
         final int sessionId = Integer.parseInt(nextArg());
-        return doCommitSession(sessionId, true /*logSuccess*/);
+        return doCommitSession(sessionId, true /*logSuccess*/).second;
     }
 
     private int runInstallCreate() throws RemoteException {
@@ -543,6 +547,12 @@
                         throw new IllegalArgumentException("Missing inherit package name");
                     }
                     break;
+                case "--pkg":
+                    sessionParams.appPackageName = nextOptionData();
+                    if (sessionParams.appPackageName == null) {
+                        throw new IllegalArgumentException("Missing package name");
+                    }
+                    break;
                 case "-S":
                     final long sizeBytes = Long.parseLong(nextOptionData());
                     if (sizeBytes <= 0) {
@@ -650,7 +660,8 @@
         }
     }
 
-    private int doCommitSession(int sessionId, boolean logSuccess) throws RemoteException {
+    private Pair<String, Integer> doCommitSession(int sessionId, boolean logSuccess)
+            throws RemoteException {
         PackageInstaller.Session session = null;
         try {
             session = new PackageInstaller.Session(
@@ -670,7 +681,7 @@
                 System.err.println("Failure ["
                         + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
             }
-            return status;
+            return new Pair<>(result.getStringExtra(PackageInstaller.EXTRA_PACKAGE_NAME), status);
         } finally {
             IoUtils.closeQuietly(session);
         }
diff --git a/cmds/uiautomator/library/Android.mk b/cmds/uiautomator/library/Android.mk
index f932388..e70bd11 100644
--- a/cmds/uiautomator/library/Android.mk
+++ b/cmds/uiautomator/library/Android.mk
@@ -49,7 +49,7 @@
     -api $(uiautomator_internal_api_file) \
     -removedApi $(uiautomator_internal_removed_api_file)
 
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR := build/tools/droiddoc/templates-sdk
+LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR := external/doclava/res/assets/templates-sdk
 LOCAL_UNINSTALLABLE_MODULE := true
 
 LOCAL_MODULE := uiautomator-stubs
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 9e486d5..b4e119e 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -52,6 +52,8 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.List;
 
+import static android.content.pm.PackageManager.FEATURE_FINGERPRINT;
+
 /**
  * Accessibility services should only be used to assist users with disabilities in using
  * Android devices and apps. They run in the background and receive callbacks by the system
@@ -618,7 +620,8 @@
      */
     @RequiresPermission(android.Manifest.permission.USE_FINGERPRINT)
     public final @Nullable FingerprintGestureController getFingerprintGestureController() {
-        if (mFingerprintGestureController == null) {
+        if ((mFingerprintGestureController == null)
+                && getPackageManager().hasSystemFeature(FEATURE_FINGERPRINT)) {
             FingerprintManager fingerprintManager = getSystemService(FingerprintManager.class);
             if ((fingerprintManager != null) && fingerprintManager.isHardwareDetected()) {
                 AccessibilityServiceInfo info = getServiceInfo();
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index e135ffd..5937dd9 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -47,6 +47,8 @@
 import java.util.Collections;
 import java.util.List;
 
+import static android.content.pm.PackageManager.FEATURE_FINGERPRINT;
+
 /**
  * This class describes an {@link AccessibilityService}. The system notifies an
  * {@link AccessibilityService} for {@link android.view.accessibility.AccessibilityEvent}s
@@ -67,10 +69,10 @@
  * @attr ref android.R.styleable#AccessibilityService_canRequestTouchExplorationMode
  * @attr ref android.R.styleable#AccessibilityService_canRetrieveWindowContent
  * @attr ref android.R.styleable#AccessibilityService_description
+ * @attr ref android.R.styleable#AccessibilityService_summary
  * @attr ref android.R.styleable#AccessibilityService_notificationTimeout
  * @attr ref android.R.styleable#AccessibilityService_packageNames
  * @attr ref android.R.styleable#AccessibilityService_settingsActivity
- *
  * @see AccessibilityService
  * @see android.view.accessibility.AccessibilityEvent
  * @see android.view.accessibility.AccessibilityManager
@@ -429,6 +431,16 @@
     private int mCapabilities;
 
     /**
+     * Resource id of the summary of the accessibility service.
+     */
+    private int mSummaryResId;
+
+    /**
+     * Non-localized summary of the accessibility service.
+     */
+    private String mNonLocalizedSummary;
+
+    /**
      * Resource id of the description of the accessibility service.
      */
     private int mDescriptionResId;
@@ -542,6 +554,15 @@
                     mNonLocalizedDescription = nonLocalizedDescription.toString().trim();
                 }
             }
+            peekedValue = asAttributes.peekValue(
+                com.android.internal.R.styleable.AccessibilityService_summary);
+            if (peekedValue != null) {
+                mSummaryResId = peekedValue.resourceId;
+                CharSequence nonLocalizedSummary = peekedValue.coerceToString();
+                if (nonLocalizedSummary != null) {
+                    mNonLocalizedSummary = nonLocalizedSummary.toString().trim();
+                }
+            }
             asAttributes.recycle();
         } catch (NameNotFoundException e) {
             throw new XmlPullParserException( "Unable to create context for: "
@@ -667,6 +688,27 @@
     }
 
     /**
+     * The localized summary of the accessibility service.
+     * <p>
+     *    <strong>Statically set from
+     *    {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong>
+     * </p>
+     * @return The localized summary.
+     */
+    public String loadSummary(PackageManager packageManager) {
+        if (mSummaryResId == 0) {
+            return mNonLocalizedSummary;
+        }
+        ServiceInfo serviceInfo = mResolveInfo.serviceInfo;
+        CharSequence summary = packageManager.getText(serviceInfo.packageName,
+                mSummaryResId, serviceInfo.applicationInfo);
+        if (summary != null) {
+            return summary.toString().trim();
+        }
+        return null;
+    }
+
+    /**
      * Gets the non-localized description of the accessibility service.
      * <p>
      *    <strong>Statically set from
@@ -724,6 +766,8 @@
         parcel.writeParcelable(mResolveInfo, 0);
         parcel.writeString(mSettingsActivityName);
         parcel.writeInt(mCapabilities);
+        parcel.writeInt(mSummaryResId);
+        parcel.writeString(mNonLocalizedSummary);
         parcel.writeInt(mDescriptionResId);
         parcel.writeString(mNonLocalizedDescription);
     }
@@ -738,6 +782,8 @@
         mResolveInfo = parcel.readParcelable(null);
         mSettingsActivityName = parcel.readString();
         mCapabilities = parcel.readInt();
+        mSummaryResId = parcel.readInt();
+        mNonLocalizedSummary = parcel.readString();
         mDescriptionResId = parcel.readInt();
         mNonLocalizedDescription = parcel.readString();
     }
@@ -788,6 +834,8 @@
         stringBuilder.append(", ");
         stringBuilder.append("settingsActivityName: ").append(mSettingsActivityName);
         stringBuilder.append(", ");
+        stringBuilder.append("summary: ").append(mNonLocalizedSummary);
+        stringBuilder.append(", ");
         appendCapabilities(stringBuilder, mCapabilities);
         return stringBuilder.toString();
     }
@@ -1042,8 +1090,7 @@
                     new CapabilityInfo(CAPABILITY_CAN_PERFORM_GESTURES,
                             R.string.capability_title_canPerformGestures,
                             R.string.capability_desc_canPerformGestures));
-            if ((context == null)
-                    || context.getSystemService(FingerprintManager.class).isHardwareDetected()) {
+            if ((context == null) || fingerprintAvailable(context)) {
                 sAvailableCapabilityInfos.put(CAPABILITY_CAN_CAPTURE_FINGERPRINT_GESTURES,
                         new CapabilityInfo(CAPABILITY_CAN_CAPTURE_FINGERPRINT_GESTURES,
                                 R.string.capability_title_canCaptureFingerprintGestures,
@@ -1053,6 +1100,10 @@
         return sAvailableCapabilityInfos;
     }
 
+    private static boolean fingerprintAvailable(Context context) {
+        return context.getPackageManager().hasSystemFeature(FEATURE_FINGERPRINT)
+                && context.getSystemService(FingerprintManager.class).isHardwareDetected();
+    }
     /**
      * @hide
      */
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index fca26f8..86adbb0 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -714,8 +714,8 @@
         mReversing = inReverse;
 
         // Now that all dependencies are set up, start the animations that should be started.
-        boolean isZeroDuration = ValueAnimator.getDurationScale() == 0f || isEmptySet(this);
-        if (!isZeroDuration) {
+        boolean isEmptySet = isEmptySet(this);
+        if (!isEmptySet) {
             startAnimation();
         }
 
@@ -727,7 +727,7 @@
                 tmpListeners.get(i).onAnimationStart(this, inReverse);
             }
         }
-        if (isZeroDuration) {
+        if (isEmptySet) {
             // In the case of empty AnimatorSet, or 0 duration scale, we will trigger the
             // onAnimationEnd() right away.
             forceToEnd();
@@ -979,7 +979,7 @@
     public boolean doAnimationFrame(long frameTime) {
         float durationScale = ValueAnimator.getDurationScale();
         if (durationScale == 0f) {
-            // Duration scale changed to 0 amid animation, end the animation right away.
+            // Duration scale is 0, end the animation right away.
             forceToEnd();
             return true;
         }
diff --git a/core/java/android/annotation/HalfFloat.java b/core/java/android/annotation/HalfFloat.java
index d3e9f08..256008c 100644
--- a/core/java/android/annotation/HalfFloat.java
+++ b/core/java/android/annotation/HalfFloat.java
@@ -37,7 +37,7 @@
  * }</pre>
  *
  * @see android.util.Half
- * @see android.util.Half#valueOf(float)
+ * @see android.util.Half#toHalf(float)
  * @see android.util.Half#toFloat(short)
  *
  * @hide
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index c56772e..0193c5f 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -844,6 +844,8 @@
 
     private boolean mHasCurrentPermissionsRequest;
 
+    private boolean mAutoFillResetNeeded;
+
     private static native String getDlWarning();
 
     /** Return the intent that started this activity. */
@@ -1780,7 +1782,7 @@
         getApplication().dispatchActivityStopped(this);
         mTranslucentCallback = null;
         mCalled = true;
-        if (isFinishing() && AutoFillManager.isClientActive(getActivityToken())) {
+        if (isFinishing() && mAutoFillResetNeeded) {
             getSystemService(AutoFillManager.class).reset();
         }
     }
@@ -2820,7 +2822,9 @@
             return;
         }
 
-        if (!mFragments.getFragmentManager().popBackStackImmediate()) {
+        FragmentManager fragmentManager = mFragments.getFragmentManager();
+
+        if (fragmentManager.isStateSaved() || !fragmentManager.popBackStackImmediate()) {
             finishAfterTransition();
         }
     }
@@ -6746,8 +6750,6 @@
         mCurrentConfig = config;
 
         mWindow.setColorMode(info.colorMode);
-
-        AutoFillManager.addClient(token, this);
     }
 
     /** @hide */
@@ -7039,7 +7041,8 @@
                 }
             }
         } else if (who.startsWith(AUTO_FILL_AUTH_WHO_PREFIX)) {
-            getSystemService(AutoFillManager.class).onAuthenticationResult(data);
+            Intent resultData = (resultCode == Activity.RESULT_OK) ? data : null;
+            getSystemService(AutoFillManager.class).onAuthenticationResult(resultData);
         } else {
             Fragment frag = mFragments.findFragmentByWho(who);
             if (frag != null) {
@@ -7213,6 +7216,12 @@
         }
     }
 
+    /** @hide */
+    @Override
+    public void resetableStateAvailable() {
+        mAutoFillResetNeeded = true;
+    }
+
     class HostCallbacks extends FragmentHostCallback<Activity> {
         public HostCallbacks() {
             super(Activity.this /*activity*/);
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index fda9966..cae37c6 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -3024,14 +3024,22 @@
 
         /**
          * Constant for {@link #importance}: This process process contains
-         * background code that is expendable.
+         * cached code that is expendable, not actively running any app components
+         * we care about.
          */
-        public static final int IMPORTANCE_BACKGROUND = 400;
+        public static final int IMPORTANCE_CACHED = 400;
+
+        /**
+         * @deprecated Renamed to {@link #IMPORTANCE_CACHED}.
+         */
+        public static final int IMPORTANCE_BACKGROUND = IMPORTANCE_CACHED;
 
         /**
          * Constant for {@link #importance}: This process is empty of any
          * actively running code.
+         * @deprecated This value is no longer reported, use {@link #IMPORTANCE_CACHED} instead.
          */
+        @Deprecated
         public static final int IMPORTANCE_EMPTY = 500;
 
         /**
@@ -3044,7 +3052,7 @@
             if (procState == PROCESS_STATE_NONEXISTENT) {
                 return IMPORTANCE_GONE;
             } else if (procState >= PROCESS_STATE_HOME) {
-                return IMPORTANCE_BACKGROUND;
+                return IMPORTANCE_CACHED;
             } else if (procState >= PROCESS_STATE_SERVICE) {
                 return IMPORTANCE_SERVICE;
             } else if (procState > PROCESS_STATE_HEAVY_WEIGHT) {
@@ -3066,7 +3074,7 @@
         public static int importanceToProcState(int importance) {
             if (importance == IMPORTANCE_GONE) {
                 return PROCESS_STATE_NONEXISTENT;
-            } else if (importance >= IMPORTANCE_BACKGROUND) {
+            } else if (importance >= IMPORTANCE_CACHED) {
                 return PROCESS_STATE_HOME;
             } else if (importance >= IMPORTANCE_SERVICE) {
                 return PROCESS_STATE_SERVICE;
@@ -3088,8 +3096,8 @@
         /**
          * The relative importance level that the system places on this
          * process.  May be one of {@link #IMPORTANCE_FOREGROUND},
-         * {@link #IMPORTANCE_VISIBLE}, {@link #IMPORTANCE_SERVICE},
-         * {@link #IMPORTANCE_BACKGROUND}, or {@link #IMPORTANCE_EMPTY}.  These
+         * {@link #IMPORTANCE_VISIBLE}, {@link #IMPORTANCE_SERVICE}, or
+         * {@link #IMPORTANCE_CACHED}.  These
          * constants are numbered so that "more important" values are always
          * smaller than "less important" values.
          */
@@ -3101,7 +3109,7 @@
          * utility of processes within a category.  This number means nothing
          * except that a smaller values are more recently used (and thus
          * more important).  Currently an LRU value is only maintained for
-         * the {@link #IMPORTANCE_BACKGROUND} category, though others may
+         * the {@link #IMPORTANCE_CACHED} category, though others may
          * be maintained in the future.
          */
         public int lru;
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 4e34552..fa64a0f 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -22,7 +22,6 @@
 import android.content.IIntentSender;
 import android.content.Intent;
 import android.content.res.Configuration;
-import android.net.NetworkPolicyManager.UidStateWithSeqObserver;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.service.voice.IVoiceInteractionSession;
@@ -234,16 +233,4 @@
      * @see android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY
      */
     public abstract void setHasOverlayUi(int pid, boolean hasOverlayUi);
-
-    /**
-     * Set observer which listens to uid state changes. Uid state change along with the sequence
-     * number associated with it needs to be passed to {@link UidStateWithSeqObserver}.
-     */
-    public abstract void setUidStateWithSeqObserver(UidStateWithSeqObserver observer);
-
-    /**
-     * Notifies that NetworkPolicyManagerService has updated the network policy rules for
-     * a specific {@param uid} and {@param procStateSeq}.
-     */
-    public abstract void notifyNetworkPolicyRulesUpdated(int uid, long procStateSeq);
 }
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index be70dcd..ce9d91f 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -180,7 +180,6 @@
     public static final boolean DEBUG_CONFIGURATION = false;
     private static final boolean DEBUG_SERVICE = false;
     private static final boolean DEBUG_MEMORY_TRIM = false;
-    private static final boolean DEBUG_NETWORK = false;
     private static final boolean DEBUG_PROVIDER = false;
     private static final boolean DEBUG_ORDER = false;
     private static final long MIN_TIME_BETWEEN_GCS = 5*1000;
@@ -203,55 +202,6 @@
     // Whether to invoke an activity callback after delivering new configuration.
     private static final boolean REPORT_TO_ACTIVITY = true;
 
-    /**
-     * This is the time main thread waits for the NetworkPolicyManagerService to notify
-     * that network is unrestricted. After this the app components will be launched anyway.
-     */
-    private long mWaitForNetworkTimeoutMs;
-
-    /**
-     * This is only for logging purposes. This will help us identify if the waiting for network
-     * is responsible for any lag that user might see.
-     */
-    private static final int WAIT_FOR_NETWORK_THRESHOLD_MS = 100; // 0.1 sec
-
-    /**
-     * State indicating that there is no need for any blocking for network.
-     */
-    public static final int NETWORK_STATE_NO_CHANGE = 0;
-
-    /**
-     * State indicating that main thread should wait for ActivityManagerService to notify
-     * before the app components are launched.
-     */
-    public static final int NETWORK_STATE_BLOCK = 1;
-
-    /**
-     * State indicating that any threads waiting for ActivityManagerService to notify should
-     * be unblocked.
-     */
-    public static final int NETWORK_STATE_UNBLOCK = 2;
-
-    /**
-     * Constant for indicating a invalid sequence number.
-     */
-    public static final long INVALID_PROC_STATE_SEQ = -1;
-
-    /**
-     * Current sequence number associated with the process state change.
-     */
-    @GuardedBy("mNetworkPolicyLock")
-    private long mCurProcStateSeq;
-
-    /**
-     * Indicates whether any component being launched should block for network before
-     * proceeding.
-     */
-    @GuardedBy("mNetworkPolicyLock")
-    private boolean mShouldBlockForNetwork;
-
-    private Object mNetworkPolicyLock = new Object();
-
     private ContextImpl mSystemContext;
 
     static volatile IPackageManager sPackageManager;
@@ -1363,18 +1313,6 @@
         }
 
         @Override
-        public void setBlockForNetworkState(int blockState, long targetProcStateSeq) {
-            synchronized (mNetworkPolicyLock) {
-                if (blockState == NETWORK_STATE_UNBLOCK) {
-                    unblockForNetworkAccessLN(targetProcStateSeq);
-                } else if (blockState == NETWORK_STATE_BLOCK) {
-                    mShouldBlockForNetwork = true;
-                }
-                mCurProcStateSeq = targetProcStateSeq;
-            }
-        }
-
-        @Override
         public void scheduleInstallProvider(ProviderInfo provider) {
             sendMessage(H.INSTALL_PROVIDER, provider);
         }
@@ -1457,13 +1395,6 @@
         public void handleTrustStorageUpdate() {
             NetworkSecurityPolicy.getInstance().handleTrustStorageUpdate();
         }
-
-        @Override
-        public void notifyNetworkStateUpdated(long curProcStateSeq) {
-            synchronized (mNetworkPolicyLock) {
-                unblockForNetworkAccessLN(curProcStateSeq);
-            }
-        }
     }
 
     private int getLifecycleSeq() {
@@ -2163,79 +2094,6 @@
         }
     }
 
-    void blockForNetworkAccessInForegroundService(long procStateSeq) {
-        synchronized (mNetworkPolicyLock) {
-            if (mCurProcStateSeq >= procStateSeq) {
-                if (mShouldBlockForNetwork) {
-                    blockForNetworkAccessLN();
-                }
-            } else {
-                mCurProcStateSeq = procStateSeq;
-                mShouldBlockForNetwork = true;
-                blockForNetworkAccessLN();
-            }
-        }
-    }
-
-    /**
-     * Block for unrestricted network. It will register a listener to AMS and wait for it to
-     * notify that network policy rules are updated. This method is called before relevant app
-     * components are launched.
-     */
-    private void blockForNetworkAccessLN() {
-        try {
-            if (ActivityManager.getService().registerNetworkRulesUpdateListener(
-                    mAppThread, mCurProcStateSeq)) {
-                try {
-                    Slog.d(TAG, "Uid: " + mBoundApplication.appInfo.uid
-                            + " seq: " + mCurProcStateSeq
-                            + ". Blocking for network. callers: " + Debug.getCallers(3));
-                    final long blockStartTime = SystemClock.elapsedRealtime();
-                    mNetworkPolicyLock.wait(mWaitForNetworkTimeoutMs);
-                    final long totalWaitTime = (SystemClock.elapsedRealtime() - blockStartTime);
-                    if (totalWaitTime >= mWaitForNetworkTimeoutMs) {
-                        Slog.wtf(TAG, "Timed out waiting for the network rules to get updated."
-                                + " Uid: " + mBoundApplication.appInfo.uid + " seq: "
-                                + mCurProcStateSeq);
-                    } else if (totalWaitTime >= WAIT_FOR_NETWORK_THRESHOLD_MS) {
-                        Slog.d(TAG, "Waited for time greater than threshold."
-                                + " Uid: " + mBoundApplication.appInfo.uid + " seq: "
-                                + mCurProcStateSeq);
-                    }
-                    if (DEBUG_NETWORK) {
-                        Slog.d(TAG, "Uid: " + mBoundApplication.appInfo.uid
-                                + " seq: " + mCurProcStateSeq
-                                + ". Time waited for network: " + totalWaitTime);
-                    }
-                } catch (InterruptedException ignored) {
-                }
-            }
-        } catch (RemoteException ignored) {
-        }
-    }
-
-    public void checkAndBlockForNetworkAccess() {
-        synchronized (mNetworkPolicyLock) {
-            if (mWaitForNetworkTimeoutMs > 0 && mShouldBlockForNetwork) {
-                blockForNetworkAccessLN();
-            }
-        }
-    }
-
-    /**
-     * Unblock the main thread if it is waiting for network.
-     */
-    private void unblockForNetworkAccessLN(long procStateSeq) {
-        if (mShouldBlockForNetwork && procStateSeq >= mCurProcStateSeq) {
-            if (DEBUG_NETWORK) {
-                Slog.d(TAG, "Unblocking threads waiting for network. uid: "
-                        + mBoundApplication.appInfo.uid + " procStateSeq: " + procStateSeq);
-            }
-            mNetworkPolicyLock.notifyAll();
-            mShouldBlockForNetwork = false;
-        }
-    }
-
     ActivityThread() {
         mResourcesManager = ResourcesManager.getInstance();
     }
@@ -2828,7 +2686,6 @@
                     activity.mIntent = customIntent;
                 }
                 r.lastNonConfigurationInstances = null;
-                checkAndBlockForNetworkAccess();
                 activity.mStartedActivity = false;
                 int theme = r.activityInfo.getThemeResource();
                 if (theme != 0) {
@@ -2916,7 +2773,7 @@
             for (int id : dm.getDisplayIds()) {
                 if (id != Display.DEFAULT_DISPLAY) {
                     Display display =
-                            dm.getCompatibleDisplay(id, appContext.getDisplayAdjustments(id));
+                            dm.getCompatibleDisplay(id, appContext.getResources());
                     appContext = (ContextImpl) appContext.createDisplayContext(display);
                     break;
                 }
@@ -5113,7 +4970,7 @@
             LoadedApk apk = ref != null ? ref.get() : null;
             if (apk != null) {
                 final ArrayList<String> oldPaths = new ArrayList<>();
-                LoadedApk.makePaths(this, apk.getApplicationInfo(), oldPaths, null /*outLibPaths*/);
+                LoadedApk.makePaths(this, apk.getApplicationInfo(), oldPaths);
                 apk.updateApplicationInfo(ai, oldPaths);
             }
 
@@ -5121,7 +4978,7 @@
             apk = ref != null ? ref.get() : null;
             if (apk != null) {
                 final ArrayList<String> oldPaths = new ArrayList<>();
-                LoadedApk.makePaths(this, apk.getApplicationInfo(), oldPaths, null /*outLibPaths*/);
+                LoadedApk.makePaths(this, apk.getApplicationInfo(), oldPaths);
                 apk.updateApplicationInfo(ai, oldPaths);
             }
 
@@ -5564,9 +5421,6 @@
         View.mDebugViewAttributes =
                 mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0;
 
-        mWaitForNetworkTimeoutMs = mCoreSettings.getLong(
-                Settings.Global.WAIT_FOR_NETWORK_TIMEOUT_MS);
-
         /**
          * For system applications on userdebug/eng builds, log stack
          * traces of disk and network access to dropbox for analysis.
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 6dd31a8..0f2ce3c 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -249,8 +249,10 @@
     public static final int OP_ENTER_PICTURE_IN_PICTURE_ON_HIDE = 67;
     /** @hide Instant app start foreground service. */
     public static final int OP_INSTANT_APP_START_FOREGROUND = 68;
+    /** @hide Answer incoming phone calls */
+    public static final int OP_ANSWER_PHONE_CALLS = 69;
     /** @hide */
-    public static final int _NUM_OP = 69;
+    public static final int _NUM_OP = 70;
 
     /** Access to coarse location information. */
     public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -356,6 +358,9 @@
     /** @hide */
     public static final String OPSTR_INSTANT_APP_START_FOREGROUND
             = "android:instant_app_start_foreground";
+    /** Answer incoming phone calls */
+    public static final String OPSTR_ANSWER_PHONE_CALLS
+            = "android:answer_phone_calls";
 
     private static final int[] RUNTIME_AND_APPOP_PERMISSIONS_OPS = {
             // RUNTIME PERMISSIONS
@@ -388,6 +393,7 @@
             OP_ADD_VOICEMAIL,
             OP_USE_SIP,
             OP_PROCESS_OUTGOING_CALLS,
+            OP_ANSWER_PHONE_CALLS,
             // Microphone
             OP_RECORD_AUDIO,
             // Camera
@@ -480,6 +486,7 @@
             OP_REQUEST_INSTALL_PACKAGES,
             OP_ENTER_PICTURE_IN_PICTURE_ON_HIDE,
             OP_INSTANT_APP_START_FOREGROUND,
+            OP_ANSWER_PHONE_CALLS
     };
 
     /**
@@ -556,6 +563,7 @@
             null, // OP_REQUEST_INSTALL_PACKAGES
             null,
             OPSTR_INSTANT_APP_START_FOREGROUND,
+            OPSTR_ANSWER_PHONE_CALLS,
     };
 
     /**
@@ -632,6 +640,7 @@
             "REQUEST_INSTALL_PACKAGES",
             "OP_ENTER_PICTURE_IN_PICTURE_ON_HIDE",
             "INSTANT_APP_START_FOREGROUND",
+            "ANSWER_PHONE_CALLS",
     };
 
     /**
@@ -708,6 +717,7 @@
             Manifest.permission.REQUEST_INSTALL_PACKAGES,
             null, // no permission for entering picture-in-picture on hide
             Manifest.permission.INSTANT_APP_FOREGROUND_SERVICE,
+            Manifest.permission.ANSWER_PHONE_CALLS,
     };
 
     /**
@@ -785,6 +795,7 @@
             null, // REQUEST_INSTALL_PACKAGES
             null, // ENTER_PICTURE_IN_PICTURE_ON_HIDE
             null, // INSTANT_APP_START_FOREGROUND
+            null, // ANSWER_PHONE_CALLS
     };
 
     /**
@@ -861,6 +872,7 @@
             false, // REQUEST_INSTALL_PACKAGES
             false, // ENTER_PICTURE_IN_PICTURE_ON_HIDE
             false, // INSTANT_APP_START_FOREGROUND
+            false, // ANSWER_PHONE_CALLS
     };
 
     /**
@@ -936,6 +948,7 @@
             AppOpsManager.MODE_DEFAULT,  // OP_REQUEST_INSTALL_PACKAGES
             AppOpsManager.MODE_ALLOWED,  // OP_ENTER_PICTURE_IN_PICTURE_ON_HIDE
             AppOpsManager.MODE_DEFAULT,  // OP_INSTANT_APP_START_FOREGROUND
+            AppOpsManager.MODE_ALLOWED, // ANSWER_PHONE_CALLS
     };
 
     /**
@@ -1015,6 +1028,7 @@
             false, // OP_REQUEST_INSTALL_PACKAGES
             false, // OP_ENTER_PICTURE_IN_PICTURE_ON_HIDE
             false,
+            false, // ANSWER_PHONE_CALLS
     };
 
     /**
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 1652299..97992ca 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -65,6 +65,7 @@
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.LayerDrawable;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -805,9 +806,13 @@
 
     @Override
     public boolean isInstantApp() {
+        return isInstantApp(mContext.getPackageName());
+    }
+
+    @Override
+    public boolean isInstantApp(String packageName) {
         try {
-            return mPM.isInstantApp(mContext.getPackageName(),
-                    mContext.getUserId());
+            return mPM.isInstantApp(packageName, mContext.getUserId());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1024,12 +1029,18 @@
     }
 
     @Override
-    @SuppressWarnings("unchecked")
     public List<ProviderInfo> queryContentProviders(String processName,
             int uid, int flags) {
+        return queryContentProviders(processName, uid, flags, null);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public List<ProviderInfo> queryContentProviders(String processName,
+            int uid, int flags, String metaDataKey) {
         try {
             ParceledListSlice<ProviderInfo> slice =
-                    mPM.queryContentProviders(processName, uid, flags);
+                    mPM.queryContentProviders(processName, uid, flags, metaDataKey);
             return slice != null ? slice.getList() : Collections.<ProviderInfo>emptyList();
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -2119,10 +2130,15 @@
     @Override
     public void getPackageSizeInfoAsUser(String packageName, int userHandle,
             IPackageStatsObserver observer) {
-        try {
-            mPM.getPackageSizeInfo(packageName, userHandle, observer);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
+        if (mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.O) {
+            throw new UnsupportedOperationException(
+                    "Shame on you for calling a hidden API. Shame!");
+        } else if (observer != null) {
+            Log.d(TAG, "Shame on you for calling a hidden API. Shame!");
+            try {
+                observer.onGetStatsCompleted(null, false);
+            } catch (RemoteException ignored) {
+            }
         }
     }
 
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 045bd0a..0ab4b80 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -38,6 +38,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.AssetManager;
+import android.content.res.CompatResources;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
@@ -49,6 +50,7 @@
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Build;
+import android.os.Build.VERSION_CODES;
 import android.os.Bundle;
 import android.os.Debug;
 import android.os.Environment;
@@ -1925,8 +1927,8 @@
             final int displayId = mDisplay != null
                     ? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY;
 
-            c.mResources = createResources(mActivityToken, pi, displayId, null,
-                    getDisplayAdjustments(displayId).getCompatibilityInfo());
+            c.setResources(createResources(mActivityToken, pi, displayId, null,
+                    getDisplayAdjustments(displayId).getCompatibilityInfo()));
             if (c.mResources != null) {
                 return c;
             }
@@ -1962,8 +1964,8 @@
             final int displayId = mDisplay != null
                     ? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY;
 
-            c.mResources = createResources(mActivityToken, pi, displayId, null,
-                    getDisplayAdjustments(displayId).getCompatibilityInfo());
+            c.setResources(createResources(mActivityToken, pi, displayId, null,
+                    getDisplayAdjustments(displayId).getCompatibilityInfo()));
             if (c.mResources != null) {
                 return c;
             }
@@ -1990,7 +1992,7 @@
         final int displayId = mDisplay != null
                 ? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY;
 
-        context.mResources = ResourcesManager.getInstance().getResources(
+        context.setResources(ResourcesManager.getInstance().getResources(
                 mActivityToken,
                 mPackageInfo.getResDir(),
                 paths,
@@ -1999,7 +2001,7 @@
                 displayId,
                 null,
                 mPackageInfo.getCompatibilityInfo(),
-                classLoader);
+                classLoader));
         return context;
     }
 
@@ -2013,8 +2015,8 @@
                 mUser, mFlags, mClassLoader);
 
         final int displayId = mDisplay != null ? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY;
-        context.mResources = createResources(mActivityToken, mPackageInfo, displayId,
-                overrideConfiguration, getDisplayAdjustments(displayId).getCompatibilityInfo());
+        context.setResources(createResources(mActivityToken, mPackageInfo, displayId,
+                overrideConfiguration, getDisplayAdjustments(displayId).getCompatibilityInfo()));
         return context;
     }
 
@@ -2028,8 +2030,8 @@
                 mUser, mFlags, mClassLoader);
 
         final int displayId = display.getDisplayId();
-        context.mResources = createResources(mActivityToken, mPackageInfo, displayId, null,
-                getDisplayAdjustments(displayId).getCompatibilityInfo());
+        context.setResources(createResources(mActivityToken, mPackageInfo, displayId, null,
+                getDisplayAdjustments(displayId).getCompatibilityInfo()));
         context.mDisplay = display;
         return context;
     }
@@ -2067,24 +2069,17 @@
 
     @Override
     public Display getDisplay() {
-        final DisplayAdjustments displayAdjustments = mResources.getDisplayAdjustments();
         if (mDisplay == null) {
             return mResourcesManager.getAdjustedDisplay(Display.DEFAULT_DISPLAY,
-                    displayAdjustments);
+                    mResources);
         }
 
-        if (!mDisplay.getDisplayAdjustments().equals(displayAdjustments)) {
-            mDisplay = mResourcesManager.getAdjustedDisplay(mDisplay.getDisplayId(),
-                    displayAdjustments);
-        }
         return mDisplay;
     }
 
     @Override
     public void updateDisplay(int displayId) {
-        final DisplayAdjustments displayAdjustments = mResources.getDisplayAdjustments();
-        mDisplay = mResourcesManager.getAdjustedDisplay(displayId,
-                displayAdjustments);
+        mDisplay = mResourcesManager.getAdjustedDisplay(displayId, mResources);
     }
 
     @Override
@@ -2143,7 +2138,7 @@
         LoadedApk packageInfo = new LoadedApk(mainThread);
         ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, 0,
                 null);
-        context.mResources = packageInfo.getResources();
+        context.setResources(packageInfo.getResources());
         context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
                 context.mResourcesManager.getDisplayMetrics());
         return context;
@@ -2153,7 +2148,7 @@
         if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
         ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, 0,
                 null);
-        context.mResources = packageInfo.getResources();
+        context.setResources(packageInfo.getResources());
         return context;
     }
 
@@ -2192,7 +2187,7 @@
 
         // Create the base resources for which all configuration contexts for this Activity
         // will be rebased upon.
-        context.mResources = resourcesManager.createBaseActivityResources(activityToken,
+        context.setResources(resourcesManager.createBaseActivityResources(activityToken,
                 packageInfo.getResDir(),
                 splitDirs,
                 packageInfo.getOverlayDirs(),
@@ -2200,9 +2195,9 @@
                 displayId,
                 overrideConfiguration,
                 compatInfo,
-                classLoader);
+                classLoader));
         context.mDisplay = resourcesManager.getAdjustedDisplay(displayId,
-                context.mResources.getDisplayAdjustments());
+                context.getResources());
         return context;
     }
 
@@ -2239,7 +2234,7 @@
         if (container != null) {
             mBasePackageName = container.mBasePackageName;
             mOpPackageName = container.mOpPackageName;
-            mResources = container.mResources;
+            setResources(container.mResources);
             mDisplay = container.mDisplay;
         } else {
             mBasePackageName = packageInfo.mPackageName;
@@ -2258,6 +2253,13 @@
         mContentResolver = new ApplicationContentResolver(this, mainThread, user);
     }
 
+    void setResources(Resources r) {
+        if (r instanceof CompatResources) {
+            ((CompatResources) r).setContext(this);
+        }
+        mResources = r;
+    }
+
     void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
         mPackageInfo.installSystemApplicationInfo(info, classLoader);
     }
diff --git a/core/java/android/app/EphemeralResolveInfo.aidl b/core/java/android/app/EphemeralResolveInfo.aidl
index db71d25..fe28081 100644
--- a/core/java/android/app/EphemeralResolveInfo.aidl
+++ b/core/java/android/app/EphemeralResolveInfo.aidl
@@ -16,4 +16,5 @@
 
 package android.app;
 
+/** @deprecated */
 parcelable EphemeralResolveInfo;
diff --git a/core/java/android/app/EphemeralResolverService.java b/core/java/android/app/EphemeralResolverService.java
index 45652ef..445d3bd 100644
--- a/core/java/android/app/EphemeralResolverService.java
+++ b/core/java/android/app/EphemeralResolverService.java
@@ -18,9 +18,11 @@
 
 import android.annotation.SystemApi;
 import android.app.Service;
+import android.app.InstantAppResolverService.InstantAppResolutionCallback;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.EphemeralResolveInfo;
+import android.content.pm.InstantAppResolveInfo;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -29,20 +31,17 @@
 import android.os.Message;
 import android.os.RemoteException;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
  * Base class for implementing the resolver service.
  * @hide
+ * @deprecated use InstantAppResolverService instead
  */
+@Deprecated
 @SystemApi
-public abstract class EphemeralResolverService extends Service {
-    public static final String EXTRA_RESOLVE_INFO = "android.app.extra.RESOLVE_INFO";
-    public static final String EXTRA_SEQUENCE = "android.app.extra.SEQUENCE";
-    private static final String EXTRA_PREFIX = "android.app.PREFIX";
-    private static final String EXTRA_HOSTNAME = "android.app.HOSTNAME";
-    private Handler mHandler;
-
+public abstract class EphemeralResolverService extends InstantAppResolverService {
     /**
      * Called to retrieve resolve info for ephemeral applications.
      *
@@ -74,90 +73,28 @@
         throw new IllegalStateException("Must define");
     }
 
-    /**
-     * Returns a {@link Looper} to perform service operations on.
-     */
+    @Override
     public Looper getLooper() {
-        return getBaseContext().getMainLooper();
+        return super.getLooper();
     }
 
     @Override
-    public final void attachBaseContext(Context base) {
-        super.attachBaseContext(base);
-        mHandler = new ServiceHandler(getLooper());
+    void _onGetInstantAppResolveInfo(int[] digestPrefix, InstantAppResolutionCallback callback) {
+        final List<EphemeralResolveInfo> response = onGetEphemeralResolveInfo(digestPrefix);
+        final int responseSize = response == null ? 0 : response.size();
+        final List<InstantAppResolveInfo> resultList = new ArrayList<>(responseSize);
+        for (int i = 0; i < responseSize; i++) {
+            resultList.add(response.get(i).getInstantAppResolveInfo());
+        }
+        callback.onInstantAppResolveInfo(resultList);
     }
 
     @Override
-    public final IBinder onBind(Intent intent) {
-        return new IEphemeralResolver.Stub() {
-            @Override
-            public void getEphemeralResolveInfoList(
-                    IRemoteCallback callback, int digestPrefix[], int sequence) {
-                final Message msg = mHandler.obtainMessage(
-                        ServiceHandler.MSG_GET_EPHEMERAL_RESOLVE_INFO, sequence, 0, callback);
-                final Bundle data = new Bundle();
-                data.putIntArray(EXTRA_PREFIX, digestPrefix);
-                msg.setData(data);
-                msg.sendToTarget();
-            }
-
-            @Override
-            public void getEphemeralIntentFilterList(
-                    IRemoteCallback callback, String hostName, int sequence) {
-                final Message msg = mHandler.obtainMessage(
-                        ServiceHandler.MSG_GET_EPHEMERAL_INTENT_FILTER, sequence, 0, callback);
-                final Bundle data = new Bundle();
-                data.putString(EXTRA_HOSTNAME, hostName);
-                msg.setData(data);
-                msg.sendToTarget();
-            }
-        };
-    }
-
-    private final class ServiceHandler extends Handler {
-        public static final int MSG_GET_EPHEMERAL_RESOLVE_INFO = 1;
-        public static final int MSG_GET_EPHEMERAL_INTENT_FILTER = 2;
-
-        public ServiceHandler(Looper looper) {
-            super(looper, null /*callback*/, true /*async*/);
-        }
-
-        @Override
-        @SuppressWarnings("unchecked")
-        public void handleMessage(Message message) {
-            final int action = message.what;
-            switch (action) {
-                case MSG_GET_EPHEMERAL_RESOLVE_INFO: {
-                    final IRemoteCallback callback = (IRemoteCallback) message.obj;
-                    final int[] digestPrefix = message.getData().getIntArray(EXTRA_PREFIX);
-                    final List<EphemeralResolveInfo> resolveInfo =
-                            onGetEphemeralResolveInfo(digestPrefix);
-                    final Bundle data = new Bundle();
-                    data.putInt(EXTRA_SEQUENCE, message.arg1);
-                    data.putParcelableList(EXTRA_RESOLVE_INFO, resolveInfo);
-                    try {
-                        callback.sendResult(data);
-                    } catch (RemoteException e) {
-                    }
-                } break;
-
-                case MSG_GET_EPHEMERAL_INTENT_FILTER: {
-                    final IRemoteCallback callback = (IRemoteCallback) message.obj;
-                    final String hostName = message.getData().getString(EXTRA_HOSTNAME);
-                    final EphemeralResolveInfo resolveInfo = onGetEphemeralIntentFilter(hostName);
-                    final Bundle data = new Bundle();
-                    data.putInt(EXTRA_SEQUENCE, message.arg1);
-                    data.putParcelable(EXTRA_RESOLVE_INFO, resolveInfo);
-                    try {
-                        callback.sendResult(data);
-                    } catch (RemoteException e) {
-                    }
-                } break;
-
-                default: {
-                    throw new IllegalArgumentException("Unknown message: " + action);
-                }
-            }
-        }
+    void _onGetInstantAppIntentFilter(int[] digestPrefix, String hostName,
+            InstantAppResolutionCallback callback) {
+        final EphemeralResolveInfo response = onGetEphemeralIntentFilter(hostName);
+        final List<InstantAppResolveInfo> resultList = new ArrayList<>(1);
+        resultList.add(response.getInstantAppResolveInfo());
+        callback.onInstantAppResolveInfo(resultList);
     }
 }
diff --git a/core/java/android/app/FragmentHostCallback.java b/core/java/android/app/FragmentHostCallback.java
index 7e415e9..41a885e 100644
--- a/core/java/android/app/FragmentHostCallback.java
+++ b/core/java/android/app/FragmentHostCallback.java
@@ -308,13 +308,11 @@
             mAllLoaderManagers = new ArrayMap<String, LoaderManager>();
         }
         LoaderManagerImpl lm = (LoaderManagerImpl) mAllLoaderManagers.get(who);
-        if (lm == null) {
-            if (create) {
-                lm = new LoaderManagerImpl(who, this, started);
-                mAllLoaderManagers.put(who, lm);
-            }
-        } else {
-            lm.updateHostController(this);
+        if (lm == null && create) {
+            lm = new LoaderManagerImpl(who, this, started);
+            mAllLoaderManagers.put(who, lm);
+        } else if (started && lm != null && !lm.mStarted){
+            lm.doStart();
         }
         return lm;
     }
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index d32cf3c..0672e3b 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -397,6 +397,19 @@
     public void invalidateOptionsMenu() { }
 
     /**
+     * Returns {@code true} if the FragmentManager's state has already been saved
+     * by its host. Any operations that would change saved state should not be performed
+     * if this method returns true. For example, any popBackStack() method, such as
+     * {@link #popBackStackImmediate()} or any FragmentTransaction using
+     * {@link FragmentTransaction#commit()} instead of
+     * {@link FragmentTransaction#commitAllowingStateLoss()} will change
+     * the state and will result in an error.
+     *
+     * @return true if this FragmentManager's state has already been saved by its host
+     */
+    public abstract boolean isStateSaved();
+
+    /**
      * Callback interface for listening to fragment state changes that happen
      * within a given FragmentManager.
      */
@@ -1523,12 +1536,14 @@
             boolean loadersRunning = false;
 
             // Must add them in the proper order. mActive fragments may be out of order
-            final int numAdded = mAdded.size();
-            for (int i = 0; i < numAdded; i++) {
-                Fragment f = mAdded.get(i);
-                moveFragmentToExpectedState(f);
-                if (f.mLoaderManager != null) {
-                    loadersRunning |= f.mLoaderManager.hasRunningLoaders();
+            if (mAdded != null) {
+                final int numAdded = mAdded.size();
+                for (int i = 0; i < numAdded; i++) {
+                    Fragment f = mAdded.get(i);
+                    moveFragmentToExpectedState(f);
+                    if (f.mLoaderManager != null) {
+                        loadersRunning |= f.mLoaderManager.hasRunningLoaders();
+                    }
                 }
             }
 
@@ -1787,6 +1802,7 @@
         }
     }
 
+    @Override
     public boolean isStateSaved() {
         return mStateSaved;
     }
@@ -1911,7 +1927,12 @@
             mTmpRecords = new ArrayList<>();
             mTmpIsPop = new ArrayList<>();
         }
-        executePostponedTransaction(null, null);
+        mExecutingActions = true;
+        try {
+            executePostponedTransaction(null, null);
+        } finally {
+            mExecutingActions = false;
+        }
     }
 
     public void execSingleAction(OpGenerator action, boolean allowStateLoss) {
@@ -2802,40 +2823,56 @@
     
     public void dispatchCreate() {
         mStateSaved = false;
+        mExecutingActions = true;
         moveToState(Fragment.CREATED, false);
+        mExecutingActions = false;
     }
     
     public void dispatchActivityCreated() {
         mStateSaved = false;
+        mExecutingActions = true;
         moveToState(Fragment.ACTIVITY_CREATED, false);
+        mExecutingActions = false;
     }
     
     public void dispatchStart() {
         mStateSaved = false;
+        mExecutingActions = true;
         moveToState(Fragment.STARTED, false);
+        mExecutingActions = false;
     }
     
     public void dispatchResume() {
         mStateSaved = false;
+        mExecutingActions = true;
         moveToState(Fragment.RESUMED, false);
+        mExecutingActions = false;
     }
     
     public void dispatchPause() {
+        mExecutingActions = true;
         moveToState(Fragment.STARTED, false);
+        mExecutingActions = false;
     }
     
     public void dispatchStop() {
+        mExecutingActions = true;
         moveToState(Fragment.STOPPED, false);
+        mExecutingActions = false;
     }
     
     public void dispatchDestroyView() {
+        mExecutingActions = true;
         moveToState(Fragment.CREATED, false);
+        mExecutingActions = false;
     }
 
     public void dispatchDestroy() {
         mDestroyed = true;
         execPendingActions();
+        mExecutingActions = true;
         moveToState(Fragment.INITIALIZING, false);
+        mExecutingActions = false;
         mHost = null;
         mContainer = null;
         mParent = null;
diff --git a/core/java/android/app/FragmentTransition.java b/core/java/android/app/FragmentTransition.java
index f62ab8d..780a922 100644
--- a/core/java/android/app/FragmentTransition.java
+++ b/core/java/android/app/FragmentTransition.java
@@ -780,8 +780,10 @@
             names = inTransaction.mSharedElementTargetNames;
         }
 
-        inSharedElements.retainAll(names);
-        if (sharedElementCallback != null) {
+        if (names != null) {
+            inSharedElements.retainAll(names);
+        }
+        if (names != null && sharedElementCallback != null) {
             sharedElementCallback.onMapSharedElements(names, inSharedElements);
             for (int i = names.size() - 1; i >= 0; i--) {
                 String name = names.get(i);
@@ -830,8 +832,9 @@
             FragmentContainerTransition fragments,
             Transition enterTransition, boolean inIsPop) {
         BackStackRecord inTransaction = fragments.lastInTransaction;
-        if (enterTransition != null && inTransaction.mSharedElementSourceNames != null &&
-                !inTransaction.mSharedElementSourceNames.isEmpty()) {
+        if (enterTransition != null && inSharedElements != null
+                && inTransaction.mSharedElementSourceNames != null
+                && !inTransaction.mSharedElementSourceNames.isEmpty()) {
             final String targetName = inIsPop
                     ? inTransaction.mSharedElementSourceNames.get(0)
                     : inTransaction.mSharedElementTargetNames.get(0);
@@ -1096,7 +1099,9 @@
         if (transition != null) {
             viewList = new ArrayList<>();
             View root = fragment.getView();
-            root.captureTransitioningViews(viewList);
+            if (root != null) {
+                root.captureTransitioningViews(viewList);
+            }
             if (sharedElements != null) {
                 viewList.removeAll(sharedElements);
             }
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 6717491..152d514 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -199,7 +199,7 @@
     int getRequestedOrientation(in IBinder token);
     void unbindFinished(in IBinder token, in Intent service, boolean doRebind);
     void setProcessForeground(in IBinder token, int pid, boolean isForeground);
-    long setServiceForeground(in ComponentName className, in IBinder token,
+    void setServiceForeground(in ComponentName className, in IBinder token,
             int id, in Notification notification, int flags);
     boolean moveActivityTaskToBack(in IBinder token, boolean nonRoot);
     void getMemoryInfo(out ActivityManager.MemoryInfo outInfo);
@@ -475,7 +475,7 @@
     void reportSizeConfigurations(in IBinder token, in int[] horizontalSizeConfiguration,
             in int[] verticalSizeConfigurations, in int[] smallestWidthConfigurations);
     boolean moveTaskToDockedStack(int taskId, int createMode, boolean toTop, boolean animate,
-            in Rect initialBounds, boolean moveHomeStackFront);
+            in Rect initialBounds);
     void suppressResizeConfigChanges(boolean suppress);
     void moveTasksToFullscreenStack(int fromStackId, boolean onTop);
     boolean moveTopActivityToPinnedStack(int stackId, in Rect bounds);
@@ -522,6 +522,7 @@
     void startLocalVoiceInteraction(in IBinder token, in Bundle options);
     void stopLocalVoiceInteraction(in IBinder token);
     boolean supportsLocalVoiceInteraction();
+    void notifyPinnedStackAnimationStarted();
     void notifyPinnedStackAnimationEnded();
     void removeStack(int stackId);
     void makePackageIdle(String packageName, int userId);
@@ -604,16 +605,6 @@
     ActivityManager.TaskSnapshot getTaskSnapshot(int taskId);
 
     void scheduleApplicationInfoChanged(in List<String> packageNames, int userId);
-     /**
-      * Registers a listener for network rules state. When the network policy rules in
-      * NetworkPolicyManagerService are updated, ActivityManagerService will notify these
-      * registered listeners.
-      *
-      * @param procStateSeq The sequence number for which the listener is interested in knowing
-      *                     the network policy rules state.
-      * @return true if the listener is registered, false otherwise.
-      */
-    boolean registerNetworkRulesUpdateListener(IApplicationThread listener, long procStateSeq);
 
     // WARNING: when these transactions are updated, check if they are any callers on the native
     // side. If so, make sure they are using the correct transaction ids and arguments.
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index 1735572..d5b4668 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -154,6 +154,4 @@
     void handleTrustStorageUpdate();
     void attachAgent(String path);
     void scheduleApplicationInfoChanged(in ApplicationInfo ai);
-    void setBlockForNetworkState(int blockState, long procStateSeq);
-    void notifyNetworkStateUpdated(long procStateSeq);
 }
diff --git a/core/java/android/app/IEphemeralResolver.aidl b/core/java/android/app/IEphemeralResolver.aidl
index 260b80c..734ad9e 100644
--- a/core/java/android/app/IEphemeralResolver.aidl
+++ b/core/java/android/app/IEphemeralResolver.aidl
@@ -18,7 +18,7 @@
 
 import android.os.IRemoteCallback;
 
-/** @hide */
+/** @hide @deprecated */
 oneway interface IEphemeralResolver {
     void getEphemeralResolveInfoList(IRemoteCallback callback, in int[] digestPrefix,
             int sequence);
diff --git a/core/java/com/android/internal/logging/legacy/Util.java b/core/java/android/app/IInstantAppResolver.aidl
similarity index 62%
copy from core/java/com/android/internal/logging/legacy/Util.java
copy to core/java/android/app/IInstantAppResolver.aidl
index 99f71ca..04e321f 100644
--- a/core/java/com/android/internal/logging/legacy/Util.java
+++ b/core/java/android/app/IInstantAppResolver.aidl
@@ -13,13 +13,16 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.internal.logging.legacy;
 
-/**
- * Created by cwren on 11/21/16.
- */
-public class Util {
-    public static boolean debug() {
-        return false;
-    }
+package android.app;
+
+import android.os.IRemoteCallback;
+
+/** @hide */
+oneway interface IInstantAppResolver {
+    void getInstantAppResolveInfoList(in int[] digestPrefix,
+            int sequence, IRemoteCallback callback);
+
+    void getInstantAppIntentFilterList(in int[] digestPrefix,
+            int sequence, String hostName, IRemoteCallback callback);
 }
diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl
index 9834350..5768d1a 100644
--- a/core/java/android/app/ITaskStackListener.aidl
+++ b/core/java/android/app/ITaskStackListener.aidl
@@ -31,11 +31,13 @@
      * Called whenever IActivityManager.startActivity is called on an activity that is already
      * running in the pinned stack and the activity is not actually started, but the task is either
      * brought to the front or a new Intent is delivered to it.
-     *
-     * @param launchedFromPackage the package name of the activity that initiated the restart
-     *                            attempt
      */
-    void onPinnedActivityRestartAttempt(String launchedFromPackage);
+    void onPinnedActivityRestartAttempt();
+
+    /**
+     * Called whenever the pinned stack is starting animating a resize.
+     */
+    void onPinnedStackAnimationStarted();
 
     /**
      * Called whenever the pinned stack is done animating a resize.
diff --git a/graphics/tests/graphicstests/res/values/colors.xml b/core/java/android/app/InstantAppResolveInfo.aidl
similarity index 67%
rename from graphics/tests/graphicstests/res/values/colors.xml
rename to core/java/android/app/InstantAppResolveInfo.aidl
index 7559e65..440e542 100644
--- a/graphics/tests/graphicstests/res/values/colors.xml
+++ b/core/java/android/app/InstantAppResolveInfo.aidl
@@ -1,7 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2006, The Android Open Source Project
+/*
+** 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.
@@ -15,10 +13,7 @@
 ** See the License for the specific language governing permissions and
 ** limitations under the License.
 */
--->
-<resources>
-    <color name="testcolor1">#ff00ff00</color>
-    <color name="testcolor2">#ffff0000</color>
-    <color name="failColor">#ff0000ff</color>
-</resources>
 
+package android.app;
+
+parcelable InstantAppResolveInfo;
diff --git a/core/java/android/app/InstantAppResolverService.java b/core/java/android/app/InstantAppResolverService.java
new file mode 100644
index 0000000..1ce30b2
--- /dev/null
+++ b/core/java/android/app/InstantAppResolverService.java
@@ -0,0 +1,176 @@
+/*
+ * 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 android.app;
+
+import android.annotation.SystemApi;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.InstantAppResolveInfo;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.IRemoteCallback;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+
+import java.util.List;
+
+/**
+ * Base class for implementing the resolver service.
+ * @hide
+ */
+@SystemApi
+public abstract class InstantAppResolverService extends Service {
+    public static final String EXTRA_RESOLVE_INFO = "android.app.extra.RESOLVE_INFO";
+    public static final String EXTRA_SEQUENCE = "android.app.extra.SEQUENCE";
+    static final String EXTRA_PREFIX = "android.app.PREFIX";
+    static final String EXTRA_HOSTNAME = "android.app.HOSTNAME";
+    Handler mHandler;
+
+    /**
+     * Called to retrieve resolve info for instant applications.
+     *
+     * @param digestPrefix The hash prefix of the instant app's domain.
+     */
+    public void onGetInstantAppResolveInfo(
+            int digestPrefix[], InstantAppResolutionCallback callback) {
+        throw new IllegalStateException("Must define");
+    }
+
+    /**
+     * Called to retrieve intent filters for instant applications.
+     *
+     * @param digestPrefix The hash prefix of the instant app's domain.
+     */
+    public void onGetInstantAppIntentFilter(
+            int digestPrefix[], InstantAppResolutionCallback callback) {
+        throw new IllegalStateException("Must define");
+    }
+
+    /**
+     * Returns a {@link Looper} to perform service operations on.
+     */
+    Looper getLooper() {
+        return getBaseContext().getMainLooper();
+    }
+
+    @Override
+    public final void attachBaseContext(Context base) {
+        super.attachBaseContext(base);
+        mHandler = new ServiceHandler(getLooper());
+    }
+
+    @Override
+    public final IBinder onBind(Intent intent) {
+        return new IInstantAppResolver.Stub() {
+            @Override
+            public void getInstantAppResolveInfoList(
+                    int digestPrefix[], int sequence, IRemoteCallback callback) {
+                final Message msg = mHandler.obtainMessage(
+                        ServiceHandler.MSG_GET_INSTANT_APP_RESOLVE_INFO, sequence, 0, callback);
+                final Bundle data = new Bundle();
+                data.putIntArray(EXTRA_PREFIX, digestPrefix);
+                msg.setData(data);
+                msg.sendToTarget();
+            }
+
+            @Override
+            public void getInstantAppIntentFilterList(
+                    int digestPrefix[], int sequence, String hostName, IRemoteCallback callback) {
+                final Message msg = mHandler.obtainMessage(
+                        ServiceHandler.MSG_GET_INSTANT_APP_INTENT_FILTER, sequence, 0, callback);
+                final Bundle data = new Bundle();
+                data.putString(EXTRA_HOSTNAME, hostName);
+                data.putIntArray(EXTRA_PREFIX, digestPrefix);
+                msg.setData(data);
+                msg.sendToTarget();
+            }
+        };
+    }
+
+    /**
+     * Callback to post results from instant app resolution.
+     */
+    public static final class InstantAppResolutionCallback {
+        private final IRemoteCallback mCallback;
+        private final int mSequence;
+        InstantAppResolutionCallback(int sequence, IRemoteCallback callback) {
+            mCallback = callback;
+            mSequence = sequence;
+        }
+
+        public void onInstantAppResolveInfo(List<InstantAppResolveInfo> resolveInfo) {
+            final Bundle data = new Bundle();
+            data.putInt(EXTRA_SEQUENCE, mSequence);
+            data.putParcelableList(EXTRA_RESOLVE_INFO, resolveInfo);
+            try {
+                mCallback.sendResult(data);
+            } catch (RemoteException e) {
+            }
+        }
+    }
+
+    @Deprecated
+    void _onGetInstantAppResolveInfo(int[] digestPrefix, InstantAppResolutionCallback callback) {
+        onGetInstantAppResolveInfo(digestPrefix, callback);
+    }
+    @Deprecated
+    void _onGetInstantAppIntentFilter(int digestPrefix[], String hostName,
+            InstantAppResolutionCallback callback) {
+        onGetInstantAppIntentFilter(digestPrefix, callback);
+    }
+
+    private final class ServiceHandler extends Handler {
+        public static final int MSG_GET_INSTANT_APP_RESOLVE_INFO = 1;
+        public static final int MSG_GET_INSTANT_APP_INTENT_FILTER = 2;
+
+        public ServiceHandler(Looper looper) {
+            super(looper, null /*callback*/, true /*async*/);
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public void handleMessage(Message message) {
+            final int action = message.what;
+            switch (action) {
+                case MSG_GET_INSTANT_APP_RESOLVE_INFO: {
+                    final IRemoteCallback callback = (IRemoteCallback) message.obj;
+                    final int sequence = message.arg1;
+                    final int[] digestPrefix = message.getData().getIntArray(EXTRA_PREFIX);
+                    _onGetInstantAppResolveInfo(
+                            digestPrefix, new InstantAppResolutionCallback(sequence, callback));
+                } break;
+
+                case MSG_GET_INSTANT_APP_INTENT_FILTER: {
+                    final IRemoteCallback callback = (IRemoteCallback) message.obj;
+                    final int sequence = message.arg1;
+                    final int[] digestPrefix = message.getData().getIntArray(EXTRA_PREFIX);
+                    final String hostName = message.getData().getString(EXTRA_HOSTNAME);
+                    _onGetInstantAppIntentFilter(
+                            digestPrefix, hostName,
+                            new InstantAppResolutionCallback(sequence, callback));
+                } break;
+
+                default: {
+                    throw new IllegalArgumentException("Unknown message: " + action);
+                }
+            }
+        }
+    }
+}
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 7ed96af..be38f42 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -278,7 +278,7 @@
         setApplicationInfo(aInfo);
 
         final List<String> newPaths = new ArrayList<>();
-        makePaths(mActivityThread, aInfo, newPaths, null /*libPaths*/);
+        makePaths(mActivityThread, aInfo, newPaths);
         final List<String> addedPaths = new ArrayList<>(newPaths.size());
 
         if (oldPaths != null) {
@@ -286,7 +286,7 @@
                 final String apkName = path.substring(path.lastIndexOf(File.separator));
                 boolean match = false;
                 for (String oldPath : oldPaths) {
-                    final String oldApkName = oldPath.substring(path.lastIndexOf(File.separator));
+                    final String oldApkName = oldPath.substring(oldPath.lastIndexOf(File.separator));
                     if (apkName.equals(oldApkName)) {
                         match = true;
                         break;
@@ -341,8 +341,17 @@
         }
     }
 
-    public static void makePaths(ActivityThread activityThread, ApplicationInfo aInfo,
-            List<String> outZipPaths, List<String> outLibPaths) {
+    public static void makePaths(ActivityThread activityThread,
+                                 ApplicationInfo aInfo,
+                                 List<String> outZipPaths) {
+        makePaths(activityThread, false, aInfo, outZipPaths, null);
+    }
+
+    public static void makePaths(ActivityThread activityThread,
+                                 boolean isBundledApp,
+                                 ApplicationInfo aInfo,
+                                 List<String> outZipPaths,
+                                 List<String> outLibPaths) {
         final String appDir = aInfo.sourceDir;
         final String libDir = aInfo.nativeLibraryDir;
         final String[] sharedLibraries = aInfo.sharedLibraryFiles;
@@ -431,7 +440,7 @@
                 }
             }
 
-            if (aInfo.isSystemApp() && !aInfo.isUpdatedSystemApp()) {
+            if (isBundledApp) {
                 // Add path to system libraries to libPaths;
                 // Access to system libs should be limited
                 // to bundled applications; this is why updated
@@ -614,11 +623,12 @@
         // space and initialize to a small value (instead of incurring growth code).
         final List<String> zipPaths = new ArrayList<>(10);
         final List<String> libPaths = new ArrayList<>(10);
-        makePaths(mActivityThread, mApplicationInfo, zipPaths, libPaths);
 
         final boolean isBundledApp = mApplicationInfo.isSystemApp()
                 && !mApplicationInfo.isUpdatedSystemApp();
 
+        makePaths(mActivityThread, isBundledApp, mApplicationInfo, zipPaths, libPaths);
+
         String libraryPermittedPath = mDataDir;
         if (isBundledApp) {
             // This is necessary to grant bundled apps access to
@@ -739,19 +749,17 @@
         }
 
         final File profileFile = getPrimaryProfileFile(mPackageName);
-        final File foreignDexProfilesFile =
-                Environment.getDataProfilesDeForeignDexDirectory(UserHandle.myUserId());
 
-        VMRuntime.registerAppInfo(profileFile.getPath(), mApplicationInfo.dataDir,
-                codePaths.toArray(new String[codePaths.size()]), foreignDexProfilesFile.getPath());
+        VMRuntime.registerAppInfo(profileFile.getPath(),
+                codePaths.toArray(new String[codePaths.size()]));
 
         // Setup the reporter to notify package manager of any relevant dex loads.
         // At this point the primary apk is loaded and will not be reported.
         // Anything loaded from now on will be tracked as a potential secondary
         // or foreign dex file. The goal is to enable:
         //    1) monitoring and compilation of secondary dex file
-        //    2) track foreign dex file usage (used to determined the
-        //       compilation filter of apks).
+        //    2) track whether or not a dex file is used by other apps (used to
+        //       determined the compilation filter of apks).
         if (BaseDexClassLoader.getReporter() != DexLoadReporter.INSTANCE) {
             // Set the dex load reporter if not already set.
             // Note that during the app's life cycle different LoadedApks may be
diff --git a/core/java/android/app/LoaderManager.java b/core/java/android/app/LoaderManager.java
index bedf31a..56dfc58 100644
--- a/core/java/android/app/LoaderManager.java
+++ b/core/java/android/app/LoaderManager.java
@@ -852,6 +852,7 @@
             mInactiveLoaders.valueAt(i).destroy();
         }
         mInactiveLoaders.clear();
+        mHost = null;
     }
 
     @Override
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 812daf8..a098591 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -72,6 +72,7 @@
 import com.android.internal.R;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.NotificationColorUtil;
+import com.android.internal.util.Preconditions;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -2702,11 +2703,11 @@
         }
 
         /**
-         * Specifies the time at which this notification should be canceled, if it is not already
-         * canceled.
+         * Specifies a duration in milliseconds after which this notification should be canceled,
+         * if it is not already canceled.
          */
-        public Builder setTimeout(long when) {
-            mN.mTimeout = when;
+        public Builder setTimeout(long durationMs) {
+            mN.mTimeout = durationMs;
             return this;
         }
 
@@ -4040,15 +4041,23 @@
         }
 
         /**
-         * Construct a RemoteViews for the final notification header only
+         * Construct a RemoteViews for the final notification header only. This will not be
+         * colorized.
          *
          * @hide
          */
         public RemoteViews makeNotificationHeader() {
+            Boolean colorized = (Boolean) mN.extras.get(EXTRA_COLORIZED);
+            mN.extras.putBoolean(EXTRA_COLORIZED, false);
             RemoteViews header = new BuilderRemoteViews(mContext.getApplicationInfo(),
                     R.layout.notification_template_header);
             resetNotificationHeader(header);
             bindNotificationHeader(header, false /* ambient */);
+            if (colorized != null) {
+                mN.extras.putBoolean(EXTRA_COLORIZED, colorized);
+            } else {
+                mN.extras.remove(EXTRA_COLORIZED);
+            }
             return header;
         }
 
@@ -4060,7 +4069,7 @@
         public RemoteViews makeAmbientNotification() {
             RemoteViews ambient = applyStandardTemplateWithActions(
                     R.layout.notification_template_material_ambient,
-                    mParams.reset().fillTextsFrom(this).hasProgress(false).ambient(true));
+                    mParams.reset().ambient(true).fillTextsFrom(this).hasProgress(false));
             return ambient;
         }
 
@@ -4167,21 +4176,14 @@
                     mN.extras.putCharSequence(EXTRA_SUB_TEXT, newSummary);
                 }
             }
-            Boolean colorized = (Boolean) mN.extras.get(EXTRA_COLORIZED);
-            mN.extras.putBoolean(EXTRA_COLORIZED, false);
 
             RemoteViews header = makeNotificationHeader();
-
+            header.setBoolean(R.id.notification_header, "setAcceptAllTouches", true);
             if (summary != null) {
                 mN.extras.putCharSequence(EXTRA_SUB_TEXT, summary);
             } else {
                 mN.extras.remove(EXTRA_SUB_TEXT);
             }
-            if (colorized != null) {
-                mN.extras.putBoolean(EXTRA_COLORIZED, colorized);
-            } else {
-                mN.extras.remove(EXTRA_COLORIZED);
-            }
             mN.color = color;
             return header;
         }
@@ -4380,7 +4382,13 @@
         }
 
         private CharSequence processLegacyText(CharSequence charSequence) {
-            if (isLegacy() || textColorsNeedInversion()) {
+            return processLegacyText(charSequence, false /* ambient */);
+        }
+
+        private CharSequence processLegacyText(CharSequence charSequence, boolean ambient) {
+            boolean isAlreadyLightText = isLegacy() || textColorsNeedInversion();
+            boolean wantLightText = ambient;
+            if (isAlreadyLightText != wantLightText) {
                 return getColorUtil().invertCharSequenceColors(charSequence);
             } else {
                 return charSequence;
@@ -7852,14 +7860,15 @@
         }
 
         final StandardTemplateParams ambient(boolean ambient) {
+            Preconditions.checkState(title == null && text == null, "must set ambient before text");
             this.ambient = ambient;
             return this;
         }
 
         final StandardTemplateParams fillTextsFrom(Builder b) {
             Bundle extras = b.mN.extras;
-            title = b.processLegacyText(extras.getCharSequence(EXTRA_TITLE));
-            text = b.processLegacyText(extras.getCharSequence(EXTRA_TEXT));
+            title = b.processLegacyText(extras.getCharSequence(EXTRA_TITLE), ambient);
+            text = b.processLegacyText(extras.getCharSequence(EXTRA_TEXT), ambient);
             return this;
         }
     }
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index 1a51608..16c85f5 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -20,8 +20,10 @@
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlSerializer;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.StringRes;
 import android.annotation.SystemApi;
-import android.graphics.Color;
 import android.media.AudioAttributes;
 import android.net.Uri;
 import android.os.Parcel;
@@ -45,6 +47,7 @@
 
     private static final String TAG_CHANNEL = "channel";
     private static final String ATT_NAME = "name";
+    private static final String ATT_NAME_RES_ID = "name_res_id";
     private static final String ATT_ID = "id";
     private static final String ATT_DELETED = "deleted";
     private static final String ATT_PRIORITY = "priority";
@@ -138,6 +141,7 @@
 
     private final String mId;
     private CharSequence mName;
+    private int mNameResId = 0;
     private int mImportance = DEFAULT_IMPORTANCE;
     private boolean mBypassDnd;
     private int mLockscreenVisibility = DEFAULT_VISIBILITY;
@@ -156,7 +160,9 @@
      * Creates a notification channel.
      *
      * @param id The id of the channel. Must be unique per package.
-     * @param name The user visible name of the channel.
+     * @param name The user visible name of the channel. Unchangeable once created; use this
+     *             constructor if the channel represents a user-defined category that does not
+     *             need to be translated.
      * @param importance The importance of the channel. This controls how interruptive notifications
      *                   posted to this channel are. See e.g.
      *                   {@link NotificationManager#IMPORTANCE_DEFAULT}.
@@ -167,6 +173,21 @@
         this.mImportance = importance;
     }
 
+    /**
+     * Creates a notification channel.
+     *
+     * @param id The id of the channel. Must be unique per package.
+     * @param nameResId The resource id of the string containing the channel name.
+     * @param importance The importance of the channel. This controls how interruptive notifications
+     *                   posted to this channel are. See e.g.
+     *                   {@link NotificationManager#IMPORTANCE_DEFAULT}.
+     */
+    public NotificationChannel(String id, @StringRes int nameResId, int importance) {
+        this.mId = id;
+        this.mNameResId = nameResId;
+        this.mImportance = importance;
+    }
+
     protected NotificationChannel(Parcel in) {
         if (in.readByte() != 0) {
             mId = in.readString();
@@ -174,6 +195,7 @@
             mId = null;
         }
         mName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+        mNameResId = in.readInt();
         mImportance = in.readInt();
         mBypassDnd = in.readByte() != 0;
         mLockscreenVisibility = in.readInt();
@@ -206,6 +228,7 @@
             dest.writeByte((byte) 0);
         }
         TextUtils.writeToParcel(mName, dest, flags);
+        dest.writeInt(mNameResId);
         dest.writeInt(mImportance);
         dest.writeByte(mBypassDnd ? (byte) 1 : (byte) 0);
         dest.writeInt(mLockscreenVisibility);
@@ -252,6 +275,13 @@
         mDeleted = deleted;
     }
 
+    /**
+     * @hide
+     */
+    public void setNameResId(@StringRes int nameResId) {
+        this.mNameResId = nameResId;
+    }
+
     // Modifiable by a notification ranker.
 
     /**
@@ -382,11 +412,18 @@
     /**
      * Returns the user visible name of this channel.
      */
-    public CharSequence getName() {
+    public @Nullable CharSequence getName() {
         return mName;
     }
 
     /**
+     * Returns the resource id of the user visible name of this channel.
+     */
+    public int getNameResId() {
+        return mNameResId;
+    }
+
+    /**
      * Returns the user specified importance {e.g. @link NotificationManager#IMPORTANCE_LOW} for
      * notifications posted to this channel.
      */
@@ -516,7 +553,10 @@
     public void writeXml(XmlSerializer out) throws IOException {
         out.startTag(null, TAG_CHANNEL);
         out.attribute(null, ATT_ID, getId());
-        out.attribute(null, ATT_NAME, getName().toString());
+        if (getName() != null) {
+            out.attribute(null, ATT_NAME, getName().toString());
+        }
+        out.attribute(null, ATT_NAME_RES_ID, Integer.toString(getNameResId()));
         if (getImportance() != DEFAULT_IMPORTANCE) {
             out.attribute(
                     null, ATT_IMPORTANCE, Integer.toString(getImportance()));
@@ -574,6 +614,7 @@
         JSONObject record = new JSONObject();
         record.put(ATT_ID, getId());
         record.put(ATT_NAME, getName());
+        record.put(ATT_NAME_RES_ID, getNameResId());
         if (getImportance() != DEFAULT_IMPORTANCE) {
             record.put(ATT_IMPORTANCE,
                     NotificationListenerService.Ranking.importanceToString(getImportance()));
@@ -691,6 +732,7 @@
 
         NotificationChannel that = (NotificationChannel) o;
 
+        if (getNameResId() != that.getNameResId()) return false;
         if (getImportance() != that.getImportance()) return false;
         if (mBypassDnd != that.mBypassDnd) return false;
         if (getLockscreenVisibility() != that.getLockscreenVisibility()) return false;
@@ -720,6 +762,7 @@
     public int hashCode() {
         int result = getId() != null ? getId().hashCode() : 0;
         result = 31 * result + (getName() != null ? getName().hashCode() : 0);
+        result = 31 * result + getNameResId();
         result = 31 * result + getImportance();
         result = 31 * result + (mBypassDnd ? 1 : 0);
         result = 31 * result + getLockscreenVisibility();
@@ -741,6 +784,7 @@
         return "NotificationChannel{" +
                 "mId='" + mId + '\'' +
                 ", mName=" + mName +
+                ", mNameResId=" + mNameResId +
                 ", mImportance=" + mImportance +
                 ", mBypassDnd=" + mBypassDnd +
                 ", mLockscreenVisibility=" + mLockscreenVisibility +
diff --git a/core/java/android/app/NotificationChannelGroup.java b/core/java/android/app/NotificationChannelGroup.java
index 8854adc..288d39a 100644
--- a/core/java/android/app/NotificationChannelGroup.java
+++ b/core/java/android/app/NotificationChannelGroup.java
@@ -15,6 +15,7 @@
  */
 package android.app;
 
+import android.annotation.StringRes;
 import android.annotation.SystemApi;
 import android.net.Uri;
 import android.os.Parcel;
@@ -40,23 +41,38 @@
 
     private static final String TAG_GROUP = "channelGroup";
     private static final String ATT_NAME = "name";
+    private static final String ATT_NAME_RES_ID = "name_res_id";
     private static final String ATT_ID = "id";
 
     private final String mId;
     private CharSequence mName;
+    private int mNameResId = 0;
     private List<NotificationChannel> mChannels = new ArrayList<>();
 
     /**
      * Creates a notification channel.
      *
      * @param id The id of the group. Must be unique per package.
-     * @param name The user visible name of the group.
+     * @param name The user visible name of the group. Unchangeable once created; use this
+     *             constructor if the group represents something user-defined that does not
+     *             need to be translated.
      */
     public NotificationChannelGroup(String id, CharSequence name) {
         this.mId = id;
         this.mName = name;
     }
 
+    /**
+     * Creates a notification channel.
+     *
+     * @param id The id of the group. Must be unique per package.
+     * @param nameResId String resource id of the user visible name of the group.
+     */
+    public NotificationChannelGroup(String id, @StringRes int nameResId) {
+        this.mId = id;
+        this.mNameResId = nameResId;
+    }
+
     protected NotificationChannelGroup(Parcel in) {
         if (in.readByte() != 0) {
             mId = in.readString();
@@ -64,6 +80,7 @@
             mId = null;
         }
         mName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+        mNameResId = in.readInt();
         in.readParcelableList(mChannels, NotificationChannel.class.getClassLoader());
     }
 
@@ -76,6 +93,7 @@
             dest.writeByte((byte) 0);
         }
         TextUtils.writeToParcel(mName, dest, flags);
+        dest.writeInt(mNameResId);
         dest.writeParcelableList(mChannels, flags);
     }
 
@@ -93,6 +111,13 @@
         return mName;
     }
 
+    /**
+     * Returns the resource id of the user visible name of this group.
+     */
+    public @StringRes int getNameResId() {
+        return mNameResId;
+    }
+
     /*
      * Returns the list of channels that belong to this group
      *
@@ -119,7 +144,12 @@
         out.startTag(null, TAG_GROUP);
 
         out.attribute(null, ATT_ID, getId());
-        out.attribute(null, ATT_NAME, getName().toString());
+        if (getName() != null) {
+            out.attribute(null, ATT_NAME, getName().toString());
+        }
+        if (getNameResId() != 0) {
+            out.attribute(null, ATT_NAME_RES_ID, Integer.toString(getNameResId()));
+        }
 
         out.endTag(null, TAG_GROUP);
     }
@@ -132,6 +162,7 @@
         JSONObject record = new JSONObject();
         record.put(ATT_ID, getId());
         record.put(ATT_NAME, getName());
+        record.put(ATT_NAME_RES_ID, getNameResId());
         return record;
     }
 
@@ -160,6 +191,7 @@
 
         NotificationChannelGroup that = (NotificationChannelGroup) o;
 
+        if (getNameResId() != that.getNameResId()) return false;
         if (getId() != null ? !getId().equals(that.getId()) : that.getId() != null) return false;
         if (getName() != null ? !getName().equals(that.getName()) : that.getName() != null) {
             return false;
@@ -171,13 +203,18 @@
 
     @Override
     public NotificationChannelGroup clone() {
-        return new NotificationChannelGroup(getId(), getName());
+        if (getName() != null) {
+            return new NotificationChannelGroup(getId(), getName());
+        } else {
+            return new NotificationChannelGroup(getId(), getNameResId());
+        }
     }
 
     @Override
     public int hashCode() {
         int result = getId() != null ? getId().hashCode() : 0;
         result = 31 * result + (getName() != null ? getName().hashCode() : 0);
+        result = 31 * result + getNameResId();
         result = 31 * result + (getChannels() != null ? getChannels().hashCode() : 0);
         return result;
     }
@@ -187,6 +224,8 @@
         return "NotificationChannelGroup{" +
                 "mId='" + mId + '\'' +
                 ", mName=" + mName +
+                ", mNameResId=" + mNameResId +
+                ", mChannels=" + mChannels +
                 '}';
     }
 }
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 5205959..d37e209 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -447,6 +447,19 @@
     }
 
     /**
+     * @hide
+     */
+    public void createNotificationChannelsForPackage(String pkg,
+            @NonNull List<NotificationChannel> channels) {
+        INotificationManager service = getService();
+        try {
+            service.createNotificationChannels(pkg, new ParceledListSlice(channels));
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Returns the notification channel settings for a given channel id.
      */
     public NotificationChannel getNotificationChannel(String channelId) {
diff --git a/core/java/android/app/QueuedWork.java b/core/java/android/app/QueuedWork.java
index a38fd43..56338f5 100644
--- a/core/java/android/app/QueuedWork.java
+++ b/core/java/android/app/QueuedWork.java
@@ -21,9 +21,11 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.Process;
+import android.os.StrictMode;
 import android.util.Log;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.ExponentiallyBucketedHistogram;
 
 import java.util.LinkedList;
 
@@ -46,11 +48,14 @@
  */
 public class QueuedWork {
     private static final String LOG_TAG = QueuedWork.class.getSimpleName();
-    private static final boolean DEBUG = true;
+    private static final boolean DEBUG = false;
 
     /** Delay for delayed runnables, as big as possible but low enough to be barely perceivable */
     private static final long DELAY = 100;
 
+    /** If a {@link #waitToFinish()} takes more than {@value #MAX_WAIT_TIME_MILLIS} ms, warn */
+    private static final long MAX_WAIT_TIME_MILLIS = 512;
+
     /** Lock for this class */
     private static final Object sLock = new Object();
 
@@ -79,6 +84,13 @@
     @GuardedBy("sLock")
     private static boolean sCanDelay = true;
 
+    /** Time (and number of instances) waited for work to get processed */
+    @GuardedBy("sLock")
+    private final static ExponentiallyBucketedHistogram
+            mWaitTimes = new ExponentiallyBucketedHistogram(
+            16);
+    private static int mNumWaits = 0;
+
     /**
      * Lazily create a handler on a separate thread.
      *
@@ -135,13 +147,9 @@
      * after Service command handling, etc. (so async work is never lost)
      */
     public static void waitToFinish() {
-        long startTime = 0;
+        long startTime = System.currentTimeMillis();
         boolean hadMessages = false;
 
-        if (DEBUG) {
-            startTime = System.currentTimeMillis();
-        }
-
         Handler handler = getHandler();
 
         synchronized (sLock) {
@@ -159,7 +167,12 @@
             sCanDelay = false;
         }
 
-        processPendingWork();
+        StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
+        try {
+            processPendingWork();
+        } finally {
+            StrictMode.setThreadPolicy(oldPolicy);
+        }
 
         try {
             while (true) {
@@ -179,11 +192,16 @@
             sCanDelay = true;
         }
 
-        if (DEBUG) {
+        synchronized (sLock) {
             long waitTime = System.currentTimeMillis() - startTime;
 
             if (waitTime > 0 || hadMessages) {
-                Log.d(LOG_TAG, "waited " + waitTime + " ms");
+                mWaitTimes.add(Long.valueOf(waitTime).intValue());
+                mNumWaits++;
+
+                if (DEBUG || mNumWaits % 1024 == 0 || waitTime > MAX_WAIT_TIME_MILLIS) {
+                    mWaitTimes.log(LOG_TAG, "waited: ");
+                }
             }
         }
     }
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 55f7df3..b42df5e 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -22,6 +22,7 @@
 import android.annotation.Nullable;
 import android.content.pm.ActivityInfo;
 import android.content.res.AssetManager;
+import android.content.res.CompatResources;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
@@ -104,10 +105,17 @@
             new WeakHashMap<>();
 
     /**
-     * A cache of DisplayId to DisplayAdjustments.
+     * A cache of DisplayId, DisplayAdjustments to Display.
      */
-    private final ArrayMap<Pair<Integer, DisplayAdjustments>, WeakReference<Display>> mDisplays =
-            new ArrayMap<>();
+    private final ArrayMap<Pair<Integer, DisplayAdjustments>, WeakReference<Display>>
+            mAdjustedDisplays = new ArrayMap<>();
+
+    /**
+     * A cache of DisplayId, Resources to Display. These display adjustments associated with these
+     * {@link Display}s will change as the resources change.
+     */
+    private final ArrayMap<Pair<Integer, Resources>, WeakReference<Display>> mResourceDisplays =
+        new ArrayMap<>();
 
     public static ResourcesManager getInstance() {
         synchronized (ResourcesManager.class) {
@@ -201,19 +209,21 @@
 
     /**
      * Returns an adjusted {@link Display} object based on the inputs or null if display isn't
-     * available.
+     * available. This method is only used within {@link ResourcesManager} to calculate display
+     * metrics based on a set {@link DisplayAdjustments}. All other usages should instead call
+     * {@link ResourcesManager#getAdjustedDisplay(int, Resources)}.
      *
      * @param displayId display Id.
      * @param displayAdjustments display adjustments.
      */
-    public Display getAdjustedDisplay(final int displayId,
+    private Display getAdjustedDisplay(final int displayId,
             @Nullable DisplayAdjustments displayAdjustments) {
         final DisplayAdjustments displayAdjustmentsCopy = (displayAdjustments != null)
                 ? new DisplayAdjustments(displayAdjustments) : new DisplayAdjustments();
         final Pair<Integer, DisplayAdjustments> key =
                 Pair.create(displayId, displayAdjustmentsCopy);
         synchronized (this) {
-            WeakReference<Display> wd = mDisplays.get(key);
+            WeakReference<Display> wd = mAdjustedDisplays.get(key);
             if (wd != null) {
                 final Display display = wd.get();
                 if (display != null) {
@@ -227,7 +237,37 @@
             }
             final Display display = dm.getCompatibleDisplay(displayId, key.second);
             if (display != null) {
-                mDisplays.put(key, new WeakReference<>(display));
+                mAdjustedDisplays.put(key, new WeakReference<>(display));
+            }
+            return display;
+        }
+    }
+
+    /**
+     * Returns an adjusted {@link Display} object based on the inputs or null if display isn't
+     * available.
+     *
+     * @param displayId display Id.
+     * @param resources The {@link Resources} backing the display adjustments.
+     */
+    public Display getAdjustedDisplay(final int displayId, Resources resources) {
+        final Pair<Integer, Resources> key = Pair.create(displayId, resources);
+        synchronized (this) {
+            WeakReference<Display> wd = mResourceDisplays.get(key);
+            if (wd != null) {
+                final Display display = wd.get();
+                if (display != null) {
+                    return display;
+                }
+            }
+            final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
+            if (dm == null) {
+                // may be null early in system startup
+                return null;
+            }
+            final Display display = dm.getCompatibleDisplay(displayId, resources);
+            if (display != null) {
+                mResourceDisplays.put(key, new WeakReference<>(display));
             }
             return display;
         }
@@ -316,6 +356,7 @@
         final DisplayMetrics dm = getDisplayMetrics(key.mDisplayId, daj);
         final Configuration config = generateConfig(key, dm);
         final ResourcesImpl impl = new ResourcesImpl(assets, dm, config, daj);
+
         if (DEBUG) {
             Slog.d(TAG, "- creating impl=" + impl + " with key: " + key);
         }
@@ -407,7 +448,8 @@
      * or the class loader is different.
      */
     private @NonNull Resources getOrCreateResourcesForActivityLocked(@NonNull IBinder activityToken,
-            @NonNull ClassLoader classLoader, @NonNull ResourcesImpl impl) {
+            @NonNull ClassLoader classLoader, @NonNull ResourcesImpl impl,
+            @NonNull CompatibilityInfo compatInfo) {
         final ActivityResources activityResources = getOrCreateActivityResourcesStructLocked(
                 activityToken);
 
@@ -426,7 +468,8 @@
             }
         }
 
-        Resources resources = new Resources(classLoader);
+        Resources resources = compatInfo.needsCompatResources() ? new CompatResources(classLoader)
+                : new Resources(classLoader);
         resources.setImpl(impl);
         activityResources.activityResources.add(new WeakReference<>(resources));
         if (DEBUG) {
@@ -441,7 +484,7 @@
      * otherwise creates a new Resources object.
      */
     private @NonNull Resources getOrCreateResourcesLocked(@NonNull ClassLoader classLoader,
-            @NonNull ResourcesImpl impl) {
+            @NonNull ResourcesImpl impl, @NonNull CompatibilityInfo compatInfo) {
         // Find an existing Resources that has this ResourcesImpl set.
         final int refCount = mResourceReferences.size();
         for (int i = 0; i < refCount; i++) {
@@ -458,7 +501,8 @@
         }
 
         // Create a new Resources reference and use the existing ResourcesImpl object.
-        Resources resources = new Resources(classLoader);
+        Resources resources = compatInfo.needsCompatResources() ? new CompatResources(classLoader)
+                : new Resources(classLoader);
         resources.setImpl(impl);
         mResourceReferences.add(new WeakReference<>(resources));
         if (DEBUG) {
@@ -574,7 +618,7 @@
                         Slog.d(TAG, "- using existing impl=" + resourcesImpl);
                     }
                     return getOrCreateResourcesForActivityLocked(activityToken, classLoader,
-                            resourcesImpl);
+                            resourcesImpl, key.mCompatInfo);
                 }
 
                 // We will create the ResourcesImpl object outside of holding this lock.
@@ -589,7 +633,7 @@
                     if (DEBUG) {
                         Slog.d(TAG, "- using existing impl=" + resourcesImpl);
                     }
-                    return getOrCreateResourcesLocked(classLoader, resourcesImpl);
+                    return getOrCreateResourcesLocked(classLoader, resourcesImpl, key.mCompatInfo);
                 }
 
                 // We will create the ResourcesImpl object outside of holding this lock.
@@ -619,9 +663,9 @@
             final Resources resources;
             if (activityToken != null) {
                 resources = getOrCreateResourcesForActivityLocked(activityToken, classLoader,
-                        resourcesImpl);
+                        resourcesImpl, key.mCompatInfo);
             } else {
-                resources = getOrCreateResourcesLocked(classLoader, resourcesImpl);
+                resources = getOrCreateResourcesLocked(classLoader, resourcesImpl, key.mCompatInfo);
             }
             return resources;
         }
@@ -811,7 +855,9 @@
             }
             int changes = mResConfiguration.updateFrom(config);
             // Things might have changed in display manager, so clear the cached displays.
-            mDisplays.clear();
+            mAdjustedDisplays.clear();
+            mResourceDisplays.clear();
+
             DisplayMetrics defaultDisplayMetrics = getDisplayMetrics();
 
             if (compat != null && (mResCompatibilityInfo == null ||
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index 9cd048e..4fe4f98 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -683,28 +683,26 @@
      * flag if killing your service would be disruptive to the user, such as
      * if your service is performing background music playback, so the user
      * would notice if their music stopped playing.
-     *
+     * 
      * <p>If you need your application to run on platform versions prior to API
      * level 5, you can use the following model to call the the older setForeground()
      * or this modern method as appropriate:
-     *
+     * 
      * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/ForegroundService.java
      *   foreground_compatibility}
-     *
+     * 
      * @param id The identifier for this notification as per
      * {@link NotificationManager#notify(int, Notification)
      * NotificationManager.notify(int, Notification)}; must not be 0.
      * @param notification The Notification to be displayed.
-     *
+     * 
      * @see #stopForeground(boolean)
      */
     public final void startForeground(int id, Notification notification) {
         try {
-            final long procStateSeq = mActivityManager.setServiceForeground(
-                    new ComponentName(this, mClassName), mToken, id, notification, 0);
-            if (procStateSeq != ActivityThread.INVALID_PROC_STATE_SEQ && mThread != null) {
-                mThread.blockForNetworkAccessInForegroundService(procStateSeq);
-            }
+            mActivityManager.setServiceForeground(
+                    new ComponentName(this, mClassName), mToken, id,
+                    notification, 0);
         } catch (RemoteException ex) {
         }
     }
diff --git a/core/java/android/app/SharedPreferencesImpl.java b/core/java/android/app/SharedPreferencesImpl.java
index 11ba7ee..063ad24 100644
--- a/core/java/android/app/SharedPreferencesImpl.java
+++ b/core/java/android/app/SharedPreferencesImpl.java
@@ -28,6 +28,7 @@
 import com.google.android.collect.Maps;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.ExponentiallyBucketedHistogram;
 import com.android.internal.util.XmlUtils;
 
 import dalvik.system.BlockGuard;
@@ -53,9 +54,12 @@
 
 final class SharedPreferencesImpl implements SharedPreferences {
     private static final String TAG = "SharedPreferencesImpl";
-    private static final boolean DEBUG = true;
+    private static final boolean DEBUG = false;
     private static final Object CONTENT = new Object();
 
+    /** If a fsync takes more than {@value #MAX_FSYNC_DURATION_MILLIS} ms, warn */
+    private static final long MAX_FSYNC_DURATION_MILLIS = 256;
+
     // Lock ordering rules:
     //  - acquire SharedPreferencesImpl.mLock before EditorImpl.mLock
     //  - acquire mWritingToDiskLock before EditorImpl.mLock
@@ -93,6 +97,11 @@
     @GuardedBy("mWritingToDiskLock")
     private long mDiskStateGeneration;
 
+    /** Time (and number of instances) of file-system sync requests */
+    @GuardedBy("mWritingToDiskLock")
+    private final ExponentiallyBucketedHistogram mSyncTimes = new ExponentiallyBucketedHistogram(16);
+    private int mNumSync = 0;
+
     SharedPreferencesImpl(File file, int mode) {
         mFile = file;
         mBackupFile = makeBackupFile(file);
@@ -139,8 +148,8 @@
                     str = new BufferedInputStream(
                             new FileInputStream(mFile), 16*1024);
                     map = XmlUtils.readMapXml(str);
-                } catch (XmlPullParserException | IOException e) {
-                    Log.w(TAG, "getSharedPreferences", e);
+                } catch (Exception e) {
+                    Log.w(TAG, "Cannot read " + mFile.getAbsolutePath(), e);
                 } finally {
                     IoUtils.closeQuietly(str);
                 }
@@ -719,15 +728,11 @@
             }
             XmlUtils.writeMapXml(mcr.mapToWriteToDisk, str);
 
-            if (DEBUG) {
-                writeTime = System.currentTimeMillis();
-            }
+            writeTime = System.currentTimeMillis();
 
             FileUtils.sync(str);
 
-            if (DEBUG) {
-                fsyncTime = System.currentTimeMillis();
-            }
+            fsyncTime = System.currentTimeMillis();
 
             str.close();
             ContextImpl.setFilePermissionsFromMode(mFile.getPath(), mMode, 0);
@@ -761,14 +766,24 @@
 
             mcr.setDiskWriteResult(true, true);
 
-            Log.d(TAG, "write: " + (existsTime - startTime) + "/"
-                    + (backupExistsTime - startTime) + "/"
-                    + (outputStreamCreateTime - startTime) + "/"
-                    + (writeTime - startTime) + "/"
-                    + (fsyncTime - startTime) + "/"
-                    + (setPermTime - startTime) + "/"
-                    + (fstatTime - startTime) + "/"
-                    + (deleteTime - startTime));
+            if (DEBUG) {
+                Log.d(TAG, "write: " + (existsTime - startTime) + "/"
+                        + (backupExistsTime - startTime) + "/"
+                        + (outputStreamCreateTime - startTime) + "/"
+                        + (writeTime - startTime) + "/"
+                        + (fsyncTime - startTime) + "/"
+                        + (setPermTime - startTime) + "/"
+                        + (fstatTime - startTime) + "/"
+                        + (deleteTime - startTime));
+            }
+
+            long fsyncDuration = fsyncTime - writeTime;
+            mSyncTimes.add(Long.valueOf(fsyncDuration).intValue());
+            mNumSync++;
+
+            if (DEBUG || mNumSync % 1024 == 0 || fsyncDuration > MAX_FSYNC_DURATION_MILLIS) {
+                mSyncTimes.log(TAG, "Time required to fsync " + mFile + ": ");
+            }
 
             return;
         } catch (XmlPullParserException e) {
diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java
index 5a0845f..a07e11e 100644
--- a/core/java/android/app/TaskStackListener.java
+++ b/core/java/android/app/TaskStackListener.java
@@ -35,7 +35,11 @@
     }
 
     @Override
-    public void onPinnedActivityRestartAttempt(String launchedFromPackage) throws RemoteException {
+    public void onPinnedActivityRestartAttempt() throws RemoteException {
+    }
+
+    @Override
+    public void onPinnedStackAnimationStarted() throws RemoteException {
     }
 
     @Override
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index 34a0c30..0fb5966 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -779,6 +779,8 @@
      * become affiliated again (even if security logging is enabled).
      * See {@link DevicePolicyManager#setAffiliationIds}
      *
+     * <p>This callback will be re-triggered if the logs are not retrieved.
+     *
      * <p>This callback is only applicable to device owners.
      *
      * @param context The running context as per {@link #onReceive}.
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 2ace0a2..3be4dd8 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -3346,6 +3346,17 @@
     public static final int KEYGUARD_DISABLE_FEATURES_ALL = 0x7fffffff;
 
     /**
+     * Keyguard features that when set on a managed profile that doesn't have its own challenge will
+     * affect the profile's parent user. These can also be set on the managed profile's parent
+     * {@link DevicePolicyManager} instance.
+     *
+     * @hide
+     */
+    public static final int PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER =
+            DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS
+            | DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT;
+
+    /**
      * Called by an application that is administering the device to request that the storage system
      * be encrypted.
      * <p>
@@ -6343,7 +6354,6 @@
      * The settings that can be updated by a profile or device owner with this method are:
      * <ul>
      * <li>{@link Settings.Secure#DEFAULT_INPUT_METHOD}</li>
-     * <li>{@link Settings.Secure#INSTALL_NON_MARKET_APPS}</li>
      * <li>{@link Settings.Secure#SKIP_FIRST_USE_HINTS}</li>
      * </ul>
      * <p>
@@ -6352,6 +6362,15 @@
      * <li>{@link Settings.Secure#LOCATION_MODE}</li>
      * </ul>
      *
+     * <strong>Note: Starting from Android O, apps should no longer call this method with the
+     * setting {@link android.provider.Settings.Secure#INSTALL_NON_MARKET_APPS}, which is
+     * deprecated. Instead, device owners or profile owners should use the restriction
+     * {@link UserManager#DISALLOW_INSTALL_UNKNOWN_SOURCES}.
+     * If any app targeting {@link android.os.Build.VERSION_CODES#O} or higher calls this method
+     * with {@link android.provider.Settings.Secure#INSTALL_NON_MARKET_APPS},
+     * an {@link UnsupportedOperationException} is thrown.
+     * </strong>
+     *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param setting The name of the setting to update.
      * @param value The value to update the setting to.
@@ -7689,7 +7708,34 @@
     /**
      * Called by a device owner to control the network logging feature.
      *
-     * <p> Network logs contain DNS lookup and connect() library call events.
+     * <p> Network logs contain DNS lookup and connect() library call events. The following library
+     *     functions are recorded while network logging is active:
+     *     <ul>
+     *       <li>{@code getaddrinfo()}</li>
+     *       <li>{@code gethostbyname()}</li>
+     *       <li>{@code connect()}</li>
+     *     </ul>
+     *
+     * <p> Network logging is a low-overhead tool for forensics but it is not guaranteed to use
+     *     full system call logging; event reporting is enabled by default for all processes but not
+     *     strongly enforced.
+     *     Events from applications using alternative implementations of libc, making direct kernel
+     *     calls, or deliberately obfuscating traffic may not be recorded.
+     *
+     * <p> Some common network events may not be reported. For example:
+     *     <ul>
+     *       <li>Applications may hardcode IP addresses to reduce the number of DNS lookups, or use
+     *           an alternative system for name resolution, and so avoid calling
+     *           {@code getaddrinfo()} or {@code gethostbyname}.</li>
+     *       <li>Applications may use datagram sockets for performance reasons, for example
+     *           for a game client. Calling {@code connect()} is unnecessary for this kind of
+     *           socket, so it will not trigger a network event.</li>
+     *     </ul>
+     *
+     * <p> It is possible to directly intercept layer 3 traffic leaving the device using an
+     *     always-on VPN service.
+     *     See {@link #setAlwaysOnVpnPackage(ComponentName, String, boolean)}
+     *     and {@link android.net.VpnService} for details.
      *
      * <p><strong>Note:</strong> The device owner won't be able to retrieve network logs if there
      * are unaffiliated secondary users or profiles on the device, regardless of whether the
@@ -7891,23 +7937,42 @@
     }
 
     /**
-     * Called by the system to find out whether the user's IME was set by the device/profile owner
-     * or the user.
+     * Called by the system to find out whether the current user's IME was set by the device/profile
+     * owner or the user.
      *
-     * @param user The user for whom to retrieve information.
      * @return {@code true} if the user's IME was set by the device or profile owner, {@code false}
      *         otherwise.
-     * @throws SecurityException if the caller does not have permission to retrieve information
-     *         about the given user's default IME. Device Owner and Profile Owner can retrieve
-     *         information about the user they run on; the System can retrieve information about any
-     *         user.
+     * @throws SecurityException if the caller is not the device owner/profile owner.
      *
      * @hide
      */
     @TestApi
-    public boolean isDefaultInputMethodSetByOwner(@NonNull UserHandle user) {
+    public boolean isCurrentInputMethodSetByOwner() {
         try {
-            return mService.isDefaultInputMethodSetByOwner(user);
+            return mService.isCurrentInputMethodSetByOwner();
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Called by the system to get a list of CA certificates that were installed by the device or
+     * profile owner.
+     *
+     * <p> The caller must be the target user's device owner/profile Owner or hold the
+     * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission.
+     *
+     * @param user The user for whom to retrieve information.
+     * @return list of aliases identifying CA certificates installed by the device or profile owner
+     * @throws SecurityException if the caller does not have permission to retrieve information
+     *         about the given user's CA certificates.
+     *
+     * @hide
+     */
+    @TestApi
+    public List<String> getOwnerInstalledCaCerts(@NonNull UserHandle user) {
+        try {
+            return mService.getOwnerInstalledCaCerts(user).getList();
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index ec97c2c..8ea911f 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -27,6 +27,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.ParceledListSlice;
+import android.content.pm.StringParceledListSlice;
 import android.graphics.Bitmap;
 import android.net.ProxyInfo;
 import android.net.Uri;
@@ -348,5 +349,6 @@
     boolean isResetPasswordTokenActive(in ComponentName admin);
     boolean resetPasswordWithToken(in ComponentName admin, String password, in byte[] token, int flags);
 
-    boolean isDefaultInputMethodSetByOwner(in UserHandle user);
+    boolean isCurrentInputMethodSetByOwner();
+    StringParceledListSlice getOwnerInstalledCaCerts(in UserHandle user);
 }
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 8d385db..2e0ca02 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -26,6 +26,7 @@
 import android.view.autofill.AutoFillValue;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 
 /**
  * Assist data automatically created by the platform's implementation
@@ -419,7 +420,7 @@
             mDisplayId = root.getDisplayId();
             mRoot = new ViewNode();
 
-            ViewNodeBuilder builder = new ViewNodeBuilder(assist, mRoot, false, 0);
+            ViewNodeBuilder builder = new ViewNodeBuilder(assist, mRoot, false);
             if ((root.getWindowFlags() & WindowManager.LayoutParams.FLAG_SECURE) != 0) {
                 if (forAutoFill) {
                     // NOTE: flags are currently not supported, hence 0
@@ -533,12 +534,16 @@
         String mIdPackage;
         String mIdType;
         String mIdEntry;
+
         // TODO(b/33197203): once we have more flags, it might be better to store the individual
         // fields (viewId and childId) of the field.
         AutoFillId mAutoFillId;
-        AutoFillType mAutoFillType;
+        @View.AutofillType int mAutofillType;
+        @View.AutoFillHint int mAutoFillHint;
         AutoFillValue mAutoFillValue;
+        String[] mAutoFillOptions;
         boolean mSanitized;
+
         int mX;
         int mY;
         int mScrollX;
@@ -580,6 +585,7 @@
         static final int FLAGS_HAS_ID = 0x00200000;
         static final int FLAGS_HAS_CHILDREN = 0x00100000;
         static final int FLAGS_HAS_URL = 0x00080000;
+        static final int FLAGS_HAS_INPUT_TYPE = 0x00040000;
         static final int FLAGS_ALL_CONTROL = 0xfff00000;
 
         int mFlags;
@@ -588,6 +594,7 @@
         CharSequence mContentDescription;
 
         ViewNodeText mText;
+        int mInputType;
         String mUrl;
         Bundle mExtras;
 
@@ -616,8 +623,10 @@
             if ((flags&FLAGS_HAS_AUTO_FILL_DATA) != 0) {
                 mSanitized = in.readInt() == 1;
                 mAutoFillId = in.readParcelable(null);
-                mAutoFillType = in.readParcelable(null);
+                mAutofillType = in.readInt();
+                mAutoFillHint = in.readInt();
                 mAutoFillValue = in.readParcelable(null);
+                mAutoFillOptions = in.readStringArray();
             }
             if ((flags&FLAGS_HAS_LARGE_COORDS) != 0) {
                 mX = in.readInt();
@@ -653,6 +662,9 @@
             if ((flags&FLAGS_HAS_TEXT) != 0) {
                 mText = new ViewNodeText(in, (flags&FLAGS_HAS_COMPLEX_TEXT) == 0);
             }
+            if ((flags&FLAGS_HAS_INPUT_TYPE) != 0) {
+                mInputType = in.readInt();
+            }
             if ((flags&FLAGS_HAS_URL) != 0) {
                 mUrl = in.readString();
             }
@@ -709,6 +721,9 @@
                     flags |= FLAGS_HAS_COMPLEX_TEXT;
                 }
             }
+            if (mInputType != 0) {
+                flags |= FLAGS_HAS_INPUT_TYPE;
+            }
             if (mUrl != null) {
                 flags |= FLAGS_HAS_URL;
             }
@@ -720,7 +735,14 @@
             }
 
             pwriter.writeString(mClassName);
-            out.writeInt(flags);
+
+            int writtenFlags = flags;
+            if ((flags&FLAGS_HAS_AUTO_FILL_DATA) != 0 && (mSanitized || !sanitizeOnWrite)) {
+                // Remove 'checked' from sanitized auto-fill request.
+                writtenFlags = flags & ~FLAGS_CHECKED;
+            }
+
+            out.writeInt(writtenFlags);
             if ((flags&FLAGS_HAS_ID) != 0) {
                 out.writeInt(mId);
                 if (mId != 0) {
@@ -735,9 +757,11 @@
                 writeSensitive = mSanitized || !sanitizeOnWrite;
                 out.writeInt(mSanitized ? 1 : 0);
                 out.writeParcelable(mAutoFillId, 0);
-                out.writeParcelable(mAutoFillType,  0);
+                out.writeInt(mAutofillType);
+                out.writeInt(mAutoFillHint);
                 final AutoFillValue sanitizedValue = writeSensitive ? mAutoFillValue : null;
                 out.writeParcelable(sanitizedValue,  0);
+                out.writeStringArray(mAutoFillOptions);
             }
             if ((flags&FLAGS_HAS_LARGE_COORDS) != 0) {
                 out.writeInt(mX);
@@ -768,6 +792,10 @@
             if ((flags&FLAGS_HAS_TEXT) != 0) {
                 mText.writeToParcel(out, (flags&FLAGS_HAS_COMPLEX_TEXT) == 0, writeSensitive);
             }
+            if ((flags&FLAGS_HAS_INPUT_TYPE) != 0) {
+                out.writeInt(mInputType);
+            }
+
             if ((flags&FLAGS_HAS_URL) != 0) {
                 out.writeString(mUrl);
             }
@@ -823,14 +851,46 @@
         }
 
         /**
+         * @deprecated TODO(b/35956626): remove once clients use getAutoFilltype()
+         */
+        @Deprecated
+        public AutoFillType getAutoFillType() {
+            switch (getAutofillType()) {
+                case View.AUTOFILL_TYPE_TEXT:
+                    return AutoFillType.forText();
+                case View.AUTOFILL_TYPE_TOGGLE:
+                    return AutoFillType.forToggle();
+                case View.AUTOFILL_TYPE_LIST:
+                    return AutoFillType.forList();
+                case View.AUTOFILL_TYPE_DATE:
+                    return AutoFillType.forDate();
+                default:
+                    return null;
+            }
+        }
+
+        /**
          * Gets the the type of value that can be used to auto-fill the view contents.
          *
          * <p>It's only set when the {@link AssistStructure} is used for auto-filling purposes, not
          * for assist.
          */
-        // TODO(b/33197203, b/33802548): add CTS/unit test
-        public AutoFillType getAutoFillType() {
-            return mAutoFillType;
+        public @View.AutofillType int getAutofillType() {
+            return mAutofillType;
+        }
+
+        /**
+         * Describes the content of a view so that a auto-fill service can fill in the appropriate
+         * data.
+         *
+         * <p>It's only set when the {@link AssistStructure} is used for auto-filling purposes, not
+         * for assist.</p>
+         *
+         * @return The hint for this view
+         */
+        // TODO(b/35364993): add CTS/unit test
+        @View.AutoFillHint public int getAutoFillHint() {
+            return mAutoFillHint;
         }
 
         /**
@@ -844,6 +904,28 @@
             return mAutoFillValue;
         }
 
+        /**
+         * Gets the options that can be used to auto-fill this structure.
+         *
+         * <p>Typically used by nodes whose {@link AutoFillType} is a list to indicate the meaning
+         * of each possible value in the list.
+         *
+         * <p>It's only set when the {@link AssistStructure} is used for auto-filling purposes, not
+         * for assist.
+         */
+        public String[] getAutoFillOptions() {
+            return mAutoFillOptions;
+        }
+
+        /**
+         * Gets the {@link android.text.InputType} bits of this structure.
+         *
+         * @return bits as defined by {@link android.text.InputType}.
+         */
+        public int getInputType() {
+            return mInputType;
+        }
+
         /** @hide */
         public boolean isSanitized() {
             return mSanitized;
@@ -1059,6 +1141,10 @@
          * <li>Root node (containing the URL of the HTML page)
          * <li>Child nodes that represent hyperlinks (contains the hyperlink URL).
          * </ol>
+         *
+         * <strong>WARNING:</strong> a {@link android.service.autofill.AutoFillService} should only
+         * use this URL for auto-fill purposes when it trusts the app generating it (i.e., the app
+         * defined by {@link AssistStructure#getActivityComponent()}).
          */
         public String getUrl() {
             return mUrl;
@@ -1187,11 +1273,10 @@
         final ViewNode mNode;
         final boolean mAsync;
 
-        ViewNodeBuilder(AssistStructure assist, ViewNode node, boolean async, int flags) {
+        ViewNodeBuilder(AssistStructure assist, ViewNode node, boolean async) {
             mAssist = assist;
             mNode = node;
             mAsync = async;
-            mNode.mSanitized = (flags & AUTO_FILL_FLAG_SANITIZED) != 0;
         }
 
         @Override
@@ -1429,16 +1514,15 @@
             ViewNode node = new ViewNode();
             setAutoFillId(node, forAutoFill, virtualId);
             mNode.mChildren[index] = node;
-            return new ViewNodeBuilder(mAssist, node, false, flags);
+            return new ViewNodeBuilder(mAssist, node, false);
         }
 
-        private ViewStructure asyncNewChild(int index, boolean forAutoFill, int virtualId,
-                int flags) {
+        private ViewStructure asyncNewChild(int index, boolean forAutoFill, int virtualId) {
             synchronized (mAssist) {
                 ViewNode node = new ViewNode();
                 setAutoFillId(node, forAutoFill, virtualId);
                 mNode.mChildren[index] = node;
-                ViewNodeBuilder builder = new ViewNodeBuilder(mAssist, node, true, flags);
+                ViewNodeBuilder builder = new ViewNodeBuilder(mAssist, node, true);
                 mAssist.mPendingAsyncChildren.add(builder);
                 return builder;
             }
@@ -1451,18 +1535,18 @@
 
         // TODO(b/33197203, b/33802548): add CTS/unit test
         @Override
-        public ViewStructure newChild(int index, int virtualId, int flags) {
+        public ViewStructure newChildForAutoFill(int index, int virtualId, int flags) {
             return newChild(index, true, virtualId, flags);
         }
 
         @Override
         public ViewStructure asyncNewChild(int index) {
-            return asyncNewChild(index, false, 0, 0);
+            return asyncNewChild(index, false, 0);
         }
 
         @Override
-        public ViewStructure asyncNewChild(int index, int virtualId, int flags) {
-            return asyncNewChild(index, true, virtualId, flags);
+        public ViewStructure asyncNewChildForAutoFill(int index, int virtualId, int flags) {
+            return asyncNewChild(index, true, virtualId);
         }
 
         @Override
@@ -1496,7 +1580,27 @@
 
         @Override
         public void setAutoFillType(AutoFillType type) {
-           mNode.mAutoFillType = type;
+            if (type == null) return;
+
+            if (type.isText()) {
+                mNode.mAutofillType = View.AUTOFILL_TYPE_TEXT;
+            } else if (type.isToggle()) {
+                mNode.mAutofillType = View.AUTOFILL_TYPE_TOGGLE;
+            } else if (type.isList()) {
+                mNode.mAutofillType = View.AUTOFILL_TYPE_LIST;
+            } else if (type.isDate()) {
+                mNode.mAutofillType = View.AUTOFILL_TYPE_DATE;
+            }
+        }
+
+        @Override
+        public void setAutofillType(@View.AutofillType int type) {
+            mNode.mAutofillType = type;
+        }
+
+        @Override
+        public void setAutoFillHint(@View.AutoFillHint int hint) {
+            mNode.mAutoFillHint = hint;
         }
 
         @Override
@@ -1504,9 +1608,16 @@
             mNode.mAutoFillValue = value;
         }
 
-        /**
-         * @hide
-         */
+        @Override
+        public void setAutoFillOptions(String[] options) {
+            mNode.mAutoFillOptions = options;
+        }
+
+        @Override
+        public void setInputType(int inputType) {
+            mNode.mInputType = inputType;
+        }
+
         @Override
         public void setSanitized(boolean sanitized) {
             mNode.mSanitized = sanitized;
@@ -1633,7 +1744,10 @@
             Log.i(TAG, prefix + " NO AUTO-FILL ID");
         } else {
             Log.i(TAG, prefix + "AutoFill info: id= " + autoFillId
-                    + ", type=" + node.getAutoFillType()
+                    + ", type=" + node.getAutofillType()
+                    + ", options=" + Arrays.toString(node.getAutoFillOptions())
+                    + ", inputType=" + node.getInputType()
+                    + ", hint=" + Integer.toHexString(node.getAutoFillHint())
                     + ", value=" + node.getAutoFillValue()
                     + ", sanitized=" + node.isSanitized());
         }
diff --git a/core/java/android/app/backup/BackupManagerMonitor.java b/core/java/android/app/backup/BackupManagerMonitor.java
index 099878b..ebad16e 100644
--- a/core/java/android/app/backup/BackupManagerMonitor.java
+++ b/core/java/android/app/backup/BackupManagerMonitor.java
@@ -54,12 +54,120 @@
   public static final String EXTRA_LOG_EVENT_CATEGORY =
           "android.app.backup.extra.LOG_EVENT_CATEGORY";
 
+
+  /**
+   * boolean: when we have an event with id LOG_EVENT_ID_KEY_VALUE_BACKUP_CANCEL we record if
+   * the call was to cancel backup of all packages
+   */
+  public static final String EXTRA_LOG_CANCEL_ALL = "android.app.backup.extra.LOG_CANCEL_ALL";
+
+  /**
+   * string: when we have an event with id LOG_EVENT_ID_ILLEGAL_KEY we send the key that was used
+   * by the app
+   */
+  public static final String EXTRA_LOG_ILLEGAL_KEY = "android.app.backup.extra.LOG_ILLEGAL_KEY";
+
+  /**
+   * long: when we have an event with id LOG_EVENT_ID_ERROR_PREFLIGHT we send the error code that
+   * was returned by the transport during preflight
+   */
+  public static final String EXTRA_LOG_PREFLIGHT_ERROR =
+          "android.app.backup.extra.LOG_PREFLIGHT_ERROR";
+
+  /**
+   * string: when we have an event with id LOG_EVENT_ID_EXCEPTION_FULL_BACKUP we send the
+   * exception's stacktrace
+   */
+  public static final String EXTRA_LOG_EXCEPTION_FULL_BACKUP =
+          "android.app.backup.extra.LOG_EXCEPTION_FULL_BACKUP";
+
+  /**
+   * int: when we have an event with id LOG_EVENT_ID_RESTORE_VERSION_HIGHER we send the
+   * restore package version
+   */
+  public static final String EXTRA_LOG_RESTORE_VERSION =
+          "android.app.backup.extra.LOG_RESTORE_VERSION";
+
+  /**
+   * boolean: when we have an event with id LOG_EVENT_ID_RESTORE_VERSION_HIGHER we record if
+   * ApplicationInfo.FLAG_RESTORE_ANY_VERSION flag is set
+   */
+  public static final String EXTRA_LOG_RESTORE_ANYWAY =
+          "android.app.backup.extra.LOG_RESTORE_ANYWAY";
+
+
+  /**
+   * boolean: when we have an event with id LOG_EVENT_ID_APK_NOT_INSTALLED we record if
+   * the policy allows to install apks provided with the dataset
+   */
+  public static final String EXTRA_LOG_POLICY_ALLOW_APKS =
+          "android.app.backup.extra.LOG_POLICY_ALLOW_APKS";
+
+
+  /**
+   * string: when we have an event with id LOG_EVENT_ID_EXPECTED_DIFFERENT_PACKAGE we record the
+   * package name provided in the restore manifest
+   */
+  public static final String EXTRA_LOG_MANIFEST_PACKAGE_NAME =
+          "android.app.backup.extra.LOG_MANIFEST_PACKAGE_NAME";
+
+  /**
+   * string: when we have an event with id LOG_EVENT_ID_WIDGET_METADATA_MISMATCH we record the
+   * package name provided in the widget metadata
+   */
+  public static final String EXTRA_LOG_WIDGET_PACKAGE_NAME =
+          "android.app.backup.extra.LOG_WIDGET_PACKAGE_NAME";
+
+  /**
+   * int: when we have event of id LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER we send the version
+   * of the backup.
+   */
+  public static final String EXTRA_LOG_OLD_VERSION = "android.app.backup.extra.LOG_OLD_VERSION";
+
   // TODO complete this list with all log messages. And document properly.
-  public static final int LOG_EVENT_ID_FULL_BACKUP_TIMEOUT = 4;
-  public static final int LOG_EVENT_ID_KEY_VALUE_BACKUP_TIMEOUT = 21;
+  public static final int LOG_EVENT_ID_FULL_BACKUP_CANCEL = 4;
+  public static final int LOG_EVENT_ID_ILLEGAL_KEY = 5;
+  public static final int LOG_EVENT_ID_NO_DATA_TO_SEND = 7;
+  public static final int LOG_EVENT_ID_PACKAGE_INELIGIBLE = 9;
+  public static final int LOG_EVENT_ID_PACKAGE_KEY_VALUE_PARTICIPANT = 10;
+  public static final int LOG_EVENT_ID_PACKAGE_STOPPED = 11;
+  public static final int LOG_EVENT_ID_PACKAGE_NOT_FOUND = 12;
+  public static final int LOG_EVENT_ID_BACKUP_DISABLED = 13;
+  public static final int LOG_EVENT_ID_DEVICE_NOT_PROVISIONED = 14;
+  public static final int LOG_EVENT_ID_PACKAGE_TRANSPORT_NOT_PRESENT = 15;
+  public static final int LOG_EVENT_ID_ERROR_PREFLIGHT = 16;
+  public static final int LOG_EVENT_ID_QUOTA_HIT_PREFLIGHT = 18;
+  public static final int LOG_EVENT_ID_EXCEPTION_FULL_BACKUP = 19;
+  public static final int LOG_EVENT_ID_KEY_VALUE_BACKUP_CANCEL = 21;
+  public static final int LOG_EVENT_ID_NO_RESTORE_METADATA_AVAILABLE = 22;
+  public static final int LOG_EVENT_ID_NO_PM_METADATA_RECEIVED = 23;
+  public static final int LOG_EVENT_ID_PM_AGENT_HAS_NO_METADATA = 24;
+  public static final int LOG_EVENT_ID_LOST_TRANSPORT = 25;
+  public static final int LOG_EVENT_ID_PACKAGE_NOT_PRESENT = 26;
+  public static final int LOG_EVENT_ID_RESTORE_VERSION_HIGHER = 27;
+  public static final int LOG_EVENT_ID_APP_HAS_NO_AGENT = 28;
+  public static final int LOG_EVENT_ID_SIGNATURE_MISMATCH = 29;
+  public static final int LOG_EVENT_ID_CANT_FIND_AGENT = 30;
   public static final int LOG_EVENT_ID_KEY_VALUE_RESTORE_TIMEOUT = 31;
+  public static final int LOG_EVENT_ID_RESTORE_ANY_VERSION = 34;
+  public static final int LOG_EVENT_ID_VERSIONS_MATCH = 35;
+  public static final int LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER = 36;
+  public static final int LOG_EVENT_ID_FULL_RESTORE_SIGNATURE_MISMATCH = 37;
+  public static final int LOG_EVENT_ID_SYSTEM_APP_NO_AGENT = 38;
+  public static final int LOG_EVENT_ID_FULL_RESTORE_ALLOW_BACKUP_FALSE = 39;
+  public static final int LOG_EVENT_ID_APK_NOT_INSTALLED = 40;
+  public static final int LOG_EVENT_ID_CANNOT_RESTORE_WITHOUT_APK = 41;
+  public static final int LOG_EVENT_ID_MISSING_SIGNATURE = 42;
+  public static final int LOG_EVENT_ID_EXPECTED_DIFFERENT_PACKAGE = 43;
+  public static final int LOG_EVENT_ID_UNKNOWN_VERSION = 44;
   public static final int LOG_EVENT_ID_FULL_RESTORE_TIMEOUT = 45;
+  public static final int LOG_EVENT_ID_CORRUPT_MANIFEST = 46;
+  public static final int LOG_EVENT_ID_WIDGET_METADATA_MISMATCH = 47;
+  public static final int LOG_EVENT_ID_WIDGET_UNKNOWN_VERSION = 48;
   public static final int LOG_EVENT_ID_NO_PACKAGES = 49;
+  public static final int LOG_EVENT_ID_TRANSPORT_IS_NULL = 50;
+
+
 
 
 
diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java
index 2d6b45d..6652eee 100644
--- a/core/java/android/app/job/JobInfo.java
+++ b/core/java/android/app/job/JobInfo.java
@@ -174,12 +174,26 @@
      */
     public static final int FLAG_WILL_BE_FOREGROUND = 1 << 0;
 
+    /**
+     * @hide
+     */
+    public static final int CONSTRAINT_FLAG_CHARGING = 1 << 0;
+
+    /**
+     * @hide
+     */
+    public static final int CONSTRAINT_FLAG_BATTERY_NOT_LOW = 1 << 1;
+
+    /**
+     * @hide
+     */
+    public static final int CONSTRAINT_FLAG_DEVICE_IDLE = 1 << 2;
+
     private final int jobId;
     private final PersistableBundle extras;
     private final Bundle transientExtras;
     private final ComponentName service;
-    private final boolean requireCharging;
-    private final boolean requireDeviceIdle;
+    private final int constraintFlags;
     private final TriggerContentUri[] triggerContentUris;
     private final long triggerContentUpdateDelay;
     private final long triggerContentMaxDelay;
@@ -241,14 +255,28 @@
      * Whether this job needs the device to be plugged in.
      */
     public boolean isRequireCharging() {
-        return requireCharging;
+        return (constraintFlags & CONSTRAINT_FLAG_CHARGING) != 0;
+    }
+
+    /**
+     * Whether this job needs the device's battery level to not be at below the critical threshold.
+     */
+    public boolean isRequireBatteryNotLow() {
+        return (constraintFlags & CONSTRAINT_FLAG_BATTERY_NOT_LOW) != 0;
     }
 
     /**
      * Whether this job needs the device to be in an Idle maintenance window.
      */
     public boolean isRequireDeviceIdle() {
-        return requireDeviceIdle;
+        return (constraintFlags & CONSTRAINT_FLAG_DEVICE_IDLE) != 0;
+    }
+
+    /**
+     * @hide
+     */
+    public int getConstraintFlags() {
+        return constraintFlags;
     }
 
     /**
@@ -376,8 +404,7 @@
         extras = in.readPersistableBundle();
         transientExtras = in.readBundle();
         service = in.readParcelable(null);
-        requireCharging = in.readInt() == 1;
-        requireDeviceIdle = in.readInt() == 1;
+        constraintFlags = in.readInt();
         triggerContentUris = in.createTypedArray(TriggerContentUri.CREATOR);
         triggerContentUpdateDelay = in.readLong();
         triggerContentMaxDelay = in.readLong();
@@ -398,11 +425,10 @@
 
     private JobInfo(JobInfo.Builder b) {
         jobId = b.mJobId;
-        extras = b.mExtras.deepcopy();
-        transientExtras = b.mTransientExtras.deepcopy();
+        extras = b.mExtras.deepCopy();
+        transientExtras = b.mTransientExtras.deepCopy();
         service = b.mJobService;
-        requireCharging = b.mRequiresCharging;
-        requireDeviceIdle = b.mRequiresDeviceIdle;
+        constraintFlags = b.mConstraintFlags;
         triggerContentUris = b.mTriggerContentUris != null
                 ? b.mTriggerContentUris.toArray(new TriggerContentUri[b.mTriggerContentUris.size()])
                 : null;
@@ -434,8 +460,7 @@
         out.writePersistableBundle(extras);
         out.writeBundle(transientExtras);
         out.writeParcelable(service, flags);
-        out.writeInt(requireCharging ? 1 : 0);
-        out.writeInt(requireDeviceIdle ? 1 : 0);
+        out.writeInt(constraintFlags);
         out.writeTypedArray(triggerContentUris, flags);
         out.writeLong(triggerContentUpdateDelay);
         out.writeLong(triggerContentMaxDelay);
@@ -563,8 +588,7 @@
         private int mPriority = PRIORITY_DEFAULT;
         private int mFlags;
         // Requirements.
-        private boolean mRequiresCharging;
-        private boolean mRequiresDeviceIdle;
+        private int mConstraintFlags;
         private int mNetworkType;
         private ArrayList<TriggerContentUri> mTriggerContentUris;
         private long mTriggerContentUpdateDelay = -1;
@@ -651,7 +675,21 @@
          * @param requiresCharging Whether or not the device is plugged in.
          */
         public Builder setRequiresCharging(boolean requiresCharging) {
-            mRequiresCharging = requiresCharging;
+            mConstraintFlags = (mConstraintFlags&~CONSTRAINT_FLAG_CHARGING)
+                    | (requiresCharging ? CONSTRAINT_FLAG_CHARGING : 0);
+            return this;
+        }
+
+        /**
+         * Specify that to run this job, the device's battery level must not be low.
+         * This defaults to false.  If true, the job will only run when the battery level
+         * is not low, which is generally the point where the user is given a "low battery"
+         * warning.
+         * @param batteryNotLow Whether or not the device's battery level must not be low.
+         */
+        public Builder setRequiresBatteryNotLow(boolean batteryNotLow) {
+            mConstraintFlags = (mConstraintFlags&~CONSTRAINT_FLAG_BATTERY_NOT_LOW)
+                    | (batteryNotLow ? CONSTRAINT_FLAG_BATTERY_NOT_LOW : 0);
             return this;
         }
 
@@ -666,7 +704,8 @@
          *                           window.
          */
         public Builder setRequiresDeviceIdle(boolean requiresDeviceIdle) {
-            mRequiresDeviceIdle = requiresDeviceIdle;
+            mConstraintFlags = (mConstraintFlags&~CONSTRAINT_FLAG_DEVICE_IDLE)
+                    | (requiresDeviceIdle ? CONSTRAINT_FLAG_DEVICE_IDLE : 0);
             return this;
         }
 
@@ -816,8 +855,8 @@
          */
         public JobInfo build() {
             // Allow jobs with no constraints - What am I, a database?
-            if (!mHasEarlyConstraint && !mHasLateConstraint && !mRequiresCharging &&
-                    !mRequiresDeviceIdle && mNetworkType == NETWORK_TYPE_NONE &&
+            if (!mHasEarlyConstraint && !mHasLateConstraint && mConstraintFlags == 0 &&
+                    mNetworkType == NETWORK_TYPE_NONE &&
                     mTriggerContentUris == null) {
                 throw new IllegalArgumentException("You're trying to build a job with no " +
                         "constraints, this is not allowed.");
@@ -843,7 +882,7 @@
                 throw new IllegalArgumentException("Can't call setTransientExtras() on a " +
                         "persisted job");
             }
-            if (mBackoffPolicySet && mRequiresDeviceIdle) {
+            if (mBackoffPolicySet && (mConstraintFlags & CONSTRAINT_FLAG_DEVICE_IDLE) != 0) {
                 throw new IllegalArgumentException("An idle mode job will not respect any" +
                         " back-off policy, so calling setBackoffCriteria with" +
                         " setRequiresDeviceIdle is an error.");
diff --git a/core/java/com/android/internal/logging/legacy/Util.java b/core/java/android/app/usage/CacheQuotaHint.aidl
similarity index 77%
copy from core/java/com/android/internal/logging/legacy/Util.java
copy to core/java/android/app/usage/CacheQuotaHint.aidl
index 99f71ca..0470ea7 100644
--- a/core/java/com/android/internal/logging/legacy/Util.java
+++ b/core/java/android/app/usage/CacheQuotaHint.aidl
@@ -13,13 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.internal.logging.legacy;
 
-/**
- * Created by cwren on 11/21/16.
- */
-public class Util {
-    public static boolean debug() {
-        return false;
-    }
-}
+package android.app.usage;
+
+/** {@hide} */
+parcelable CacheQuotaHint;
\ No newline at end of file
diff --git a/core/java/android/app/usage/CacheQuotaHint.java b/core/java/android/app/usage/CacheQuotaHint.java
new file mode 100644
index 0000000..1d5c2b0
--- /dev/null
+++ b/core/java/android/app/usage/CacheQuotaHint.java
@@ -0,0 +1,160 @@
+/*
+ * 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 android.app.usage;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.Objects;
+
+/**
+ * CacheQuotaHint represents a triplet of a uid, the volume UUID it is stored upon, and
+ * its usage stats. When processed, it obtains a cache quota as defined by the system which
+ * allows apps to understand how much cache to use.
+ * {@hide}
+ */
+@SystemApi
+public final class CacheQuotaHint implements Parcelable {
+    public static final long QUOTA_NOT_SET = -1;
+    private final String mUuid;
+    private final int mUid;
+    private final UsageStats mUsageStats;
+    private final long mQuota;
+
+    /**
+     * Create a new request.
+     * @param builder A builder for this object.
+     */
+    public CacheQuotaHint(Builder builder) {
+        this.mUuid = builder.mUuid;
+        this.mUid = builder.mUid;
+        this.mUsageStats = builder.mUsageStats;
+        this.mQuota = builder.mQuota;
+    }
+
+    public String getVolumeUuid() {
+        return mUuid;
+    }
+
+    public int getUid() {
+        return mUid;
+    }
+
+    public long getQuota() {
+        return mQuota;
+    }
+
+    public UsageStats getUsageStats() {
+        return mUsageStats;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mUuid);
+        dest.writeInt(mUid);
+        dest.writeLong(mQuota);
+        dest.writeParcelable(mUsageStats, 0);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o instanceof CacheQuotaHint) {
+            final CacheQuotaHint other = (CacheQuotaHint) o;
+            return Objects.equals(mUuid, other.mUuid)
+                    && Objects.equals(mUsageStats, other.mUsageStats)
+                    && mUid == other.mUid && mQuota == other.mQuota;
+        }
+
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(this.mUuid, this.mUid, this.mUsageStats, this.mQuota);
+    }
+
+    public static final class Builder {
+        private String mUuid;
+        private int mUid;
+        private UsageStats mUsageStats;
+        private long mQuota;
+
+        public Builder() {
+        }
+
+        public Builder(CacheQuotaHint hint) {
+            setVolumeUuid(hint.getVolumeUuid());
+            setUid(hint.getUid());
+            setUsageStats(hint.getUsageStats());
+            setQuota(hint.getQuota());
+        }
+
+        public @NonNull Builder setVolumeUuid(@Nullable String uuid) {
+            mUuid = uuid;
+            return this;
+        }
+
+        public @NonNull Builder setUid(int uid) {
+            Preconditions.checkArgumentNonnegative(uid, "Proposed uid was negative.");
+            mUid = uid;
+            return this;
+        }
+
+        public @NonNull Builder setUsageStats(@Nullable UsageStats stats) {
+            mUsageStats = stats;
+            return this;
+        }
+
+        public @NonNull Builder setQuota(long quota) {
+            Preconditions.checkArgument((quota >= QUOTA_NOT_SET));
+            mQuota = quota;
+            return this;
+        }
+
+        public @NonNull CacheQuotaHint build() {
+            return new CacheQuotaHint(this);
+        }
+    }
+
+    public static final Parcelable.Creator<CacheQuotaHint> CREATOR =
+            new Creator<CacheQuotaHint>() {
+                @Override
+                public CacheQuotaHint createFromParcel(Parcel in) {
+                    final Builder builder = new Builder();
+                    return builder.setVolumeUuid(in.readString())
+                            .setUid(in.readInt())
+                            .setQuota(in.readLong())
+                            .setUsageStats(in.readParcelable(UsageStats.class.getClassLoader()))
+                            .build();
+                }
+
+                @Override
+                public CacheQuotaHint[] newArray(int size) {
+                    return new CacheQuotaHint[size];
+                }
+            };
+}
diff --git a/core/java/android/app/usage/CacheQuotaService.java b/core/java/android/app/usage/CacheQuotaService.java
new file mode 100644
index 0000000..b9430ab
--- /dev/null
+++ b/core/java/android/app/usage/CacheQuotaService.java
@@ -0,0 +1,112 @@
+/*
+ * 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 android.app.usage;
+
+import android.annotation.SystemApi;
+import android.app.Service;
+import android.app.usage.ICacheQuotaService;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteCallback;
+import android.util.Log;
+import android.util.Pair;
+
+import java.util.List;
+
+/**
+ * CacheQuoteService defines a service which accepts cache quota requests and processes them,
+ * thereby filling out how much quota each request deserves.
+ * {@hide}
+ */
+@SystemApi
+public abstract class CacheQuotaService extends Service {
+    private static final String TAG = "CacheQuotaService";
+
+    /**
+     * The {@link Intent} action that must be declared as handled by a service
+     * in its manifest for the system to recognize it as a quota providing service.
+     */
+    public static final String SERVICE_INTERFACE = "android.app.usage.CacheQuotaService";
+
+    /** {@hide} **/
+    public static final String REQUEST_LIST_KEY = "requests";
+
+    private CacheQuotaServiceWrapper mWrapper;
+    private Handler mHandler;
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        mWrapper = new CacheQuotaServiceWrapper();
+        mHandler = new ServiceHandler(getMainLooper());
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return mWrapper;
+    }
+
+    /**
+     * Processes the cache quota list upon receiving a list of requests.
+     * @param requests A list of cache quotas to fulfill.
+     * @return A completed list of cache quota requests.
+     */
+    public abstract List<CacheQuotaHint> onComputeCacheQuotaHints(
+            List<CacheQuotaHint> requests);
+
+    private final class CacheQuotaServiceWrapper extends ICacheQuotaService.Stub {
+        @Override
+        public void computeCacheQuotaHints(
+                RemoteCallback callback, List<CacheQuotaHint> requests) {
+            final Pair<RemoteCallback, List<CacheQuotaHint>> pair =
+                    Pair.create(callback, requests);
+            Message msg = mHandler.obtainMessage(ServiceHandler.MSG_SEND_LIST, pair);
+            mHandler.sendMessage(msg);
+        }
+    }
+
+    private final class ServiceHandler extends Handler {
+        public static final int MSG_SEND_LIST = 1;
+
+        public ServiceHandler(Looper looper) {
+            super(looper, null, true);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            final int action = msg.what;
+            switch (action) {
+                case MSG_SEND_LIST:
+                    final Pair<RemoteCallback, List<CacheQuotaHint>> pair =
+                            (Pair<RemoteCallback, List<CacheQuotaHint>>) msg.obj;
+                    List<CacheQuotaHint> processed = onComputeCacheQuotaHints(pair.second);
+                    final Bundle data = new Bundle();
+                    data.putParcelableList(REQUEST_LIST_KEY, processed);
+
+                    final RemoteCallback callback = pair.first;
+                    callback.sendResult(data);
+                    break;
+                default:
+                    Log.w(TAG, "Handling unknown message: " + action);
+            }
+        }
+    }
+}
diff --git a/core/java/com/android/internal/logging/legacy/Util.java b/core/java/android/app/usage/ICacheQuotaService.aidl
similarity index 70%
copy from core/java/com/android/internal/logging/legacy/Util.java
copy to core/java/android/app/usage/ICacheQuotaService.aidl
index 99f71ca..8d984e0 100644
--- a/core/java/com/android/internal/logging/legacy/Util.java
+++ b/core/java/android/app/usage/ICacheQuotaService.aidl
@@ -13,13 +13,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.internal.logging.legacy;
 
-/**
- * Created by cwren on 11/21/16.
- */
-public class Util {
-    public static boolean debug() {
-        return false;
-    }
+package android.app.usage;
+
+import android.os.RemoteCallback;
+import android.app.usage.CacheQuotaHint;
+
+/** {@hide} */
+oneway interface ICacheQuotaService {
+    void computeCacheQuotaHints(in RemoteCallback callback, in List<CacheQuotaHint> requests);
 }
diff --git a/core/java/android/app/usage/IStorageStatsManager.aidl b/core/java/android/app/usage/IStorageStatsManager.aidl
index 62ebf60..76c0293 100644
--- a/core/java/android/app/usage/IStorageStatsManager.aidl
+++ b/core/java/android/app/usage/IStorageStatsManager.aidl
@@ -21,8 +21,10 @@
 
 /** {@hide} */
 interface IStorageStatsManager {
+    boolean isQuotaSupported(String volumeUuid, String callingPackage);
     long getTotalBytes(String volumeUuid, String callingPackage);
     long getFreeBytes(String volumeUuid, String callingPackage);
+    StorageStats queryStatsForPackage(String volumeUuid, String packageName, int userId, String callingPackage);
     StorageStats queryStatsForUid(String volumeUuid, int uid, String callingPackage);
     StorageStats queryStatsForUser(String volumeUuid, int userId, String callingPackage);
     ExternalStorageStats queryExternalStatsForUser(String volumeUuid, int userId, String callingPackage);
diff --git a/core/java/android/app/usage/StorageStatsManager.java b/core/java/android/app/usage/StorageStatsManager.java
index 9d30771..081ccd9 100644
--- a/core/java/android/app/usage/StorageStatsManager.java
+++ b/core/java/android/app/usage/StorageStatsManager.java
@@ -19,6 +19,7 @@
 import android.annotation.WorkerThread;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
 import android.os.RemoteException;
 import android.os.UserHandle;
 
@@ -46,6 +47,15 @@
         mService = Preconditions.checkNotNull(service);
     }
 
+    /** {@hide} */
+    public boolean isQuotaSupported(String volumeUuid) {
+        try {
+            return mService.isQuotaSupported(volumeUuid, mContext.getOpPackageName());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
     /**
      * Return the total space on the requested storage volume.
      * <p>
@@ -91,6 +101,37 @@
     }
 
     /**
+     * Return storage statistics for a specific package on the requested storage
+     * volume.
+     * <p>
+     * This method may take several seconds to calculate the requested values,
+     * so it should only be called from a worker thread.
+     * <p class="note">
+     * Note: if the requested package uses the {@code android:sharedUserId}
+     * manifest feature, this call will be forced into a slower manual
+     * calculation path. If possible, consider always using
+     * {@link #queryStatsForUid(String, int)}, which is typically faster.
+     * </p>
+     *
+     * @param volumeUuid the UUID of the storage volume you're interested in, or
+     *            {@code null} to specify the default internal storage.
+     * @param packageName the package name you're interested in.
+     * @param user the user you're interested in.
+     * @see ApplicationInfo#volumeUuid
+     * @see PackageInfo#packageName
+     */
+    @WorkerThread
+    public StorageStats queryStatsForPackage(String volumeUuid, String packageName,
+            UserHandle user) {
+        try {
+            return mService.queryStatsForPackage(volumeUuid, packageName, user.getIdentifier(),
+                    mContext.getOpPackageName());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Return storage statistics for a specific UID on the requested storage
      * volume.
      * <p>
diff --git a/core/java/android/app/usage/UsageStatsManagerInternal.java b/core/java/android/app/usage/UsageStatsManagerInternal.java
index a6f91fe..08595dd 100644
--- a/core/java/android/app/usage/UsageStatsManagerInternal.java
+++ b/core/java/android/app/usage/UsageStatsManagerInternal.java
@@ -19,7 +19,7 @@
 import android.content.ComponentName;
 import android.content.res.Configuration;
 
-import java.io.IOException;
+import java.util.List;
 
 /**
  * UsageStatsManager local system service interface.
@@ -127,4 +127,7 @@
 
     public abstract void applyRestoredPayload(int user, String key, byte[] payload);
 
+    /* Cache Quota Service API */
+    public abstract List<UsageStats> queryUsageStatsForUser(
+            int userId, int interval, long beginTime, long endTime);
 }
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index 077331e..67c791d 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -417,6 +417,17 @@
     public static final String EXTRA_APPWIDGET_OLD_IDS = "appWidgetOldIds";
 
     /**
+     * An extra that can be passed to
+     * {@link #requestPinAppWidget(ComponentName, Bundle, PendingIntent)}. This would allow the
+     * launcher app to present a custom preview to the user.
+     *
+     * <p>
+     * The value should be a {@link RemoteViews} similar to what is used with
+     * {@link #updateAppWidget} calls.
+     */
+    public static final String EXTRA_APPWIDGET_PREVIEW = "appWidgetPreview";
+
+    /**
      * Field for the manifest meta-data tag.
      *
      * @see AppWidgetProviderInfo
@@ -1073,7 +1084,7 @@
 
     /**
      * Return {@code TRUE} if the default launcher supports
-     * {@link #requestPinAppWidget(ComponentName, PendingIntent)}
+     * {@link #requestPinAppWidget(ComponentName, Bundle, PendingIntent)}
      */
     public boolean isRequestPinAppWidgetSupported() {
         try {
@@ -1084,6 +1095,15 @@
     }
 
     /**
+     * Only used during development. Can be deleted before release.
+     * @hide
+     */
+    public boolean requestPinAppWidget(@NonNull ComponentName provider,
+            @Nullable PendingIntent successCallback) {
+        return requestPinAppWidget(provider, null, successCallback);
+    }
+
+    /**
      * Request to pin an app widget on the current launcher. It's up to the launcher to accept this
      * request (optionally showing a user confirmation). If the request is accepted, the caller will
      * get a confirmation with extra {@link #EXTRA_APPWIDGET_ID}.
@@ -1099,6 +1119,8 @@
      *
      * @param provider The {@link ComponentName} for the {@link
      *    android.content.BroadcastReceiver BroadcastReceiver} provider for your AppWidget.
+     * @param extras In not null, this is passed to the launcher app. For eg {@link
+     *    #EXTRA_APPWIDGET_PREVIEW} can be used for a custom preview.
      * @param successCallback If not null, this intent will be sent when the widget is created.
      *
      * @return {@code TRUE} if the launcher supports this feature. Note the API will return without
@@ -1113,10 +1135,10 @@
      * service or when the user is locked.
      */
     public boolean requestPinAppWidget(@NonNull ComponentName provider,
-            @Nullable PendingIntent successCallback) {
+            @Nullable Bundle extras, @Nullable PendingIntent successCallback) {
         try {
-            return mService.requestPinAppWidget(mPackageName, provider,
-                successCallback == null ? null : successCallback.getIntentSender());
+            return mService.requestPinAppWidget(mPackageName, provider, extras,
+                    successCallback == null ? null : successCallback.getIntentSender());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 4534767..d36692a 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -26,6 +26,7 @@
 import android.app.ActivityThread;
 import android.bluetooth.le.BluetoothLeAdvertiser;
 import android.bluetooth.le.BluetoothLeScanner;
+import android.bluetooth.le.PeriodicAdvertisingManager;
 import android.bluetooth.le.ScanCallback;
 import android.bluetooth.le.ScanFilter;
 import android.bluetooth.le.ScanRecord;
@@ -525,6 +526,7 @@
 
     private static BluetoothLeScanner sBluetoothLeScanner;
     private static BluetoothLeAdvertiser sBluetoothLeAdvertiser;
+    private static PeriodicAdvertisingManager sPeriodicAdvertisingManager;
 
     private final IBluetoothManager mManagerService;
     private IBluetooth mService;
@@ -630,6 +632,30 @@
     }
 
     /**
+     * Returns a {@link PeriodicAdvertisingManager} object for Bluetooth LE Periodic Advertising
+     * operations. Will return null if Bluetooth is turned off or if Bluetooth LE Periodic
+     * Advertising is not supported on this device.
+     * <p>
+     * Use {@link #isLePeriodicAdvertisingSupported()} to check whether LE Periodic Advertising is
+     * supported on this device before calling this method.
+     */
+    public PeriodicAdvertisingManager getPeriodicAdvertisingManager() {
+      if (!getLeAccess())
+        return null;
+
+      if (!isLePeriodicAdvertisingSupported())
+        return null;
+
+      synchronized (mLock) {
+        if (sPeriodicAdvertisingManager == null) {
+          sPeriodicAdvertisingManager =
+              new PeriodicAdvertisingManager(mManagerService);
+        }
+      }
+      return sPeriodicAdvertisingManager;
+    }
+
+    /**
      * Returns a {@link BluetoothLeScanner} object for Bluetooth LE scan operations.
      */
     public BluetoothLeScanner getBluetoothLeScanner() {
@@ -1385,6 +1411,78 @@
     }
 
     /**
+     * Return true if LE 2M PHY feature is supported.
+     *
+     * @return true if chipset supports LE 2M PHY feature
+     */
+    public boolean isLe2MPhySupported() {
+        if (!getLeAccess()) return false;
+        try {
+            mServiceLock.readLock().lock();
+            if (mService != null) return mService.isLe2MPhySupported();
+        } catch (RemoteException e) {
+            Log.e(TAG, "failed to get isExtendedAdvertisingSupported, error: ", e);
+        } finally {
+            mServiceLock.readLock().unlock();
+        }
+        return false;
+    }
+
+    /**
+     * Return true if LE Coded PHY feature is supported.
+     *
+     * @return true if chipset supports LE Coded PHY feature
+     */
+    public boolean isLeCodedPhySupported() {
+        if (!getLeAccess()) return false;
+        try {
+            mServiceLock.readLock().lock();
+            if (mService != null) return mService.isLeCodedPhySupported();
+        } catch (RemoteException e) {
+            Log.e(TAG, "failed to get isLeCodedPhySupported, error: ", e);
+        } finally {
+            mServiceLock.readLock().unlock();
+        }
+        return false;
+    }
+
+    /**
+     * Return true if LE Periodic Advertising feature is supported.
+     *
+     * @return true if chipset supports LE Periodic Advertising feature
+     */
+    public boolean isLeExtendedAdvertisingSupported() {
+        if (!getLeAccess()) return false;
+        try {
+            mServiceLock.readLock().lock();
+            if (mService != null) return mService.isLeExtendedAdvertisingSupported();
+        } catch (RemoteException e) {
+            Log.e(TAG, "failed to get isLeExtendedAdvertisingSupported, error: ", e);
+        } finally {
+            mServiceLock.readLock().unlock();
+        }
+        return false;
+    }
+
+    /**
+     * Return true if LE Periodic Advertising feature is supported.
+     *
+     * @return true if chipset supports LE Periodic Advertising feature
+     */
+    public boolean isLePeriodicAdvertisingSupported() {
+        if (!getLeAccess()) return false;
+        try {
+            mServiceLock.readLock().lock();
+            if (mService != null) return mService.isLePeriodicAdvertisingSupported();
+        } catch (RemoteException e) {
+            Log.e(TAG, "failed to get isLePeriodicAdvertisingSupported, error: ", e);
+        } finally {
+            mServiceLock.readLock().unlock();
+        }
+        return false;
+    }
+
+    /**
      * Return true if hardware has entries available for matching beacons
      *
      * @return true if there are hw entries available for matching beacons
@@ -1858,6 +1956,35 @@
         return listenUsingL2capOn(port, false, false);
     }
 
+
+    /**
+     * Construct an insecure L2CAP server socket.
+     * Call #accept to retrieve connections to this socket.
+     * <p>To auto assign a port without creating a SDP record use
+     * {@link SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
+     * @param port    the PSM to listen on
+     * @return An L2CAP BluetoothServerSocket
+     * @throws IOException On error, for example Bluetooth not available, or
+     *                     insufficient permissions.
+     * @hide
+     */
+    public BluetoothServerSocket listenUsingInsecureL2capOn(int port) throws IOException {
+        BluetoothServerSocket socket = new BluetoothServerSocket(
+                BluetoothSocket.TYPE_L2CAP, false, false, port, false, false);
+        int errno = socket.mSocket.bindListen();
+        if(port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
+            socket.setChannel(socket.mSocket.getPort());
+        }
+        if (errno != 0) {
+            //TODO(BT): Throw the same exception error code
+            // that the previous code was using.
+            //socket.mSocket.throwErrnoNative(errno);
+            throw new IOException("Error: " + errno);
+        }
+        return socket;
+
+    }
+
     /**
      * Read the local Out of Band Pairing Data
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 5c9e2ee..31fc294 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -592,6 +592,42 @@
      */
     public static final int TRANSPORT_LE = 2;
 
+    /**
+     * 1M initiating PHY.
+     */
+    public static final int PHY_LE_1M = 1;
+
+    /**
+     * 2M initiating PHY.
+     */
+    public static final int PHY_LE_2M = 2;
+
+    /**
+     * LE Coded initiating PHY.
+     */
+    public static final int PHY_LE_CODED = 4;
+
+    /**
+     * Any LE PHY.
+     */
+    public static final int PHY_LE_ANY = PHY_LE_1M | PHY_LE_2M | PHY_LE_CODED;
+
+    /**
+     * No preferred coding when transmitting on the LE Coded PHY.
+     */
+    public static final int PHY_OPTION_NO_PREFERRED = 0;
+
+    /**
+     * Prefer the S=2 coding to be used when transmitting on the LE Coded PHY.
+     */
+    public static final int PHY_OPTION_S2 = 1;
+
+    /**
+     * Prefer the S=8 coding to be used when transmitting on the LE Coded PHY.
+     */
+    public static final int PHY_OPTION_S8 = 2;
+
+
     /** @hide */
     public static final String EXTRA_MAS_INSTANCE =
         "android.bluetooth.device.extra.MAS_INSTANCE";
@@ -1412,6 +1448,27 @@
     }
 
     /**
+     * Create an L2cap {@link BluetoothSocket} ready to start an insecure
+     * outgoing connection to this remote device on given channel.
+     * <p>The remote device will be not authenticated and communication on this
+     * socket will not be encrypted.
+     * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing
+     * connection.
+     * <p>Valid L2CAP PSM channels are in range 1 to 2^16.
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
+     *
+     * @param channel L2cap PSM/channel to connect to
+     * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection
+     * @throws IOException on error, for example Bluetooth not available, or
+     *                     insufficient permissions
+     * @hide
+     */
+    public BluetoothSocket createInsecureL2capSocket(int channel) throws IOException {
+        return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP, -1, false, false, this, channel,
+                null);
+    }
+
+    /**
      * Create an RFCOMM {@link BluetoothSocket} ready to start a secure
      * outgoing connection to this remote device using SDP lookup of uuid.
      * <p>This is designed to be used with {@link
@@ -1594,6 +1651,67 @@
      */
     public BluetoothGatt connectGatt(Context context, boolean autoConnect,
                                      BluetoothGattCallback callback, int transport) {
+        return (connectGatt(context, autoConnect,callback, TRANSPORT_AUTO, PHY_LE_1M));
+    }
+
+    /**
+     * Connect to GATT Server hosted by this device. Caller acts as GATT client.
+     * The callback is used to deliver results to Caller, such as connection status as well
+     * as any further GATT client operations.
+     * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
+     * GATT client operations.
+     * @param callback GATT callback handler that will receive asynchronous callbacks.
+     * @param autoConnect Whether to directly connect to the remote device (false)
+     *                    or to automatically connect as soon as the remote
+     *                    device becomes available (true).
+     * @throws IllegalArgumentException if callback is null
+     */
+    public BluetoothGatt connectGatt(Context context, boolean autoConnect,
+                                     BluetoothGattCallbackExt callback) {
+        return (connectGatt(context, autoConnect,callback, TRANSPORT_AUTO));
+    }
+
+    /**
+     * Connect to GATT Server hosted by this device. Caller acts as GATT client.
+     * The callback is used to deliver results to Caller, such as connection status as well
+     * as any further GATT client operations.
+     * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
+     * GATT client operations.
+     * @param callback GATT callback handler that will receive asynchronous callbacks.
+     * @param autoConnect Whether to directly connect to the remote device (false)
+     *                    or to automatically connect as soon as the remote
+     *                    device becomes available (true).
+     * @param transport preferred transport for GATT connections to remote dual-mode devices
+     *             {@link BluetoothDevice#TRANSPORT_AUTO} or
+     *             {@link BluetoothDevice#TRANSPORT_BREDR} or {@link BluetoothDevice#TRANSPORT_LE}
+     * @throws IllegalArgumentException if callback is null
+     */
+    public BluetoothGatt connectGatt(Context context, boolean autoConnect,
+                                     BluetoothGattCallbackExt callback, int transport) {
+        return (connectGatt(context, autoConnect,callback, TRANSPORT_AUTO, PHY_LE_1M));
+    }
+
+    /**
+     * Connect to GATT Server hosted by this device. Caller acts as GATT client.
+     * The callback is used to deliver results to Caller, such as connection status as well
+     * as any further GATT client operations.
+     * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
+     * GATT client operations.
+     * @param callback GATT callback handler that will receive asynchronous callbacks.
+     * @param autoConnect Whether to directly connect to the remote device (false)
+     *                    or to automatically connect as soon as the remote
+     *                    device becomes available (true).
+     * @param transport preferred transport for GATT connections to remote dual-mode devices
+     *             {@link BluetoothDevice#TRANSPORT_AUTO} or
+     *             {@link BluetoothDevice#TRANSPORT_BREDR} or {@link BluetoothDevice#TRANSPORT_LE}
+     * @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of
+     *             {@link BluetoothDevice#PHY_LE_1M}, {@link BluetoothDevice#PHY_LE_2M},
+     *             and {@link BluetoothDevice#PHY_LE_CODED}. This option does not take effect if
+     *             {@code autoConnect} is set to true.
+     * @throws IllegalArgumentException if callback is null
+     */
+    public BluetoothGatt connectGatt(Context context, boolean autoConnect,
+                                     BluetoothGattCallbackExt callback, int transport, int phy) {
         // TODO(Bluetooth) check whether platform support BLE
         //     Do the check here or in GattServer?
         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
@@ -1604,7 +1722,7 @@
                 // BLE is not supported
                 return null;
             }
-            BluetoothGatt gatt = new BluetoothGatt(iGatt, this, transport);
+            BluetoothGatt gatt = new BluetoothGatt(iGatt, this, transport, phy);
             gatt.connect(autoConnect, callback);
             return gatt;
         } catch (RemoteException e) {Log.e(TAG, "", e);}
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 12ebdac..11dbf70 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -31,7 +31,7 @@
  * <p>This class provides Bluetooth GATT functionality to enable communication
  * with Bluetooth Smart or Smart Ready devices.
  *
- * <p>To connect to a remote peripheral device, create a {@link BluetoothGattCallback}
+ * <p>To connect to a remote peripheral device, create a {@link BluetoothGattCallbackExt}
  * and call {@link BluetoothDevice#connectGatt} to get a instance of this class.
  * GATT capable devices can be discovered using the Bluetooth device discovery or BLE
  * scan process.
@@ -42,7 +42,7 @@
     private static final boolean VDBG = false;
 
     private IBluetoothGatt mService;
-    private BluetoothGattCallback mCallback;
+    private BluetoothGattCallbackExt mCallback;
     private int mClientIf;
     private BluetoothDevice mDevice;
     private boolean mAutoConnect;
@@ -51,6 +51,7 @@
     private final Object mStateLock = new Object();
     private Boolean mDeviceBusy = false;
     private int mTransport;
+    private int mPhy;
 
     private static final int AUTH_RETRY_STATE_IDLE = 0;
     private static final int AUTH_RETRY_STATE_NO_MITM = 1;
@@ -132,10 +133,10 @@
     /*package*/ static final int AUTHENTICATION_MITM = 2;
 
     /**
-     * Bluetooth GATT callbacks. Overrides the default BluetoothGattCallback implementation.
+     * Bluetooth GATT callbacks. Overrides the default BluetoothGattCallbackExt implementation.
      */
-    private final IBluetoothGattCallback mBluetoothGattCallback =
-        new IBluetoothGattCallback.Stub() {
+    private final IBluetoothGattCallbackExt mBluetoothGattCallbackExt =
+        new IBluetoothGattCallbackExt.Stub() {
             /**
              * Application interface registered - app is ready to go
              * @hide
@@ -161,13 +162,51 @@
                 }
                 try {
                     mService.clientConnect(mClientIf, mDevice.getAddress(),
-                                           !mAutoConnect, mTransport); // autoConnect is inverse of "isDirect"
+                                           !mAutoConnect, mTransport, mPhy); // autoConnect is inverse of "isDirect"
                 } catch (RemoteException e) {
                     Log.e(TAG,"",e);
                 }
             }
 
             /**
+             * Phy update callback
+             * @hide
+             */
+            @Override
+            public void onPhyUpdate(String address, int txPhy, int rxPhy, int status) {
+                if (DBG) Log.d(TAG, "onPhyUpdate() - status=" + status
+                                 + " address=" + address + " txPhy=" + txPhy + " rxPhy=" + rxPhy);
+                if (!address.equals(mDevice.getAddress())) {
+                    return;
+                }
+
+                try {
+                    mCallback.onPhyUpdate(BluetoothGatt.this, txPhy, rxPhy, status);
+                } catch (Exception ex) {
+                    Log.w(TAG, "Unhandled exception in callback", ex);
+                }
+            }
+
+            /**
+             * Phy read callback
+             * @hide
+             */
+            @Override
+            public void onPhyRead(String address, int txPhy, int rxPhy, int status) {
+                if (DBG) Log.d(TAG, "onPhyRead() - status=" + status
+                                 + " address=" + address + " txPhy=" + txPhy + " rxPhy=" + rxPhy);
+                if (!address.equals(mDevice.getAddress())) {
+                    return;
+                }
+
+                try {
+                    mCallback.onPhyRead(BluetoothGatt.this, txPhy, rxPhy, status);
+                } catch (Exception ex) {
+                    Log.w(TAG, "Unhandled exception in callback", ex);
+                }
+            }
+
+            /**
              * Client connection state changed
              * @hide
              */
@@ -503,10 +542,11 @@
         };
 
     /*package*/ BluetoothGatt(IBluetoothGatt iGatt, BluetoothDevice device,
-                                int transport) {
+                                int transport, int phy) {
         mService = iGatt;
         mDevice = device;
         mTransport = transport;
+        mPhy = phy;
         mServices = new ArrayList<BluetoothGattService>();
 
         mConnState = CONN_STATE_IDLE;
@@ -578,7 +618,7 @@
     /**
      * Register an application callback to start using GATT.
      *
-     * <p>This is an asynchronous call. The callback {@link BluetoothGattCallback#onAppRegistered}
+     * <p>This is an asynchronous call. The callback {@link BluetoothGattCallbackExt#onAppRegistered}
      * is used to notify success or failure if the function returns true.
      *
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
@@ -587,7 +627,7 @@
      * @return If true, the callback will be called to notify success or failure,
      *         false on immediate error
      */
-    private boolean registerApp(BluetoothGattCallback callback) {
+    private boolean registerApp(BluetoothGattCallbackExt callback) {
         if (DBG) Log.d(TAG, "registerApp()");
         if (mService == null) return false;
 
@@ -596,7 +636,7 @@
         if (DBG) Log.d(TAG, "registerApp() - UUID=" + uuid);
 
         try {
-            mService.registerClient(new ParcelUuid(uuid), mBluetoothGattCallback);
+            mService.registerClient(new ParcelUuid(uuid), mBluetoothGattCallbackExt);
         } catch (RemoteException e) {
             Log.e(TAG,"",e);
             return false;
@@ -626,7 +666,7 @@
      *
      * <p>The connection may not be established right away, but will be
      * completed when the remote device is available. A
-     * {@link BluetoothGattCallback#onConnectionStateChange} callback will be
+     * {@link BluetoothGattCallbackExt#onConnectionStateChange} callback will be
      * invoked when the connection state changes as a result of this function.
      *
      * <p>The autoConnect parameter determines whether to actively connect to
@@ -644,7 +684,7 @@
      *                    device becomes available (true).
      * @return true, if the connection attempt was initiated successfully
      */
-    /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback) {
+    /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallbackExt callback) {
         if (DBG) Log.d(TAG, "connect() - device: " + mDevice.getAddress() + ", auto: " + autoConnect);
         synchronized(mStateLock) {
             if (mConnState != CONN_STATE_IDLE) {
@@ -696,7 +736,7 @@
     public boolean connect() {
         try {
             mService.clientConnect(mClientIf, mDevice.getAddress(),
-                                   false, mTransport); // autoConnect is inverse of "isDirect"
+                                   false, mTransport, mPhy); // autoConnect is inverse of "isDirect"
             return true;
         } catch (RemoteException e) {
             Log.e(TAG,"",e);
@@ -705,6 +745,45 @@
     }
 
     /**
+     * Set the preferred connection PHY for this app. Please note that this is just a
+     * recommendation, wether the PHY change will happen depends on other applications peferences,
+     * local and remote controller capabilities. Controller can override these settings.
+     * <p>
+     * {@link BluetoothGattCallbackExt#onPhyUpdate} will be triggered as a result of this call, even
+     * if no PHY change happens. It is also triggered when remote device updates the PHY.
+     *
+     * @param txPhy preferred transmitter PHY. Bitwise OR of any of
+     *             {@link BluetoothDevice#PHY_LE_1M}, {@link BluetoothDevice#PHY_LE_2M}, and
+     *             {@link BluetoothDevice#PHY_LE_CODED}.
+     * @param rxPhy preferred receiver PHY. Bitwise OR of any of
+     *             {@link BluetoothDevice#PHY_LE_1M}, {@link BluetoothDevice#PHY_LE_2M}, and
+     *             {@link BluetoothDevice#PHY_LE_CODED}.
+     * @param phyOptions preferred coding to use when transmitting on the LE Coded PHY. Can be one
+     *             of {@link BluetoothDevice#PHY_OPTION_NO_PREFERRED},
+     *             {@link BluetoothDevice#PHY_OPTION_S2} or {@link BluetoothDevice#PHY_OPTION_S8}
+     */
+    public void setPreferredPhy(int txPhy, int rxPhy, int phyOptions) {
+        try {
+            mService.clientSetPreferredPhy(mClientIf, mDevice.getAddress(), txPhy, rxPhy,
+                                           phyOptions);
+        } catch (RemoteException e) {
+            Log.e(TAG,"",e);
+        }
+    }
+
+    /**
+     * Read the current transmitter PHY and receiver PHY of the connection. The values are returned
+     * in {@link BluetoothGattCallbackExt#onPhyRead}
+     */
+    public void readPhy() {
+        try {
+            mService.clientReadPhy(mClientIf, mDevice.getAddress());
+        } catch (RemoteException e) {
+            Log.e(TAG,"",e);
+        }
+    }
+
+    /**
      * Return the remote bluetooth device this GATT client targets to
      *
      * @return remote bluetooth device
@@ -718,7 +797,7 @@
      * characteristics and descriptors.
      *
      * <p>This is an asynchronous operation. Once service discovery is completed,
-     * the {@link BluetoothGattCallback#onServicesDiscovered} callback is
+     * the {@link BluetoothGattCallbackExt#onServicesDiscovered} callback is
      * triggered. If the discovery was successful, the remote services can be
      * retrieved using the {@link #getServices} function.
      *
@@ -797,7 +876,7 @@
      * Reads the requested characteristic from the associated remote device.
      *
      * <p>This is an asynchronous operation. The result of the read operation
-     * is reported by the {@link BluetoothGattCallback#onCharacteristicRead}
+     * is reported by the {@link BluetoothGattCallbackExt#onCharacteristicRead}
      * callback.
      *
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
@@ -839,7 +918,7 @@
      * Writes a given characteristic and its values to the associated remote device.
      *
      * <p>Once the write operation has been completed, the
-     * {@link BluetoothGattCallback#onCharacteristicWrite} callback is invoked,
+     * {@link BluetoothGattCallbackExt#onCharacteristicWrite} callback is invoked,
      * reporting the result of the operation.
      *
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
@@ -883,7 +962,7 @@
      * Reads the value for a given descriptor from the associated remote device.
      *
      * <p>Once the read operation has been completed, the
-     * {@link BluetoothGattCallback#onDescriptorRead} callback is
+     * {@link BluetoothGattCallbackExt#onDescriptorRead} callback is
      * triggered, signaling the result of the operation.
      *
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
@@ -924,7 +1003,7 @@
     /**
      * Write the value of a given descriptor to the associated remote device.
      *
-     * <p>A {@link BluetoothGattCallback#onDescriptorWrite} callback is
+     * <p>A {@link BluetoothGattCallbackExt#onDescriptorWrite} callback is
      * triggered to report the result of the write operation.
      *
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
@@ -968,7 +1047,7 @@
      * <p>Once a reliable write transaction has been initiated, all calls
      * to {@link #writeCharacteristic} are sent to the remote device for
      * verification and queued up for atomic execution. The application will
-     * receive an {@link BluetoothGattCallback#onCharacteristicWrite} callback
+     * receive an {@link BluetoothGattCallbackExt#onCharacteristicWrite} callback
      * in response to every {@link #writeCharacteristic} call and is responsible
      * for verifying if the value has been transmitted accurately.
      *
@@ -1002,7 +1081,7 @@
      * <p>This function will commit all queued up characteristic write
      * operations for a given remote device.
      *
-     * <p>A {@link BluetoothGattCallback#onReliableWriteCompleted} callback is
+     * <p>A {@link BluetoothGattCallbackExt#onReliableWriteCompleted} callback is
      * invoked to indicate whether the transaction has been executed correctly.
      *
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
@@ -1060,7 +1139,7 @@
      * Enable or disable notifications/indications for a given characteristic.
      *
      * <p>Once notifications are enabled for a characteristic, a
-     * {@link BluetoothGattCallback#onCharacteristicChanged} callback will be
+     * {@link BluetoothGattCallbackExt#onCharacteristicChanged} callback will be
      * triggered if the remote device indicates that the given characteristic
      * has changed.
      *
@@ -1115,7 +1194,7 @@
     /**
      * Read the RSSI for a connected remote device.
      *
-     * <p>The {@link BluetoothGattCallback#onReadRemoteRssi} callback will be
+     * <p>The {@link BluetoothGattCallbackExt#onReadRemoteRssi} callback will be
      * invoked when the RSSI value has been read.
      *
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
@@ -1143,7 +1222,7 @@
      * the data sent is truncated to the MTU size. This function may be used
      * to request a larger MTU size to be able to send more data at once.
      *
-     * <p>A {@link BluetoothGattCallback#onMtuChanged} callback will indicate
+     * <p>A {@link BluetoothGattCallbackExt#onMtuChanged} callback will indicate
      * whether this operation was successful.
      *
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
diff --git a/core/java/android/bluetooth/BluetoothGattCallback.java b/core/java/android/bluetooth/BluetoothGattCallback.java
index a915620..4da106d 100644
--- a/core/java/android/bluetooth/BluetoothGattCallback.java
+++ b/core/java/android/bluetooth/BluetoothGattCallback.java
@@ -18,138 +18,22 @@
 
 /**
  * This abstract class is used to implement {@link BluetoothGatt} callbacks.
+ * @deprecated use {@link BluetoothGattCallbackExt}
  */
-public abstract class BluetoothGattCallback {
+public abstract class BluetoothGattCallback extends BluetoothGattCallbackExt {
 
     /**
-     * Callback indicating when GATT client has connected/disconnected to/from a remote
-     * GATT server.
-     *
-     * @param gatt GATT client
-     * @param status Status of the connect or disconnect operation.
-     *               {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
-     * @param newState Returns the new connection state. Can be one of
-     *                  {@link BluetoothProfile#STATE_DISCONNECTED} or
-     *                  {@link BluetoothProfile#STATE_CONNECTED}
+     * @hide
      */
-    public void onConnectionStateChange(BluetoothGatt gatt, int status,
-                                        int newState) {
+    @Override
+    public void onPhyUpdate(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
     }
 
     /**
-     * Callback invoked when the list of remote services, characteristics and descriptors
-     * for the remote device have been updated, ie new services have been discovered.
-     *
-     * @param gatt GATT client invoked {@link BluetoothGatt#discoverServices}
-     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the remote device
-     *               has been explored successfully.
+     * @hide
      */
-    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
+    @Override
+    public void onPhyRead(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
     }
 
-    /**
-     * Callback reporting the result of a characteristic read operation.
-     *
-     * @param gatt GATT client invoked {@link BluetoothGatt#readCharacteristic}
-     * @param characteristic Characteristic that was read from the associated
-     *                       remote device.
-     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the read operation
-     *               was completed successfully.
-     */
-    public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
-                                     int status) {
-    }
-
-    /**
-     * Callback indicating the result of a characteristic write operation.
-     *
-     * <p>If this callback is invoked while a reliable write transaction is
-     * in progress, the value of the characteristic represents the value
-     * reported by the remote device. An application should compare this
-     * value to the desired value to be written. If the values don't match,
-     * the application must abort the reliable write transaction.
-     *
-     * @param gatt GATT client invoked {@link BluetoothGatt#writeCharacteristic}
-     * @param characteristic Characteristic that was written to the associated
-     *                       remote device.
-     * @param status The result of the write operation
-     *               {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
-     */
-    public void onCharacteristicWrite(BluetoothGatt gatt,
-                                      BluetoothGattCharacteristic characteristic, int status) {
-    }
-
-    /**
-     * Callback triggered as a result of a remote characteristic notification.
-     *
-     * @param gatt GATT client the characteristic is associated with
-     * @param characteristic Characteristic that has been updated as a result
-     *                       of a remote notification event.
-     */
-    public void onCharacteristicChanged(BluetoothGatt gatt,
-                                        BluetoothGattCharacteristic characteristic) {
-    }
-
-    /**
-     * Callback reporting the result of a descriptor read operation.
-     *
-     * @param gatt GATT client invoked {@link BluetoothGatt#readDescriptor}
-     * @param descriptor Descriptor that was read from the associated
-     *                   remote device.
-     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the read operation
-     *               was completed successfully
-     */
-    public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
-                                 int status) {
-    }
-
-    /**
-     * Callback indicating the result of a descriptor write operation.
-     *
-     * @param gatt GATT client invoked {@link BluetoothGatt#writeDescriptor}
-     * @param descriptor Descriptor that was writte to the associated
-     *                   remote device.
-     * @param status The result of the write operation
-     *               {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
-     */
-    public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
-                                  int status) {
-    }
-
-    /**
-     * Callback invoked when a reliable write transaction has been completed.
-     *
-     * @param gatt GATT client invoked {@link BluetoothGatt#executeReliableWrite}
-     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the reliable write
-     *               transaction was executed successfully
-     */
-    public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
-    }
-
-    /**
-     * Callback reporting the RSSI for a remote device connection.
-     *
-     * This callback is triggered in response to the
-     * {@link BluetoothGatt#readRemoteRssi} function.
-     *
-     * @param gatt GATT client invoked {@link BluetoothGatt#readRemoteRssi}
-     * @param rssi The RSSI value for the remote device
-     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the RSSI was read successfully
-     */
-    public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
-    }
-
-    /**
-     * Callback indicating the MTU for a given device connection has changed.
-     *
-     * This callback is triggered in response to the
-     * {@link BluetoothGatt#requestMtu} function, or in response to a connection
-     * event.
-     *
-     * @param gatt GATT client invoked {@link BluetoothGatt#requestMtu}
-     * @param mtu The new MTU size
-     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the MTU has been changed successfully
-     */
-    public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
-    }
 }
diff --git a/core/java/android/bluetooth/BluetoothGattCallbackExt.java b/core/java/android/bluetooth/BluetoothGattCallbackExt.java
new file mode 100644
index 0000000..63774c8
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothGattCallbackExt.java
@@ -0,0 +1,182 @@
+/*
+ * 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 android.bluetooth;
+
+/**
+ * This abstract class is used to implement {@link BluetoothGatt} callbacks.
+ */
+public abstract class BluetoothGattCallbackExt {
+
+    /**
+     * Callback triggered as result of {@link BluetoothGatt#setPreferredPhy}, or as a result of
+     * remote device changing the PHY.
+     *
+     * @param gatt GATT client
+     * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
+     *             {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
+     * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
+     *             {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
+     * @param status status of the operation
+     */
+    public void onPhyUpdate(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
+    }
+
+    /**
+     * Callback triggered as result of {@link BluetoothGatt#readPhy}
+     *
+     * @param gatt GATT client
+     * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
+     *             {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
+     * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
+     *             {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
+     * @param status status of the operation
+     */
+    public void onPhyRead(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
+    }
+
+    /**
+     * Callback indicating when GATT client has connected/disconnected to/from a remote
+     * GATT server.
+     *
+     * @param gatt GATT client
+     * @param status Status of the connect or disconnect operation.
+     *               {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
+     * @param newState Returns the new connection state. Can be one of
+     *                  {@link BluetoothProfile#STATE_DISCONNECTED} or
+     *                  {@link BluetoothProfile#STATE_CONNECTED}
+     */
+    public void onConnectionStateChange(BluetoothGatt gatt, int status,
+                                        int newState) {
+    }
+
+    /**
+     * Callback invoked when the list of remote services, characteristics and descriptors
+     * for the remote device have been updated, ie new services have been discovered.
+     *
+     * @param gatt GATT client invoked {@link BluetoothGatt#discoverServices}
+     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the remote device
+     *               has been explored successfully.
+     */
+    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
+    }
+
+    /**
+     * Callback reporting the result of a characteristic read operation.
+     *
+     * @param gatt GATT client invoked {@link BluetoothGatt#readCharacteristic}
+     * @param characteristic Characteristic that was read from the associated
+     *                       remote device.
+     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the read operation
+     *               was completed successfully.
+     */
+    public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
+                                     int status) {
+    }
+
+    /**
+     * Callback indicating the result of a characteristic write operation.
+     *
+     * <p>If this callback is invoked while a reliable write transaction is
+     * in progress, the value of the characteristic represents the value
+     * reported by the remote device. An application should compare this
+     * value to the desired value to be written. If the values don't match,
+     * the application must abort the reliable write transaction.
+     *
+     * @param gatt GATT client invoked {@link BluetoothGatt#writeCharacteristic}
+     * @param characteristic Characteristic that was written to the associated
+     *                       remote device.
+     * @param status The result of the write operation
+     *               {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
+     */
+    public void onCharacteristicWrite(BluetoothGatt gatt,
+                                      BluetoothGattCharacteristic characteristic, int status) {
+    }
+
+    /**
+     * Callback triggered as a result of a remote characteristic notification.
+     *
+     * @param gatt GATT client the characteristic is associated with
+     * @param characteristic Characteristic that has been updated as a result
+     *                       of a remote notification event.
+     */
+    public void onCharacteristicChanged(BluetoothGatt gatt,
+                                        BluetoothGattCharacteristic characteristic) {
+    }
+
+    /**
+     * Callback reporting the result of a descriptor read operation.
+     *
+     * @param gatt GATT client invoked {@link BluetoothGatt#readDescriptor}
+     * @param descriptor Descriptor that was read from the associated
+     *                   remote device.
+     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the read operation
+     *               was completed successfully
+     */
+    public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
+                                 int status) {
+    }
+
+    /**
+     * Callback indicating the result of a descriptor write operation.
+     *
+     * @param gatt GATT client invoked {@link BluetoothGatt#writeDescriptor}
+     * @param descriptor Descriptor that was writte to the associated
+     *                   remote device.
+     * @param status The result of the write operation
+     *               {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
+     */
+    public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
+                                  int status) {
+    }
+
+    /**
+     * Callback invoked when a reliable write transaction has been completed.
+     *
+     * @param gatt GATT client invoked {@link BluetoothGatt#executeReliableWrite}
+     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the reliable write
+     *               transaction was executed successfully
+     */
+    public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
+    }
+
+    /**
+     * Callback reporting the RSSI for a remote device connection.
+     *
+     * This callback is triggered in response to the
+     * {@link BluetoothGatt#readRemoteRssi} function.
+     *
+     * @param gatt GATT client invoked {@link BluetoothGatt#readRemoteRssi}
+     * @param rssi The RSSI value for the remote device
+     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the RSSI was read successfully
+     */
+    public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
+    }
+
+    /**
+     * Callback indicating the MTU for a given device connection has changed.
+     *
+     * This callback is triggered in response to the
+     * {@link BluetoothGatt#requestMtu} function, or in response to a connection
+     * event.
+     *
+     * @param gatt GATT client invoked {@link BluetoothGatt#requestMtu}
+     * @param mtu The new MTU size
+     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the MTU has been changed successfully
+     */
+    public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
+    }
+}
diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java
index 5ffceba..9ee739f 100644
--- a/core/java/android/bluetooth/BluetoothGattServer.java
+++ b/core/java/android/bluetooth/BluetoothGattServer.java
@@ -46,7 +46,7 @@
 
     private BluetoothAdapter mAdapter;
     private IBluetoothGatt mService;
-    private BluetoothGattServerCallback mCallback;
+    private BluetoothGattServerCallbackExt mCallback;
 
     private Object mServerIfLock = new Object();
     private int mServerIf;
@@ -59,8 +59,8 @@
     /**
      * Bluetooth GATT interface callbacks
      */
-    private final IBluetoothGattServerCallback mBluetoothGattServerCallback =
-        new IBluetoothGattServerCallback.Stub() {
+    private final IBluetoothGattServerCallbackExt mBluetoothGattServerCallback =
+        new IBluetoothGattServerCallbackExt.Stub() {
             /**
              * Application interface registered - app is ready to go
              * @hide
@@ -292,6 +292,42 @@
                     Log.w(TAG, "Unhandled exception: " + ex);
                 }
             }
+
+            /**
+             * The PHY for a connection was updated
+             * @hide
+             */
+            public void onPhyUpdate(String address, int txPhy, int rxPhy, int status) {
+                if (DBG) Log.d(TAG, "onPhyUpdate() - " + "device=" + address + ", txPHy=" + txPhy
+                    + ", rxPHy=" + rxPhy);
+
+                BluetoothDevice device = mAdapter.getRemoteDevice(address);
+                if (device == null) return;
+
+                try {
+                    mCallback.onPhyUpdate(device, txPhy, rxPhy, status);
+                } catch (Exception ex) {
+                    Log.w(TAG, "Unhandled exception: " + ex);
+                }
+            }
+
+            /**
+             * The PHY for a connection was read
+             * @hide
+             */
+            public void onPhyRead(String address, int txPhy, int rxPhy, int status) {
+                if (DBG) Log.d(TAG, "onPhyUpdate() - " + "device=" + address + ", txPHy=" + txPhy
+                    + ", rxPHy=" + rxPhy);
+
+                BluetoothDevice device = mAdapter.getRemoteDevice(address);
+                if (device == null) return;
+
+                try {
+                    mCallback.onPhyRead(device, txPhy, rxPhy, status);
+                } catch (Exception ex) {
+                    Log.w(TAG, "Unhandled exception: " + ex);
+                }
+            }
         };
 
     /**
@@ -360,7 +396,7 @@
      * @return true, the callback will be called to notify success or failure,
      *         false on immediate error
      */
-    /*package*/ boolean registerCallback(BluetoothGattServerCallback callback) {
+    /*package*/ boolean registerCallback(BluetoothGattServerCallbackExt callback) {
         if (DBG) Log.d(TAG, "registerCallback()");
         if (mService == null) {
             Log.e(TAG, "GATT service not available");
@@ -436,7 +472,7 @@
      *
      * <p>The connection may not be established right away, but will be
      * completed when the remote device is available. A
-     * {@link BluetoothGattServerCallback#onConnectionStateChange} callback will be
+     * {@link BluetoothGattServerCallbackExt#onConnectionStateChange} callback will be
      * invoked when the connection state changes as a result of this function.
      *
      * <p>The autoConnect paramter determines whether to actively connect to
@@ -488,16 +524,58 @@
     }
 
     /**
+     * Set the preferred connection PHY for this app. Please note that this is just a
+     * recommendation, wether the PHY change will happen depends on other applications peferences,
+     * local and remote controller capabilities. Controller can override these settings.
+     * <p>
+     * {@link BluetoothGattServerCallbackExt#onPhyUpdate} will be triggered as a result of this call, even
+     * if no PHY change happens. It is also triggered when remote device updates the PHY.
+     *
+     * @param device The remote device to send this response to
+     * @param txPhy preferred transmitter PHY. Bitwise OR of any of
+     *             {@link BluetoothDevice#PHY_LE_1M}, {@link BluetoothDevice#PHY_LE_2M}, and
+     *             {@link BluetoothDevice#PHY_LE_CODED}.
+     * @param rxPhy preferred receiver PHY. Bitwise OR of any of
+     *             {@link BluetoothDevice#PHY_LE_1M}, {@link BluetoothDevice#PHY_LE_2M}, and
+     *             {@link BluetoothDevice#PHY_LE_CODED}.
+     * @param phyOptions preferred coding to use when transmitting on the LE Coded PHY. Can be one
+     *             of {@link BluetoothDevice#PHY_OPTION_NO_PREFERRED},
+     *             {@link BluetoothDevice#PHY_OPTION_S2} or {@link BluetoothDevice#PHY_OPTION_S8}
+     */
+    public void setPreferredPhy(BluetoothDevice device, int txPhy, int rxPhy, int phyOptions) {
+        try {
+            mService.serverSetPreferredPhy(mServerIf, device.getAddress(), txPhy, rxPhy,
+                                           phyOptions);
+        } catch (RemoteException e) {
+            Log.e(TAG,"",e);
+        }
+    }
+
+    /**
+     * Read the current transmitter PHY and receiver PHY of the connection. The values are returned
+     * in {@link BluetoothGattServerCallbackExt#onPhyRead}
+     *
+     * @param device The remote device to send this response to
+     */
+    public void readPhy(BluetoothDevice device) {
+        try {
+            mService.serverReadPhy(mServerIf, device.getAddress());
+        } catch (RemoteException e) {
+            Log.e(TAG,"",e);
+        }
+    }
+
+    /**
      * Send a response to a read or write request to a remote device.
      *
      * <p>This function must be invoked in when a remote read/write request
      * is received by one of these callback methods:
      *
      * <ul>
-     *      <li>{@link BluetoothGattServerCallback#onCharacteristicReadRequest}
-     *      <li>{@link BluetoothGattServerCallback#onCharacteristicWriteRequest}
-     *      <li>{@link BluetoothGattServerCallback#onDescriptorReadRequest}
-     *      <li>{@link BluetoothGattServerCallback#onDescriptorWriteRequest}
+     *      <li>{@link BluetoothGattServerCallbackExt#onCharacteristicReadRequest}
+     *      <li>{@link BluetoothGattServerCallbackExt#onCharacteristicWriteRequest}
+     *      <li>{@link BluetoothGattServerCallbackExt#onDescriptorReadRequest}
+     *      <li>{@link BluetoothGattServerCallbackExt#onDescriptorWriteRequest}
      * </ul>
      *
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
diff --git a/core/java/android/bluetooth/BluetoothGattServerCallback.java b/core/java/android/bluetooth/BluetoothGattServerCallback.java
index 2afcf9a..75ceb52 100644
--- a/core/java/android/bluetooth/BluetoothGattServerCallback.java
+++ b/core/java/android/bluetooth/BluetoothGattServerCallback.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * 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.
@@ -20,141 +20,21 @@
 
 /**
  * This abstract class is used to implement {@link BluetoothGattServer} callbacks.
+ * @deprecated please use {@link BluetoothGattServerCallbackExt}
  */
-public abstract class BluetoothGattServerCallback {
+public abstract class BluetoothGattServerCallback extends BluetoothGattServerCallbackExt {
 
     /**
-     * Callback indicating when a remote device has been connected or disconnected.
-     *
-     * @param device Remote device that has been connected or disconnected.
-     * @param status Status of the connect or disconnect operation.
-     * @param newState Returns the new connection state. Can be one of
-     *                  {@link BluetoothProfile#STATE_DISCONNECTED} or
-     *                  {@link BluetoothProfile#STATE_CONNECTED}
+     * @hide
      */
-    public void onConnectionStateChange(BluetoothDevice device, int status,
-                                        int newState) {
+    @Override
+    public void onPhyUpdate(BluetoothDevice device, int txPhy, int rxPhy, int status) {
     }
 
     /**
-     * Indicates whether a local service has been added successfully.
-     *
-     * @param status Returns {@link BluetoothGatt#GATT_SUCCESS} if the service
-     *               was added successfully.
-     * @param service The service that has been added
+     * @hide
      */
-    public void onServiceAdded(int status, BluetoothGattService service) {
-    }
-
-    /**
-     * A remote client has requested to read a local characteristic.
-     *
-     * <p>An application must call {@link BluetoothGattServer#sendResponse}
-     * to complete the request.
-     *
-     * @param device The remote device that has requested the read operation
-     * @param requestId The Id of the request
-     * @param offset Offset into the value of the characteristic
-     * @param characteristic Characteristic to be read
-     */
-    public void onCharacteristicReadRequest(BluetoothDevice device, int requestId,
-                        int offset, BluetoothGattCharacteristic characteristic) {
-    }
-
-    /**
-     * A remote client has requested to write to a local characteristic.
-     *
-     * <p>An application must call {@link BluetoothGattServer#sendResponse}
-     * to complete the request.
-     *
-     * @param device The remote device that has requested the write operation
-     * @param requestId The Id of the request
-     * @param characteristic Characteristic to be written to.
-     * @param preparedWrite true, if this write operation should be queued for
-     *                      later execution.
-     * @param responseNeeded true, if the remote device requires a response
-     * @param offset The offset given for the value
-     * @param value The value the client wants to assign to the characteristic
-     */
-    public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId,
-                                             BluetoothGattCharacteristic characteristic,
-                                             boolean preparedWrite, boolean responseNeeded,
-                                             int offset, byte[] value) {
-    }
-
-    /**
-     * A remote client has requested to read a local descriptor.
-     *
-     * <p>An application must call {@link BluetoothGattServer#sendResponse}
-     * to complete the request.
-     *
-     * @param device The remote device that has requested the read operation
-     * @param requestId The Id of the request
-     * @param offset Offset into the value of the characteristic
-     * @param descriptor Descriptor to be read
-     */
-    public void onDescriptorReadRequest(BluetoothDevice device, int requestId,
-                                        int offset, BluetoothGattDescriptor descriptor) {
-    }
-
-    /**
-     * A remote client has requested to write to a local descriptor.
-     *
-     * <p>An application must call {@link BluetoothGattServer#sendResponse}
-     * to complete the request.
-     *
-     * @param device The remote device that has requested the write operation
-     * @param requestId The Id of the request
-     * @param descriptor Descriptor to be written to.
-     * @param preparedWrite true, if this write operation should be queued for
-     *                      later execution.
-     * @param responseNeeded true, if the remote device requires a response
-     * @param offset The offset given for the value
-     * @param value The value the client wants to assign to the descriptor
-     */
-    public void onDescriptorWriteRequest(BluetoothDevice device, int requestId,
-                                         BluetoothGattDescriptor descriptor,
-                                         boolean preparedWrite, boolean responseNeeded,
-                                         int offset,  byte[] value) {
-    }
-
-    /**
-     * Execute all pending write operations for this device.
-     *
-     * <p>An application must call {@link BluetoothGattServer#sendResponse}
-     * to complete the request.
-     *
-     * @param device The remote device that has requested the write operations
-     * @param requestId The Id of the request
-     * @param execute Whether the pending writes should be executed (true) or
-     *                cancelled (false)
-     */
-    public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) {
-    }
-
-    /**
-     * Callback invoked when a notification or indication has been sent to
-     * a remote device.
-     *
-     * <p>When multiple notifications are to be sent, an application must
-     * wait for this callback to be received before sending additional
-     * notifications.
-     *
-     * @param device The remote device the notification has been sent to
-     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the operation was successful
-     */
-    public void onNotificationSent(BluetoothDevice device, int status) {
-    }
-
-    /**
-     * Callback indicating the MTU for a given device connection has changed.
-     *
-     * <p>This callback will be invoked if a remote client has requested to change
-     * the MTU for a given connection.
-     *
-     * @param device The remote device that requested the MTU change
-     * @param mtu The new MTU size
-     */
-    public void onMtuChanged(BluetoothDevice device, int mtu) {
+    @Override
+    public void onPhyRead(BluetoothDevice device, int txPhy, int rxPhy, int status) {
     }
 }
diff --git a/core/java/android/bluetooth/BluetoothGattServerCallbackExt.java b/core/java/android/bluetooth/BluetoothGattServerCallbackExt.java
new file mode 100644
index 0000000..455cce0
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothGattServerCallbackExt.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+
+/**
+ * This abstract class is used to implement {@link BluetoothGattServer} callbacks.
+ */
+public abstract class BluetoothGattServerCallbackExt {
+
+    /**
+     * Callback indicating when a remote device has been connected or disconnected.
+     *
+     * @param device Remote device that has been connected or disconnected.
+     * @param status Status of the connect or disconnect operation.
+     * @param newState Returns the new connection state. Can be one of
+     *                  {@link BluetoothProfile#STATE_DISCONNECTED} or
+     *                  {@link BluetoothProfile#STATE_CONNECTED}
+     */
+    public void onConnectionStateChange(BluetoothDevice device, int status,
+                                        int newState) {
+    }
+
+    /**
+     * Indicates whether a local service has been added successfully.
+     *
+     * @param status Returns {@link BluetoothGatt#GATT_SUCCESS} if the service
+     *               was added successfully.
+     * @param service The service that has been added
+     */
+    public void onServiceAdded(int status, BluetoothGattService service) {
+    }
+
+    /**
+     * A remote client has requested to read a local characteristic.
+     *
+     * <p>An application must call {@link BluetoothGattServer#sendResponse}
+     * to complete the request.
+     *
+     * @param device The remote device that has requested the read operation
+     * @param requestId The Id of the request
+     * @param offset Offset into the value of the characteristic
+     * @param characteristic Characteristic to be read
+     */
+    public void onCharacteristicReadRequest(BluetoothDevice device, int requestId,
+                        int offset, BluetoothGattCharacteristic characteristic) {
+    }
+
+    /**
+     * A remote client has requested to write to a local characteristic.
+     *
+     * <p>An application must call {@link BluetoothGattServer#sendResponse}
+     * to complete the request.
+     *
+     * @param device The remote device that has requested the write operation
+     * @param requestId The Id of the request
+     * @param characteristic Characteristic to be written to.
+     * @param preparedWrite true, if this write operation should be queued for
+     *                      later execution.
+     * @param responseNeeded true, if the remote device requires a response
+     * @param offset The offset given for the value
+     * @param value The value the client wants to assign to the characteristic
+     */
+    public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId,
+                                             BluetoothGattCharacteristic characteristic,
+                                             boolean preparedWrite, boolean responseNeeded,
+                                             int offset, byte[] value) {
+    }
+
+    /**
+     * A remote client has requested to read a local descriptor.
+     *
+     * <p>An application must call {@link BluetoothGattServer#sendResponse}
+     * to complete the request.
+     *
+     * @param device The remote device that has requested the read operation
+     * @param requestId The Id of the request
+     * @param offset Offset into the value of the characteristic
+     * @param descriptor Descriptor to be read
+     */
+    public void onDescriptorReadRequest(BluetoothDevice device, int requestId,
+                                        int offset, BluetoothGattDescriptor descriptor) {
+    }
+
+    /**
+     * A remote client has requested to write to a local descriptor.
+     *
+     * <p>An application must call {@link BluetoothGattServer#sendResponse}
+     * to complete the request.
+     *
+     * @param device The remote device that has requested the write operation
+     * @param requestId The Id of the request
+     * @param descriptor Descriptor to be written to.
+     * @param preparedWrite true, if this write operation should be queued for
+     *                      later execution.
+     * @param responseNeeded true, if the remote device requires a response
+     * @param offset The offset given for the value
+     * @param value The value the client wants to assign to the descriptor
+     */
+    public void onDescriptorWriteRequest(BluetoothDevice device, int requestId,
+                                         BluetoothGattDescriptor descriptor,
+                                         boolean preparedWrite, boolean responseNeeded,
+                                         int offset,  byte[] value) {
+    }
+
+    /**
+     * Execute all pending write operations for this device.
+     *
+     * <p>An application must call {@link BluetoothGattServer#sendResponse}
+     * to complete the request.
+     *
+     * @param device The remote device that has requested the write operations
+     * @param requestId The Id of the request
+     * @param execute Whether the pending writes should be executed (true) or
+     *                cancelled (false)
+     */
+    public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) {
+    }
+
+    /**
+     * Callback invoked when a notification or indication has been sent to
+     * a remote device.
+     *
+     * <p>When multiple notifications are to be sent, an application must
+     * wait for this callback to be received before sending additional
+     * notifications.
+     *
+     * @param device The remote device the notification has been sent to
+     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the operation was successful
+     */
+    public void onNotificationSent(BluetoothDevice device, int status) {
+    }
+
+    /**
+     * Callback indicating the MTU for a given device connection has changed.
+     *
+     * <p>This callback will be invoked if a remote client has requested to change
+     * the MTU for a given connection.
+     *
+     * @param device The remote device that requested the MTU change
+     * @param mtu The new MTU size
+     */
+    public void onMtuChanged(BluetoothDevice device, int mtu) {
+    }
+
+    /**
+     * Callback triggered as result of {@link BluetoothGattServer#setPreferredPhy}, or as a result
+     * of remote device changing the PHY.
+     *
+     * @param device The remote device
+     * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
+     *             {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
+     * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
+     *             {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
+     * @param status status of the operation
+     */
+    public void onPhyUpdate(BluetoothDevice device, int txPhy, int rxPhy, int status) {
+    }
+
+    /**
+     * Callback triggered as result of {@link BluetoothGattServer#readPhy}
+     *
+     * @param device The remote device that requested the PHY read
+     * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
+     *             {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
+     * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
+     *             {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
+     * @param status status of the operation
+     */
+    public void onPhyRead(BluetoothDevice device, int txPhy, int rxPhy, int status) {
+    }
+}
diff --git a/core/java/android/bluetooth/BluetoothMapClient.java b/core/java/android/bluetooth/BluetoothMapClient.java
index 4252482..ccab3cd 100644
--- a/core/java/android/bluetooth/BluetoothMapClient.java
+++ b/core/java/android/bluetooth/BluetoothMapClient.java
@@ -50,6 +50,15 @@
     public static final String ACTION_MESSAGE_DELIVERED_SUCCESSFULLY =
             "android.bluetooth.mapmce.profile.action.MESSAGE_DELIVERED_SUCCESSFULLY";
 
+    /* Extras used in ACTION_MESSAGE_RECEIVED intent.
+     * NOTE: HANDLE is only valid for a single session with the device. */
+    public static final String EXTRA_MESSAGE_HANDLE =
+            "android.bluetooth.mapmce.profile.extra.MESSAGE_HANDLE";
+    public static final String EXTRA_SENDER_CONTACT_URI =
+            "android.bluetooth.mapmce.profile.extra.SENDER_CONTACT_URI";
+    public static final String EXTRA_SENDER_CONTACT_NAME =
+            "android.bluetooth.mapmce.profile.extra.SENDER_CONTACT_NAME";
+
     private IBluetoothMapClient mService;
     private final Context mContext;
     private ServiceListener mServiceListener;
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index 53fef2a..76ca554 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -104,6 +104,10 @@
     boolean isOffloadedFilteringSupported();
     boolean isOffloadedScanBatchingSupported();
     boolean isActivityAndEnergyReportingSupported();
+    boolean isLe2MPhySupported();
+    boolean isLeCodedPhySupported();
+    boolean isLeExtendedAdvertisingSupported();
+    boolean isLePeriodicAdvertisingSupported();
     BluetoothActivityEnergyInfo reportActivityInfo();
 
     /**
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index aa2291e..33fedc7 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -20,15 +20,20 @@
 import android.bluetooth.BluetoothGattService;
 import android.bluetooth.le.AdvertiseSettings;
 import android.bluetooth.le.AdvertiseData;
+import android.bluetooth.le.AdvertisingSetParameters;
+import android.bluetooth.le.PeriodicAdvertisingParameters;
 import android.bluetooth.le.ScanFilter;
+import android.bluetooth.le.ScanResult;
 import android.bluetooth.le.ScanSettings;
 import android.bluetooth.le.ResultStorageDescriptor;
 import android.os.ParcelUuid;
 import android.os.WorkSource;
 
-import android.bluetooth.IBluetoothGattCallback;
-import android.bluetooth.IBluetoothGattServerCallback;
+import android.bluetooth.IBluetoothGattCallbackExt;
+import android.bluetooth.IBluetoothGattServerCallbackExt;
 import android.bluetooth.le.IAdvertiserCallback;
+import android.bluetooth.le.IAdvertisingSetCallback;
+import android.bluetooth.le.IPeriodicAdvertisingCallback;
 import android.bluetooth.le.IScannerCallback;
 
 /**
@@ -53,10 +58,29 @@
                                in AdvertiseSettings settings);
     void stopMultiAdvertising(in int advertiserId);
 
-    void registerClient(in ParcelUuid appId, in IBluetoothGattCallback callback);
+    void startAdvertisingSet(in AdvertisingSetParameters parameters, in AdvertiseData advertiseData,
+                                in AdvertiseData scanResponse, in PeriodicAdvertisingParameters periodicParameters,
+                                in AdvertiseData periodicData, in IAdvertisingSetCallback callback);
+    void stopAdvertisingSet(in IAdvertisingSetCallback callback);
+
+    void enableAdverisingSet(in int advertiserId, in boolean enable);
+    void setAdvertisingData(in int advertiserId, in AdvertiseData data);
+    void setScanResponseData(in int advertiserId, in AdvertiseData data);
+    void setAdvertisingParameters(in int advertiserId, in AdvertisingSetParameters parameters);
+    void setPeriodicAdvertisingParameters(in int advertiserId, in PeriodicAdvertisingParameters parameters);
+    void setPeriodicAdvertisingData(in int advertiserId, in AdvertiseData data);
+    void periodicAdvertisingEnable(in int advertiserId, in boolean enable);
+
+    void registerSync(in ScanResult scanResult, in int skip, in int timeout, in IPeriodicAdvertisingCallback callback);
+    void unregisterSync(in IPeriodicAdvertisingCallback callback);
+
+    void registerClient(in ParcelUuid appId, in IBluetoothGattCallbackExt callback);
+
     void unregisterClient(in int clientIf);
-    void clientConnect(in int clientIf, in String address, in boolean isDirect, in int transport);
+    void clientConnect(in int clientIf, in String address, in boolean isDirect, in int transport, in int phy);
     void clientDisconnect(in int clientIf, in String address);
+    void clientSetPreferredPhy(in int clientIf, in String address, in int txPhy, in int rxPhy, in int phyOptions);
+    void clientReadPhy(in int clientIf, in String address);
     void refreshDevice(in int clientIf, in String address);
     void discoverServices(in int clientIf, in String address);
     void readCharacteristic(in int clientIf, in String address, in int handle, in int authReq);
@@ -72,10 +96,12 @@
     void configureMTU(in int clientIf, in String address, in int mtu);
     void connectionParameterUpdate(in int clientIf, in String address, in int connectionPriority);
 
-    void registerServer(in ParcelUuid appId, in IBluetoothGattServerCallback callback);
+    void registerServer(in ParcelUuid appId, in IBluetoothGattServerCallbackExt callback);
     void unregisterServer(in int serverIf);
     void serverConnect(in int serverIf, in String address, in boolean isDirect, in int transport);
     void serverDisconnect(in int serverIf, in String address);
+    void serverSetPreferredPhy(in int clientIf, in String address, in int txPhy, in int rxPhy, in int phyOptions);
+    void serverReadPhy(in int clientIf, in String address);
     void addService(in int serverIf, in BluetoothGattService service);
     void removeService(in int serverIf, in int handle);
     void clearServices(in int serverIf);
diff --git a/core/java/android/bluetooth/IBluetoothGattCallback.aidl b/core/java/android/bluetooth/IBluetoothGattCallbackExt.aidl
similarity index 88%
rename from core/java/android/bluetooth/IBluetoothGattCallback.aidl
rename to core/java/android/bluetooth/IBluetoothGattCallbackExt.aidl
index 72cb618..736f4b2 100644
--- a/core/java/android/bluetooth/IBluetoothGattCallback.aidl
+++ b/core/java/android/bluetooth/IBluetoothGattCallbackExt.aidl
@@ -22,10 +22,12 @@
  * Callback definitions for interacting with BLE / GATT
  * @hide
  */
-oneway interface IBluetoothGattCallback {
+oneway interface IBluetoothGattCallbackExt {
     void onClientRegistered(in int status, in int clientIf);
     void onClientConnectionState(in int status, in int clientIf,
                                  in boolean connected, in String address);
+    void onPhyUpdate(in String address, in int txPhy, in int rxPhy, in int status);
+    void onPhyRead(in String address, in int txPhy, in int rxPhy, in int status);
     void onSearchComplete(in String address, in List<BluetoothGattService> services, in int status);
     void onCharacteristicRead(in String address, in int status, in int handle, in byte[] value);
     void onCharacteristicWrite(in String address, in int status, in int handle);
diff --git a/core/java/android/bluetooth/IBluetoothGattServerCallback.aidl b/core/java/android/bluetooth/IBluetoothGattServerCallbackExt.aidl
similarity index 87%
rename from core/java/android/bluetooth/IBluetoothGattServerCallback.aidl
rename to core/java/android/bluetooth/IBluetoothGattServerCallbackExt.aidl
index 1a924fb..091ffb3 100644
--- a/core/java/android/bluetooth/IBluetoothGattServerCallback.aidl
+++ b/core/java/android/bluetooth/IBluetoothGattServerCallbackExt.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * 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.
@@ -21,7 +21,7 @@
  * Callback definitions for interacting with BLE / GATT
  * @hide
  */
-oneway interface IBluetoothGattServerCallback {
+oneway interface IBluetoothGattServerCallbackExt {
     void onServerRegistered(in int status, in int serverIf);
     void onServerConnectionState(in int status, in int serverIf,
                                  in boolean connected, in String address);
@@ -40,4 +40,6 @@
     void onExecuteWrite(in String address, in int transId, in boolean execWrite);
     void onNotificationSent(in String address, in int status);
     void onMtuChanged(in String address, in int mtu);
+    void onPhyUpdate(in String address, in int txPhy, in int rxPhy, in int status);
+    void onPhyRead(in String address, in int txPhy, in int rxPhy, in int status);
 }
diff --git a/core/java/android/bluetooth/le/AdvertisingSet.java b/core/java/android/bluetooth/le/AdvertisingSet.java
new file mode 100644
index 0000000..1524022
--- /dev/null
+++ b/core/java/android/bluetooth/le/AdvertisingSet.java
@@ -0,0 +1,162 @@
+/*
+ * 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 android.bluetooth.le;
+
+import android.bluetooth.IBluetoothGatt;
+import android.bluetooth.IBluetoothManager;
+import android.bluetooth.le.IAdvertisingSetCallback;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * This class provides a way to control single Bluetooth LE advertising instance.
+ * <p>
+ * To get an instance of {@link AdvertisingSet}, call the
+ * {@link BluetoothLeAdvertiser#startAdvertisingSet} method.
+ * <p>
+ * <b>Note:</b> Most of the methods here require {@link android.Manifest.permission#BLUETOOTH_ADMIN}
+ * permission.
+ *
+ * @see AdvertiseData
+ */
+public final class AdvertisingSet {
+    private static final String TAG = "AdvertisingSet";
+
+    private final IBluetoothGatt gatt;
+    private int advertiserId;
+
+    /* package */ AdvertisingSet(int advertiserId,
+                                 IBluetoothManager bluetoothManager) {
+        this.advertiserId = advertiserId;
+
+        try {
+          this.gatt = bluetoothManager.getBluetoothGatt();
+        } catch (RemoteException e) {
+          Log.e(TAG, "Failed to get Bluetooth gatt - ", e);
+          throw new IllegalStateException("Failed to get Bluetooth");
+        }
+    }
+
+    /* package */ void setAdvertiserId(int advertiserId) {
+      this.advertiserId = advertiserId;
+    }
+
+    /**
+     * Enables Advertising. This method returns immediately, the operation status is
+     * delivered
+     * through {@code callback.onAdvertisingEnabled()}.
+     * <p>
+     * Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
+     *
+     */
+    public void enableAdvertising(boolean enable) {
+        try {
+            gatt.enableAdverisingSet(this.advertiserId, enable);
+        } catch (RemoteException e) {
+            Log.e(TAG, "remote exception - ", e);
+        }
+    }
+
+    /**
+     * Set/update data being Advertised. Make sure that data doesn't exceed the size limit for
+     * specified AdvertisingSetParameters. This method returns immediately, the operation status is
+     * delivered through {@code callback.onAdvertisingDataSet()}.
+     * <p>
+     * Advertising data must be empty if non-legacy scannable advertising is used.
+     */
+    public void setAdvertisingData(AdvertiseData data) {
+        try {
+            gatt.setAdvertisingData(this.advertiserId, data);
+        } catch (RemoteException e) {
+            Log.e(TAG, "remote exception - ", e);
+        }
+    }
+
+    /**
+     * Set/update scan response data. Make sure that data doesn't exceed the size limit for
+     * specified AdvertisingSetParameters. This method returns immediately, the operation status
+     * is delivered through {@code callback.onScanResponseDataSet()}.
+     */
+    public void setScanResponseData(AdvertiseData data) {
+        try {
+            gatt.setScanResponseData(this.advertiserId, data);
+        } catch (RemoteException e) {
+            Log.e(TAG, "remote exception - ", e);
+        }
+    }
+
+    /**
+     * Update advertising parameters associated with this AdvertisingSet. Must be called when
+     * advertising is not active. This method returns immediately, the operation status is delivered
+     * through {@code callback.onAdvertisingParametersUpdated}.
+     */
+    public void setAdvertisingParameters(AdvertisingSetParameters parameters) {
+        try {
+            gatt.setAdvertisingParameters(this.advertiserId, parameters);
+        } catch (RemoteException e) {
+            Log.e(TAG, "remote exception - ", e);
+        }
+    }
+
+    /**
+     * Update periodic advertising parameters associated with this set. Must be called when
+     * periodic advertising is not enabled. This method returns immediately, the operation
+     * status is delivered through {@code callback.onPeriodicAdvertisingParametersUpdated()}.
+     */
+    public void setPeriodicAdvertisingParameters(PeriodicAdvertisingParameters parameters) {
+        try {
+            gatt.setPeriodicAdvertisingParameters(this.advertiserId, parameters);
+        } catch (RemoteException e) {
+            Log.e(TAG, "remote exception - ", e);
+        }
+    }
+
+    /**
+     * Used to set periodic advertising data, must be called after setPeriodicAdvertisingParameters,
+     * or after advertising was started with periodic advertising data set. This method returns
+     * immediately, the operation status is delivered through
+     * {@code callback.onPeriodicAdvertisingDataSet()}.
+     */
+    public void setPeriodicAdvertisingData(AdvertiseData data) {
+        try {
+            gatt.setPeriodicAdvertisingData(this.advertiserId, data);
+        } catch (RemoteException e) {
+            Log.e(TAG, "remote exception - ", e);
+        }
+    }
+
+    /**
+     * Used to enable/disable periodic advertising. This method returns immediately, the operation
+     * status is delivered through {@code callback.onPeriodicAdvertisingEnable()}.
+     */
+    public void periodicAdvertisingEnable(boolean enable) {
+        try {
+            gatt.periodicAdvertisingEnable(this.advertiserId, enable);
+        } catch (RemoteException e) {
+            Log.e(TAG, "remote exception - ", e);
+        }
+    }
+
+    /**
+     * Returns advertiserId associated with thsi advertising set.
+     *
+     * @hide
+     */
+    public int getAdvertiserId(){
+      return advertiserId;
+    }
+}
\ No newline at end of file
diff --git a/core/java/android/bluetooth/le/AdvertisingSetCallback.java b/core/java/android/bluetooth/le/AdvertisingSetCallback.java
new file mode 100644
index 0000000..ceed8d9
--- /dev/null
+++ b/core/java/android/bluetooth/le/AdvertisingSetCallback.java
@@ -0,0 +1,144 @@
+/*
+ * 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 android.bluetooth.le;
+
+import android.bluetooth.BluetoothDevice;
+
+/**
+ * Bluetooth LE advertising set callbacks, used to deliver advertising operation
+ * status.
+ */
+public abstract class AdvertisingSetCallback {
+
+    /**
+     * The requested operation was successful.
+     */
+    public static final int ADVERTISE_SUCCESS = 0;
+
+    /**
+     * Failed to start advertising as the advertise data to be broadcasted is too
+     * large.
+     */
+    public static final int ADVERTISE_FAILED_DATA_TOO_LARGE = 1;
+
+    /**
+     * Failed to start advertising because no advertising instance is available.
+     */
+    public static final int ADVERTISE_FAILED_TOO_MANY_ADVERTISERS = 2;
+
+    /**
+     * Failed to start advertising as the advertising is already started.
+     */
+    public static final int ADVERTISE_FAILED_ALREADY_STARTED = 3;
+
+    /**
+     * Operation failed due to an internal error.
+     */
+    public static final int ADVERTISE_FAILED_INTERNAL_ERROR = 4;
+
+    /**
+     * This feature is not supported on this platform.
+     */
+    public static final int ADVERTISE_FAILED_FEATURE_UNSUPPORTED = 5;
+
+    /**
+     * Callback triggered in response to {@link BluetoothLeAdvertiser#startAdvertisingSet}
+     * indicating result of the operation. If status is ADVERTISE_SUCCESS, then advertisingSet
+     * contains the started set and it is advertising. If error occured, advertisingSet is
+     * null, and status will be set to proper error code.
+     *
+     * @param advertisingSet The advertising set that was started or null if error.
+     * @param status Status of the operation.
+     */
+    public void onAdvertisingSetStarted(AdvertisingSet advertisingSet, int status) {}
+
+    /**
+     * Callback triggered in response to {@link BluetoothLeAdvertiser#stopAdvertisingSet}
+     * indicating advertising set is stopped.
+     *
+     * @param advertisingSet The advertising set.
+     */
+    public void onAdvertisingSetStopped(AdvertisingSet advertisingSet) {}
+
+    /**
+     * Callback triggered in response to {@link BluetoothLeAdvertiser#startAdvertisingSet} indicating
+     * result of the operation. If status is ADVERTISE_SUCCESS, then advertising set is advertising.
+     *
+     * @param advertisingSet The advertising set.
+     * @param status Status of the operation.
+     */
+    public void onAdvertisingEnabled(AdvertisingSet advertisingSet, boolean enable, int status) {}
+
+    /**
+     * Callback triggered in response to {@link AdvertisingSet#setAdvertisingData} indicating
+     * result of the operation. If status is ADVERTISE_SUCCESS, then data was changed.
+     *
+     * @param advertisingSet The advertising set.
+     * @param status Status of the operation.
+     */
+    public void onAdvertisingDataSet(AdvertisingSet advertisingSet, int status) {}
+
+    /**
+     * Callback triggered in response to {@link AdvertisingSet#setAdvertisingData} indicating
+     * result of the operation.
+     *
+     * @param advertisingSet The advertising set.
+     * @param status Status of the operation.
+     */
+    public void onScanResponseDataSet(AdvertisingSet advertisingSet, int status) {}
+
+    /**
+     * Callback triggered in response to {@link AdvertisingSet#setAdvertisingParameters}
+     * indicating result of the operation.
+     *
+     * @param advertisingSet The advertising set.
+     * @param status Status of the operation.
+     */
+    public void onAdvertisingParametersUpdated(AdvertisingSet advertisingSet,
+                                               int status) {}
+
+    /**
+     * Callback triggered in response to {@link AdvertisingSet#setPeriodicAdvertisingParameters}
+     * indicating result of the operation.
+     *
+     * @param advertisingSet The advertising set.
+     * @param status Status of the operation.
+     */
+    public void
+    onPeriodicAdvertisingParametersUpdated(AdvertisingSet advertisingSet,
+                                           int status) {}
+
+    /**
+     * Callback triggered in response to {@link AdvertisingSet#setPeriodicAdvertisingData}
+     * indicating result of the operation.
+     *
+     * @param advertisingSet The advertising set.
+     * @param status Status of the operation.
+     */
+    public void onPeriodicAdvertisingDataSet(AdvertisingSet advertisingSet,
+                                             int status) {}
+
+    /**
+     * Callback triggered in response to {@link AdvertisingSet#periodicAdvertisingEnable}
+     * indicating result of the operation.
+     *
+     * @param advertisingSet The advertising set.
+     * @param status Status of the operation.
+     */
+    public void onPeriodicAdvertisingEnable(AdvertisingSet advertisingSet, boolean enable,
+                                            int status) {}
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/logging/legacy/Util.java b/core/java/android/bluetooth/le/AdvertisingSetParameters.aidl
similarity index 77%
copy from core/java/com/android/internal/logging/legacy/Util.java
copy to core/java/android/bluetooth/le/AdvertisingSetParameters.aidl
index 99f71ca..39034a0 100644
--- a/core/java/com/android/internal/logging/legacy/Util.java
+++ b/core/java/android/bluetooth/le/AdvertisingSetParameters.aidl
@@ -13,13 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.internal.logging.legacy;
 
-/**
- * Created by cwren on 11/21/16.
- */
-public class Util {
-    public static boolean debug() {
-        return false;
-    }
-}
+package android.bluetooth.le;
+
+parcelable AdvertisingSetParameters;
diff --git a/core/java/android/bluetooth/le/AdvertisingSetParameters.java b/core/java/android/bluetooth/le/AdvertisingSetParameters.java
new file mode 100644
index 0000000..03a01e1
--- /dev/null
+++ b/core/java/android/bluetooth/le/AdvertisingSetParameters.java
@@ -0,0 +1,409 @@
+/*
+ * 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 android.bluetooth.le;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * The {@link AdvertisingSetParameters} provide a way to adjust advertising
+ * preferences for each
+ * Bluetooth LE advertising set. Use {@link AdvertisingSetParameters.Builder} to
+ * create an
+ * instance of this class.
+ */
+public final class AdvertisingSetParameters implements Parcelable {
+
+    /**
+     * 1M advertiser PHY.
+     */
+    public static final int PHY_LE_1M = 1;
+
+    /**
+     * 2M advertiser PHY.
+     */
+    public static final int PHY_LE_2M = 2;
+
+    /**
+     * LE Coded advertiser PHY.
+     */
+    public static final int PHY_LE_CODED = 3;
+
+    /**
+    * Advertise on low frequency, around every 1000ms. This is the default and
+    * preferred advertising mode as it consumes the least power.
+    */
+    public static final int INTERVAL_LOW = 1600;
+
+    /**
+     * Advertise on medium frequency, around every 250ms. This is balanced
+     * between advertising frequency and power consumption.
+     */
+    public static final int INTERVAL_MEDIUM = 400;
+
+    /**
+     * Perform high frequency, low latency advertising, around every 100ms. This
+     * has the highest power consumption and should not be used for continuous
+     * background advertising.
+     */
+    public static final int INTERVAL_HIGH = 160;
+
+    /**
+     * Minimum value for advertising interval.
+     */
+    public static final int INTERVAL_MIN = 160;
+
+    /**
+     * Maximum value for advertising interval.
+     */
+    public static final int INTERVAL_MAX = 16777215;
+
+    /**
+     * Advertise using the lowest transmission (TX) power level. Low transmission
+     * power can be used to restrict the visibility range of advertising packets.
+     */
+    public static final int TX_POWER_ULTRA_LOW = -21;
+
+    /**
+     * Advertise using low TX power level.
+     */
+    public static final int TX_POWER_LOW = -15;
+
+    /**
+     * Advertise using medium TX power level.
+     */
+    public static final int TX_POWER_MEDIUM = -7;
+
+    /**
+     * Advertise using high TX power level. This corresponds to largest visibility
+     * range of the advertising packet.
+     */
+    public static final int TX_POWER_HIGH = 1;
+
+    /**
+     * Minimum value for TX power.
+     */
+    public static final int TX_POWER_MIN = -127;
+
+    /**
+     * Maximum value for TX power.
+     */
+    public static final int TX_POWER_MAX = 1;
+
+    /**
+     * The maximum limited advertisement duration as specified by the Bluetooth
+     * SIG
+     */
+    private static final int LIMITED_ADVERTISING_MAX_MILLIS = 180 * 1000;
+
+    private final boolean isLegacy;
+    private final boolean isAnonymous;
+    private final boolean includeTxPower;
+    private final int primaryPhy;
+    private final int secondaryPhy;
+    private final boolean connectable;
+    private final int interval;
+    private final int txPowerLevel;
+    private final int timeoutMillis;
+
+    private AdvertisingSetParameters(boolean connectable, boolean isLegacy,
+                                     boolean isAnonymous, boolean includeTxPower,
+                                     int primaryPhy, int secondaryPhy,
+                                     int interval, int txPowerLevel,
+                                     int timeoutMillis) {
+        this.connectable = connectable;
+        this.isLegacy = isLegacy;
+        this.isAnonymous = isAnonymous;
+        this.includeTxPower = includeTxPower;
+        this.primaryPhy = primaryPhy;
+        this.secondaryPhy = secondaryPhy;
+        this.interval = interval;
+        this.txPowerLevel = txPowerLevel;
+        this.timeoutMillis = timeoutMillis;
+    }
+
+    private AdvertisingSetParameters(Parcel in) {
+        connectable = in.readInt() != 0 ? true : false;
+        isLegacy = in.readInt() != 0 ? true : false;
+        isAnonymous = in.readInt() != 0 ? true : false;
+        includeTxPower = in.readInt() != 0 ? true : false;
+        primaryPhy = in.readInt();
+        secondaryPhy = in.readInt();
+        interval = in.readInt();
+        txPowerLevel = in.readInt();
+        timeoutMillis = in.readInt();
+    }
+
+    /**
+     * Returns whether the advertisement will be connectable.
+     */
+    public boolean isConnectable() { return connectable; }
+
+    /**
+     * Returns whether the legacy advertisement will be used.
+     */
+    public boolean isLegacy() { return isLegacy; }
+
+    /**
+     * Returns whether the advertisement will be anonymous.
+     */
+    public boolean isAnonymous() { return isAnonymous; }
+
+    /**
+     * Returns whether the TX Power will be included.
+     */
+    public boolean includeTxPower() { return includeTxPower; }
+
+    /**
+     * Returns the primary advertising phy.
+     */
+    public int getPrimaryPhy() { return primaryPhy; }
+
+    /**
+     * Returns the secondary advertising phy.
+     */
+    public int getSecondaryPhy() { return secondaryPhy; }
+
+    /**
+     * Returns the advertising interval.
+     */
+    public int getInterval() { return interval; }
+
+    /**
+     * Returns the TX power level for advertising.
+     */
+    public int getTxPowerLevel() { return txPowerLevel; }
+
+    /**
+     * Returns the advertising time limit in milliseconds.
+     */
+    public int getTimeout() { return timeoutMillis; }
+
+    @Override
+    public String toString() {
+        return "AdvertisingSetParameters [connectable=" + connectable
+             + ", isLegacy=" + isLegacy
+             + ", isAnonymous=" + isAnonymous
+             + ", includeTxPower=" + includeTxPower
+             + ", primaryPhy=" + primaryPhy
+             + ", secondaryPhy=" + secondaryPhy
+             + ", interval=" + interval
+             + ", txPowerLevel=" + txPowerLevel
+             + ", timeoutMillis=" + timeoutMillis + "]";
+    }
+
+    @Override
+    public int describeContents() {
+       return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(connectable ? 1 : 0);
+        dest.writeInt(isLegacy ? 1 : 0);
+        dest.writeInt(isAnonymous ? 1 : 0);
+        dest.writeInt(includeTxPower ? 1 : 0);
+        dest.writeInt(primaryPhy);
+        dest.writeInt(secondaryPhy);
+        dest.writeInt(interval);
+        dest.writeInt(txPowerLevel);
+        dest.writeInt(timeoutMillis);
+    }
+
+    public static final Parcelable.Creator<AdvertisingSetParameters> CREATOR =
+        new Creator<AdvertisingSetParameters>() {
+          @Override
+          public AdvertisingSetParameters[] newArray(int size) {
+            return new AdvertisingSetParameters[size];
+          }
+
+          @Override
+          public AdvertisingSetParameters createFromParcel(Parcel in) {
+            return new AdvertisingSetParameters(in);
+          }
+        };
+
+    /**
+     * Builder class for {@link AdvertisingSetParameters}.
+     */
+    public static final class Builder {
+
+        private boolean connectable = true;
+        private boolean isLegacy = false;
+        private boolean isAnonymous = false;
+        private boolean includeTxPower = false;
+        private int primaryPhy = PHY_LE_1M;
+        private int secondaryPhy = PHY_LE_1M;
+        private int interval = INTERVAL_LOW;
+        private int txPowerLevel = TX_POWER_MEDIUM;
+        private int timeoutMillis = 0;
+
+        /**
+         * Set whether the advertisement type should be connectable or
+         * non-connectable.
+         * Legacy advertisements can be both connectable and scannable. Other
+         * advertisements can be connectable only if not scannable.
+         * @param connectable Controls whether the advertisment type will be
+         * connectable (true) or non-connectable (false).
+         */
+        public Builder setConnectable(boolean connectable) {
+            this.connectable = connectable;
+            return this;
+        }
+
+        /**
+         * When set to true, advertising set will advertise 4.x Spec compliant
+         * advertisements.
+         *
+         * @param isLegacy wether legacy advertising mode should be used.
+         */
+        public Builder setLegacyMode(boolean isLegacy) {
+            this.isLegacy = isLegacy;
+            return this;
+        }
+
+        /**
+         * Set wether advertiser address should be ommited from all packets. If this
+         * mode is used, periodic advertising can't be enabled for this set.
+         *
+         * This is used only if legacy mode is not used.
+         *
+         * @param isAnonymous wether anonymous advertising should be used.
+         */
+        public Builder setAnonymouus(boolean isAnonymous) {
+            this.isAnonymous = isAnonymous;
+            return this;
+        }
+
+        /**
+         * Set wether TX power should be included in the extended header.
+         *
+         * This is used only if legacy mode is not used.
+         *
+         * @param includeTxPower wether TX power should be included in extended
+         * header
+         */
+        public Builder setIncludeTxPower(boolean includeTxPower) {
+            this.includeTxPower = includeTxPower;
+            return this;
+        }
+
+        /**
+         * Set the primary physical channel used for this advertising set.
+         *
+         * This is used only if legacy mode is not used.
+         *
+         * @param primaryPhy Primary advertising physical channel, can only be
+         *            {@link AdvertisingSetParameters#PHY_LE_1M} or
+         *            {@link AdvertisingSetParameters#PHY_LE_CODED}.
+         * @throws IllegalArgumentException If the primaryPhy is invalid.
+         */
+        public Builder setPrimaryPhy(int primaryPhy) {
+            if (primaryPhy != PHY_LE_1M && primaryPhy != PHY_LE_CODED) {
+               throw new IllegalArgumentException("bad primaryPhy " + primaryPhy);
+            }
+            this.primaryPhy = primaryPhy;
+            return this;
+        }
+
+        /**
+         * Set the secondary physical channel used for this advertising set.
+         *
+         * This is used only if legacy mode is not used.
+         *
+         * @param secondaryPhy Secondary advertising physical channel, can only be
+         *            one of {@link AdvertisingSetParameters#PHY_LE_1M},
+         *            {@link AdvertisingSetParameters#PHY_LE_2M} or
+         *            {@link AdvertisingSetParameters#PHY_LE_CODED}.
+         * @throws IllegalArgumentException If the secondaryPhy is invalid.
+         */
+        public Builder setSecondaryPhy(int secondaryPhy) {
+            if (secondaryPhy != PHY_LE_1M && secondaryPhy !=PHY_LE_2M &&
+                secondaryPhy != PHY_LE_CODED) {
+               throw new IllegalArgumentException("bad secondaryPhy " + secondaryPhy);
+            }
+            this.secondaryPhy = secondaryPhy;
+            return this;
+        }
+
+        /**
+         * Set advertising interval.
+         *
+         * @param interval Bluetooth LE Advertising interval, in 0.625ms unit. Valid
+         *            range is from 160 (100ms) to 16777215 (10,485.759375 s).
+         *            Recommended values are:
+         *            {@link AdvertisingSetParameters#INTERVAL_LOW},
+         *            {@link AdvertisingSetParameters#INTERVAL_MEDIUM}, or
+         *            {@link AdvertisingSetParameters#INTERVAL_HIGH}.
+         * @throws IllegalArgumentException If the interval is invalid.
+         */
+        public Builder setInterval(int interval) {
+            if (interval < INTERVAL_MIN || interval > INTERVAL_MAX) {
+               throw new IllegalArgumentException("unknown interval " + interval);
+            }
+            this.interval = interval;
+            return this;
+        }
+
+        /**
+         * Set the transmission power level for the advertising.
+         * @param txPowerLevel Transmission power of Bluetooth LE Advertising, in
+         *             dBm. The valid range is [-127, 1] Recommended values are:
+         *             {@link AdvertisingSetParameters#TX_POWER_ULTRA_LOW},
+         *             {@link AdvertisingSetParameters#TX_POWER_LOW},
+         *             {@link AdvertisingSetParameters#TX_POWER_MEDIUM}, or
+         *             {@link AdvertisingSetParameters#TX_POWER_HIGH}.
+         *
+         * @throws IllegalArgumentException If the {@code txPowerLevel} is invalid.
+         */
+        public Builder setTxPowerLevel(int txPowerLevel) {
+            if (txPowerLevel < TX_POWER_MIN || txPowerLevel > TX_POWER_MAX) {
+                throw new IllegalArgumentException("unknown txPowerLevel " +
+                                                   txPowerLevel);
+            }
+            this.txPowerLevel = txPowerLevel;
+            return this;
+        }
+
+        /**
+         * Limit advertising to a given amount of time.
+         * @param timeoutMillis Advertising time limit. May not exceed 180000
+         * milliseconds. A value of 0 will disable the time limit.
+         * @throws IllegalArgumentException If the provided timeout is over 180000
+         * ms.
+         */
+        public Builder setTimeout(int timeoutMillis) {
+            if (timeoutMillis < 0 || timeoutMillis > LIMITED_ADVERTISING_MAX_MILLIS) {
+                throw new IllegalArgumentException("timeoutMillis invalid (must be 0-" +
+                                                   LIMITED_ADVERTISING_MAX_MILLIS +
+                                                   " milliseconds)");
+            }
+            this.timeoutMillis = timeoutMillis;
+            return this;
+        }
+
+        /**
+         * Build the {@link AdvertisingSetParameters} object.
+         */
+        public AdvertisingSetParameters build() {
+            return new AdvertisingSetParameters(connectable, isLegacy, isAnonymous,
+                                                includeTxPower, primaryPhy,
+                                                secondaryPhy, interval, txPowerLevel,
+                                                timeoutMillis);
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
index 94d03e5..e03c947 100644
--- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
+++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
@@ -62,6 +62,9 @@
     private BluetoothAdapter mBluetoothAdapter;
     private final Map<AdvertiseCallback, AdvertiseCallbackWrapper>
             mLeAdvertisers = new HashMap<AdvertiseCallback, AdvertiseCallbackWrapper>();
+    private final Map<AdvertisingSetCallback, IAdvertisingSetCallback>
+            advertisingSetCallbackWrappers = new HashMap<>();
+    private final Map<Integer, AdvertisingSet> advertisingSets = new HashMap<>();
 
     /**
      * Use BluetoothAdapter.getLeAdvertiser() instead.
@@ -156,6 +159,93 @@
     }
 
     /**
+    * Creates a new advertising set. If operation succeed, device will start advertising. This
+    * method returns immediately, the operation status is delivered through
+    * {@code callback.onNewAdvertisingSet()}.
+    * <p>
+    * @param parameters advertising set parameters.
+    * @param advertiseData Advertisement data to be broadcasted.
+    * @param scanResponse Scan response associated with the advertisement data.
+    * @param periodicData Periodic advertising data.
+    * @param callback Callback for advertising set.
+    */
+    public void startAdvertisingSet(AdvertisingSetParameters parameters,
+                                    AdvertiseData advertiseData, AdvertiseData scanResponse,
+                                    PeriodicAdvertisingParameters periodicParameters,
+                                    AdvertiseData periodicData, AdvertisingSetCallback callback) {
+        startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
+                            periodicData, callback, new Handler(Looper.getMainLooper()));
+    }
+
+    /**
+    * Creates a new advertising set. If operation succeed, device will start advertising. This
+    * method returns immediately, the operation status is delivered through
+    * {@code callback.onNewAdvertisingSet()}.
+    * <p>
+    * @param parameters advertising set parameters.
+    * @param advertiseData Advertisement data to be broadcasted.
+    * @param scanResponse Scan response associated with the advertisement data.
+    * @param periodicData Periodic advertising data.
+    * @param callback Callback for advertising set.
+    * @param handler thread upon which the callbacks will be invoked.
+    */
+    public void startAdvertisingSet(AdvertisingSetParameters parameters,
+                                    AdvertiseData advertiseData, AdvertiseData scanResponse,
+                                    PeriodicAdvertisingParameters periodicParameters,
+                                    AdvertiseData periodicData, AdvertisingSetCallback callback,
+                                    Handler handler) {
+        BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
+
+        if (callback == null) {
+          throw new IllegalArgumentException("callback cannot be null");
+        }
+
+        IBluetoothGatt gatt;
+        try {
+          gatt = mBluetoothManager.getBluetoothGatt();
+        } catch (RemoteException e) {
+          Log.e(TAG, "Failed to get Bluetooth gatt - ", e);
+          throw new IllegalStateException("Failed to get Bluetooth");
+        }
+
+        IAdvertisingSetCallback wrapped = wrap(callback, handler);
+        advertisingSetCallbackWrappers.put(callback, wrapped);
+
+        try {
+            gatt.startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
+                                     periodicData, wrapped);
+        } catch (RemoteException e) {
+          Log.e(TAG, "Failed to start advertising set - ", e);
+          throw new IllegalStateException("Failed to start advertising set");
+        }
+    }
+
+    /**
+     * Used to dispose of a {@link AdvertisingSet} object, obtained with {@link
+     * BluetoothLeAdvertiser#startAdvertisingSet}.
+     */
+    public void stopAdvertisingSet(AdvertisingSetCallback callback) {
+        if (callback == null) {
+          throw new IllegalArgumentException("callback cannot be null");
+        }
+
+        IAdvertisingSetCallback wrapped = advertisingSetCallbackWrappers.remove(callback);
+        if (wrapped == null) {
+            throw new IllegalArgumentException(
+                "callback does not represent valid registered callback.");
+        }
+
+        IBluetoothGatt gatt;
+        try {
+            gatt = mBluetoothManager.getBluetoothGatt();
+            gatt.stopAdvertisingSet(wrapped);
+       } catch (RemoteException e) {
+            Log.e(TAG, "Failed to stop advertising - ", e);
+            throw new IllegalStateException("Failed to stop advertising");
+        }
+    }
+
+    /**
      * Cleans up advertisers. Should be called when bluetooth is down.
      *
      * @hide
@@ -219,6 +309,110 @@
         return array == null ? 0 : array.length;
     }
 
+    IAdvertisingSetCallback wrap(AdvertisingSetCallback callback, Handler handler) {
+        return new IAdvertisingSetCallback.Stub() {
+            public void onAdvertisingSetStarted(int advertiserId, int status) {
+                handler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        if (status != AdvertisingSetCallback.ADVERTISE_SUCCESS) {
+                            callback.onAdvertisingSetStarted(null, status);
+                            advertisingSetCallbackWrappers.remove(callback);
+                            return;
+                        }
+
+                        AdvertisingSet advertisingSet =
+                            new AdvertisingSet(advertiserId, mBluetoothManager);
+                        advertisingSets.put(advertiserId, advertisingSet);
+                        callback.onAdvertisingSetStarted(advertisingSet, status);
+                    }
+                });
+            }
+
+            public void onAdvertisingSetStopped(int advertiserId) {
+                handler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        AdvertisingSet advertisingSet = advertisingSets.get(advertiserId);
+                        callback.onAdvertisingSetStopped(advertisingSet);
+                        advertisingSets.remove(advertiserId);
+                        advertisingSetCallbackWrappers.remove(callback);
+                    }
+                });
+            }
+
+            public void onAdvertisingEnabled(int advertiserId, boolean enabled, int status) {
+                handler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        AdvertisingSet advertisingSet = advertisingSets.get(advertiserId);
+                        callback.onAdvertisingEnabled(advertisingSet, enabled, status);
+                    }
+                });
+            }
+
+            public void onAdvertisingDataSet(int advertiserId, int status) {
+                handler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        AdvertisingSet advertisingSet = advertisingSets.get(advertiserId);
+                        callback.onAdvertisingDataSet(advertisingSet, status);
+                    }
+                });
+            }
+
+            public void onScanResponseDataSet(int advertiserId, int status) {
+                handler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        AdvertisingSet advertisingSet = advertisingSets.get(advertiserId);
+                        callback.onScanResponseDataSet(advertisingSet, status);
+                    }
+                });
+            }
+
+            public void onAdvertisingParametersUpdated(int advertiserId, int status) {
+                handler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        AdvertisingSet advertisingSet = advertisingSets.get(advertiserId);
+                        callback.onAdvertisingParametersUpdated(advertisingSet, status);
+                    }
+                });
+            }
+
+            public void onPeriodicAdvertisingParametersUpdated(int advertiserId, int status) {
+                handler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        AdvertisingSet advertisingSet = advertisingSets.get(advertiserId);
+                        callback.onPeriodicAdvertisingParametersUpdated(advertisingSet, status);
+                    }
+                });
+            }
+
+            public void onPeriodicAdvertisingDataSet(int advertiserId, int status) {
+                handler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        AdvertisingSet advertisingSet = advertisingSets.get(advertiserId);
+                        callback.onPeriodicAdvertisingDataSet(advertisingSet, status);
+                    }
+                });
+            }
+
+            public void onPeriodicAdvertisingEnable(int advertiserId, boolean enable, int status) {
+                handler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        AdvertisingSet advertisingSet = advertisingSets.get(advertiserId);
+                        callback.onPeriodicAdvertisingEnable(advertisingSet, enable, status);
+                    }
+                });
+            }
+        };
+    }
+
     /**
      * Bluetooth GATT interface callbacks for advertising.
      */
diff --git a/core/java/android/bluetooth/le/IAdvertisingSetCallback.aidl b/core/java/android/bluetooth/le/IAdvertisingSetCallback.aidl
new file mode 100644
index 0000000..4b0a111
--- /dev/null
+++ b/core/java/android/bluetooth/le/IAdvertisingSetCallback.aidl
@@ -0,0 +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 android.bluetooth.le;
+
+/**
+ * Callback definitions for interacting with Advertiser
+ * @hide
+ */
+oneway interface IAdvertisingSetCallback {
+  void onAdvertisingSetStarted(in int advertiserId, in int status);
+  void onAdvertisingSetStopped(in int advertiserId);
+  void onAdvertisingEnabled(in int advertiserId, in boolean enable, in int status);
+  void onAdvertisingDataSet(in int advertiserId, in int status);
+  void onScanResponseDataSet(in int advertiserId, in int status);
+  void onAdvertisingParametersUpdated(in int advertiserId, in int status);
+  void onPeriodicAdvertisingParametersUpdated(in int advertiserId, in int status);
+  void onPeriodicAdvertisingDataSet(in int advertiserId, in int status);
+  void onPeriodicAdvertisingEnable(in int advertiserId, in boolean enable, in int status);
+}
diff --git a/core/java/android/bluetooth/le/IPeriodicAdvertisingCallback.aidl b/core/java/android/bluetooth/le/IPeriodicAdvertisingCallback.aidl
new file mode 100644
index 0000000..a76c54d
--- /dev/null
+++ b/core/java/android/bluetooth/le/IPeriodicAdvertisingCallback.aidl
@@ -0,0 +1,31 @@
+/*
+ * 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 android.bluetooth.le;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.le.PeriodicAdvertisingReport;
+
+/**
+ * Callback definitions for interacting with Periodic Advertising
+ * @hide
+ */
+oneway interface IPeriodicAdvertisingCallback {
+
+  void onSyncEstablished(in int syncHandle, in BluetoothDevice device, in int advertisingSid,
+                         in int skip, in int timeout, in int status);
+  void onPeriodicAdvertisingReport(in PeriodicAdvertisingReport report);
+  void onSyncLost(in int syncHandle);
+}
diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java b/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java
new file mode 100644
index 0000000..6616231
--- /dev/null
+++ b/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java
@@ -0,0 +1,77 @@
+/*
+ * 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 android.bluetooth.le;
+
+import android.bluetooth.BluetoothDevice;
+
+/**
+ * Bluetooth LE periodic advertising callbacks, used to deliver periodic
+ * advertising operation status.
+ *
+ * @see PeriodicAdvertisingManager#createSync
+ */
+public abstract class PeriodicAdvertisingCallback {
+
+    /**
+     * The requested operation was successful.
+     *
+     * @hide
+     */
+    public static final int SYNC_SUCCESS = 0;
+
+    /**
+     * Sync failed to be established because remote device did not respond.
+     */
+    public static final int SYNC_NO_RESPONSE = 1;
+
+    /**
+     *  Sync failed to be established because controller can't support more syncs.
+     */
+    public static final int SYNC_NO_RESOURCES = 2;
+
+
+    /**
+     * Callback when synchronization was established.
+     *
+     * @param syncHandle handle used to identify this synchronization.
+     * @param device remote device.
+     * @param advertisingSid synchronized advertising set id.
+     * @param skip  The number of periodic advertising packets that can be skipped
+     * after a successful receive in force. @see PeriodicAdvertisingManager#createSync
+     * @param timeout Synchronization timeout for the periodic advertising in force. One
+     * unit is 10ms. @see PeriodicAdvertisingManager#createSync
+     * @param timeout
+     * @param status operation status.
+     */
+    public void onSyncEstablished(int syncHandle, BluetoothDevice device,
+                                  int advertisingSid, int skip, int timeout,
+                                  int status) {}
+
+    /**
+     * Callback when periodic advertising report is received.
+     *
+     * @param report periodic advertising report.
+     */
+    public void onPeriodicAdvertisingReport(PeriodicAdvertisingReport report) {}
+
+    /**
+     * Callback when periodic advertising synchronization was lost.
+     *
+     * @param syncHandle handle used to identify this synchronization.
+     */
+    public void onSyncLost(int syncHandle) {}
+}
diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java b/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java
new file mode 100644
index 0000000..12c8a8c
--- /dev/null
+++ b/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java
@@ -0,0 +1,237 @@
+/*
+ * 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 android.bluetooth.le;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.IBluetoothGatt;
+import android.bluetooth.IBluetoothManager;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.util.Log;
+import java.util.IdentityHashMap;
+import java.util.Map;
+
+/**
+ * This class provides methods to perform periodic advertising related
+ * operations. An application can register for periodic advertisements using
+ * {@link PeriodicAdvertisingManager#registerSync}.
+ * <p>
+ * Use {@link BluetoothAdapter#getPeriodicAdvertisingManager()} to get an
+ * instance of {@link PeriodicAdvertisingManager}.
+ * <p>
+ * <b>Note:</b> Most of the methods here require
+ * {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
+ */
+public final class PeriodicAdvertisingManager {
+
+  private static final String TAG = "PeriodicAdvertisingManager";
+
+  private static final int SKIP_MIN = 0;
+  private static final int SKIP_MAX = 499;
+  private static final int TIMEOUT_MIN = 10;
+  private static final int TIMEOUT_MAX = 16384;
+
+  private static final int SYNC_STARTING = -1;
+
+  private final IBluetoothManager mBluetoothManager;
+  private BluetoothAdapter mBluetoothAdapter;
+
+  /* maps callback, to callback wrapper and sync handle */
+  Map<PeriodicAdvertisingCallback,
+      IPeriodicAdvertisingCallback /* callbackWrapper */> callbackWrappers;
+
+  /**
+   * Use {@link BluetoothAdapter#getBluetoothLeScanner()} instead.
+   *
+   * @param bluetoothManager BluetoothManager that conducts overall Bluetooth Management.
+   * @hide
+   */
+  public PeriodicAdvertisingManager(IBluetoothManager bluetoothManager) {
+    mBluetoothManager = bluetoothManager;
+    mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+    callbackWrappers = new IdentityHashMap<>();
+  }
+
+  /**
+   * Synchronize with periodic advertising pointed to by the {@code scanResult}.
+   * The {@code scanResult} used must contain a valid advertisingSid. First
+   * call to registerSync will use the {@code skip} and {@code timeout} provided.
+   * Subsequent calls from other apps, trying to sync with same set will reuse
+   * existing sync, thus {@code skip} and {@code timeout} values will not take
+   * effect. The values in effect will be returned in
+   * {@link PeriodicAdvertisingCallback#onSyncEstablished}.
+   *
+   * @param scanResult Scan result containing advertisingSid.
+   * @param skip The number of periodic advertising packets that can be skipped
+   * after a successful receive. Must be between 0 and 499.
+   * @param timeout Synchronization timeout for the periodic advertising. One
+   * unit is 10ms. Must be between 10 (100ms) and 16384 (163.84s).
+   * @param callback Callback used to deliver all operations status.
+   * @throws IllegalArgumentException if {@code scanResult} is null or {@code
+   * skip} is invalid or {@code timeout} is invalid or {@code callback} is null.
+   */
+  public void registerSync(ScanResult scanResult, int skip, int timeout,
+                         PeriodicAdvertisingCallback callback) {
+    registerSync(scanResult, skip, timeout, callback, null);
+  }
+
+  /**
+   * Synchronize with periodic advertising pointed to by the {@code scanResult}.
+   * The {@code scanResult} used must contain a valid advertisingSid. First
+   * call to registerSync will use the {@code skip} and {@code timeout} provided.
+   * Subsequent calls from other apps, trying to sync with same set will reuse
+   * existing sync, thus {@code skip} and {@code timeout} values will not take
+   * effect. The values in effect will be returned in
+   * {@link PeriodicAdvertisingCallback#onSyncEstablished}.
+   *
+   * @param scanResult Scan result containing advertisingSid.
+   * @param skip The number of periodic advertising packets that can be skipped
+   * after a successful receive. Must be between 0 and 499.
+   * @param timeout Synchronization timeout for the periodic advertising. One
+   * unit is 10ms. Must be between 10 (100ms) and 16384 (163.84s).
+   * @param callback Callback used to deliver all operations status.
+   * @param handler thread upon which the callbacks will be invoked.
+   * @throws IllegalArgumentException if {@code scanResult} is null or {@code
+   * skip} is invalid or {@code timeout} is invalid or {@code callback} is null.
+   */
+  public void registerSync(ScanResult scanResult, int skip, int timeout,
+                         PeriodicAdvertisingCallback callback, Handler handler) {
+    if (callback == null) {
+      throw new IllegalArgumentException("callback can't be null");
+    }
+
+    if (scanResult == null) {
+      throw new IllegalArgumentException("scanResult can't be null");
+    }
+
+    if (scanResult.getAdvertisingSid() == ScanResult.SID_NOT_PRESENT) {
+      throw new IllegalArgumentException("scanResult must contain a valid sid");
+    }
+
+    if (skip < SKIP_MIN || skip > SKIP_MAX) {
+      throw new IllegalArgumentException(
+          "timeout must be between " + TIMEOUT_MIN + " and " + TIMEOUT_MAX);
+    }
+
+    if (timeout < TIMEOUT_MIN || timeout > TIMEOUT_MAX) {
+      throw new IllegalArgumentException(
+          "timeout must be between " + TIMEOUT_MIN + " and " + TIMEOUT_MAX);
+    }
+
+    IBluetoothGatt gatt;
+    try {
+        gatt = mBluetoothManager.getBluetoothGatt();
+    } catch (RemoteException e) {
+        Log.e(TAG, "Failed to get Bluetooth gatt - ", e);
+        callback.onSyncEstablished(0, scanResult.getDevice(), scanResult.getAdvertisingSid(),
+                                   skip, timeout,
+                                   PeriodicAdvertisingCallback.SYNC_NO_RESOURCES);
+        return;
+    }
+
+    if (handler == null)
+      handler = new Handler(Looper.getMainLooper());
+
+    IPeriodicAdvertisingCallback wrapped = wrap(callback, handler);
+    callbackWrappers.put(callback, wrapped);
+
+    try {
+      gatt.registerSync(scanResult, skip, timeout, wrapped);
+    } catch (RemoteException e) {
+      Log.e(TAG, "Failed to register sync - ", e);
+      return;
+    }
+  }
+
+  /**
+   * Cancel pending attempt to create sync, or terminate existing sync.
+   *
+   * @param callback Callback used to deliver all operations status.
+   * @throws IllegalArgumentException if {@code callback} is null, or not a properly
+   * registered callback.
+   */
+  public void unregisterSync(PeriodicAdvertisingCallback callback) {
+    if (callback == null) {
+      throw new IllegalArgumentException("callback can't be null");
+    }
+
+    IBluetoothGatt gatt;
+    try {
+        gatt = mBluetoothManager.getBluetoothGatt();
+    } catch (RemoteException e) {
+        Log.e(TAG, "Failed to get Bluetooth gatt - ", e);
+        return;
+    }
+
+    IPeriodicAdvertisingCallback wrapper = callbackWrappers.remove(callback);
+    if (wrapper == null) {
+      throw new IllegalArgumentException("callback was not properly registered");
+    }
+
+    try {
+      gatt.unregisterSync(wrapper);
+    } catch (RemoteException e) {
+        Log.e(TAG, "Failed to cancel sync creation - ", e);
+        return;
+    }
+  }
+
+  private IPeriodicAdvertisingCallback wrap(PeriodicAdvertisingCallback callback, Handler handler) {
+    return new IPeriodicAdvertisingCallback.Stub() {
+      public void onSyncEstablished(int syncHandle, BluetoothDevice device,
+                                    int advertisingSid, int skip, int timeout, int status) {
+
+          handler.post(new Runnable() {
+              @Override
+              public void run() {
+                  callback.onSyncEstablished(syncHandle, device, advertisingSid, skip, timeout,
+                                             status);
+
+                  if (status != PeriodicAdvertisingCallback.SYNC_SUCCESS) {
+                      // App can still unregister the sync until notified it failed. Remove callback
+                      // after app was notifed.
+                      callbackWrappers.remove(callback);
+                  }
+              }
+          });
+      }
+
+      public void onPeriodicAdvertisingReport(PeriodicAdvertisingReport report) {
+          handler.post(new Runnable() {
+              @Override
+              public void run() {
+                callback.onPeriodicAdvertisingReport(report);
+              }
+          });
+      }
+
+      public void onSyncLost(int syncHandle) {
+          handler.post(new Runnable() {
+              @Override
+              public void run() {
+                callback.onSyncLost(syncHandle);
+                // App can still unregister the sync until notified it's lost. Remove callback after
+                // app was notifed.
+                callbackWrappers.remove(callback);
+              }
+          });
+      }
+    };
+  }
+}
diff --git a/core/java/com/android/internal/logging/legacy/Util.java b/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.aidl
similarity index 77%
copy from core/java/com/android/internal/logging/legacy/Util.java
copy to core/java/android/bluetooth/le/PeriodicAdvertisingParameters.aidl
index 99f71ca..f4bea22 100644
--- a/core/java/com/android/internal/logging/legacy/Util.java
+++ b/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.aidl
@@ -13,13 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.internal.logging.legacy;
 
-/**
- * Created by cwren on 11/21/16.
- */
-public class Util {
-    public static boolean debug() {
-        return false;
-    }
-}
+package android.bluetooth.le;
+
+parcelable PeriodicAdvertisingParameters;
diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java b/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java
new file mode 100644
index 0000000..ebc92bd
--- /dev/null
+++ b/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java
@@ -0,0 +1,134 @@
+/*
+ * 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 android.bluetooth.le;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * The {@link PeriodicAdvertisingParameters} provide a way to adjust periodic
+ * advertising preferences for each Bluetooth LE advertising set. Use {@link
+ * AdvertisingSetParameters.Builder} to create an instance of this class.
+ */
+public final class PeriodicAdvertisingParameters implements Parcelable {
+
+    private static final int INTERVAL_MAX = 80;
+    private static final int INTERVAL_MIN = 65519;
+
+    private final boolean enable;
+    private final boolean includeTxPower;
+    private final int interval;
+
+    private PeriodicAdvertisingParameters(boolean enable, boolean includeTxPower, int interval) {
+        this.enable = enable;
+        this.includeTxPower = includeTxPower;
+        this.interval = interval;
+    }
+
+    private PeriodicAdvertisingParameters(Parcel in) {
+        enable = in.readInt() != 0 ? true : false;
+        includeTxPower = in.readInt() != 0 ? true : false;
+        interval = in.readInt();
+    }
+
+    /**
+     * Returns whether the periodic advertising shall be enabled.
+     */
+    public boolean getEnable() { return enable; }
+
+    /**
+     * Returns whether the TX Power will be included.
+     */
+    public boolean getIncludeTxPower() { return includeTxPower; }
+
+    /**
+     * Returns the periodic advertising interval, in 1.25ms unit.
+     * Valid values are from 80 (100ms) to 65519 (81.89875s).
+     */
+    public int getInterval() { return interval; }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(enable ? 1 : 0);
+        dest.writeInt(includeTxPower ? 1 : 0);
+        dest.writeInt(interval);
+    }
+
+    public static final Parcelable
+        .Creator<PeriodicAdvertisingParameters> CREATOR =
+        new Creator<PeriodicAdvertisingParameters>() {
+            @Override
+            public PeriodicAdvertisingParameters[] newArray(int size) {
+                return new PeriodicAdvertisingParameters[size];
+            }
+
+            @Override
+            public PeriodicAdvertisingParameters createFromParcel(Parcel in) {
+                return new PeriodicAdvertisingParameters(in);
+            }
+        };
+
+    public static final class Builder {
+        private boolean includeTxPower = false;
+        private boolean enable = false;
+        private int interval = INTERVAL_MAX;
+
+        /**
+         * Set wether the Periodic Advertising should be enabled for this set.
+         */
+        public Builder setEnable(boolean enable) {
+            this.enable = enable;
+            return this;
+        }
+
+        /**
+         * Whether the transmission power level should be included in the periodic
+         * packet.
+         */
+        public Builder setIncludeTxPower(boolean includeTxPower) {
+            this.includeTxPower = includeTxPower;
+            return this;
+        }
+
+        /**
+         * Set advertising interval for periodic advertising, in 1.25ms unit.
+         * Valid values are from 80 (100ms) to 65519 (81.89875s).
+         * Value from range [interval, interval+20ms] will be picked as the actual value.
+         * @throws IllegalArgumentException If the interval is invalid.
+         */
+        public Builder setInterval(int interval) {
+            if (interval < INTERVAL_MIN || interval > INTERVAL_MAX) {
+                throw new IllegalArgumentException("Invalid interval (must be " + INTERVAL_MIN +
+                                                   "-" + INTERVAL_MAX + ")");
+            }
+            this.interval = interval;
+            return this;
+        }
+
+        /**
+         * Build the {@link AdvertisingSetParameters} object.
+         */
+        public PeriodicAdvertisingParameters build() {
+            return new PeriodicAdvertisingParameters(enable, includeTxPower, interval);
+        }
+    }
+}
diff --git a/core/java/com/android/internal/logging/legacy/Util.java b/core/java/android/bluetooth/le/PeriodicAdvertisingReport.aidl
similarity index 77%
copy from core/java/com/android/internal/logging/legacy/Util.java
copy to core/java/android/bluetooth/le/PeriodicAdvertisingReport.aidl
index 99f71ca..547d096 100644
--- a/core/java/com/android/internal/logging/legacy/Util.java
+++ b/core/java/android/bluetooth/le/PeriodicAdvertisingReport.aidl
@@ -13,13 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.internal.logging.legacy;
 
-/**
- * Created by cwren on 11/21/16.
- */
-public class Util {
-    public static boolean debug() {
-        return false;
-    }
-}
+package android.bluetooth.le;
+
+parcelable PeriodicAdvertisingReport;
diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java b/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java
new file mode 100644
index 0000000..3ff4ca5
--- /dev/null
+++ b/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java
@@ -0,0 +1,184 @@
+/*
+ * 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 android.bluetooth.le;
+
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * PeriodicAdvertisingReport for Bluetooth LE synchronized advertising.
+ */
+public final class PeriodicAdvertisingReport implements Parcelable {
+
+    /**
+     * The data returned is complete
+     */
+    public static final int DATA_COMPLETE = 0;
+
+    /**
+     * The data returned is incomplete. The controller was unsuccessfull to
+     * receive all chained packets, returning only partial data.
+     */
+    public static final int DATA_INCOMPLETE_TRUNCATED = 2;
+
+    private int syncHandle;
+    private int txPower;
+    private int rssi;
+    private int dataStatus;
+
+    // periodic advertising data.
+    @Nullable
+    private ScanRecord data;
+
+    // Device timestamp when the result was last seen.
+    private long timestampNanos;
+
+    /**
+     * Constructor of periodic advertising result.
+     *
+     */
+    public PeriodicAdvertisingReport(int syncHandle, int txPower, int rssi,
+                                     int dataStatus, ScanRecord data) {
+        this.syncHandle = syncHandle;
+        this.txPower = txPower;
+        this.rssi = rssi;
+        this.dataStatus = dataStatus;
+        this.data = data;
+    }
+
+    private PeriodicAdvertisingReport(Parcel in) {
+        readFromParcel(in);
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(syncHandle);
+        dest.writeLong(txPower);
+        dest.writeInt(rssi);
+        dest.writeInt(dataStatus);
+        if (data != null) {
+            dest.writeInt(1);
+            dest.writeByteArray(data.getBytes());
+        } else {
+            dest.writeInt(0);
+        }
+    }
+
+    private void readFromParcel(Parcel in) {
+        syncHandle = in.readInt();
+        txPower = in.readInt();
+        rssi = in.readInt();
+        dataStatus = in.readInt();
+        if (in.readInt() == 1) {
+            data = ScanRecord.parseFromBytes(in.createByteArray());
+        }
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * Returns the synchronization handle.
+     */
+    public int getSyncHandle() {
+        return syncHandle;
+    }
+
+    /**
+     * Returns the transmit power in dBm. The valid range is [-127, 126]. Value
+     * of 127 means information was not available.
+     */
+    public int getTxPower() {
+        return txPower;
+    }
+
+    /**
+     * Returns the received signal strength in dBm. The valid range is [-127, 20].
+     */
+    public int getRssi() {
+        return rssi;
+    }
+
+    /**
+     * Returns the data status. Can be one of {@link PeriodicAdvertisingReport#DATA_COMPLETE}
+     * or {@link PeriodicAdvertisingReport#DATA_INCOMPLETE_TRUNCATED}.
+     */
+    public int getDataStatus() {
+        return dataStatus;
+    }
+
+    /**
+     * Returns the data contained in this periodic advertising report.
+     */
+    @Nullable
+    public ScanRecord getData() {
+        return data;
+    }
+
+    /**
+     * Returns timestamp since boot when the scan record was observed.
+     */
+    public long getTimestampNanos() {
+        return timestampNanos;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(syncHandle, txPower, rssi, dataStatus, data, timestampNanos);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+        PeriodicAdvertisingReport other = (PeriodicAdvertisingReport) obj;
+        return (syncHandle == other.syncHandle) &&
+            (txPower == other.txPower) &&
+            (rssi == other.rssi) &&
+            (dataStatus == other.dataStatus) &&
+            Objects.equals(data, other.data) &&
+            (timestampNanos == other.timestampNanos);
+    }
+
+    @Override
+    public String toString() {
+      return "PeriodicAdvertisingReport{syncHandle=" + syncHandle +
+          ", txPower=" + txPower + ", rssi=" + rssi + ", dataStatus=" + dataStatus +
+          ", data=" + Objects.toString(data) + ", timestampNanos=" + timestampNanos + '}';
+    }
+
+    public static final Parcelable.Creator<PeriodicAdvertisingReport> CREATOR = new Creator<PeriodicAdvertisingReport>() {
+            @Override
+        public PeriodicAdvertisingReport createFromParcel(Parcel source) {
+            return new PeriodicAdvertisingReport(source);
+        }
+
+            @Override
+        public PeriodicAdvertisingReport[] newArray(int size) {
+            return new PeriodicAdvertisingReport[size];
+        }
+    };
+}
diff --git a/core/java/android/bluetooth/le/ScanResult.java b/core/java/android/bluetooth/le/ScanResult.java
index 2fdfe7f..583ddd2 100644
--- a/core/java/android/bluetooth/le/ScanResult.java
+++ b/core/java/android/bluetooth/le/ScanResult.java
@@ -27,7 +27,56 @@
  * ScanResult for Bluetooth LE scan.
  */
 public final class ScanResult implements Parcelable {
-    // Remote bluetooth device.
+
+    /**
+     * For chained advertisements, inidcates tha the data contained in this
+     * scan result is complete.
+     */
+    public static final int DATA_COMPLETE = 0x00;
+
+    /**
+     * For chained advertisements, indicates that the controller was
+     * unable to receive all chained packets and the scan result contains
+     * incomplete truncated data.
+     */
+    public static final int DATA_TRUNCATED = 0x02;
+
+    /**
+     * Indicates that the secondary physical layer was not used.
+     */
+    public static final int PHY_UNUSED = 0x00;
+
+    /**
+     * Bluetooth LE 1Mbit advertiser PHY.
+     */
+    public static final int PHY_LE_1M = 0x01;
+
+    /**
+     * Bluetooth LE 2Mbit advertiser PHY.
+     */
+    public static final int PHY_LE_2M = 0x02;
+
+    /**
+     * Bluetooth LE Coded advertiser PHY.
+     */
+    public static final int PHY_LE_CODED = 0x03;
+
+    /**
+     * Advertising Set ID is not present in the packet.
+     */
+    public static final int SID_NOT_PRESENT = 0xFF;
+
+    /**
+     * Mask for checking wether event type represents legacy advertisement.
+     */
+    private static final int ET_LEGACY_MASK = 0x10;
+
+    /**
+     * Mask for checking wether event type represents connectable advertisement.
+     */
+    private static final int ET_CONNECTABLE_MASK = 0x01;
+
+    // Remote Bluetooth device.
     private BluetoothDevice mDevice;
 
     // Scan record, including advertising data and scan response data.
@@ -40,13 +89,21 @@
     // Device timestamp when the result was last seen.
     private long mTimestampNanos;
 
+    private int mEventType;
+    private int mPrimaryPhy;
+    private int mSecondaryPhy;
+    private int mAdvertisingSid;
+    private int mTxPower;
+    private int mPeriodicAdvertisingInterval;
+
     /**
-     * Constructor of scan result.
+     * Constructs a new ScanResult.
      *
-     * @param device Remote bluetooth device that is found.
+     * @param device Remote Bluetooth device found.
      * @param scanRecord Scan record including both advertising data and scan response data.
      * @param rssi Received signal strength.
-     * @param timestampNanos Device timestamp when the scan result was observed.
+     * @param timestampNanos Timestamp at which the scan result was observed.
+     * @deprecated use {@link #ScanResult(BluetoothDevice, int, int, int, int, int, int, int, ScanRecord, long)}
      */
     public ScanResult(BluetoothDevice device, ScanRecord scanRecord, int rssi,
             long timestampNanos) {
@@ -54,6 +111,41 @@
         mScanRecord = scanRecord;
         mRssi = rssi;
         mTimestampNanos = timestampNanos;
+        mEventType = (DATA_COMPLETE << 5) | ET_LEGACY_MASK | ET_CONNECTABLE_MASK;
+        mPrimaryPhy = PHY_LE_1M;
+        mSecondaryPhy = PHY_UNUSED;
+        mAdvertisingSid = SID_NOT_PRESENT;
+        mTxPower = 127;
+        mPeriodicAdvertisingInterval = 0;
+    }
+
+    /**
+     * Constructs a new ScanResult.
+     *
+     * @param device Remote Bluetooth device found.
+     * @param eventType Event type.
+     * @param primaryPhy Primary advertising phy.
+     * @param secondaryPhy Secondary advertising phy.
+     * @param advertisingSid Advertising set ID.
+     * @param txPower Transmit power.
+     * @param rssi Received signal strength.
+     * @param periodicAdvertisingInterval Periodic advertising interval.
+     * @param scanRecord Scan record including both advertising data and scan response data.
+     * @param timestampNanos Timestamp at which the scan result was observed.
+     */
+    public ScanResult(BluetoothDevice device, int eventType, int primaryPhy, int secondaryPhy,
+                      int advertisingSid, int txPower, int rssi, int periodicAdvertisingInterval,
+                      ScanRecord scanRecord, long timestampNanos) {
+        mDevice = device;
+        mEventType = eventType;
+        mPrimaryPhy = primaryPhy;
+        mSecondaryPhy = secondaryPhy;
+        mAdvertisingSid = advertisingSid;
+        mTxPower = txPower;
+        mRssi = rssi;
+        mPeriodicAdvertisingInterval = periodicAdvertisingInterval;
+        mScanRecord = scanRecord;
+        mTimestampNanos = timestampNanos;
     }
 
     private ScanResult(Parcel in) {
@@ -76,6 +168,12 @@
         }
         dest.writeInt(mRssi);
         dest.writeLong(mTimestampNanos);
+        dest.writeInt(mEventType);
+        dest.writeInt(mPrimaryPhy);
+        dest.writeInt(mSecondaryPhy);
+        dest.writeInt(mAdvertisingSid);
+        dest.writeInt(mTxPower);
+        dest.writeInt(mPeriodicAdvertisingInterval);
     }
 
     private void readFromParcel(Parcel in) {
@@ -87,6 +185,12 @@
         }
         mRssi = in.readInt();
         mTimestampNanos = in.readLong();
+        mEventType = in.readInt();
+        mPrimaryPhy = in.readInt();
+        mSecondaryPhy = in.readInt();
+        mAdvertisingSid = in.readInt();
+        mTxPower = in.readInt();
+        mPeriodicAdvertisingInterval = in.readInt();
     }
 
     @Override
@@ -95,7 +199,7 @@
     }
 
     /**
-     * Returns the remote bluetooth device identified by the bluetooth device address.
+     * Returns the remote Bluetooth device identified by the Bluetooth device address.
      */
     public BluetoothDevice getDevice() {
         return mDevice;
@@ -110,7 +214,7 @@
     }
 
     /**
-     * Returns the received signal strength in dBm. The valid range is [-127, 127].
+     * Returns the received signal strength in dBm. The valid range is [-127, 126].
      */
     public int getRssi() {
         return mRssi;
@@ -123,9 +227,79 @@
         return mTimestampNanos;
     }
 
+    /**
+     * Returns true if this object represents legacy scan result.
+     * Legacy scan results do not contain advanced advertising information
+     * as specified in the Bluetooth Core Specification v5.
+     */
+    public boolean isLegacy() {
+        return (mEventType & ET_LEGACY_MASK) != 0;
+    }
+
+    /**
+     * Returns true if this object represents connectable scan result.
+     */
+    public boolean isConnectable() {
+        return (mEventType & ET_CONNECTABLE_MASK) != 0;
+    }
+
+    /**
+     * Returns the data status.
+     * Can be one of {@link ScanResult#DATA_COMPLETE} or
+     * {@link ScanResult#DATA_TRUNCATED}.
+     */
+    public int getDataStatus() {
+        // return bit 5 and 6
+        return (mEventType >> 5) & 0x03;
+    }
+
+    /**
+     * Returns the primary Physical Layer
+     * on which this advertisment was received.
+     * Can be one of {@link ScanResult#PHY_LE_1M} or
+     * {@link ScanResult#PHY_LE_CODED}.
+     */
+    public int getPrimaryPhy() { return mPrimaryPhy; }
+
+    /**
+     * Returns the secondary Physical Layer
+     * on which this advertisment was received.
+     * Can be one of {@link ScanResult#PHY_LE_1M},
+     * {@link ScanResult#PHY_LE_2M}, {@link ScanResult#PHY_LE_CODED}
+     * or {@link ScanResult#PHY_UNUSED} - if the advertisement
+     * was not received on a secondary physical channel.
+     */
+    public int getSecondaryPhy() { return mSecondaryPhy; }
+
+    /**
+     * Returns the advertising set id.
+     * May return {@link ScanResult#SID_NOT_PRESENT} if
+     * no set id was is present.
+     */
+    public int getAdvertisingSid() { return mAdvertisingSid; }
+
+    /**
+     * Returns the transmit power in dBm.
+     * Valid range is [-127, 126]. A value of 127 indicates that the
+     * advertisement did not indicate TX power.
+     */
+    public int getTxPower() { return mTxPower; }
+
+    /**
+     * Returns the periodic advertising interval in units of 1.25ms.
+     * Valid range is 6 (7.5ms) to 65536 (81918.75ms). A value of 0 means
+     * periodic advertising is not used for this scan result.
+     */
+    public int getPeriodicAdvertisingInterval() {
+        return mPeriodicAdvertisingInterval;
+    }
+
     @Override
     public int hashCode() {
-        return Objects.hash(mDevice, mRssi, mScanRecord, mTimestampNanos);
+        return Objects.hash(mDevice, mRssi, mScanRecord, mTimestampNanos,
+                            mEventType, mPrimaryPhy, mSecondaryPhy,
+                            mAdvertisingSid, mTxPower,
+                            mPeriodicAdvertisingInterval);
     }
 
     @Override
@@ -138,15 +312,24 @@
         }
         ScanResult other = (ScanResult) obj;
         return Objects.equals(mDevice, other.mDevice) && (mRssi == other.mRssi) &&
-                Objects.equals(mScanRecord, other.mScanRecord)
-                && (mTimestampNanos == other.mTimestampNanos);
+            Objects.equals(mScanRecord, other.mScanRecord) &&
+            (mTimestampNanos == other.mTimestampNanos) &&
+            mEventType == other.mEventType &&
+            mPrimaryPhy == other.mPrimaryPhy &&
+            mSecondaryPhy == other.mSecondaryPhy &&
+            mAdvertisingSid == other.mAdvertisingSid &&
+            mTxPower == other.mTxPower &&
+            mPeriodicAdvertisingInterval == other.mPeriodicAdvertisingInterval;
     }
 
     @Override
     public String toString() {
-        return "ScanResult{" + "mDevice=" + mDevice + ", mScanRecord="
-                + Objects.toString(mScanRecord) + ", mRssi=" + mRssi + ", mTimestampNanos="
-                + mTimestampNanos + '}';
+      return "ScanResult{" + "device=" + mDevice + ", scanRecord=" +
+          Objects.toString(mScanRecord) + ", rssi=" + mRssi +
+          ", timestampNanos=" + mTimestampNanos + ", eventType=" + mEventType +
+          ", primaryPhy=" + mPrimaryPhy + ", secondaryPhy=" + mSecondaryPhy +
+          ", advertisingSid=" + mAdvertisingSid + ", txPower=" + mTxPower +
+          ", periodicAdvertisingInterval=" + mPeriodicAdvertisingInterval + '}';
     }
 
     public static final Parcelable.Creator<ScanResult> CREATOR = new Creator<ScanResult>() {
diff --git a/core/java/android/bluetooth/le/ScanSettings.java b/core/java/android/bluetooth/le/ScanSettings.java
index d616624..69c9a8c 100644
--- a/core/java/android/bluetooth/le/ScanSettings.java
+++ b/core/java/android/bluetooth/le/ScanSettings.java
@@ -122,6 +122,24 @@
     @SystemApi
     public static final int SCAN_RESULT_TYPE_ABBREVIATED = 1;
 
+    /**
+     * Use the Bluetooth LE 1Mbit PHY for scanning.
+     */
+    public static final int PHY_LE_1M = 1;
+
+    /**
+     * Use Bluetooth LE Coded PHY for scanning.
+     */
+    public static final int PHY_LE_CODED = 3;
+
+    /**
+     * Use all supported PHYs for scanning.
+     * This will check the controller capabilities, and start
+     * the scan on 1Mbit and LE Coded PHYs if supported, or on
+     * the 1Mbit PHY only.
+     */
+    public static final int PHY_LE_ALL_SUPPORTED = 255;
+
     // Bluetooth LE scan mode.
     private int mScanMode;
 
@@ -138,6 +156,11 @@
 
     private int mNumOfMatchesPerFilter;
 
+    // Include only legacy advertising results
+    private boolean mLegacy;
+
+    private int mPhy;
+
     public int getScanMode() {
         return mScanMode;
     }
@@ -165,6 +188,22 @@
     }
 
     /**
+     * Returns whether only legacy advertisements will be returned.
+     * Legacy advertisements include advertisements as specified
+     * by the Bluetooth core specification 4.2 and below.
+     */
+    public boolean getLegacy() {
+        return mLegacy;
+    }
+
+    /**
+     * Returns the physical layer used during a scan.
+     */
+    public int getPhy() {
+        return mPhy;
+    }
+
+    /**
      * Returns report delay timestamp based on the device clock.
      */
     public long getReportDelayMillis() {
@@ -172,13 +211,16 @@
     }
 
     private ScanSettings(int scanMode, int callbackType, int scanResultType,
-            long reportDelayMillis, int matchMode, int numOfMatchesPerFilter) {
+                         long reportDelayMillis, int matchMode,
+                         int numOfMatchesPerFilter, boolean legacy, int phy) {
         mScanMode = scanMode;
         mCallbackType = callbackType;
         mScanResultType = scanResultType;
         mReportDelayMillis = reportDelayMillis;
         mNumOfMatchesPerFilter = numOfMatchesPerFilter;
         mMatchMode = matchMode;
+        mLegacy = legacy;
+        mPhy = phy;
     }
 
     private ScanSettings(Parcel in) {
@@ -188,6 +230,8 @@
         mReportDelayMillis = in.readLong();
         mMatchMode = in.readInt();
         mNumOfMatchesPerFilter = in.readInt();
+        mLegacy = in.readInt() != 0 ? true : false;
+        mPhy = in.readInt();
     }
 
     @Override
@@ -198,6 +242,8 @@
         dest.writeLong(mReportDelayMillis);
         dest.writeInt(mMatchMode);
         dest.writeInt(mNumOfMatchesPerFilter);
+        dest.writeInt(mLegacy ? 1 : 0);
+        dest.writeInt(mPhy);
     }
 
     @Override
@@ -228,6 +274,9 @@
         private long mReportDelayMillis = 0;
         private int mMatchMode = MATCH_MODE_AGGRESSIVE;
         private int mNumOfMatchesPerFilter  = MATCH_NUM_MAX_ADVERTISEMENT;
+        private boolean mLegacy = true;
+        private int mPhy = PHY_LE_ALL_SUPPORTED;
+
         /**
          * Set scan mode for Bluetooth LE scan.
          *
@@ -341,11 +390,44 @@
         }
 
         /**
+         * Set whether only legacy advertisments should be returned in scan results.
+         * Legacy advertisements include advertisements as specified by the
+         * Bluetooth core specification 4.2 and below. This is true by default
+         * for compatibility with older apps.
+         *
+         * @param legacy true if only legacy advertisements will be returned
+         */
+        public Builder setLegacy(boolean legacy) {
+            mLegacy = legacy;
+            return this;
+        }
+
+        /**
+         * Set the Physical Layer to use during this scan.
+         * This is used only if {@link ScanSettings.Builder#setLegacy}
+         * is set to false.
+         * {@link android.bluetooth.BluetoothAdapter#isLeCodedPhySupported}
+         * may be used to check whether LE Coded phy is supported by calling
+         * {@link android.bluetooth.BluetoothAdapter#isLeCodedPhySupported}.
+         * Selecting an unsupported phy will result in failure to start scan.
+         *
+         * @param phy Can be one of
+         *   {@link ScanSettings#PHY_LE_1M},
+         *   {@link ScanSettings#PHY_LE_CODED} or
+         *   {@link ScanSettings#PHY_LE_ALL_SUPPORTED}
+         */
+        public Builder setPhy(int phy) {
+            mPhy = phy;
+            return this;
+        }
+
+        /**
          * Build {@link ScanSettings}.
          */
         public ScanSettings build() {
             return new ScanSettings(mScanMode, mCallbackType, mScanResultType,
-                    mReportDelayMillis, mMatchMode, mNumOfMatchesPerFilter);
+                                    mReportDelayMillis, mMatchMode,
+                                    mNumOfMatchesPerFilter, mLegacy, mPhy);
         }
     }
 }
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index c0c1a4d..6fa32b4 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -26,6 +26,8 @@
 import android.os.Looper;
 import android.os.RemoteException;
 
+import java.util.List;
+
 /**
  * System level service for managing companion devices
  *
@@ -102,6 +104,11 @@
      * special capabilities have a negative effect on the device's battery and user's data
      * usage, therefore you should requested them when absolutely necessary.</p>
      *
+     * <p>You can call {@link #getAssociations} to get the list of currently associated
+     * devices, and {@link #disassociate} to remove an association. Consider doing so when the
+     * association is no longer relevant to avoid unnecessary battery and/or data drain resulting
+     * from special privileges that the association provides</p>
+     *
      * @param request specific details about this request
      * @param callback will be called once there's at least one device found for user to choose from
      * @param handler A handler to control which thread the callback will be delivered on, or null,
@@ -119,6 +126,8 @@
         try {
             mService.associate(
                     request,
+                    //TODO implicit pointer to outer class -> =null onDestroy
+                    //TODO onStop if isFinishing -> stopScan
                     new IFindDeviceCallback.Stub() {
                         @Override
                         public void onSuccess(PendingIntent launcher) {
@@ -138,6 +147,38 @@
         }
     }
 
+    /**
+     * @return a list of MAC addresses of devices that have been previously associated with the
+     * current app. You can use these with {@link #disassociate}
+     */
+    @NonNull
+    public List<String> getAssociations() {
+        try {
+            return mService.getAssociations(mContext.getPackageName());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Remove the association between this app and the device with the given mac address.
+     *
+     * <p>Any privileges provided via being associated with a given device will be revoked</p>
+     *
+     * <p>Consider doing so when the
+     * association is no longer relevant to avoid unnecessary battery and/or data drain resulting
+     * from special privileges that the association provides</p>
+     *
+     * @param deviceMacAddress the MAC address of device to disassociate from this app
+     */
+    public void disassociate(@NonNull String deviceMacAddress) {
+        try {
+            mService.disassociate(deviceMacAddress, mContext.getPackageName());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
     /** @hide */
     public void requestNotificationAccess() {
         //TODO implement
diff --git a/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl b/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl
index 4d77963..5398c3c 100644
--- a/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl
+++ b/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl
@@ -20,6 +20,7 @@
 import android.companion.ICompanionDeviceDiscoveryServiceCallback;
 import android.companion.IFindDeviceCallback;
 
+
 /** @hide */
 interface ICompanionDeviceDiscoveryService {
     void startDiscovery(
diff --git a/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl b/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl
index 7af708e..6bbb58da 100644
--- a/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl
+++ b/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl
@@ -18,5 +18,5 @@
 
 /** @hide */
 interface ICompanionDeviceDiscoveryServiceCallback {
-    void onDeviceSelected(String packageName, int userId);
+    oneway void onDeviceSelected(String packageName, int userId, String deviceAddress);
 }
diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl
index 1d30ada..495141d 100644
--- a/core/java/android/companion/ICompanionDeviceManager.aidl
+++ b/core/java/android/companion/ICompanionDeviceManager.aidl
@@ -29,6 +29,9 @@
         in IFindDeviceCallback callback,
         in String callingPackage);
 
+    List<String> getAssociations(String callingPackage);
+    void disassociate(String deviceMacAddress, String callingPackage);
+
     //TODO add these
 //    boolean haveNotificationAccess(String packageName);
 //    oneway void requestNotificationAccess(String packageName);
diff --git a/core/java/android/content/AsyncTaskLoader.java b/core/java/android/content/AsyncTaskLoader.java
index 7241e0d..b7545bf 100644
--- a/core/java/android/content/AsyncTaskLoader.java
+++ b/core/java/android/content/AsyncTaskLoader.java
@@ -170,6 +170,9 @@
     protected boolean onCancelLoad() {
         if (DEBUG) Log.v(TAG, "onCancelLoad: mTask=" + mTask);
         if (mTask != null) {
+            if (!mStarted) {
+                mContentChanged = true;
+            }
             if (mCancellingTask != null) {
                 // There was a pending task already waiting for a previous
                 // one being canceled; just drop it.
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 4480b41..5579c9a 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -36,6 +36,7 @@
 import android.graphics.Point;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.CancellationSignal;
 import android.os.DeadObjectException;
@@ -306,6 +307,18 @@
      */
     public static final String QUERY_ARG_SORT_COLLATION = "android:query-sort-collation";
 
+    /**
+     * Allows provider to report back to client which keys were honored.
+     *
+     * Key identifying a {@code String[]} containing all QUERY_ARG_SORT* arguments
+     * honored by the provider. Include this in {@link Cursor} extras {@link Bundle}
+     * when any QUERY_ARG_SORT* value was honored during the preparation of the
+     * results {@link Cursor}.
+     *
+     * @see #QUERY_ARG_SORT_COLUMNS, #QUERY_ARG_SORT_DIRECTION, #QUERY_ARG_SORT_COLLATION.
+     */
+    public static final String EXTRA_HONORED_ARGS = "android.content.extra.HONORED_ARGS";
+
     /** @hide */
     @IntDef(flag = false, value = {
             QUERY_SORT_DIRECTION_ASCENDING,
@@ -353,8 +366,9 @@
     public static final String QUERY_ARG_LIMIT = "android:query-page-limit";
 
     /**
-     * Added to {@link Cursor} extras {@link Bundle} to indicate size of the
-     * full, un-offset, un-limited recordset.
+     * Added to {@link Cursor} extras {@link Bundle} to indicate total size of
+     * recordset when paging is active. Providers must include this when
+     * implementing paging support.
      *
      * <p>When full size of the recordset is unknown a provider may return -1
      * to indicate this.
@@ -363,7 +377,7 @@
      * send content change notification once (if) full recordset size becomes
      * known.
      */
-    public static final String QUERY_RESULT_SIZE = "android:query-result-size";
+    public static final String EXTRA_TOTAL_SIZE = "android.content.extra.TOTAL_SIZE";
 
     /**
      * This is the Android platform's base MIME type for a content: URI
@@ -500,6 +514,12 @@
     public ContentResolver(Context context) {
         mContext = context != null ? context : ActivityThread.currentApplication();
         mPackageName = mContext.getOpPackageName();
+        if (android.os.Process.myUid() == android.os.Process.PHONE_UID) {
+            // STOPSHIP: Telephony needs to fix b/35792675
+            mTargetSdkVersion = Build.VERSION_CODES.N_MR1;
+        } else {
+            mTargetSdkVersion = mContext.getApplicationInfo().targetSdkVersion;
+        }
     }
 
     /** @hide */
@@ -697,6 +717,13 @@
      * <li>Provide an explicit projection, to prevent reading data from storage
      * that aren't going to be used.
      *
+     * Provider must identify which QUERY_ARG_SORT* arguments were honored during
+     * the preparation of the result set by including the respective argument keys
+     * in the {@link Cursor} extras {@link Bundle}. See {@link #EXTRA_HONORED_ARGS}
+     * for details.
+     *
+     * @see #QUERY_ARG_SORT_COLUMNS, #QUERY_ARG_SORT_DIRECTION, #QUERY_ARG_SORT_COLLATION.
+     *
      * @param uri The URI, using the content:// scheme, for the content to
      *         retrieve.
      * @param projection A list of which columns to return. Passing null will
@@ -1868,13 +1895,18 @@
     /**
      * Register an observer class that gets callbacks when data identified by a
      * given content URI changes.
+     * <p>
+     * Starting in {@link android.os.Build.VERSION_CODES#O}, all content
+     * notifications must be backed by a valid {@link ContentProvider}.
      *
-     * @param uri The URI to watch for changes. This can be a specific row URI, or a base URI
-     * for a whole class of content.
-     * @param notifyForDescendants When false, the observer will be notified whenever a
-     * change occurs to the exact URI specified by <code>uri</code> or to one of the
-     * URI's ancestors in the path hierarchy.  When true, the observer will also be notified
-     * whenever a change occurs to the URI's descendants in the path hierarchy.
+     * @param uri The URI to watch for changes. This can be a specific row URI,
+     *            or a base URI for a whole class of content.
+     * @param notifyForDescendants When false, the observer will be notified
+     *            whenever a change occurs to the exact URI specified by
+     *            <code>uri</code> or to one of the URI's ancestors in the path
+     *            hierarchy. When true, the observer will also be notified
+     *            whenever a change occurs to the URI's descendants in the path
+     *            hierarchy.
      * @param observer The object that receives callbacks when changes occur.
      * @see #unregisterContentObserver
      */
@@ -1886,7 +1918,7 @@
                 ContentProvider.getUriWithoutUserId(uri),
                 notifyForDescendants,
                 observer,
-                ContentProvider.getUserIdFromUri(uri, UserHandle.myUserId()));
+                ContentProvider.getUserIdFromUri(uri, mContext.getUserId()));
     }
 
     /** @hide - designated user version */
@@ -1894,7 +1926,7 @@
             ContentObserver observer, @UserIdInt int userHandle) {
         try {
             getContentService().registerContentObserver(uri, notifyForDescendents,
-                    observer.getContentObserver(), userHandle);
+                    observer.getContentObserver(), userHandle, mTargetSdkVersion);
         } catch (RemoteException e) {
         }
     }
@@ -1918,16 +1950,22 @@
     }
 
     /**
-     * Notify registered observers that a row was updated and attempt to sync changes
-     * to the network.
-     * To register, call {@link #registerContentObserver(android.net.Uri , boolean, android.database.ContentObserver) registerContentObserver()}.
-     * By default, CursorAdapter objects will get this notification.
+     * Notify registered observers that a row was updated and attempt to sync
+     * changes to the network.
+     * <p>
+     * To observe events sent through this call, use
+     * {@link #registerContentObserver(Uri, boolean, ContentObserver)}.
+     * <p>
+     * Starting in {@link android.os.Build.VERSION_CODES#O}, all content
+     * notifications must be backed by a valid {@link ContentProvider}.
      *
      * @param uri The uri of the content that was changed.
-     * @param observer The observer that originated the change, may be <code>null</null>.
-     * The observer that originated the change will only receive the notification if it
-     * has requested to receive self-change notifications by implementing
-     * {@link ContentObserver#deliverSelfNotifications()} to return true.
+     * @param observer The observer that originated the change, may be
+     *            <code>null</null>. The observer that originated the change
+     *            will only receive the notification if it has requested to
+     *            receive self-change notifications by implementing
+     *            {@link ContentObserver#deliverSelfNotifications()} to return
+     *            true.
      */
     public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer) {
         notifyChange(uri, observer, true /* sync to network */);
@@ -1935,17 +1973,25 @@
 
     /**
      * Notify registered observers that a row was updated.
-     * To register, call {@link #registerContentObserver(android.net.Uri , boolean, android.database.ContentObserver) registerContentObserver()}.
-     * By default, CursorAdapter objects will get this notification.
-     * If syncToNetwork is true, this will attempt to schedule a local sync using the sync
-     * adapter that's registered for the authority of the provided uri. No account will be
-     * passed to the sync adapter, so all matching accounts will be synchronized.
+     * <p>
+     * To observe events sent through this call, use
+     * {@link #registerContentObserver(Uri, boolean, ContentObserver)}.
+     * <p>
+     * If syncToNetwork is true, this will attempt to schedule a local sync
+     * using the sync adapter that's registered for the authority of the
+     * provided uri. No account will be passed to the sync adapter, so all
+     * matching accounts will be synchronized.
+     * <p>
+     * Starting in {@link android.os.Build.VERSION_CODES#O}, all content
+     * notifications must be backed by a valid {@link ContentProvider}.
      *
      * @param uri The uri of the content that was changed.
-     * @param observer The observer that originated the change, may be <code>null</null>.
-     * The observer that originated the change will only receive the notification if it
-     * has requested to receive self-change notifications by implementing
-     * {@link ContentObserver#deliverSelfNotifications()} to return true.
+     * @param observer The observer that originated the change, may be
+     *            <code>null</null>. The observer that originated the change
+     *            will only receive the notification if it has requested to
+     *            receive self-change notifications by implementing
+     *            {@link ContentObserver#deliverSelfNotifications()} to return
+     *            true.
      * @param syncToNetwork If true, same as {@link #NOTIFY_SYNC_TO_NETWORK}.
      * @see #requestSync(android.accounts.Account, String, android.os.Bundle)
      */
@@ -1956,22 +2002,30 @@
                 ContentProvider.getUriWithoutUserId(uri),
                 observer,
                 syncToNetwork,
-                ContentProvider.getUserIdFromUri(uri, UserHandle.myUserId()));
+                ContentProvider.getUserIdFromUri(uri, mContext.getUserId()));
     }
 
     /**
      * Notify registered observers that a row was updated.
-     * To register, call {@link #registerContentObserver(android.net.Uri, boolean, android.database.ContentObserver) registerContentObserver()}.
-     * By default, CursorAdapter objects will get this notification.
-     * If syncToNetwork is true, this will attempt to schedule a local sync using the sync
-     * adapter that's registered for the authority of the provided uri. No account will be
-     * passed to the sync adapter, so all matching accounts will be synchronized.
+     * <p>
+     * To observe events sent through this call, use
+     * {@link #registerContentObserver(Uri, boolean, ContentObserver)}.
+     * <p>
+     * If syncToNetwork is true, this will attempt to schedule a local sync
+     * using the sync adapter that's registered for the authority of the
+     * provided uri. No account will be passed to the sync adapter, so all
+     * matching accounts will be synchronized.
+     * <p>
+     * Starting in {@link android.os.Build.VERSION_CODES#O}, all content
+     * notifications must be backed by a valid {@link ContentProvider}.
      *
      * @param uri The uri of the content that was changed.
-     * @param observer The observer that originated the change, may be <code>null</null>.
-     * The observer that originated the change will only receive the notification if it
-     * has requested to receive self-change notifications by implementing
-     * {@link ContentObserver#deliverSelfNotifications()} to return true.
+     * @param observer The observer that originated the change, may be
+     *            <code>null</null>. The observer that originated the change
+     *            will only receive the notification if it has requested to
+     *            receive self-change notifications by implementing
+     *            {@link ContentObserver#deliverSelfNotifications()} to return
+     *            true.
      * @param flags Additional flags: {@link #NOTIFY_SYNC_TO_NETWORK}.
      * @see #requestSync(android.accounts.Account, String, android.os.Bundle)
      */
@@ -1982,7 +2036,7 @@
                 ContentProvider.getUriWithoutUserId(uri),
                 observer,
                 flags,
-                ContentProvider.getUserIdFromUri(uri, UserHandle.myUserId()));
+                ContentProvider.getUserIdFromUri(uri, mContext.getUserId()));
     }
 
     /**
@@ -1997,7 +2051,7 @@
                     uri, observer == null ? null : observer.getContentObserver(),
                     observer != null && observer.deliverSelfNotifications(),
                     syncToNetwork ? NOTIFY_SYNC_TO_NETWORK : 0,
-                    userHandle);
+                    userHandle, mTargetSdkVersion);
         } catch (RemoteException e) {
         }
     }
@@ -2013,7 +2067,7 @@
             getContentService().notifyChange(
                     uri, observer == null ? null : observer.getContentObserver(),
                     observer != null && observer.deliverSelfNotifications(), flags,
-                    userHandle);
+                    userHandle, mTargetSdkVersion);
         } catch (RemoteException e) {
         }
     }
@@ -2932,6 +2986,7 @@
     private final Context mContext;
 
     final String mPackageName;
+    final int mTargetSdkVersion;
 
     private static final String TAG = "ContentResolver";
 
@@ -3002,17 +3057,19 @@
             query += " COLLATE NOCASE";
         }
 
-        switch (queryArgs.getInt(
-                QUERY_ARG_SORT_DIRECTION, Integer.MIN_VALUE)) {
-            case QUERY_SORT_DIRECTION_ASCENDING:
-                query += " ASC";
-                break;
-            case QUERY_SORT_DIRECTION_DESCENDING:
-                query += " DESC";
-                break;
-            default:
-                throw new IllegalArgumentException("Unsupported sort direction value."
-                        + " See ContentResolver documentation for details.");
+        int sortDir = queryArgs.getInt(QUERY_ARG_SORT_DIRECTION, Integer.MIN_VALUE);
+        if (sortDir != Integer.MIN_VALUE) {
+            switch (sortDir) {
+                case QUERY_SORT_DIRECTION_ASCENDING:
+                    query += " ASC";
+                    break;
+                case QUERY_SORT_DIRECTION_DESCENDING:
+                    query += " DESC";
+                    break;
+                default:
+                    throw new IllegalArgumentException("Unsupported sort direction value."
+                            + " See ContentResolver documentation for details.");
+            }
         }
         return query;
     }
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 44f6c43..de503c0 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -730,12 +730,6 @@
      */
     public abstract boolean moveSharedPreferencesFrom(Context sourceContext, String name);
 
-    /** @removed */
-    @Deprecated
-    public boolean migrateSharedPreferencesFrom(Context sourceContext, String name) {
-        return moveSharedPreferencesFrom(sourceContext, name);
-    }
-
     /**
      * Delete an existing shared preferences file.
      *
@@ -1451,12 +1445,6 @@
      */
     public abstract boolean moveDatabaseFrom(Context sourceContext, String name);
 
-    /** @removed */
-    @Deprecated
-    public boolean migrateDatabaseFrom(Context sourceContext, String name) {
-        return moveDatabaseFrom(sourceContext, name);
-    }
-
     /**
      * Delete an existing private SQLiteDatabase associated with this Context's
      * application package.
@@ -2723,6 +2711,7 @@
             VIBRATOR_SERVICE,
             //@hide: STATUS_BAR_SERVICE,
             CONNECTIVITY_SERVICE,
+            IPSEC_SERVICE,
             //@hide: UPDATE_LOCK_SERVICE,
             //@hide: NETWORKMANAGEMENT_SERVICE,
             NETWORK_STATS_SERVICE,
@@ -2826,6 +2815,9 @@
      *  <dt> {@link #CONNECTIVITY_SERVICE} ("connection")
      *  <dd> A {@link android.net.ConnectivityManager ConnectivityManager} for
      *  handling management of network connections.
+     *  <dt> {@link #IPSEC_SERVICE} ("ipsec")
+     *  <dd> A {@link android.net.IpSecManager IpSecManager} for managing IPSec on
+     *  sockets and networks.
      *  <dt> {@link #WIFI_SERVICE} ("wifi")
      *  <dd> A {@link android.net.wifi.WifiManager WifiManager} for management of Wi-Fi
      *  connectivity.  On releases before NYC, it should only be obtained from an application
@@ -3166,6 +3158,15 @@
     public static final String CONNECTIVITY_SERVICE = "connectivity";
 
     /**
+     * Use with {@link #getSystemService} to retrieve a
+     * {@link android.net.IpSecManager} for encrypting Sockets or Networks with
+     * IPSec.
+     *
+     * @see #getSystemService
+     */
+    public static final String IPSEC_SERVICE = "ipsec";
+
+    /**
      * Use with {@link #getSystemService} to retrieve a {@link
      * android.os.IUpdateLock} for managing runtime sequences that
      * must not be interrupted by headless OTA application or similar.
@@ -4382,12 +4383,6 @@
      */
     public abstract Context createDeviceProtectedStorageContext();
 
-    /** @removed */
-    @Deprecated
-    public Context createDeviceEncryptedStorageContext() {
-        return createDeviceProtectedStorageContext();
-    }
-
     /**
      * Return a new Context object for the current Context but whose storage
      * APIs are backed by credential-protected storage. This is the default
@@ -4416,12 +4411,6 @@
     @SystemApi
     public abstract Context createCredentialProtectedStorageContext();
 
-    /** @removed */
-    @Deprecated
-    public Context createCredentialEncryptedStorageContext() {
-        return createCredentialProtectedStorageContext();
-    }
-
     /**
      * Gets the display adjustments holder for this context.  This information
      * is provided on a per-application or activity basis and is used to simulate lower density
@@ -4462,12 +4451,6 @@
      */
     public abstract boolean isDeviceProtectedStorage();
 
-    /** @removed */
-    @Deprecated
-    public boolean isDeviceEncryptedStorage() {
-        return isDeviceProtectedStorage();
-    }
-
     /**
      * Indicates if the storage APIs of this Context are backed by
      * credential-protected storage.
@@ -4478,12 +4461,6 @@
     @SystemApi
     public abstract boolean isCredentialProtectedStorage();
 
-    /** @removed */
-    @Deprecated
-    public boolean isCredentialEncryptedStorage() {
-        return isCredentialProtectedStorage();
-    }
-
     /**
      * @hide
      */
diff --git a/core/java/android/content/IContentService.aidl b/core/java/android/content/IContentService.aidl
index 3446e03..c500116 100644
--- a/core/java/android/content/IContentService.aidl
+++ b/core/java/android/content/IContentService.aidl
@@ -42,7 +42,7 @@
      *     USER_CURRENT are properly handled.
      */
     void registerContentObserver(in Uri uri, boolean notifyForDescendants,
-            IContentObserver observer, int userHandle);
+            IContentObserver observer, int userHandle, int targetSdkVersion);
 
     /**
      * Notify observers of a particular user's view of the provider.
@@ -53,7 +53,7 @@
      */
     void notifyChange(in Uri uri, IContentObserver observer,
             boolean observerWantsSelfNotifications, int flags,
-            int userHandle);
+            int userHandle, int targetSdkVersion);
 
     void requestSync(in Account account, String authority, in Bundle extras);
     /**
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index b0505ac..d6306e0 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1115,6 +1115,15 @@
     public static final String ACTION_SIM_ACTIVATION_REQUEST =
             "android.intent.action.SIM_ACTIVATION_REQUEST";
     /**
+     * Activity Action: Main entry point for carrier setup apps.
+     * <p>Carrier apps that provide an implementation for this action may be invoked to configure
+     * carrier service and typically require
+     * {@link android.telephony.TelephonyManager#hasCarrierPrivileges() carrier privileges} to
+     * fulfill their duties.
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_CARRIER_SETUP = "android.intent.action.CARRIER_SETUP";
+    /**
      * Activity Action: Send a message to someone specified by the data.
      * <p>Input: {@link #getData} is URI describing the target.
      * <p>Output: nothing.
@@ -1315,6 +1324,7 @@
      * Output: nothing.
      * @hide
      */
+    @SystemApi
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_VOICE_ASSIST = "android.intent.action.VOICE_ASSIST";
 
@@ -1455,7 +1465,7 @@
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_SHOW_KEYBOARD_SHORTCUTS =
-            "android.intent.action.SHOW_KEYBOARD_SHORTCUTS";
+            "com.android.intent.action.SHOW_KEYBOARD_SHORTCUTS";
 
     /**
      * Activity Action: Dismiss the Keyboard Shortcuts Helper screen.
@@ -1465,7 +1475,7 @@
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_DISMISS_KEYBOARD_SHORTCUTS =
-            "android.intent.action.DISMISS_KEYBOARD_SHORTCUTS";
+            "com.android.intent.action.DISMISS_KEYBOARD_SHORTCUTS";
 
     /**
      * Activity Action: Show settings for managing network data usage of a
@@ -2873,6 +2883,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static final String ACTION_PRE_BOOT_COMPLETED =
             "android.intent.action.PRE_BOOT_COMPLETED";
 
@@ -3113,7 +3124,7 @@
      * @hide
      */
     public static final String ACTION_SHOW_BRIGHTNESS_DIALOG =
-            "android.intent.action.SHOW_BRIGHTNESS_DIALOG";
+            "com.android.intent.action.SHOW_BRIGHTNESS_DIALOG";
 
     /**
      * Broadcast Action:  A global button was pressed.  Includes a single
@@ -3313,6 +3324,16 @@
     public static final String ACTION_MASTER_CLEAR = "android.intent.action.MASTER_CLEAR";
 
     /**
+     * Broadcast intent sent by the RecoverySystem to inform listeners that a master clear (wipe)
+     * is about to be performed.
+     * @hide
+     */
+    @SystemApi
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_MASTER_CLEAR_NOTIFICATION
+            = "android.intent.action.MASTER_CLEAR_NOTIFICATION";
+
+    /**
      * Boolean intent extra to be used with {@link #ACTION_MASTER_CLEAR} in order to force a factory
      * reset even if {@link android.os.UserManager#DISALLOW_FACTORY_RESET} is set.
      *
@@ -3384,6 +3405,17 @@
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_PROCESS_TEXT = "android.intent.action.PROCESS_TEXT";
+
+    /**
+     * Broadcast Action: The sim card state has changed.
+     * For more details see TelephonyIntents.ACTION_SIM_STATE_CHANGED. This is here
+     * because TelephonyIntents is an internal class.
+     * @hide
+     */
+    @SystemApi
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED";
+
     /**
      * The name of the extra used to define the text to be processed, as a
      * CharSequence. Note that this may be a styled CharSequence, so you must use
@@ -9238,6 +9270,13 @@
             mClipData.prepareToLeaveProcess(leavingPackage, getFlags());
         }
 
+        if (mExtras != null && !mExtras.isParcelled()) {
+            final Object intent = mExtras.get(Intent.EXTRA_INTENT);
+            if (intent instanceof Intent) {
+                ((Intent) intent).prepareToLeaveProcess(leavingPackage);
+            }
+        }
+
         if (mAction != null && mData != null && StrictMode.vmFileUriExposureEnabled()
                 && leavingPackage) {
             switch (mAction) {
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index 56609eb..93204d1 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -16,6 +16,7 @@
 
 package android.content;
 
+import android.annotation.SystemApi;
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -138,6 +139,7 @@
  * will only match an Intent that does not have any categories.
  */
 public class IntentFilter implements Parcelable {
+    private static final String AGLOB_STR = "aglob";
     private static final String SGLOB_STR = "sglob";
     private static final String PREFIX_STR = "prefix";
     private static final String LITERAL_STR = "literal";
@@ -482,11 +484,13 @@
     }
 
     /** @hide */
+    @SystemApi
     public final void setOrder(int order) {
         mOrder = order;
     }
 
     /** @hide */
+    @SystemApi
     public final int getOrder() {
         return mOrder;
     }
@@ -1594,6 +1598,9 @@
                 case PatternMatcher.PATTERN_SIMPLE_GLOB:
                     serializer.attribute(null, SGLOB_STR, pe.getPath());
                     break;
+                case PatternMatcher.PATTERN_ADVANCED_GLOB:
+                    serializer.attribute(null, AGLOB_STR, pe.getPath());
+                    break;
             }
             serializer.endTag(null, SSP_STR);
         }
@@ -1621,6 +1628,9 @@
                 case PatternMatcher.PATTERN_SIMPLE_GLOB:
                     serializer.attribute(null, SGLOB_STR, pe.getPath());
                     break;
+                case PatternMatcher.PATTERN_ADVANCED_GLOB:
+                    serializer.attribute(null, AGLOB_STR, pe.getPath());
+                    break;
             }
             serializer.endTag(null, PATH_STR);
         }
@@ -1673,6 +1683,8 @@
                     addDataSchemeSpecificPart(ssp, PatternMatcher.PATTERN_PREFIX);
                 } else if ((ssp=parser.getAttributeValue(null, SGLOB_STR)) != null) {
                     addDataSchemeSpecificPart(ssp, PatternMatcher.PATTERN_SIMPLE_GLOB);
+                } else if ((ssp=parser.getAttributeValue(null, AGLOB_STR)) != null) {
+                    addDataSchemeSpecificPart(ssp, PatternMatcher.PATTERN_ADVANCED_GLOB);
                 }
             } else if (tagName.equals(AUTH_STR)) {
                 String host = parser.getAttributeValue(null, HOST_STR);
@@ -1688,6 +1700,8 @@
                     addDataPath(path, PatternMatcher.PATTERN_PREFIX);
                 } else if ((path=parser.getAttributeValue(null, SGLOB_STR)) != null) {
                     addDataPath(path, PatternMatcher.PATTERN_SIMPLE_GLOB);
+                } else if ((path=parser.getAttributeValue(null, AGLOB_STR)) != null) {
+                    addDataPath(path, PatternMatcher.PATTERN_ADVANCED_GLOB);
                 }
             } else {
                 Log.w("IntentFilter", "Unknown tag parsing IntentFilter: " + tagName);
diff --git a/core/java/android/content/om/IOverlayManager.aidl b/core/java/android/content/om/IOverlayManager.aidl
index 4f5d960..86c1aa8 100644
--- a/core/java/android/content/om/IOverlayManager.aidl
+++ b/core/java/android/content/om/IOverlayManager.aidl
@@ -89,6 +89,11 @@
     boolean setEnabled(in String packageName, in boolean enable, in int userId);
 
     /**
+     * Version of setEnabled that will also disable any other overlays for the target package.
+     */
+    boolean setEnabledExclusive(in String packageName, in boolean enable, in int userId);
+
+    /**
      * Change the priority of the given overlay to be just higher than the
      * overlay with package name newParentPackageName. Both overlay packages
      * must have the same target and user.
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 9737b11..b4d77a0 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -720,10 +720,6 @@
      */
     public String deviceProtectedDataDir;
 
-    /** @removed */
-    @Deprecated
-    public String deviceEncryptedDataDir;
-
     /**
      * Full path to the credential-protected directory assigned to the package
      * for its persistent data.
@@ -733,10 +729,6 @@
     @SystemApi
     public String credentialProtectedDataDir;
 
-    /** @removed */
-    @Deprecated
-    public String credentialEncryptedDataDir;
-
     /**
      * Full path to the directory where native JNI libraries are stored.
      */
@@ -1140,8 +1132,8 @@
         seInfoUser = orig.seInfoUser;
         sharedLibraryFiles = orig.sharedLibraryFiles;
         dataDir = orig.dataDir;
-        deviceEncryptedDataDir = deviceProtectedDataDir = orig.deviceProtectedDataDir;
-        credentialEncryptedDataDir = credentialProtectedDataDir = orig.credentialProtectedDataDir;
+        deviceProtectedDataDir = orig.deviceProtectedDataDir;
+        credentialProtectedDataDir = orig.credentialProtectedDataDir;
         uid = orig.uid;
         minSdkVersion = orig.minSdkVersion;
         targetSdkVersion = orig.targetSdkVersion;
@@ -1264,8 +1256,8 @@
         seInfoUser = source.readString();
         sharedLibraryFiles = source.readStringArray();
         dataDir = source.readString();
-        deviceEncryptedDataDir = deviceProtectedDataDir = source.readString();
-        credentialEncryptedDataDir = credentialProtectedDataDir = source.readString();
+        deviceProtectedDataDir = source.readString();
+        credentialProtectedDataDir = source.readString();
         uid = source.readInt();
         minSdkVersion = source.readInt();
         targetSdkVersion = source.readInt();
@@ -1336,10 +1328,10 @@
             return;
         }
 
-        deviceEncryptedDataDir = deviceProtectedDataDir = Environment
+        deviceProtectedDataDir = Environment
                 .getDataUserDePackageDirectory(volumeUuid, userId, packageName)
                 .getAbsolutePath();
-        credentialEncryptedDataDir = credentialProtectedDataDir = Environment
+        credentialProtectedDataDir = Environment
                 .getDataUserCePackageDirectory(volumeUuid, userId, packageName)
                 .getAbsolutePath();
 
diff --git a/core/java/android/content/pm/AuxiliaryResolveInfo.java b/core/java/android/content/pm/AuxiliaryResolveInfo.java
new file mode 100644
index 0000000..69bfeca
--- /dev/null
+++ b/core/java/android/content/pm/AuxiliaryResolveInfo.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Intent;
+import android.content.IntentFilter;
+
+/**
+ * Auxiliary application resolution response.
+ * <p>
+ * Used when resolution occurs, but, the target is not actually on the device.
+ * This happens resolving instant apps that haven't been installed yet or if
+ * the application consists of multiple feature splits and the needed split
+ * hasn't been installed.
+ * @hide
+ */
+public final class AuxiliaryResolveInfo extends IntentFilter {
+    /** Resolved information returned from the external instant resolver */
+    public final InstantAppResolveInfo resolveInfo;
+    /** The resolved package. Copied from {@link #resolveInfo}. */
+    public final String packageName;
+    /** The resolve split. Copied from the matched filter in {@link #resolveInfo}. */
+    public final String splitName;
+    /** Whether or not instant resolution needs the second phase */
+    public final boolean needsPhaseTwo;
+    /** Opaque token to track the instant application resolution */
+    public final String token;
+    /** The version code of the package */
+    public final int versionCode;
+
+    /** Create a response for installing an instant application. */
+    public AuxiliaryResolveInfo(@NonNull InstantAppResolveInfo resolveInfo,
+            @NonNull IntentFilter orig,
+            @Nullable String splitName,
+            @NonNull String token,
+            boolean needsPhase2) {
+        super(orig);
+        this.resolveInfo = resolveInfo;
+        this.packageName = resolveInfo.getPackageName();
+        this.splitName = splitName;
+        this.token = token;
+        this.needsPhaseTwo = needsPhase2;
+        this.versionCode = resolveInfo.getVersionCode();
+    }
+
+    /** Create a response for installing a split on demand. */
+    public AuxiliaryResolveInfo(@NonNull String packageName,
+            @Nullable String splitName,
+            int versionCode) {
+        super();
+        this.packageName = packageName;
+        this.splitName = splitName;
+        this.versionCode = versionCode;
+        this.resolveInfo = null;
+        this.token = null;
+        this.needsPhaseTwo = false;
+    }
+}
\ No newline at end of file
diff --git a/core/java/android/content/pm/BaseParceledListSlice.java b/core/java/android/content/pm/BaseParceledListSlice.java
new file mode 100644
index 0000000..c4e4e06
--- /dev/null
+++ b/core/java/android/content/pm/BaseParceledListSlice.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Transfer a large list of Parcelable objects across an IPC.  Splits into
+ * multiple transactions if needed.
+ *
+ * Caveat: for efficiency and security, all elements must be the same concrete type.
+ * In order to avoid writing the class name of each object, we must ensure that
+ * each object is the same type, or else unparceling then reparceling the data may yield
+ * a different result if the class name encoded in the Parcelable is a Base type.
+ * See b/17671747.
+ *
+ * @hide
+ */
+abstract class BaseParceledListSlice<T> implements Parcelable {
+    private static String TAG = "ParceledListSlice";
+    private static boolean DEBUG = false;
+
+    /*
+     * TODO get this number from somewhere else. For now set it to a quarter of
+     * the 1MB limit.
+     */
+    private static final int MAX_IPC_SIZE = IBinder.MAX_IPC_SIZE;
+
+    private final List<T> mList;
+
+    public BaseParceledListSlice(List<T> list) {
+        mList = list;
+    }
+
+    @SuppressWarnings("unchecked")
+    BaseParceledListSlice(Parcel p, ClassLoader loader) {
+        final int N = p.readInt();
+        mList = new ArrayList<T>(N);
+        if (DEBUG) Log.d(TAG, "Retrieving " + N + " items");
+        if (N <= 0) {
+            return;
+        }
+
+        Parcelable.Creator<?> creator = readParcelableCreator(p, loader);
+        Class<?> listElementClass = null;
+
+        int i = 0;
+        while (i < N) {
+            if (p.readInt() == 0) {
+                break;
+            }
+
+            final T parcelable = readCreator(creator, p, loader);
+            if (listElementClass == null) {
+                listElementClass = parcelable.getClass();
+            } else {
+                verifySameType(listElementClass, parcelable.getClass());
+            }
+
+            mList.add(parcelable);
+
+            if (DEBUG) Log.d(TAG, "Read inline #" + i + ": " + mList.get(mList.size()-1));
+            i++;
+        }
+        if (i >= N) {
+            return;
+        }
+        final IBinder retriever = p.readStrongBinder();
+        while (i < N) {
+            if (DEBUG) Log.d(TAG, "Reading more @" + i + " of " + N + ": retriever=" + retriever);
+            Parcel data = Parcel.obtain();
+            Parcel reply = Parcel.obtain();
+            data.writeInt(i);
+            try {
+                retriever.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failure retrieving array; only received " + i + " of " + N, e);
+                return;
+            }
+            while (i < N && reply.readInt() != 0) {
+                final T parcelable = reply.readCreator(creator, loader);
+                verifySameType(listElementClass, parcelable.getClass());
+
+                mList.add(parcelable);
+
+                if (DEBUG) Log.d(TAG, "Read extra #" + i + ": " + mList.get(mList.size()-1));
+                i++;
+            }
+            reply.recycle();
+            data.recycle();
+        }
+    }
+
+    private T readCreator(Parcelable.Creator<?> creator, Parcel p, ClassLoader loader) {
+        if (creator instanceof Parcelable.ClassLoaderCreator<?>) {
+            Parcelable.ClassLoaderCreator<?> classLoaderCreator =
+                    (Parcelable.ClassLoaderCreator<?>) creator;
+            return (T) classLoaderCreator.createFromParcel(p, loader);
+        }
+        return (T) creator.createFromParcel(p);
+    }
+
+    private static void verifySameType(final Class<?> expected, final Class<?> actual) {
+        if (!actual.equals(expected)) {
+            throw new IllegalArgumentException("Can't unparcel type "
+                    + actual.getName() + " in list of type "
+                    + expected.getName());
+        }
+    }
+
+    public List<T> getList() {
+        return mList;
+    }
+
+    /**
+     * Write this to another Parcel. Note that this discards the internal Parcel
+     * and should not be used anymore. This is so we can pass this to a Binder
+     * where we won't have a chance to call recycle on this.
+     */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        final int N = mList.size();
+        final int callFlags = flags;
+        dest.writeInt(N);
+        if (DEBUG) Log.d(TAG, "Writing " + N + " items");
+        if (N > 0) {
+            final Class<?> listElementClass = mList.get(0).getClass();
+            writeParcelableCreator(mList.get(0), dest);
+            int i = 0;
+            while (i < N && dest.dataSize() < MAX_IPC_SIZE) {
+                dest.writeInt(1);
+
+                final T parcelable = mList.get(i);
+                verifySameType(listElementClass, parcelable.getClass());
+                writeElement(parcelable, dest, callFlags);
+
+                if (DEBUG) Log.d(TAG, "Wrote inline #" + i + ": " + mList.get(i));
+                i++;
+            }
+            if (i < N) {
+                dest.writeInt(0);
+                Binder retriever = new Binder() {
+                    @Override
+                    protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
+                            throws RemoteException {
+                        if (code != FIRST_CALL_TRANSACTION) {
+                            return super.onTransact(code, data, reply, flags);
+                        }
+                        int i = data.readInt();
+                        if (DEBUG) Log.d(TAG, "Writing more @" + i + " of " + N);
+                        while (i < N && reply.dataSize() < MAX_IPC_SIZE) {
+                            reply.writeInt(1);
+
+                            final T parcelable = mList.get(i);
+                            verifySameType(listElementClass, parcelable.getClass());
+                            writeElement(parcelable, reply, callFlags);
+
+                            if (DEBUG) Log.d(TAG, "Wrote extra #" + i + ": " + mList.get(i));
+                            i++;
+                        }
+                        if (i < N) {
+                            if (DEBUG) Log.d(TAG, "Breaking @" + i + " of " + N);
+                            reply.writeInt(0);
+                        }
+                        return true;
+                    }
+                };
+                if (DEBUG) Log.d(TAG, "Breaking @" + i + " of " + N + ": retriever=" + retriever);
+                dest.writeStrongBinder(retriever);
+            }
+        }
+    }
+
+    protected abstract void writeElement(T parcelable, Parcel reply, int callFlags);
+
+    protected abstract void writeParcelableCreator(T parcelable, Parcel dest);
+
+    protected abstract Parcelable.Creator<?> readParcelableCreator(Parcel from, ClassLoader loader);
+}
diff --git a/core/java/android/content/pm/ContainerEncryptionParams.aidl b/core/java/android/content/pm/ContainerEncryptionParams.aidl
deleted file mode 100644
index c13d946..0000000
--- a/core/java/android/content/pm/ContainerEncryptionParams.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.pm;
-
-parcelable ContainerEncryptionParams;
diff --git a/core/java/android/content/pm/EphemeralIntentFilter.java b/core/java/android/content/pm/EphemeralIntentFilter.java
index 0674e7c..f7d83a9 100644
--- a/core/java/android/content/pm/EphemeralIntentFilter.java
+++ b/core/java/android/content/pm/EphemeralIntentFilter.java
@@ -30,31 +30,34 @@
  * Information about an ephemeral application intent filter.
  * @hide
  */
+@Deprecated
 @SystemApi
 public final class EphemeralIntentFilter implements Parcelable {
-    private final String mSplitName;
-    /** The filters used to match domain */
-    private final List<IntentFilter> mFilters = new ArrayList<IntentFilter>();
+    private final InstantAppIntentFilter mInstantAppIntentFilter;
 
     public EphemeralIntentFilter(@Nullable String splitName, @NonNull List<IntentFilter> filters) {
-        if (filters == null || filters.size() == 0) {
-            throw new IllegalArgumentException();
-        }
-        mSplitName = splitName;
-        mFilters.addAll(filters);
+        mInstantAppIntentFilter = new InstantAppIntentFilter(splitName, filters);
+    }
+
+    EphemeralIntentFilter(@NonNull InstantAppIntentFilter intentFilter) {
+        mInstantAppIntentFilter = intentFilter;
     }
 
     EphemeralIntentFilter(Parcel in) {
-        mSplitName = in.readString();
-        in.readList(mFilters, null /*loader*/);
+        mInstantAppIntentFilter = in.readParcelable(null /*loader*/);
     }
 
     public String getSplitName() {
-        return mSplitName;
+        return mInstantAppIntentFilter.getSplitName();
     }
 
     public List<IntentFilter> getFilters() {
-        return mFilters;
+        return mInstantAppIntentFilter.getFilters();
+    }
+
+    /** @hide */
+    InstantAppIntentFilter getInstantAppIntentFilter() {
+        return mInstantAppIntentFilter;
     }
 
     @Override
@@ -64,33 +67,18 @@
 
     @Override
     public void writeToParcel(Parcel out, int flags) {
-        out.writeString(mSplitName);
-        out.writeList(mFilters);
+        out.writeParcelable(mInstantAppIntentFilter, flags);
     }
 
     public static final Parcelable.Creator<EphemeralIntentFilter> CREATOR
             = new Parcelable.Creator<EphemeralIntentFilter>() {
+        @Override
         public EphemeralIntentFilter createFromParcel(Parcel in) {
             return new EphemeralIntentFilter(in);
         }
-
+        @Override
         public EphemeralIntentFilter[] newArray(int size) {
             return new EphemeralIntentFilter[size];
         }
     };
-
-    /** @hide */
-    public static final class EphemeralResolveIntentInfo extends IntentFilter {
-        private final EphemeralIntentFilter mResolveInfo;
-
-        public EphemeralResolveIntentInfo(@NonNull IntentFilter orig,
-                @NonNull EphemeralIntentFilter resolveInfo) {
-            super(orig);
-            this.mResolveInfo = resolveInfo;
-        }
-
-        public EphemeralIntentFilter getEphemeralResolveInfo() {
-            return mResolveInfo;
-        }
-    }
 }
diff --git a/core/java/android/content/pm/EphemeralRequest.java b/core/java/android/content/pm/EphemeralRequest.java
deleted file mode 100644
index 7f2b3ee1..0000000
--- a/core/java/android/content/pm/EphemeralRequest.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.pm;
-
-import android.content.Intent;
-
-/**
- * Information needed to make an ephemeral application resolution request.
- * @hide
- */
-public final class EphemeralRequest {
-    /** Response from the first phase of ephemeral application resolution */
-    public final EphemeralResponse responseObj;
-    /** The original intent that triggered ephemeral application resolution */
-    public final Intent origIntent;
-    /** Resolved type of the intent */
-    public final String resolvedType;
-    /** The intent that would launch if there were no ephemeral applications */
-    public final Intent launchIntent;
-    /** The name of the package requesting the ephemeral application */
-    public final String callingPackage;
-    /** ID of the user requesting the ephemeral application */
-    public final int userId;
-
-    public EphemeralRequest(EphemeralResponse responseObj, Intent origIntent,
-            String resolvedType, Intent launchIntent, String callingPackage, int userId) {
-        this.responseObj = responseObj;
-        this.origIntent = origIntent;
-        this.resolvedType = resolvedType;
-        this.launchIntent = launchIntent;
-        this.callingPackage = callingPackage;
-        this.userId = userId;
-    }
-}
\ No newline at end of file
diff --git a/core/java/android/content/pm/EphemeralResolveInfo.java b/core/java/android/content/pm/EphemeralResolveInfo.java
index 1d7b8f2..a6e8268 100644
--- a/core/java/android/content/pm/EphemeralResolveInfo.java
+++ b/core/java/android/content/pm/EphemeralResolveInfo.java
@@ -20,6 +20,7 @@
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.content.IntentFilter;
+import android.content.pm.InstantAppResolveInfo.InstantAppDigest;
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -34,18 +35,13 @@
  * Information about an ephemeral application.
  * @hide
  */
+@Deprecated
 @SystemApi
 public final class EphemeralResolveInfo implements Parcelable {
     /** Algorithm that will be used to generate the domain digest */
     public static final String SHA_ALGORITHM = "SHA-256";
 
-    private final EphemeralDigest mDigest;
-    private final String mPackageName;
-    /** The filters used to match domain */
-    private final List<EphemeralIntentFilter> mFilters;
-    /** The version code of the app that this class resolves to */
-    private final int mVersionCode;
-    /** Filters only for legacy clients */
+    private final InstantAppResolveInfo mInstantAppResolveInfo;
     @Deprecated
     private final List<IntentFilter> mLegacyFilters;
 
@@ -55,13 +51,12 @@
         if (uri == null || packageName == null || filters == null || filters.isEmpty()) {
             throw new IllegalArgumentException();
         }
-        mDigest = new EphemeralDigest(uri.getHost());
-        mPackageName = packageName;
-        mFilters = new ArrayList<EphemeralIntentFilter>();
-        mFilters.add(new EphemeralIntentFilter(packageName, filters));
+        final List<EphemeralIntentFilter> ephemeralFilters = new ArrayList<>(1);
+        ephemeralFilters.add(new EphemeralIntentFilter(packageName, filters));
+        mInstantAppResolveInfo = new InstantAppResolveInfo(uri.getHost(), packageName,
+                createInstantAppIntentFilterList(ephemeralFilters));
         mLegacyFilters = new ArrayList<IntentFilter>(filters.size());
         mLegacyFilters.addAll(filters);
-        mVersionCode = -1;
     }
 
     @Deprecated
@@ -71,22 +66,11 @@
     }
 
     public EphemeralResolveInfo(@NonNull EphemeralDigest digest, @Nullable String packageName,
-            @Nullable List<EphemeralIntentFilter> filters, int versionConde) {
-        // validate arguments
-        if ((packageName == null && (filters != null && filters.size() != 0))
-                || (packageName != null && (filters == null || filters.size() == 0))) {
-            throw new IllegalArgumentException();
-        }
-        mDigest = digest;
-        if (filters != null) {
-            mFilters = new ArrayList<EphemeralIntentFilter>(filters.size());
-            mFilters.addAll(filters);
-        } else {
-            mFilters = null;
-        }
+            @Nullable List<EphemeralIntentFilter> filters, int versionCode) {
+        mInstantAppResolveInfo = new InstantAppResolveInfo(
+                digest.getInstantAppDigest(), packageName,
+                createInstantAppIntentFilterList(filters), versionCode);
         mLegacyFilters = null;
-        mPackageName = packageName;
-        mVersionCode = versionConde;
     }
 
     public EphemeralResolveInfo(@NonNull String hostName, @Nullable String packageName,
@@ -95,33 +79,53 @@
     }
 
     EphemeralResolveInfo(Parcel in) {
-        mDigest = in.readParcelable(null /*loader*/);
-        mPackageName = in.readString();
-        mFilters = new ArrayList<EphemeralIntentFilter>();
-        in.readList(mFilters, null /*loader*/);
-        mVersionCode = in.readInt();
+        mInstantAppResolveInfo = in.readParcelable(null /*loader*/);
         mLegacyFilters = new ArrayList<IntentFilter>();
         in.readList(mLegacyFilters, null /*loader*/);
     }
 
+    /** @hide */
+    public InstantAppResolveInfo getInstantAppResolveInfo() {
+        return mInstantAppResolveInfo;
+    }
+
+    private static List<InstantAppIntentFilter> createInstantAppIntentFilterList(
+            List<EphemeralIntentFilter> filters) {
+        if (filters == null) {
+            return null;
+        }
+        final int filterCount = filters.size();
+        final List<InstantAppIntentFilter> returnList = new ArrayList<>(filterCount);
+        for (int i = 0; i < filterCount; i++) {
+            returnList.add(filters.get(i).getInstantAppIntentFilter());
+        }
+        return returnList;
+    }
+
     public byte[] getDigestBytes() {
-        return mDigest.getDigestBytes()[0];
+        return mInstantAppResolveInfo.getDigestBytes();
     }
 
     public int getDigestPrefix() {
-        return mDigest.getDigestPrefix()[0];
+        return mInstantAppResolveInfo.getDigestPrefix();
     }
 
     public String getPackageName() {
-        return mPackageName;
+        return mInstantAppResolveInfo.getPackageName();
     }
 
     public List<EphemeralIntentFilter> getIntentFilters() {
-        return mFilters;
+        final List<InstantAppIntentFilter> filters = mInstantAppResolveInfo.getIntentFilters();
+        final int filterCount = filters.size();
+        final List<EphemeralIntentFilter> returnList = new ArrayList<>(filterCount);
+        for (int i = 0; i < filterCount; i++) {
+            returnList.add(new EphemeralIntentFilter(filters.get(i)));
+        }
+        return returnList;
     }
 
     public int getVersionCode() {
-        return mVersionCode;
+        return mInstantAppResolveInfo.getVersionCode();
     }
 
     @Deprecated
@@ -136,19 +140,17 @@
 
     @Override
     public void writeToParcel(Parcel out, int flags) {
-        out.writeParcelable(mDigest, flags);
-        out.writeString(mPackageName);
-        out.writeList(mFilters);
-        out.writeInt(mVersionCode);
+        out.writeParcelable(mInstantAppResolveInfo, flags);
         out.writeList(mLegacyFilters);
     }
 
     public static final Parcelable.Creator<EphemeralResolveInfo> CREATOR
             = new Parcelable.Creator<EphemeralResolveInfo>() {
+        @Override
         public EphemeralResolveInfo createFromParcel(Parcel in) {
             return new EphemeralResolveInfo(in);
         }
-
+        @Override
         public EphemeralResolveInfo[] newArray(int size) {
             return new EphemeralResolveInfo[size];
         }
@@ -167,12 +169,7 @@
      */
     @SystemApi
     public static final class EphemeralDigest implements Parcelable {
-        private static final int DIGEST_MASK = 0xfffff000;
-        private static final int DIGEST_PREFIX_COUNT = 5;
-        /** Full digest of the domain hashes */
-        private final byte[][] mDigestBytes;
-        /** The first 4 bytes of the domain hashes */
-        private final int[] mDigestPrefix;
+        private final InstantAppDigest mInstantAppDigest;
 
         public EphemeralDigest(@NonNull String hostName) {
             this(hostName, -1 /*maxDigests*/);
@@ -180,73 +177,24 @@
 
         /** @hide */
         public EphemeralDigest(@NonNull String hostName, int maxDigests) {
-            if (hostName == null) {
-                throw new IllegalArgumentException();
-            }
-            mDigestBytes = generateDigest(hostName.toLowerCase(Locale.ENGLISH), maxDigests);
-            mDigestPrefix = new int[mDigestBytes.length];
-            for (int i = 0; i < mDigestBytes.length; i++) {
-                mDigestPrefix[i] =
-                        ((mDigestBytes[i][0] & 0xFF) << 24
-                                | (mDigestBytes[i][1] & 0xFF) << 16
-                                | (mDigestBytes[i][2] & 0xFF) << 8
-                                | (mDigestBytes[i][3] & 0xFF) << 0)
-                        & DIGEST_MASK;
-            }
-        }
-
-        private static byte[][] generateDigest(String hostName, int maxDigests) {
-            ArrayList<byte[]> digests = new ArrayList<>();
-            try {
-                final MessageDigest digest = MessageDigest.getInstance(SHA_ALGORITHM);
-                if (maxDigests <= 0) {
-                    final byte[] hostBytes = hostName.getBytes();
-                    digests.add(digest.digest(hostBytes));
-                } else {
-                    int prevDot = hostName.lastIndexOf('.');
-                    prevDot = hostName.lastIndexOf('.', prevDot - 1);
-                    // shortcut for short URLs
-                    if (prevDot < 0) {
-                        digests.add(digest.digest(hostName.getBytes()));
-                    } else {
-                        byte[] hostBytes =
-                                hostName.substring(prevDot + 1, hostName.length()).getBytes();
-                        digests.add(digest.digest(hostBytes));
-                        int digestCount = 1;
-                        while (prevDot >= 0 && digestCount < maxDigests) {
-                            prevDot = hostName.lastIndexOf('.', prevDot - 1);
-                            hostBytes =
-                                    hostName.substring(prevDot + 1, hostName.length()).getBytes();
-                            digests.add(digest.digest(hostBytes));
-                            digestCount++;
-                        }
-                    }
-                }
-            } catch (NoSuchAlgorithmException e) {
-                throw new IllegalStateException("could not find digest algorithm");
-            }
-            return digests.toArray(new byte[digests.size()][]);
+            mInstantAppDigest = new InstantAppDigest(hostName, maxDigests);
         }
 
         EphemeralDigest(Parcel in) {
-            final int digestCount = in.readInt();
-            if (digestCount == -1) {
-                mDigestBytes = null;
-            } else {
-                mDigestBytes = new byte[digestCount][];
-                for (int i = 0; i < digestCount; i++) {
-                    mDigestBytes[i] = in.createByteArray();
-                }
-            }
-            mDigestPrefix = in.createIntArray();
+            mInstantAppDigest = in.readParcelable(null /*loader*/);
+        }
+
+        /** @hide */
+        InstantAppDigest getInstantAppDigest() {
+            return mInstantAppDigest;
         }
 
         public byte[][] getDigestBytes() {
-            return mDigestBytes;
+            return mInstantAppDigest.getDigestBytes();
         }
 
         public int[] getDigestPrefix() {
-            return mDigestPrefix;
+            return mInstantAppDigest.getDigestPrefix();
         }
 
         @Override
@@ -256,24 +204,17 @@
 
         @Override
         public void writeToParcel(Parcel out, int flags) {
-            if (mDigestBytes == null) {
-                out.writeInt(-1);
-            } else {
-                out.writeInt(mDigestBytes.length);
-                for (int i = 0; i < mDigestBytes.length; i++) {
-                    out.writeByteArray(mDigestBytes[i]);
-                }
-            }
-            out.writeIntArray(mDigestPrefix);
+            out.writeParcelable(mInstantAppDigest, flags);
         }
 
         @SuppressWarnings("hiding")
         public static final Parcelable.Creator<EphemeralDigest> CREATOR =
                 new Parcelable.Creator<EphemeralDigest>() {
+            @Override
             public EphemeralDigest createFromParcel(Parcel in) {
                 return new EphemeralDigest(in);
             }
-
+            @Override
             public EphemeralDigest[] newArray(int size) {
                 return new EphemeralDigest[size];
             }
diff --git a/core/java/android/content/pm/EphemeralResponse.java b/core/java/android/content/pm/EphemeralResponse.java
deleted file mode 100644
index 6e569f7..0000000
--- a/core/java/android/content/pm/EphemeralResponse.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.pm;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.IntentFilter;
-
-/**
- * Ephemeral application resolution response.
- * @hide
- */
-public final class EphemeralResponse extends IntentFilter {
-    /** Resolved information returned from the external ephemeral resolver */
-    public final EphemeralResolveInfo resolveInfo;
-    /** The resolved package. Copied from {@link #resolveInfo}. */
-    public final String packageName;
-    /** The resolve split. Copied from the matched filter in {@link #resolveInfo}. */
-    public final String splitName;
-    /** Whether or not ephemeral resolution needs the second phase */
-    public final boolean needsPhase2;
-    /** Opaque token to track the ephemeral application resolution */
-    public final String token;
-
-    public EphemeralResponse(@NonNull EphemeralResolveInfo resolveInfo,
-            @NonNull IntentFilter orig,
-            @Nullable String splitName,
-            @NonNull String token,
-            boolean needsPhase2) {
-        super(orig);
-        this.resolveInfo = resolveInfo;
-        this.packageName = resolveInfo.getPackageName();
-        this.splitName = splitName;
-        this.token = token;
-        this.needsPhase2 = needsPhase2;
-    }
-}
\ No newline at end of file
diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl
index c08bd1d..41311eb 100644
--- a/core/java/android/content/pm/ILauncherApps.aidl
+++ b/core/java/android/content/pm/ILauncherApps.aidl
@@ -55,7 +55,8 @@
             String callingPackage, String packageName, int flags, in UserHandle user);
 
     ParceledListSlice getShortcuts(String callingPackage, long changedSince, String packageName,
-            in List shortcutIds, in ComponentName componentName, int flags, in UserHandle user);
+            in List shortcutIds, in ComponentName componentName, in Intent intent, int flags,
+            in UserHandle user);
     void pinShortcuts(String callingPackage, String packageName, in List<String> shortcutIds,
             in UserHandle user);
     boolean startShortcut(String callingPackage, String packageName, String id,
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index ffb777d..147b3e1 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -22,7 +22,6 @@
 import android.content.IntentFilter;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.ContainerEncryptionParams;
 import android.content.pm.ChangedPackages;
 import android.content.pm.InstantAppInfo;
 import android.content.pm.FeatureInfo;
@@ -38,7 +37,6 @@
 import android.content.pm.InstrumentationInfo;
 import android.content.pm.KeySet;
 import android.content.pm.PackageInfo;
-import android.content.pm.ManifestDigest;
 import android.content.pm.PackageCleanItem;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.ProviderInfo;
@@ -213,7 +211,7 @@
             inout List<ProviderInfo> outInfo);
 
     ParceledListSlice queryContentProviders(
-            String processName, int uid, int flags);
+            String processName, int uid, int flags, String metaDataKey);
 
     InstrumentationInfo getInstrumentationInfo(
             in ComponentName className, int flags);
diff --git a/core/java/android/content/pm/IPinItemRequest.aidl b/core/java/android/content/pm/IPinItemRequest.aidl
index efe2835..4b4dffa 100644
--- a/core/java/android/content/pm/IPinItemRequest.aidl
+++ b/core/java/android/content/pm/IPinItemRequest.aidl
@@ -16,6 +16,8 @@
 package android.content.pm;
 
 import android.os.Bundle;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.pm.ShortcutInfo;
 
 /**
  * {@hide}
@@ -23,4 +25,7 @@
 interface IPinItemRequest {
     boolean isValid();
     boolean accept(in Bundle options);
+    ShortcutInfo getShortcutInfo();
+    AppWidgetProviderInfo getAppWidgetProviderInfo();
+    Bundle getExtras();
 }
diff --git a/core/java/android/content/pm/InstantAppInfo.java b/core/java/android/content/pm/InstantAppInfo.java
index 898ee110..67afc92 100644
--- a/core/java/android/content/pm/InstantAppInfo.java
+++ b/core/java/android/content/pm/InstantAppInfo.java
@@ -75,7 +75,7 @@
     }
 
     /**
-     * @return The pakcage name.
+     * @return The package name.
      */
     public @NonNull String getPackageName() {
         if (mApplicationInfo != null) {
diff --git a/core/java/android/content/pm/InstantAppIntentFilter.java b/core/java/android/content/pm/InstantAppIntentFilter.java
new file mode 100644
index 0000000..257ab967
--- /dev/null
+++ b/core/java/android/content/pm/InstantAppIntentFilter.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 android.content.pm;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.content.IntentFilter;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Information about an instant application intent filter.
+ * @hide
+ */
+@SystemApi
+public final class InstantAppIntentFilter implements Parcelable {
+    private final String mSplitName;
+    /** The filters used to match domain */
+    private final List<IntentFilter> mFilters = new ArrayList<IntentFilter>();
+
+    public InstantAppIntentFilter(@Nullable String splitName, @NonNull List<IntentFilter> filters) {
+        if (filters == null || filters.size() == 0) {
+            throw new IllegalArgumentException();
+        }
+        mSplitName = splitName;
+        mFilters.addAll(filters);
+    }
+
+    InstantAppIntentFilter(Parcel in) {
+        mSplitName = in.readString();
+        in.readList(mFilters, null /*loader*/);
+    }
+
+    public String getSplitName() {
+        return mSplitName;
+    }
+
+    public List<IntentFilter> getFilters() {
+        return mFilters;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeString(mSplitName);
+        out.writeList(mFilters);
+    }
+
+    public static final Parcelable.Creator<InstantAppIntentFilter> CREATOR
+            = new Parcelable.Creator<InstantAppIntentFilter>() {
+        @Override
+        public InstantAppIntentFilter createFromParcel(Parcel in) {
+            return new InstantAppIntentFilter(in);
+        }
+        @Override
+        public InstantAppIntentFilter[] newArray(int size) {
+            return new InstantAppIntentFilter[size];
+        }
+    };
+}
diff --git a/core/java/android/content/pm/InstantAppRequest.java b/core/java/android/content/pm/InstantAppRequest.java
new file mode 100644
index 0000000..b45169d
--- /dev/null
+++ b/core/java/android/content/pm/InstantAppRequest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.content.Intent;
+
+/**
+ * Information needed to make an instant application resolution request.
+ * @hide
+ */
+public final class InstantAppRequest {
+    /** Response from the first phase of instant application resolution */
+    public final AuxiliaryResolveInfo responseObj;
+    /** The original intent that triggered instant application resolution */
+    public final Intent origIntent;
+    /** Resolved type of the intent */
+    public final String resolvedType;
+    /** The name of the package requesting the instant application */
+    public final String callingPackage;
+    /** ID of the user requesting the instant application */
+    public final int userId;
+
+    public InstantAppRequest(AuxiliaryResolveInfo responseObj, Intent origIntent,
+            String resolvedType, String callingPackage, int userId) {
+        this.responseObj = responseObj;
+        this.origIntent = origIntent;
+        this.resolvedType = resolvedType;
+        this.callingPackage = callingPackage;
+        this.userId = userId;
+    }
+}
\ No newline at end of file
diff --git a/core/java/android/content/pm/InstantAppResolveInfo.java b/core/java/android/content/pm/InstantAppResolveInfo.java
new file mode 100644
index 0000000..603192a
--- /dev/null
+++ b/core/java/android/content/pm/InstantAppResolveInfo.java
@@ -0,0 +1,250 @@
+/*
+ * 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 android.content.pm;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.content.IntentFilter;
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * Information about an instant application.
+ * @hide
+ */
+@SystemApi
+public final class InstantAppResolveInfo implements Parcelable {
+    /** Algorithm that will be used to generate the domain digest */
+    public static final String SHA_ALGORITHM = "SHA-256";
+
+    private final InstantAppDigest mDigest;
+    private final String mPackageName;
+    /** The filters used to match domain */
+    private final List<InstantAppIntentFilter> mFilters;
+    /** The version code of the app that this class resolves to */
+    private final int mVersionCode;
+
+    public InstantAppResolveInfo(@NonNull InstantAppDigest digest, @Nullable String packageName,
+            @Nullable List<InstantAppIntentFilter> filters, int versionConde) {
+        // validate arguments
+        if ((packageName == null && (filters != null && filters.size() != 0))
+                || (packageName != null && (filters == null || filters.size() == 0))) {
+            throw new IllegalArgumentException();
+        }
+        mDigest = digest;
+        if (filters != null) {
+            mFilters = new ArrayList<InstantAppIntentFilter>(filters.size());
+            mFilters.addAll(filters);
+        } else {
+            mFilters = null;
+        }
+        mPackageName = packageName;
+        mVersionCode = versionConde;
+    }
+
+    public InstantAppResolveInfo(@NonNull String hostName, @Nullable String packageName,
+            @Nullable List<InstantAppIntentFilter> filters) {
+        this(new InstantAppDigest(hostName), packageName, filters, -1 /*versionCode*/);
+    }
+
+    InstantAppResolveInfo(Parcel in) {
+        mDigest = in.readParcelable(null /*loader*/);
+        mPackageName = in.readString();
+        mFilters = new ArrayList<InstantAppIntentFilter>();
+        in.readList(mFilters, null /*loader*/);
+        mVersionCode = in.readInt();
+    }
+
+    public byte[] getDigestBytes() {
+        return mDigest.getDigestBytes()[0];
+    }
+
+    public int getDigestPrefix() {
+        return mDigest.getDigestPrefix()[0];
+    }
+
+    public String getPackageName() {
+        return mPackageName;
+    }
+
+    public List<InstantAppIntentFilter> getIntentFilters() {
+        return mFilters;
+    }
+
+    public int getVersionCode() {
+        return mVersionCode;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeParcelable(mDigest, flags);
+        out.writeString(mPackageName);
+        out.writeList(mFilters);
+        out.writeInt(mVersionCode);
+    }
+
+    public static final Parcelable.Creator<InstantAppResolveInfo> CREATOR
+            = new Parcelable.Creator<InstantAppResolveInfo>() {
+        public InstantAppResolveInfo createFromParcel(Parcel in) {
+            return new InstantAppResolveInfo(in);
+        }
+
+        public InstantAppResolveInfo[] newArray(int size) {
+            return new InstantAppResolveInfo[size];
+        }
+    };
+
+    /**
+     * Helper class to generate and store each of the digests and prefixes
+     * sent to the Instant App Resolver.
+     * <p>
+     * Since intent filters may want to handle multiple hosts within a
+     * domain [eg “*.google.com”], the resolver is presented with multiple
+     * hash prefixes. For example, "a.b.c.d.e" generates digests for
+     * "d.e", "c.d.e", "b.c.d.e" and "a.b.c.d.e".
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final class InstantAppDigest implements Parcelable {
+        private static final int DIGEST_MASK = 0xfffff000;
+        private static final int DIGEST_PREFIX_COUNT = 5;
+        /** Full digest of the domain hashes */
+        private final byte[][] mDigestBytes;
+        /** The first 4 bytes of the domain hashes */
+        private final int[] mDigestPrefix;
+
+        public InstantAppDigest(@NonNull String hostName) {
+            this(hostName, -1 /*maxDigests*/);
+        }
+
+        /** @hide */
+        public InstantAppDigest(@NonNull String hostName, int maxDigests) {
+            if (hostName == null) {
+                throw new IllegalArgumentException();
+            }
+            mDigestBytes = generateDigest(hostName.toLowerCase(Locale.ENGLISH), maxDigests);
+            mDigestPrefix = new int[mDigestBytes.length];
+            for (int i = 0; i < mDigestBytes.length; i++) {
+                mDigestPrefix[i] =
+                        ((mDigestBytes[i][0] & 0xFF) << 24
+                                | (mDigestBytes[i][1] & 0xFF) << 16
+                                | (mDigestBytes[i][2] & 0xFF) << 8
+                                | (mDigestBytes[i][3] & 0xFF) << 0)
+                        & DIGEST_MASK;
+            }
+        }
+
+        private static byte[][] generateDigest(String hostName, int maxDigests) {
+            ArrayList<byte[]> digests = new ArrayList<>();
+            try {
+                final MessageDigest digest = MessageDigest.getInstance(SHA_ALGORITHM);
+                if (maxDigests <= 0) {
+                    final byte[] hostBytes = hostName.getBytes();
+                    digests.add(digest.digest(hostBytes));
+                } else {
+                    int prevDot = hostName.lastIndexOf('.');
+                    prevDot = hostName.lastIndexOf('.', prevDot - 1);
+                    // shortcut for short URLs
+                    if (prevDot < 0) {
+                        digests.add(digest.digest(hostName.getBytes()));
+                    } else {
+                        byte[] hostBytes =
+                                hostName.substring(prevDot + 1, hostName.length()).getBytes();
+                        digests.add(digest.digest(hostBytes));
+                        int digestCount = 1;
+                        while (prevDot >= 0 && digestCount < maxDigests) {
+                            prevDot = hostName.lastIndexOf('.', prevDot - 1);
+                            hostBytes =
+                                    hostName.substring(prevDot + 1, hostName.length()).getBytes();
+                            digests.add(digest.digest(hostBytes));
+                            digestCount++;
+                        }
+                    }
+                }
+            } catch (NoSuchAlgorithmException e) {
+                throw new IllegalStateException("could not find digest algorithm");
+            }
+            return digests.toArray(new byte[digests.size()][]);
+        }
+
+        InstantAppDigest(Parcel in) {
+            final int digestCount = in.readInt();
+            if (digestCount == -1) {
+                mDigestBytes = null;
+            } else {
+                mDigestBytes = new byte[digestCount][];
+                for (int i = 0; i < digestCount; i++) {
+                    mDigestBytes[i] = in.createByteArray();
+                }
+            }
+            mDigestPrefix = in.createIntArray();
+        }
+
+        public byte[][] getDigestBytes() {
+            return mDigestBytes;
+        }
+
+        public int[] getDigestPrefix() {
+            return mDigestPrefix;
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel out, int flags) {
+            if (mDigestBytes == null) {
+                out.writeInt(-1);
+            } else {
+                out.writeInt(mDigestBytes.length);
+                for (int i = 0; i < mDigestBytes.length; i++) {
+                    out.writeByteArray(mDigestBytes[i]);
+                }
+            }
+            out.writeIntArray(mDigestPrefix);
+        }
+
+        @SuppressWarnings("hiding")
+        public static final Parcelable.Creator<InstantAppDigest> CREATOR =
+                new Parcelable.Creator<InstantAppDigest>() {
+            @Override
+            public InstantAppDigest createFromParcel(Parcel in) {
+                return new InstantAppDigest(in);
+            }
+            @Override
+            public InstantAppDigest[] newArray(int size) {
+                return new InstantAppDigest[size];
+            }
+        };
+    }
+}
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 40deeae..abdef08 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -37,7 +37,7 @@
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
-import android.graphics.drawable.MaskableIconDrawable;
+import android.graphics.drawable.AdaptiveIconDrawable;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -275,7 +275,18 @@
         @Deprecated
         public static final int FLAG_GET_MANIFEST = FLAG_MATCH_MANIFEST;
 
-        /** @hide */
+        /**
+         * Include chooser shortcuts in the result.
+         * STOPSHIP TODO: Unless explicitly requesting chooser fields, we should strip out chooser
+         *           relevant fields from the Shortcut. This should also be adequately documented.
+         */
+        public static final int FLAG_MATCH_CHOOSER = 1 << 4;
+
+        /**
+         * Does not retrieve CHOOSER only shortcuts.
+         * TODO: Add another flag for MATCH_ALL_PINNED
+         * @hide
+         */
         public static final int FLAG_MATCH_ALL_KINDS =
                 FLAG_GET_DYNAMIC | FLAG_GET_PINNED | FLAG_GET_MANIFEST;
 
@@ -308,6 +319,7 @@
                         FLAG_MATCH_DYNAMIC,
                         FLAG_MATCH_PINNED,
                         FLAG_MATCH_MANIFEST,
+                        FLAG_MATCH_CHOOSER,
                         FLAG_GET_KEY_FIELDS_ONLY,
                 })
         @Retention(RetentionPolicy.SOURCE)
@@ -324,6 +336,9 @@
         @Nullable
         ComponentName mActivity;
 
+        @Nullable
+        Intent mIntent;
+
         @QueryFlags
         int mQueryFlags;
 
@@ -368,6 +383,14 @@
         }
 
         /**
+         * If non-null, returns only shortcuts with intent filters that match this intent.
+         */
+        public ShortcutQuery setIntent(@Nullable Intent intent) {
+            mIntent = intent;
+            return this;
+        }
+
+        /**
          * Set query options.  At least one of the {@code MATCH} flags should be set.  Otherwise,
          * no shortcuts will be returned.
          *
@@ -681,7 +704,7 @@
         try {
             return mService.getShortcuts(mContext.getPackageName(),
                     query.mChangedSince, query.mPackage, query.mShortcutIds, query.mActivity,
-                    query.mQueryFlags, user)
+                    query.mIntent, query.mQueryFlags, user)
                     .getList();
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -806,8 +829,8 @@
                 final Bitmap bmp = BitmapFactory.decodeFileDescriptor(pfd.getFileDescriptor());
                 if (bmp != null) {
                     BitmapDrawable dr = new BitmapDrawable(mContext.getResources(), bmp);
-                    if (shortcut.hasMaskableBitmap()) {
-                        return new MaskableIconDrawable(null, dr);
+                    if (shortcut.hasAdaptiveBitmap()) {
+                        return new AdaptiveIconDrawable(null, dr);
                     } else {
                         return dr;
                     }
@@ -831,7 +854,7 @@
                             icon.getResId(), shortcut.getUserHandle(), density);
                 }
                 case Icon.TYPE_BITMAP:
-                case Icon.TYPE_BITMAP_MASKABLE: {
+                case Icon.TYPE_ADAPTIVE_BITMAP: {
                     return icon.loadDrawable(mContext);
                 }
                 default:
@@ -1291,28 +1314,14 @@
         public @interface RequestType {}
 
         private final int mRequestType;
-        private final ShortcutInfo mShortcutInfo;
-        private final AppWidgetProviderInfo mAppWidgetInfo;
         private final IPinItemRequest mInner;
 
         /**
          * @hide
          */
-        public PinItemRequest(ShortcutInfo shortcutInfo, IPinItemRequest inner) {
-            mRequestType = REQUEST_TYPE_SHORTCUT;
-            mShortcutInfo = shortcutInfo;
-            mAppWidgetInfo = null;
+        public PinItemRequest(IPinItemRequest inner, int type) {
             mInner = inner;
-        }
-
-        /**
-         * @hide
-         */
-        public PinItemRequest(AppWidgetProviderInfo appWidgetInfo, IPinItemRequest inner) {
-            mRequestType = REQUEST_TYPE_APPWIDGET;
-            mShortcutInfo = null;
-            mAppWidgetInfo = appWidgetInfo;
-            mInner = inner;
+            mRequestType = type;
         }
 
         /**
@@ -1330,7 +1339,11 @@
          */
         @Nullable
         public ShortcutInfo getShortcutInfo() {
-            return mShortcutInfo;
+            try {
+                return mInner.getShortcutInfo();
+            } catch (RemoteException e) {
+                throw e.rethrowAsRuntimeException();
+            }
         }
 
         /**
@@ -1339,12 +1352,28 @@
          */
         @Nullable
         public AppWidgetProviderInfo getAppWidgetProviderInfo(Context context) {
-            if (mAppWidgetInfo != null) {
-                AppWidgetProviderInfo info = mAppWidgetInfo.clone();
+            try {
+                final AppWidgetProviderInfo info = mInner.getAppWidgetProviderInfo();
+                if (info == null) {
+                    return null;
+                }
                 info.updateDimensions(context.getResources().getDisplayMetrics());
                 return info;
+            } catch (RemoteException e) {
+                throw e.rethrowAsRuntimeException();
             }
-            return null;
+        }
+
+        /**
+         * Any extras sent by the requesting app.
+         */
+        @Nullable
+        public Bundle getExtras() {
+            try {
+                return mInner.getExtras();
+            } catch (RemoteException e) {
+                throw e.rethrowAsRuntimeException();
+            }
         }
 
         /**
@@ -1381,22 +1410,12 @@
             final ClassLoader cl = getClass().getClassLoader();
 
             mRequestType = source.readInt();
-            mShortcutInfo = mRequestType == REQUEST_TYPE_SHORTCUT ?
-                (ShortcutInfo) source.readParcelable(cl) : null;
-            mAppWidgetInfo = mRequestType == REQUEST_TYPE_APPWIDGET ?
-                (AppWidgetProviderInfo) source.readParcelable(cl) : null;
             mInner = IPinItemRequest.Stub.asInterface(source.readStrongBinder());
         }
 
         @Override
         public void writeToParcel(Parcel dest, int flags) {
             dest.writeInt(mRequestType);
-            if (mRequestType == REQUEST_TYPE_SHORTCUT) {
-                dest.writeParcelable(mShortcutInfo, flags);
-            }
-            if (mRequestType == REQUEST_TYPE_APPWIDGET) {
-                dest.writeParcelable(mAppWidgetInfo, flags);
-            }
             dest.writeStrongBinder(mInner.asBinder());
         }
 
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 278a6d0..76c29bc 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -95,6 +95,18 @@
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_SESSION_DETAILS = "android.content.pm.action.SESSION_DETAILS";
 
+    /**
+     * Broadcast Action: Explicit broadcast sent to the last known default launcher when a session
+     * for a new install is committed. For managed profile, this is sent to the default launcher
+     * of the primary profile.
+     * <p>
+     * The associated session is defined in {@link #EXTRA_SESSION} and the user for which this
+     * session was created in {@link Intent#EXTRA_USER}.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_SESSION_COMMITTED =
+            "android.content.pm.action.SESSION_COMMITTED";
+
     /** {@hide} */
     public static final String
             ACTION_CONFIRM_PERMISSIONS = "android.content.pm.action.CONFIRM_PERMISSIONS";
@@ -107,6 +119,13 @@
     public static final String EXTRA_SESSION_ID = "android.content.pm.extra.SESSION_ID";
 
     /**
+     * {@link SessionInfo} that an operation is working with.
+     *
+     * @see Intent#getParcelableExtra(String)
+     */
+    public static final String EXTRA_SESSION = "android.content.pm.extra.SESSION";
+
+    /**
      * Package name that an operation is working with.
      *
      * @see Intent#getStringExtra(String)
@@ -446,6 +465,7 @@
     }
 
     /** {@hide} */
+    @SystemApi
     public void setPermissionsResult(int sessionId, boolean accepted) {
         try {
             mInstaller.setPermissionsResult(sessionId, accepted);
@@ -826,9 +846,9 @@
          * user intervention, and so it may not happen immediately. The final
          * result of the commit will be reported through the given callback.
          * <p>
-         * Once this method is called, no additional mutations may be performed
-         * on the session. If the device reboots before the session has been
-         * finalized, you may commit the session again.
+         * Once this method is called, the session is sealed and no additional
+         * mutations may be performed on the session. If the device reboots
+         * before the session has been finalized, you may commit the session again.
          *
          * @throws SecurityException if streams opened through
          *             {@link #openWrite(String, long, long)} are still open.
@@ -1184,6 +1204,8 @@
         /** {@hide} */
         public int mode;
         /** {@hide} */
+        public int installReason;
+        /** {@hide} */
         public long sizeBytes;
         /** {@hide} */
         public String appPackageName;
@@ -1206,6 +1228,7 @@
             active = source.readInt() != 0;
 
             mode = source.readInt();
+            installReason = source.readInt();
             sizeBytes = source.readLong();
             appPackageName = source.readString();
             appIcon = source.readParcelable(null);
@@ -1256,6 +1279,25 @@
             return active;
         }
 
+        /**
+         * Return if this session is sealed.
+         * <p>
+         * Once sealed, no further changes may be made to the session. A session
+         * is sealed the moment {@link Session#commit(IntentSender)} is called.
+         */
+        public boolean isSealed() {
+            return sealed;
+        }
+
+        /**
+         * Return the reason for installing this package.
+         *
+         * @see PackageManager#INSTALL_REASON_UNKNOWN
+         */
+        public int getInstallReason() {
+            return installReason;
+        }
+
         /** {@hide} */
         @Deprecated
         public boolean isOpen() {
@@ -1324,6 +1366,7 @@
             dest.writeInt(active ? 1 : 0);
 
             dest.writeInt(mode);
+            dest.writeInt(installReason);
             dest.writeLong(sizeBytes);
             dest.writeString(appPackageName);
             dest.writeParcelable(appIcon, flags);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 5733982..3a875bc 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -34,6 +34,7 @@
 import android.app.PackageDeleteObserver;
 import android.app.PackageInstallObserver;
 import android.app.admin.DevicePolicyManager;
+import android.app.usage.StorageStatsManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -133,6 +134,7 @@
             MATCH_SYSTEM_ONLY,
             MATCH_FACTORY_ONLY,
             MATCH_DEBUG_TRIAGED_MISSING,
+            MATCH_INSTANT,
             GET_DISABLED_COMPONENTS,
             GET_DISABLED_UNTIL_USED_COMPONENTS,
             GET_UNINSTALLED_PACKAGES,
@@ -148,6 +150,7 @@
             MATCH_SYSTEM_ONLY,
             MATCH_DEBUG_TRIAGED_MISSING,
             MATCH_DISABLED_UNTIL_USED_COMPONENTS,
+            MATCH_INSTANT,
             GET_DISABLED_UNTIL_USED_COMPONENTS,
             GET_UNINSTALLED_PACKAGES,
     })
@@ -167,6 +170,7 @@
             MATCH_DIRECT_BOOT_UNAWARE,
             MATCH_SYSTEM_ONLY,
             MATCH_UNINSTALLED_PACKAGES,
+            MATCH_INSTANT,
             GET_DISABLED_COMPONENTS,
             GET_DISABLED_UNTIL_USED_COMPONENTS,
             GET_UNINSTALLED_PACKAGES,
@@ -188,6 +192,7 @@
             MATCH_DIRECT_BOOT_UNAWARE,
             MATCH_SYSTEM_ONLY,
             MATCH_UNINSTALLED_PACKAGES,
+            MATCH_INSTANT,
             GET_DISABLED_COMPONENTS,
             GET_DISABLED_UNTIL_USED_COMPONENTS,
             GET_UNINSTALLED_PACKAGES,
@@ -411,17 +416,6 @@
      */
     public static final int MATCH_DIRECT_BOOT_AWARE = 0x00080000;
 
-    /** @removed */
-    @Deprecated
-    public static final int MATCH_ENCRYPTION_UNAWARE = 0x00040000;
-    /** @removed */
-    @Deprecated
-    public static final int MATCH_ENCRYPTION_AWARE = 0x00080000;
-    /** @removed */
-    @Deprecated
-    public static final int MATCH_ENCRYPTION_AWARE_AND_UNAWARE = MATCH_ENCRYPTION_AWARE
-            | MATCH_ENCRYPTION_UNAWARE;
-
     /**
      * Querying flag: include only components from applications that are marked
      * with {@link ApplicationInfo#FLAG_SYSTEM}.
@@ -455,6 +449,7 @@
      * instant app. By default, instant app components are not matched.
      * @hide
      */
+    @SystemApi
     public static final int MATCH_INSTANT = 0x00800000;
 
     /**
@@ -624,8 +619,10 @@
      * should be installed as forward locked, i.e. only the app itself should
      * have access to its code and non-resource assets.
      *
+     * @deprecated new installs into ASEC containers are no longer supported.
      * @hide
      */
+    @Deprecated
     public static final int INSTALL_FORWARD_LOCK = 0x00000001;
 
     /**
@@ -648,8 +645,11 @@
      * Flag parameter for {@link #installPackage} to indicate that this package
      * must be installed to an ASEC on a {@link VolumeInfo#TYPE_PUBLIC}.
      *
+     * @deprecated new installs into ASEC containers are no longer supported;
+     *             use adoptable storage instead.
      * @hide
      */
+    @Deprecated
     public static final int INSTALL_EXTERNAL = 0x00000008;
 
     /**
@@ -751,7 +751,8 @@
     public static final int DONT_KILL_APP = 0x00000001;
 
     /** @hide */
-    @IntDef({INSTALL_REASON_UNKNOWN, INSTALL_REASON_POLICY})
+    @IntDef({INSTALL_REASON_UNKNOWN, INSTALL_REASON_POLICY, INSTALL_REASON_DEVICE_RESTORE,
+            INSTALL_REASON_DEVICE_SETUP, INSTALL_REASON_USER})
     @Retention(RetentionPolicy.SOURCE)
     public @interface InstallReason {}
 
@@ -766,6 +767,21 @@
     public static final int INSTALL_REASON_POLICY = 1;
 
     /**
+     * Code indicating that this package was installed as part of restoring from another device.
+     */
+    public static final int INSTALL_REASON_DEVICE_RESTORE = 2;
+
+    /**
+     * Code indicating that this package was installed as part of device setup.
+     */
+    public static final int INSTALL_REASON_DEVICE_SETUP = 3;
+
+    /**
+     * Code indicating that the package installation was initiated by the user.
+     */
+    public static final int INSTALL_REASON_USER = 4;
+
+    /**
      * Installation return code: this is passed to the
      * {@link IPackageInstallObserver} on success.
      *
@@ -3729,6 +3745,7 @@
      *
      * @hide
      */
+    @SystemApi
     @RequiresPermission(Manifest.permission.ACCESS_INSTANT_APPS)
     public abstract @NonNull List<InstantAppInfo> getInstantApps();
 
@@ -3739,14 +3756,16 @@
      *
      * @hide
      */
+    @SystemApi
     @RequiresPermission(Manifest.permission.ACCESS_INSTANT_APPS)
     public abstract @Nullable Drawable getInstantAppIcon(String packageName);
 
     /**
-     * Gets whether the caller is an instant app.
+     * Gets whether this application is an instant app.
      *
      * @return Whether caller is an instant app.
      *
+     * @see #isInstantApp(String)
      * @see #setInstantAppCookie(byte[])
      * @see #getInstantAppCookie()
      * @see #getInstantAppCookieMaxSize()
@@ -3754,12 +3773,26 @@
     public abstract boolean isInstantApp();
 
     /**
+     * Gets whether the given package is an instant app.
+     *
+     * @param packageName The package to check
+     * @return Whether the given package is an instant app.
+     *
+     * @see #isInstantApp()
+     * @see #setInstantAppCookie(byte[])
+     * @see #getInstantAppCookie()
+     * @see #getInstantAppCookieMaxSize()
+     */
+    public abstract boolean isInstantApp(String packageName);
+
+    /**
      * Gets the maximum size in bytes of the cookie data an instant app
      * can store on the device.
      *
      * @return The max cookie size in bytes.
      *
      * @see #isInstantApp()
+     * @see #isInstantApp(String)
      * @see #setInstantAppCookie(byte[])
      * @see #getInstantAppCookie()
      */
@@ -3776,6 +3809,7 @@
      * @return The cookie.
      *
      * @see #isInstantApp()
+     * @see #isInstantApp(String)
      * @see #setInstantAppCookie(byte[])
      * @see #getInstantAppCookieMaxSize()
      */
@@ -3798,6 +3832,7 @@
      * @return Whether the cookie was set.
      *
      * @see #isInstantApp()
+     * @see #isInstantApp(String)
      * @see #getInstantAppCookieMaxSize()
      * @see #getInstantAppCookie()
      */
@@ -4468,6 +4503,27 @@
             String processName, int uid, @ComponentInfoFlags int flags);
 
     /**
+     * Same as {@link #queryContentProviders}, except when {@code metaDataKey} is not null,
+     * it only returns providers which have metadata with the {@code metaDataKey} key.
+     *
+     * <p>DO NOT USE the {@code metaDataKey} parameter, unless you're the contacts provider.
+     * You really shouldn't need it.  Other apps should use {@link #queryIntentContentProviders}
+     * instead.
+     *
+     * <p>The {@code metaDataKey} parameter was added to allow the contacts provider to quickly
+     * scan the GAL providers on the device.  Unfortunately the discovery protocol used metadata
+     * to mark GAL providers, rather than intent filters, so we can't use
+     * {@link #queryIntentContentProviders} for that.
+     *
+     * @hide
+     */
+    public List<ProviderInfo> queryContentProviders(
+            String processName, int uid, @ComponentInfoFlags int flags, String metaDataKey) {
+        // Provide the default implementation for mocks.
+        return queryContentProviders(processName, uid, flags);
+    }
+
+    /**
      * Retrieve all of the information we know about a particular
      * instrumentation class.
      *
@@ -4968,6 +5024,7 @@
      */
     public PackageInfo getPackageArchiveInfo(String archiveFilePath, @PackageInfoFlags int flags) {
         final PackageParser parser = new PackageParser();
+        parser.setCallback(new PackageParser.CallbackImpl(this));
         final File apkFile = new File(archiveFilePath);
         try {
             if ((flags & (MATCH_DIRECT_BOOT_UNAWARE | MATCH_DIRECT_BOOT_AWARE)) != 0) {
@@ -5410,8 +5467,10 @@
      * the status of the operation. observer may be null to indicate that
      * no callback is desired.
      *
+     * @deprecated use {@link StorageStatsManager} instead.
      * @hide
      */
+    @Deprecated
     public abstract void getPackageSizeInfoAsUser(String packageName, @UserIdInt int userId,
             IPackageStatsObserver observer);
 
@@ -5419,8 +5478,10 @@
      * Like {@link #getPackageSizeInfoAsUser(String, int, IPackageStatsObserver)}, but
      * returns the size for the calling user.
      *
+     * @deprecated use {@link StorageStatsManager} instead.
      * @hide
      */
+    @Deprecated
     public void getPackageSizeInfo(String packageName, IPackageStatsObserver observer) {
         getPackageSizeInfoAsUser(packageName, UserHandle.myUserId(), observer);
     }
@@ -6093,6 +6154,9 @@
      *
      * @see #INSTALL_REASON_UNKNOWN
      * @see #INSTALL_REASON_POLICY
+     * @see #INSTALL_REASON_DEVICE_RESTORE
+     * @see #INSTALL_REASON_DEVICE_SETUP
+     * @see #INSTALL_REASON_USER
      *
      * @hide
      */
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 7d59bd6..6272822 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -213,12 +213,11 @@
      * @param responseObj The response of the first phase of ephemeral resolution
      * @param origIntent The original intent that triggered ephemeral resolution
      * @param resolvedType The resolved type of the intent
-     * @param launchIntent The intent that would launch if there was no ephemeral application
      * @param callingPackage The name of the package requesting the ephemeral application
      * @param userId The ID of the user that triggered ephemeral resolution
      */
-    public abstract void requestEphemeralResolutionPhaseTwo(EphemeralResponse responseObj,
-            Intent origIntent, String resolvedType, Intent launchIntent, String callingPackage,
+    public abstract void requestInstantAppResolutionPhaseTwo(AuxiliaryResolveInfo responseObj,
+            Intent origIntent, String resolvedType, String callingPackage,
             int userId);
 
     /**
@@ -307,4 +306,10 @@
      */
     public abstract boolean setEnabledOverlayPackages(int userId, String targetPackageName,
             List<String> overlayPackageNames);
+
+    /**
+     * Resolves an intent, allowing instant apps to be resolved.
+     */
+    public abstract ResolveInfo resolveIntent(Intent intent, String resolvedType,
+            int flags, int userId);
 }
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 98e71a0..a1c325a 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -285,6 +285,7 @@
     private String[] mSeparateProcesses;
     private boolean mOnlyCoreApps;
     private DisplayMetrics mMetrics;
+    private Callback mCallback;
     private File mCacheDir;
 
     private static final int SDK_VERSION = Build.VERSION.SDK_INT;
@@ -506,6 +507,37 @@
         mCacheDir = cacheDir;
     }
 
+    /**
+     * Callback interface for retrieving information that may be needed while parsing
+     * a package.
+     */
+    public interface Callback {
+        boolean hasFeature(String feature);
+    }
+
+    /**
+     * Standard implementation of {@link Callback} on top of the public {@link PackageManager}
+     * class.
+     */
+    public static final class CallbackImpl implements Callback {
+        private final PackageManager mPm;
+
+        public CallbackImpl(PackageManager pm) {
+            mPm = pm;
+        }
+
+        @Override public boolean hasFeature(String feature) {
+            return mPm.hasSystemFeature(feature);
+        }
+    }
+
+    /**
+     * Set the {@link Callback} that can be used while parsing.
+     */
+    public void setCallback(Callback cb) {
+        mCallback = cb;
+    }
+
     public static final boolean isApkFile(File file) {
         return isApkPath(file.getName());
     }
@@ -2065,9 +2097,6 @@
                         com.android.internal.R.styleable.AndroidManifestResourceOverlay);
                 pkg.mOverlayTarget = sa.getString(
                         com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage);
-                pkg.mOverlayPriority = sa.getInt(
-                        com.android.internal.R.styleable.AndroidManifestResourceOverlay_priority,
-                        -1);
                 sa.recycle();
 
                 if (pkg.mOverlayTarget == null) {
@@ -2075,12 +2104,6 @@
                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                     return null;
                 }
-                if (pkg.mOverlayPriority < 0 || pkg.mOverlayPriority > 9999) {
-                    outError[0] = "<overlay> priority must be between 0 and 9999";
-                    mParseError =
-                        PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
-                    return null;
-                }
                 XmlUtils.skipCurrentTag(parser);
 
             } else if (tagName.equals(TAG_KEY_SETS)) {
@@ -2088,15 +2111,15 @@
                     return null;
                 }
             } else if (tagName.equals(TAG_PERMISSION_GROUP)) {
-                if (parsePermissionGroup(pkg, flags, res, parser, outError) == null) {
+                if (!parsePermissionGroup(pkg, flags, res, parser, outError)) {
                     return null;
                 }
             } else if (tagName.equals(TAG_PERMISSION)) {
-                if (parsePermission(pkg, res, parser, outError) == null) {
+                if (!parsePermission(pkg, res, parser, outError)) {
                     return null;
                 }
             } else if (tagName.equals(TAG_PERMISSION_TREE)) {
-                if (parsePermissionTree(pkg, res, parser, outError) == null) {
+                if (!parsePermissionTree(pkg, res, parser, outError)) {
                     return null;
                 }
             } else if (tagName.equals(TAG_USES_PERMISSION)) {
@@ -2689,9 +2712,9 @@
         certSha256 = certSha256.replace(":", "").toLowerCase();
         pkg.usesStaticLibraries = ArrayUtils.add(pkg.usesStaticLibraries, lname);
         pkg.usesStaticLibrariesVersions = ArrayUtils.appendInt(
-                pkg.usesStaticLibrariesVersions, version);
+                pkg.usesStaticLibrariesVersions, version, true);
         pkg.usesStaticLibrariesCertDigests = ArrayUtils.appendElement(String.class,
-                pkg.usesStaticLibrariesCertDigests, certSha256);
+                pkg.usesStaticLibrariesCertDigests, certSha256, true);
 
         XmlUtils.skipCurrentTag(parser);
 
@@ -2717,22 +2740,44 @@
             }
         }
 
+        final String requiredFeature = sa.getNonConfigurationString(
+                com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredFeature, 0);
+
+        final String requiredNotfeature = sa.getNonConfigurationString(
+                com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredNotFeature, 0);
+
         sa.recycle();
 
-        if ((maxSdkVersion == 0) || (maxSdkVersion >= Build.VERSION.RESOURCES_SDK_INT)) {
-            if (name != null) {
-                int index = pkg.requestedPermissions.indexOf(name);
-                if (index == -1) {
-                    pkg.requestedPermissions.add(name.intern());
-                } else {
-                    Slog.w(TAG, "Ignoring duplicate uses-permissions/uses-permissions-sdk-m: "
-                            + name + " in package: " + pkg.packageName + " at: "
-                            + parser.getPositionDescription());
-                }
-            }
+        XmlUtils.skipCurrentTag(parser);
+
+        if (name == null) {
+            return true;
         }
 
-        XmlUtils.skipCurrentTag(parser);
+        if ((maxSdkVersion != 0) && (maxSdkVersion < Build.VERSION.RESOURCES_SDK_INT)) {
+            return true;
+        }
+
+        // Only allow requesting this permission if the platform supports the given feature.
+        if (requiredFeature != null && mCallback != null && !mCallback.hasFeature(requiredFeature)) {
+            return true;
+        }
+
+        // Only allow requesting this permission if the platform doesn't support the given feature.
+        if (requiredNotfeature != null && mCallback != null
+                && mCallback.hasFeature(requiredNotfeature)) {
+            return true;
+        }
+
+        int index = pkg.requestedPermissions.indexOf(name);
+        if (index == -1) {
+            pkg.requestedPermissions.add(name.intern());
+        } else {
+            Slog.w(TAG, "Ignoring duplicate uses-permissions/uses-permissions-sdk-m: "
+                    + name + " in package: " + pkg.packageName + " at: "
+                    + parser.getPositionDescription());
+        }
+
         return true;
     }
 
@@ -2745,15 +2790,15 @@
         String cls = clsSeq.toString();
         char c = cls.charAt(0);
         if (c == '.') {
-            return (pkg + cls).intern();
+            return pkg + cls;
         }
         if (cls.indexOf('.') < 0) {
             StringBuilder b = new StringBuilder(pkg);
             b.append('.');
             b.append(cls);
-            return b.toString().intern();
+            return b.toString();
         }
-        return cls.intern();
+        return cls;
     }
 
     private static String buildCompoundName(String pkg,
@@ -2773,7 +2818,7 @@
                         + pkg + ": " + nameError;
                 return null;
             }
-            return (pkg + proc).intern();
+            return pkg + proc;
         }
         String nameError = validateName(proc, true, false);
         if (nameError != null && !"system".equals(proc)) {
@@ -2781,7 +2826,7 @@
                     + pkg + ": " + nameError;
             return null;
         }
-        return proc.intern();
+        return proc;
     }
 
     private static String buildProcessName(String pkg, String defProc,
@@ -2960,7 +3005,7 @@
         return true;
     }
 
-    private PermissionGroup parsePermissionGroup(Package owner, int flags, Resources res,
+    private boolean parsePermissionGroup(Package owner, int flags, Resources res,
             XmlResourceParser parser, String[] outError)
             throws XmlPullParserException, IOException {
         PermissionGroup perm = new PermissionGroup(owner);
@@ -2977,7 +3022,7 @@
                 com.android.internal.R.styleable.AndroidManifestPermissionGroup_banner)) {
             sa.recycle();
             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
-            return null;
+            return false;
         }
 
         perm.info.descriptionRes = sa.getResourceId(
@@ -2996,22 +3041,22 @@
         if (!parseAllMetaData(res, parser, "<permission-group>", perm,
                 outError)) {
             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
-            return null;
+            return false;
         }
 
         owner.permissionGroups.add(perm);
 
-        return perm;
+        return true;
     }
 
-    private Permission parsePermission(Package owner, Resources res,
+    private boolean parsePermission(Package owner, Resources res,
             XmlResourceParser parser, String[] outError)
         throws XmlPullParserException, IOException {
-        Permission perm = new Permission(owner);
 
         TypedArray sa = res.obtainAttributes(parser,
                 com.android.internal.R.styleable.AndroidManifestPermission);
 
+        Permission perm = new Permission(owner);
         if (!parsePackageItemInfo(owner, perm.info, outError,
                 "<permission>", sa, true /*nameRequired*/,
                 com.android.internal.R.styleable.AndroidManifestPermission_name,
@@ -3022,7 +3067,7 @@
                 com.android.internal.R.styleable.AndroidManifestPermission_banner)) {
             sa.recycle();
             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
-            return null;
+            return false;
         }
 
         // Note: don't allow this value to be a reference to a resource
@@ -3049,7 +3094,7 @@
         if (perm.info.protectionLevel == -1) {
             outError[0] = "<permission> does not specify protectionLevel";
             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
-            return null;
+            return false;
         }
 
         perm.info.protectionLevel = PermissionInfo.fixProtectionLevel(perm.info.protectionLevel);
@@ -3061,21 +3106,21 @@
                 outError[0] = "<permission>  protectionLevel specifies a non-ephemeral flag but is "
                         + "not based on signature type";
                 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
-                return null;
+                return false;
             }
         }
 
         if (!parseAllMetaData(res, parser, "<permission>", perm, outError)) {
             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
-            return null;
+            return false;
         }
 
         owner.permissions.add(perm);
 
-        return perm;
+        return true;
     }
 
-    private Permission parsePermissionTree(Package owner, Resources res,
+    private boolean parsePermissionTree(Package owner, Resources res,
             XmlResourceParser parser, String[] outError)
         throws XmlPullParserException, IOException {
         Permission perm = new Permission(owner);
@@ -3093,7 +3138,7 @@
                 com.android.internal.R.styleable.AndroidManifestPermissionTree_banner)) {
             sa.recycle();
             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
-            return null;
+            return false;
         }
 
         sa.recycle();
@@ -3106,7 +3151,7 @@
             outError[0] = "<permission-tree> name has less than three segments: "
                 + perm.info.name;
             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
-            return null;
+            return false;
         }
 
         perm.info.descriptionRes = 0;
@@ -3116,12 +3161,12 @@
         if (!parseAllMetaData(res, parser, "<permission-tree>", perm,
                 outError)) {
             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
-            return null;
+            return false;
         }
 
         owner.permissions.add(perm);
 
-        return perm;
+        return true;
     }
 
     private Instrumentation parseInstrumentation(Package owner, Resources res,
@@ -4822,6 +4867,13 @@
                             PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission);
                 }
 
+                path = sa.getNonConfigurationString(
+                        com.android.internal.R.styleable.AndroidManifestPathPermission_pathAdvancedPattern, 0);
+                if (path != null) {
+                    pa = new PathPermission(path,
+                            PatternMatcher.PATTERN_ADVANCED_GLOB, readPermission, writePermission);
+                }
+
                 sa.recycle();
 
                 if (pa != null) {
@@ -5083,7 +5135,7 @@
             if (v != null) {
                 if (v.type == TypedValue.TYPE_STRING) {
                     CharSequence cs = v.coerceToString();
-                    data.putString(name, cs != null ? cs.toString().intern() : null);
+                    data.putString(name, cs != null ? cs.toString() : null);
                 } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
                     data.putBoolean(name, v.data != 0);
                 } else if (v.type >= TypedValue.TYPE_FIRST_INT
@@ -5344,6 +5396,16 @@
                     outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
                 }
 
+                str = sa.getNonConfigurationString(
+                        com.android.internal.R.styleable.AndroidManifestData_pathAdvancedPattern, 0);
+                if (str != null) {
+                    if (!allowGlobs) {
+                        outError[0] = "pathAdvancedPattern not allowed here; path must be literal";
+                        return false;
+                    }
+                    outInfo.addDataPath(str, PatternMatcher.PATTERN_ADVANCED_GLOB);
+                }
+
                 sa.recycle();
                 XmlUtils.skipCurrentTag(parser);
             } else if (!RIGID_PARSER) {
@@ -5518,7 +5580,6 @@
         public String mRequiredAccountType;
 
         public String mOverlayTarget;
-        public int mOverlayPriority;
         public boolean mTrustedOverlay;
 
         /**
@@ -5866,7 +5927,7 @@
             // We use the boot classloader for all classes that we load.
             final ClassLoader boot = Object.class.getClassLoader();
 
-            packageName = dest.readString();
+            packageName = dest.readString().intern();
             manifestPackageName = dest.readString();
             splitNames = dest.readStringArray();
             volumeUuid = dest.readString();
@@ -5879,6 +5940,9 @@
             splitPrivateFlags = dest.createIntArray();
             baseHardwareAccelerated = (dest.readInt() == 1);
             applicationInfo = dest.readParcelable(boot);
+            if (applicationInfo.permission != null) {
+                applicationInfo.permission = applicationInfo.permission.intern();
+            }
 
             // We don't serialize the "owner" package and the application info object for each of
             // these components, in order to save space and to avoid circular dependencies while
@@ -5899,7 +5963,10 @@
             fixupOwner(instrumentation);
 
             dest.readStringList(requestedPermissions);
+            internStringArrayList(requestedPermissions);
             protectedBroadcasts = dest.createStringArrayList();
+            internStringArrayList(protectedBroadcasts);
+
             parentPackage = dest.readParcelable(boot);
 
             childPackages = new ArrayList<>();
@@ -5909,16 +5976,23 @@
             }
 
             staticSharedLibName = dest.readString();
+            if (staticSharedLibName != null) {
+                staticSharedLibName = staticSharedLibName.intern();
+            }
             staticSharedLibVersion = dest.readInt();
             libraryNames = dest.createStringArrayList();
+            internStringArrayList(libraryNames);
             usesLibraries = dest.createStringArrayList();
+            internStringArrayList(usesLibraries);
             usesOptionalLibraries = dest.createStringArrayList();
+            internStringArrayList(usesOptionalLibraries);
             usesLibraryFiles = dest.readStringArray();
 
             final int libCount = dest.readInt();
             if (libCount > 0) {
                 usesStaticLibraries = new ArrayList<>(libCount);
                 dest.readStringList(usesStaticLibraries);
+                internStringArrayList(usesStaticLibraries);
                 usesStaticLibrariesVersions = new int[libCount];
                 dest.readIntArray(usesStaticLibrariesVersions);
                 usesStaticLibrariesCertDigests = new String[libCount];
@@ -5937,7 +6011,13 @@
             mAppMetaData = dest.readBundle();
             mVersionCode = dest.readInt();
             mVersionName = dest.readString();
+            if (mVersionName != null) {
+                mVersionName = mVersionName.intern();
+            }
             mSharedUserId = dest.readString();
+            if (mSharedUserId != null) {
+                mSharedUserId = mSharedUserId.intern();
+            }
             mSharedUserLabel = dest.readInt();
 
             mSignatures = (Signature[]) dest.readParcelableArray(boot, Signature.class);
@@ -5976,7 +6056,6 @@
             mRestrictedAccountType = dest.readString();
             mRequiredAccountType = dest.readString();
             mOverlayTarget = dest.readString();
-            mOverlayPriority = dest.readInt();
             mTrustedOverlay = (dest.readInt() == 1);
             mSigningKeys = (ArraySet<PublicKey>) dest.readArraySet(boot);
             mUpgradeKeySets = (ArraySet<String>) dest.readArraySet(boot);
@@ -5988,6 +6067,15 @@
             restrictUpdateHash = dest.createByteArray();
         }
 
+        private static void internStringArrayList(List<String> list) {
+            if (list != null) {
+                final int N = list.size();
+                for (int i = 0; i < N; ++i) {
+                    list.set(i, list.get(i).intern());
+                }
+            }
+        }
+
         /**
          * Sets the package owner and the the {@code applicationInfo} for every component
          * owner by this package.
@@ -6083,7 +6171,6 @@
             dest.writeString(mRestrictedAccountType);
             dest.writeString(mRequiredAccountType);
             dest.writeString(mOverlayTarget);
-            dest.writeInt(mOverlayPriority);
             dest.writeInt(mTrustedOverlay ? 1 : 0);
             dest.writeArraySet(mSigningKeys);
             dest.writeArraySet(mUpgradeKeySets);
@@ -6375,6 +6462,10 @@
             super(in);
             final ClassLoader boot = Object.class.getClassLoader();
             info = in.readParcelable(boot);
+            if (info.group != null) {
+                info.group = info.group.intern();
+            }
+
             tree = (in.readInt() == 1);
             group = in.readParcelable(boot);
         }
@@ -6528,6 +6619,7 @@
             ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName);
         }
         ai.seInfoUser = SELinuxUtil.assignSeinfoUser(state);
+        ai.resourceDirs = state.resourceDirs;
     }
 
     public static ApplicationInfo generateApplicationInfo(Package p, int flags,
@@ -6651,6 +6743,10 @@
             for (ActivityIntentInfo aii : intents) {
                 aii.activity = this;
             }
+
+            if (info.permission != null) {
+                info.permission = info.permission.intern();
+            }
         }
 
         public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Activity>() {
@@ -6735,6 +6831,10 @@
             for (ServiceIntentInfo aii : intents) {
                 aii.service = this;
             }
+
+            if (info.permission != null) {
+                info.permission = info.permission.intern();
+            }
         }
 
         public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Service>() {
@@ -6816,6 +6916,18 @@
             for (ProviderIntentInfo aii : intents) {
                 aii.provider = this;
             }
+
+            if (info.readPermission != null) {
+                info.readPermission = info.readPermission.intern();
+            }
+
+            if (info.writePermission != null) {
+                info.writePermission = info.writePermission.intern();
+            }
+
+            if (info.authority != null) {
+                info.authority = info.authority.intern();
+            }
         }
 
         public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Provider>() {
@@ -6888,6 +7000,14 @@
         private Instrumentation(Parcel in) {
             super(in);
             info = in.readParcelable(Object.class.getClassLoader());
+
+            if (info.targetPackage != null) {
+                info.targetPackage = info.targetPackage.intern();
+            }
+
+            if (info.targetProcess != null) {
+                info.targetProcess = info.targetProcess.intern();
+            }
         }
 
         public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Instrumentation>() {
diff --git a/core/java/android/content/pm/PackageStats.java b/core/java/android/content/pm/PackageStats.java
index cb9039b..27b3506 100644
--- a/core/java/android/content/pm/PackageStats.java
+++ b/core/java/android/content/pm/PackageStats.java
@@ -16,14 +16,22 @@
 
 package android.content.pm;
 
+import android.app.usage.StorageStatsManager;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.UserHandle;
+import android.text.TextUtils;
+
+import java.util.Objects;
 
 /**
- * implementation of PackageStats associated with a
- * application package.
+ * implementation of PackageStats associated with a application package.
+ *
+ * @deprecated this class is an orphan that could never be obtained from a valid
+ *             public API. If you need package storage statistics use the new
+ *             {@link StorageStatsManager} APIs.
  */
+@Deprecated
 public class PackageStats implements Parcelable {
     /** Name of the package to which this stats applies. */
     public String packageName;
@@ -173,4 +181,31 @@
         dest.writeLong(externalMediaSize);
         dest.writeLong(externalObbSize);
     }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof PackageStats)) {
+            return false;
+        }
+
+        final PackageStats otherStats = (PackageStats) obj;
+        return ((TextUtils.equals(packageName, otherStats.packageName))
+                && userHandle == otherStats.userHandle
+                && codeSize == otherStats.codeSize
+                && dataSize == otherStats.dataSize
+                && cacheSize == otherStats.cacheSize
+                && externalCodeSize == otherStats.externalCodeSize
+                && externalDataSize == otherStats.externalDataSize
+                && externalCacheSize == otherStats.externalCacheSize
+                && externalMediaSize == otherStats.externalMediaSize
+                && externalObbSize == otherStats.externalObbSize);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(packageName, userHandle, codeSize, dataSize,
+                cacheSize, externalCodeSize, externalDataSize, externalCacheSize, externalMediaSize,
+                externalObbSize);
+    }
+
 }
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index 24f1164..ee56a18 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -31,6 +31,8 @@
 
 import com.android.internal.util.ArrayUtils;
 
+import java.util.Arrays;
+
 /**
  * Per-user state information about a package.
  * @hide
@@ -54,6 +56,8 @@
     public ArraySet<String> disabledComponents;
     public ArraySet<String> enabledComponents;
 
+    public String[] resourceDirs;
+
     public PackageUserState() {
         installed = true;
         hidden = false;
@@ -81,6 +85,8 @@
         installReason = o.installReason;
         disabledComponents = ArrayUtils.cloneOrNull(o.disabledComponents);
         enabledComponents = ArrayUtils.cloneOrNull(o.enabledComponents);
+        resourceDirs =
+            o.resourceDirs == null ? null : Arrays.copyOf(o.resourceDirs, o.resourceDirs.length);
     }
 
     /**
diff --git a/core/java/android/content/pm/ParceledListSlice.java b/core/java/android/content/pm/ParceledListSlice.java
index 945858e6..d12e884 100644
--- a/core/java/android/content/pm/ParceledListSlice.java
+++ b/core/java/android/content/pm/ParceledListSlice.java
@@ -16,14 +16,9 @@
 
 package android.content.pm;
 
-import android.os.Binder;
-import android.os.IBinder;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.os.RemoteException;
-import android.util.Log;
 
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
@@ -31,171 +26,46 @@
  * Transfer a large list of Parcelable objects across an IPC.  Splits into
  * multiple transactions if needed.
  *
- * Caveat: for efficiency and security, all elements must be the same concrete type.
- * In order to avoid writing the class name of each object, we must ensure that
- * each object is the same type, or else unparceling then reparceling the data may yield
- * a different result if the class name encoded in the Parcelable is a Base type.
- * See b/17671747.
+ * @see BaseParceledListSlice
  *
  * @hide
  */
-public class ParceledListSlice<T extends Parcelable> implements Parcelable {
-    private static String TAG = "ParceledListSlice";
-    private static boolean DEBUG = false;
+public class ParceledListSlice<T extends Parcelable> extends BaseParceledListSlice<T> {
+    public ParceledListSlice(List<T> list) {
+        super(list);
+    }
 
-    /*
-     * TODO get this number from somewhere else. For now set it to a quarter of
-     * the 1MB limit.
-     */
-    private static final int MAX_IPC_SIZE = IBinder.MAX_IPC_SIZE;
-
-    private final List<T> mList;
+    private ParceledListSlice(Parcel in, ClassLoader loader) {
+        super(in, loader);
+    }
 
     public static <T extends Parcelable> ParceledListSlice<T> emptyList() {
         return new ParceledListSlice<T>(Collections.<T> emptyList());
     }
 
-    public ParceledListSlice(List<T> list) {
-        mList = list;
-    }
-
-    @SuppressWarnings("unchecked")
-    private ParceledListSlice(Parcel p, ClassLoader loader) {
-        final int N = p.readInt();
-        mList = new ArrayList<T>(N);
-        if (DEBUG) Log.d(TAG, "Retrieving " + N + " items");
-        if (N <= 0) {
-            return;
-        }
-
-        Parcelable.Creator<?> creator = p.readParcelableCreator(loader);
-        Class<?> listElementClass = null;
-
-        int i = 0;
-        while (i < N) {
-            if (p.readInt() == 0) {
-                break;
-            }
-
-            final T parcelable = p.readCreator(creator, loader);
-            if (listElementClass == null) {
-                listElementClass = parcelable.getClass();
-            } else {
-                verifySameType(listElementClass, parcelable.getClass());
-            }
-
-            mList.add(parcelable);
-
-            if (DEBUG) Log.d(TAG, "Read inline #" + i + ": " + mList.get(mList.size()-1));
-            i++;
-        }
-        if (i >= N) {
-            return;
-        }
-        final IBinder retriever = p.readStrongBinder();
-        while (i < N) {
-            if (DEBUG) Log.d(TAG, "Reading more @" + i + " of " + N + ": retriever=" + retriever);
-            Parcel data = Parcel.obtain();
-            Parcel reply = Parcel.obtain();
-            data.writeInt(i);
-            try {
-                retriever.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
-            } catch (RemoteException e) {
-                Log.w(TAG, "Failure retrieving array; only received " + i + " of " + N, e);
-                return;
-            }
-            while (i < N && reply.readInt() != 0) {
-                final T parcelable = reply.readCreator(creator, loader);
-                verifySameType(listElementClass, parcelable.getClass());
-
-                mList.add(parcelable);
-
-                if (DEBUG) Log.d(TAG, "Read extra #" + i + ": " + mList.get(mList.size()-1));
-                i++;
-            }
-            reply.recycle();
-            data.recycle();
-        }
-    }
-
-    private static void verifySameType(final Class<?> expected, final Class<?> actual) {
-        if (!actual.equals(expected)) {
-            throw new IllegalArgumentException("Can't unparcel type "
-                    + actual.getName() + " in list of type "
-                    + expected.getName());
-        }
-    }
-
-    public List<T> getList() {
-        return mList;
-    }
-
     @Override
     public int describeContents() {
         int contents = 0;
-        for (int i=0; i<mList.size(); i++) {
-            contents |= mList.get(i).describeContents();
+        final List<T> list = getList();
+        for (int i=0; i<list.size(); i++) {
+            contents |= list.get(i).describeContents();
         }
         return contents;
     }
 
-    /**
-     * Write this to another Parcel. Note that this discards the internal Parcel
-     * and should not be used anymore. This is so we can pass this to a Binder
-     * where we won't have a chance to call recycle on this.
-     */
     @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        final int N = mList.size();
-        final int callFlags = flags;
-        dest.writeInt(N);
-        if (DEBUG) Log.d(TAG, "Writing " + N + " items");
-        if (N > 0) {
-            final Class<?> listElementClass = mList.get(0).getClass();
-            dest.writeParcelableCreator(mList.get(0));
-            int i = 0;
-            while (i < N && dest.dataSize() < MAX_IPC_SIZE) {
-                dest.writeInt(1);
+    protected void writeElement(T parcelable, Parcel dest, int callFlags) {
+        parcelable.writeToParcel(dest, callFlags);
+    }
 
-                final T parcelable = mList.get(i);
-                verifySameType(listElementClass, parcelable.getClass());
-                parcelable.writeToParcel(dest, callFlags);
+    @Override
+    protected void writeParcelableCreator(T parcelable, Parcel dest) {
+        dest.writeParcelableCreator((Parcelable) parcelable);
+    }
 
-                if (DEBUG) Log.d(TAG, "Wrote inline #" + i + ": " + mList.get(i));
-                i++;
-            }
-            if (i < N) {
-                dest.writeInt(0);
-                Binder retriever = new Binder() {
-                    @Override
-                    protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
-                            throws RemoteException {
-                        if (code != FIRST_CALL_TRANSACTION) {
-                            return super.onTransact(code, data, reply, flags);
-                        }
-                        int i = data.readInt();
-                        if (DEBUG) Log.d(TAG, "Writing more @" + i + " of " + N);
-                        while (i < N && reply.dataSize() < MAX_IPC_SIZE) {
-                            reply.writeInt(1);
-
-                            final T parcelable = mList.get(i);
-                            verifySameType(listElementClass, parcelable.getClass());
-                            parcelable.writeToParcel(reply, callFlags);
-
-                            if (DEBUG) Log.d(TAG, "Wrote extra #" + i + ": " + mList.get(i));
-                            i++;
-                        }
-                        if (i < N) {
-                            if (DEBUG) Log.d(TAG, "Breaking @" + i + " of " + N);
-                            reply.writeInt(0);
-                        }
-                        return true;
-                    }
-                };
-                if (DEBUG) Log.d(TAG, "Breaking @" + i + " of " + N + ": retriever=" + retriever);
-                dest.writeStrongBinder(retriever);
-            }
-        }
+    @Override
+    protected Parcelable.Creator<?> readParcelableCreator(Parcel from, ClassLoader loader) {
+        return from.readParcelableCreator(loader);
     }
 
     @SuppressWarnings("unchecked")
@@ -210,6 +80,7 @@
             return new ParceledListSlice(in, loader);
         }
 
+        @Override
         public ParceledListSlice[] newArray(int size) {
             return new ParceledListSlice[size];
         }
diff --git a/core/java/android/content/pm/ResolveInfo.java b/core/java/android/content/pm/ResolveInfo.java
index f8b4570..650b4c0 100644
--- a/core/java/android/content/pm/ResolveInfo.java
+++ b/core/java/android/content/pm/ResolveInfo.java
@@ -61,11 +61,17 @@
     public ProviderInfo providerInfo;
 
     /**
-     * The ephemeral application that corresponds to this resolution match. This will
-     * only be set in specific circumstances.
+     * An auxiliary response that may modify the resolved information. This is
+     * only set under certain circumstances; such as when resolving instant apps
+     * or components defined in un-installed splits.
      * @hide
      */
-    public EphemeralResponse ephemeralResponse;
+    public AuxiliaryResolveInfo auxiliaryInfo;
+
+    /**
+     * Whether or not an instant app is available for the resolved intent.
+     */
+    public boolean instantAppAvailable;
 
     /**
      * The IntentFilter that was matched for this ResolveInfo.
@@ -324,6 +330,7 @@
         system = orig.system;
         targetUserId = orig.targetUserId;
         handleAllWebDataURI = orig.handleAllWebDataURI;
+        instantAppAvailable = orig.instantAppAvailable;
     }
 
     public String toString() {
@@ -387,6 +394,7 @@
         dest.writeInt(noResourceId ? 1 : 0);
         dest.writeInt(iconResourceId);
         dest.writeInt(handleAllWebDataURI ? 1 : 0);
+        dest.writeInt(instantAppAvailable ? 1 : 0);
     }
 
     public static final Creator<ResolveInfo> CREATOR
@@ -434,6 +442,7 @@
         noResourceId = source.readInt() != 0;
         iconResourceId = source.readInt();
         handleAllWebDataURI = source.readInt() != 0;
+        instantAppAvailable = source.readInt() != 0;
     }
 
     public static class DisplayNameComparator
diff --git a/core/java/android/content/pm/SELinuxUtil.java b/core/java/android/content/pm/SELinuxUtil.java
index 55b5e29..025c0fe 100644
--- a/core/java/android/content/pm/SELinuxUtil.java
+++ b/core/java/android/content/pm/SELinuxUtil.java
@@ -32,11 +32,10 @@
 
     /** @hide */
     public static String assignSeinfoUser(PackageUserState userState) {
-        String seInfo = "";
-        if (userState.instantApp)
-            seInfo += INSTANT_APP_STR;
-        seInfo += COMPLETE_STR;
-        return seInfo;
+        if (userState.instantApp) {
+           return INSTANT_APP_STR + COMPLETE_STR;
+        }
+        return COMPLETE_STR;
     }
 
 }
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index f1f2683..5201694 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -21,8 +21,10 @@
 import android.annotation.UserIdInt;
 import android.app.TaskStackBuilder;
 import android.content.ComponentName;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.LauncherApps.ShortcutQuery;
 import android.content.res.Resources;
 import android.content.res.Resources.NotFoundException;
@@ -38,10 +40,12 @@
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.MemInfoReader;
 import com.android.internal.util.Preconditions;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
 
@@ -92,9 +96,17 @@
     public static final int FLAG_IMMUTABLE = 1 << 8;
 
     /** @hide */
-    public static final int FLAG_MASKABLE_BITMAP = 1 << 9;
+    public static final int FLAG_ADAPTIVE_BITMAP = 1 << 9;
 
     /** @hide */
+    public static final int FLAG_CHOOSER = 1 << 10;
+
+    /**
+     * TODO: Add FLAG_CHOOSER_INFO_OMITTED to reflect that chooser info was omitted in the Shortcut
+     *       due to the context in which it was retrieved.
+     * TODO: Add a FLAG_LAUNCHABLE to reflect whether or not the Shortcut has a launchable intent
+     * @hide
+     */
     @IntDef(flag = true,
             value = {
             FLAG_DYNAMIC,
@@ -106,7 +118,8 @@
             FLAG_DISABLED,
             FLAG_STRINGS_RESOLVED,
             FLAG_IMMUTABLE,
-            FLAG_MASKABLE_BITMAP,
+            FLAG_ADAPTIVE_BITMAP,
+            FLAG_CHOOSER,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ShortcutFlags {}
@@ -201,6 +214,24 @@
     @Nullable
     private PersistableBundle[] mIntentPersistableExtrases;
 
+    /**
+     * If used in a chooser, extras that should be added into the intent passed through.
+     */
+    @Nullable
+    private PersistableBundle mChooserExtras;
+
+    /**
+     * Intent filters to be used if the shortcut is to be used in a chooser context.
+     */
+    @Nullable
+    private IntentFilter[] mChooserIntentFilters;
+
+    /**
+     * Component names corresponding to the above intent filters.
+     */
+    @Nullable
+    private ComponentName[] mChooserComponentNames;
+
     private int mRank;
 
     /**
@@ -250,6 +281,13 @@
         mDisabledMessageResId = b.mDisabledMessageResId;
         mCategories = cloneCategories(b.mCategories);
         mIntents = cloneIntents(b.mIntents);
+        if (b.mChooserIntentFilters != null) {
+            mChooserIntentFilters = b.mChooserIntentFilters.toArray(new IntentFilter[0]);
+        }
+        if (b.mChooserComponentNames != null) {
+            mChooserComponentNames = b.mChooserComponentNames.toArray(new ComponentName[0]);
+        }
+        mChooserExtras = b.mChooserExtras;
         fixUpIntentExtras();
         mRank = b.mRank;
         mExtras = b.mExtras;
@@ -330,8 +368,28 @@
         if (mTitle == null && mTitleResId == 0) {
             throw new IllegalArgumentException("Short label must be provided");
         }
-        Preconditions.checkNotNull(mIntents, "Shortcut Intent must be provided");
-        Preconditions.checkArgument(mIntents.length > 0, "Shortcut Intent must be provided");
+
+        // For a shortcut to be valid, there should either be an Intent, or a non-empty set of
+        // intent filters.
+        if (mIntents == null || mIntents.length == 0) {
+            Preconditions.checkNotNull(mChooserIntentFilters,
+                    "Intent must be provided if not a chooser target");
+            Preconditions.checkNotNull(mChooserComponentNames,
+                    "Intent must be provided if not a chooser target");
+        }
+
+        // If ChooserIntentFilter are provided, they should match the length of the provided
+        // component names.
+        if (mChooserIntentFilters != null) {
+            if (mChooserComponentNames == null
+                    || mChooserIntentFilters.length != mChooserComponentNames.length) {
+                throw new IllegalArgumentException("Inconsistent intent filters and "
+                        + "component names given");
+            }
+            if (mChooserIntentFilters.length == 0 || mChooserComponentNames.length == 0) {
+                throw new IllegalArgumentException("Empty intent filter and component names given");
+            }
+        }
     }
 
     /**
@@ -376,6 +434,10 @@
                 mDisabledMessageResName = source.mDisabledMessageResName;
                 mIconResName = source.mIconResName;
             }
+            // TODO: Omit these by default and add a new clone flag.
+            mChooserIntentFilters = source.mChooserIntentFilters;
+            mChooserComponentNames = source.mChooserComponentNames;
+            mChooserExtras = source.mChooserExtras;
         } else {
             // Set this bit.
             mFlags |= FLAG_KEY_FIELDS_ONLY;
@@ -503,6 +565,25 @@
     }
 
     /**
+     * Whether the shortcut has any intentFilter matching the passed in one.
+     * @hide
+     */
+    @VisibleForTesting
+    public boolean hasMatchingFilter(ContentResolver resolver, Intent intent) {
+        if (mChooserIntentFilters == null) {
+            return false;
+        }
+        for (IntentFilter filter : mChooserIntentFilters) {
+            int match = filter.match(resolver, intent, false, TAG);
+            if (match > 0) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+
+    /**
      * Extract the entry name from a fully-donated resource name.
      * e.g. "com.android.app1:drawable/icon1" -> "icon1"
      * @hide
@@ -685,6 +766,15 @@
         if (source.mExtras != null) {
             mExtras = source.mExtras;
         }
+        if (source.mChooserExtras != null) {
+            mChooserExtras = source.mChooserExtras;
+        }
+        if (source.mChooserIntentFilters != null) {
+            mChooserIntentFilters = source.mChooserIntentFilters;
+        }
+        if (source.mChooserComponentNames != null) {
+            mChooserComponentNames = source.mChooserComponentNames;
+        }
     }
 
     /**
@@ -694,7 +784,7 @@
         switch (icon.getType()) {
             case Icon.TYPE_RESOURCE:
             case Icon.TYPE_BITMAP:
-            case Icon.TYPE_BITMAP_MASKABLE:
+            case Icon.TYPE_ADAPTIVE_BITMAP:
                 break; // OK
             default:
                 throw getInvalidIconException();
@@ -746,6 +836,12 @@
 
         private PersistableBundle mExtras;
 
+        private PersistableBundle mChooserExtras;
+
+        private List<IntentFilter> mChooserIntentFilters;
+
+        private List<ComponentName> mChooserComponentNames;
+
         /**
          * Old style constructor.
          * @hide
@@ -821,7 +917,7 @@
          * and will be ignored.
          *
          * <p>Only icons created with {@link Icon#createWithBitmap(Bitmap)},
-         * {@link Icon#createWithMaskableBitmap(Bitmap)}
+         * {@link Icon#createWithAdaptiveBitmap(Bitmap)}
          * and {@link Icon#createWithResource} are supported.
          * Other types, such as URI-based icons, are not supported.
          *
@@ -1032,6 +1128,40 @@
         }
 
         /**
+         * Extras that can be added which will be added to the Intent used to launch the app if
+         * launched from a chooser context.
+         */
+        @NonNull
+        public Builder setChooserExtras(@NonNull PersistableBundle extras) {
+            mChooserExtras = extras;
+            return this;
+        }
+
+        /**
+         * IntentFilters and the components that should resolve a match for a given chooser target.
+         * If multiple matches are found, the component corresponding to the closest match will be
+         * used.
+         *
+         * @param filter IntendFilter that if matched will have the intent forwarded to the given
+         *               component
+         * @param name The component that an intent that passes this filter will resolve to.
+         */
+        public Builder addChooserIntentFilter(@NonNull IntentFilter filter,
+                @NonNull ComponentName name) {
+            Preconditions.checkNotNull(filter, "intent filter cannot be null");
+            Preconditions.checkNotNull(name, "component name cannot be null");
+
+            if (mChooserIntentFilters == null || mChooserComponentNames == null) {
+                mChooserIntentFilters = new ArrayList<>();
+                mChooserComponentNames = new ArrayList<>();
+            }
+
+            mChooserIntentFilters.add(filter);
+            mChooserComponentNames.add(name);
+            return this;
+        }
+
+        /**
          * Creates a {@link ShortcutInfo} instance.
          */
         @NonNull
@@ -1232,6 +1362,30 @@
     }
 
     /**
+     * Retrieve the extras that will be added in to any intent launched through the chooser.
+     */
+    @NonNull
+    public PersistableBundle getChooserExtras() {
+        return mChooserExtras;
+    }
+
+    /**
+     * Retrieve the list of intent filters for chooser targets.
+     */
+    @NonNull
+    public IntentFilter[] getChooserIntentFilters() {
+        return mChooserIntentFilters;
+    }
+
+    /**
+     * Retrieve the list of component names corresponding to the above intent filters.
+     */
+    @NonNull
+    public ComponentName[] getChooserComponentNames() {
+        return mChooserComponentNames;
+    }
+
+    /**
      * "Rank" of a shortcut, which is a non-negative, sequential value that's unique for each
      * {@link #getActivity} for each of the two types of shortcuts (static and dynamic).
      *
@@ -1352,6 +1506,11 @@
         return hasFlags(FLAG_PINNED);
     }
 
+    /** Return whether a shortcut can be shown in the chooser. */
+    public boolean isChooser() {
+        return hasFlags(FLAG_CHOOSER);
+    }
+
     /**
      * Return whether a shortcut is static; that is, whether a shortcut is
      * published from AndroidManifest.xml.  If {@code true}, the shortcut is
@@ -1380,6 +1539,14 @@
         return isPinned() && !(isDynamic() || isManifestShortcut());
     }
 
+    /**
+     * @return true if pinned but neither static nor dynamic.
+     * @hide
+     */
+    public boolean isDynamicOrChooser() {
+        return hasFlags(FLAG_DYNAMIC) || hasFlags(FLAG_CHOOSER);
+    }
+
     /** @hide */
     public boolean isOriginallyFromManifest() {
         return hasFlags(FLAG_IMMUTABLE);
@@ -1448,12 +1615,13 @@
     }
 
     /**
-     * Return whether a shortcut's icon is maskable.
+     * Return whether a shortcut's icon is adaptive bitmap following design guideline
+     * defined in {@link AdaptiveIconDrawable}.
      *
      * @hide internal/unit tests only
      */
-    public boolean hasMaskableBitmap() {
-        return hasFlags(FLAG_MASKABLE_BITMAP);
+    public boolean hasAdaptiveBitmap() {
+        return hasFlags(FLAG_ADAPTIVE_BITMAP);
     }
 
     /**
@@ -1661,6 +1829,19 @@
                 mCategories.add(source.readString().intern());
             }
         }
+
+        // We put a placeholder empty array in to keep the parcelable order, but can do away with
+        // them at this point if they're empty.
+        mChooserComponentNames = source.readParcelableArray(cl, ComponentName.class);
+        if (mChooserComponentNames.length == 0) {
+            mChooserComponentNames = null;
+        }
+
+        mChooserIntentFilters = source.readParcelableArray(cl, IntentFilter.class);
+        if (mChooserIntentFilters.length == 0) {
+            mChooserIntentFilters = null;
+        }
+        mChooserExtras = source.readPersistableBundle(cl);
     }
 
     @Override
@@ -1707,6 +1888,17 @@
         } else {
             dest.writeInt(0);
         }
+        if (mChooserComponentNames != null) {
+            dest.writeParcelableArray(mChooserComponentNames, flags);
+        } else {
+            dest.writeParcelableArray(new ComponentName[0], flags);
+        }
+        if (mChooserIntentFilters != null) {
+            dest.writeParcelableArray(mChooserIntentFilters, flags);
+        } else {
+            dest.writeParcelableArray(new IntentFilter[0], flags);
+        }
+        dest.writePersistableBundle(mChooserExtras);
     }
 
     public static final Creator<ShortcutInfo> CREATOR =
diff --git a/core/java/android/content/pm/ShortcutServiceInternal.java b/core/java/android/content/pm/ShortcutServiceInternal.java
index 87a6d4a..3de19d1 100644
--- a/core/java/android/content/pm/ShortcutServiceInternal.java
+++ b/core/java/android/content/pm/ShortcutServiceInternal.java
@@ -24,6 +24,7 @@
 import android.content.Intent;
 import android.content.IntentSender;
 import android.content.pm.LauncherApps.ShortcutQuery;
+import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
 
 import java.util.List;
@@ -44,8 +45,8 @@
             getShortcuts(int launcherUserId,
             @NonNull String callingPackage, long changedSince,
             @Nullable String packageName, @Nullable List<String> shortcutIds,
-            @Nullable ComponentName componentName, @ShortcutQuery.QueryFlags int flags,
-            int userId);
+            @Nullable ComponentName componentName, @Nullable Intent intent,
+            @ShortcutQuery.QueryFlags int flags, int userId);
 
     public abstract boolean
             isPinnedByCaller(int launcherUserId, @NonNull String callingPackage,
@@ -72,8 +73,8 @@
             @NonNull String callingPackage);
 
     public abstract boolean requestPinAppWidget(@NonNull String callingPackage,
-            @NonNull AppWidgetProviderInfo appWidget, @Nullable IntentSender resultIntent,
-            int userId);
+            @NonNull AppWidgetProviderInfo appWidget, @Nullable Bundle extras,
+            @Nullable IntentSender resultIntent, int userId);
 
     public abstract boolean isRequestPinItemSupported(int callingUserId, int requestType);
 }
diff --git a/core/java/android/content/pm/ManifestDigest.aidl b/core/java/android/content/pm/StringParceledListSlice.aidl
similarity index 86%
rename from core/java/android/content/pm/ManifestDigest.aidl
rename to core/java/android/content/pm/StringParceledListSlice.aidl
index ebabab0..345f3a7 100644
--- a/core/java/android/content/pm/ManifestDigest.aidl
+++ b/core/java/android/content/pm/StringParceledListSlice.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright 2011, The Android Open Source Project
+ * 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.
@@ -16,4 +16,4 @@
 
 package android.content.pm;
 
-parcelable ManifestDigest;
+parcelable StringParceledListSlice;
diff --git a/core/java/android/content/pm/StringParceledListSlice.java b/core/java/android/content/pm/StringParceledListSlice.java
new file mode 100644
index 0000000..9540744
--- /dev/null
+++ b/core/java/android/content/pm/StringParceledListSlice.java
@@ -0,0 +1,83 @@
+/*
+ * 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 android.content.pm;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Transfer a large list of Parcelable objects across an IPC.  Splits into
+ * multiple transactions if needed.
+ *
+ * @see BaseParceledListSlice
+ *
+ * @hide
+ */
+public class StringParceledListSlice extends BaseParceledListSlice<String> {
+    public StringParceledListSlice(List<String> list) {
+        super(list);
+    }
+
+    private StringParceledListSlice(Parcel in, ClassLoader loader) {
+        super(in, loader);
+    }
+
+    public static StringParceledListSlice emptyList() {
+        return new StringParceledListSlice(Collections.<String> emptyList());
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    protected void writeElement(String parcelable, Parcel reply, int callFlags) {
+        reply.writeString(parcelable);
+    }
+
+    @Override
+    protected void writeParcelableCreator(String parcelable, Parcel dest) {
+        return;
+    }
+
+    @Override
+    protected Parcelable.Creator<?> readParcelableCreator(Parcel from, ClassLoader loader) {
+        return Parcel.STRING_CREATOR;
+    }
+
+    @SuppressWarnings("unchecked")
+    public static final Parcelable.ClassLoaderCreator<StringParceledListSlice> CREATOR =
+            new Parcelable.ClassLoaderCreator<StringParceledListSlice>() {
+        public StringParceledListSlice createFromParcel(Parcel in) {
+            return new StringParceledListSlice(in, null);
+        }
+
+        @Override
+        public StringParceledListSlice createFromParcel(Parcel in, ClassLoader loader) {
+            return new StringParceledListSlice(in, loader);
+        }
+
+        @Override
+        public StringParceledListSlice[] newArray(int size) {
+            return new StringParceledListSlice[size];
+        }
+    };
+}
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 37e32ff..af953e6 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -222,19 +222,21 @@
      */
     final boolean getResourceValue(@AnyRes int resId, int densityDpi, @NonNull TypedValue outValue,
             boolean resolveRefs) {
-        final int block = loadResourceValue(resId, (short) densityDpi, outValue, resolveRefs);
-        if (block < 0) {
-            return false;
-        }
+        synchronized (this) {
+            final int block = loadResourceValue(resId, (short) densityDpi, outValue, resolveRefs);
+            if (block < 0) {
+                return false;
+            }
 
-        // Convert the changing configurations flags populated by native code.
-        outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava(
-                outValue.changingConfigurations);
+            // Convert the changing configurations flags populated by native code.
+            outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava(
+                    outValue.changingConfigurations);
 
-        if (outValue.type == TypedValue.TYPE_STRING) {
-            outValue.string = mStringBlocks[block].get(outValue.data);
+            if (outValue.type == TypedValue.TYPE_STRING) {
+                outValue.string = mStringBlocks[block].get(outValue.data);
+            }
+            return true;
         }
-        return true;
     }
 
     /**
@@ -244,18 +246,20 @@
      * @param resId the resource id of the string array
      */
     final CharSequence[] getResourceTextArray(@ArrayRes int resId) {
-        final int[] rawInfoArray = getArrayStringInfo(resId);
-        final int rawInfoArrayLen = rawInfoArray.length;
-        final int infoArrayLen = rawInfoArrayLen / 2;
-        int block;
-        int index;
-        final CharSequence[] retArray = new CharSequence[infoArrayLen];
-        for (int i = 0, j = 0; i < rawInfoArrayLen; i = i + 2, j++) {
-            block = rawInfoArray[i];
-            index = rawInfoArray[i + 1];
-            retArray[j] = index >= 0 ? mStringBlocks[block].get(index) : null;
+        synchronized (this) {
+            final int[] rawInfoArray = getArrayStringInfo(resId);
+            final int rawInfoArrayLen = rawInfoArray.length;
+            final int infoArrayLen = rawInfoArrayLen / 2;
+            int block;
+            int index;
+            final CharSequence[] retArray = new CharSequence[infoArrayLen];
+            for (int i = 0, j = 0; i < rawInfoArrayLen; i = i + 2, j++) {
+                block = rawInfoArray[i];
+                index = rawInfoArray[i + 1];
+                retArray[j] = index >= 0 ? mStringBlocks[block].get(index) : null;
+            }
+            return retArray;
         }
-        return retArray;
     }
 
     /**
@@ -320,8 +324,10 @@
     }
 
     /*package*/ final CharSequence getPooledStringForCookie(int cookie, int id) {
-        // Cookies map to string blocks starting at 1.
-        return mStringBlocks[cookie - 1].get(id);
+        synchronized (this) {
+            // Cookies map to string blocks starting at 1.
+            return mStringBlocks[cookie - 1].get(id);
+        }
     }
 
     /**
@@ -770,7 +776,6 @@
      * applications.
      * {@hide}
      */
-    @FastNative
     public native final void setConfiguration(int mcc, int mnc, String locale,
             int orientation, int touchscreen, int density, int keyboard,
             int keyboardHidden, int navigation, int screenWidth, int screenHeight,
@@ -780,18 +785,13 @@
     /**
      * Retrieve the resource identifier for the given resource name.
      */
-    @FastNative
     /*package*/ native final int getResourceIdentifier(String type,
                                                        String name,
                                                        String defPackage);
 
-    @FastNative
     /*package*/ native final String getResourceName(int resid);
-    @FastNative
     /*package*/ native final String getResourcePackageName(int resid);
-    @FastNative
     /*package*/ native final String getResourceTypeName(int resid);
-    @FastNative
     /*package*/ native final String getResourceEntryName(int resid);
     
     private native final long openAsset(String fileName, int accessMode);
@@ -805,19 +805,15 @@
     private native final int readAssetChar(long asset);
     private native final int readAsset(long asset, byte[] b, int off, int len);
     private native final long seekAsset(long asset, long offset, int whence);
-    @FastNative
     private native final long getAssetLength(long asset);
-    @FastNative
     private native final long getAssetRemainingLength(long asset);
 
     /** Returns true if the resource was found, filling in mRetStringBlock and
      *  mRetData. */
-    @FastNative
     private native final int loadResourceValue(int ident, short density, TypedValue outValue,
             boolean resolve);
     /** Returns true if the resource was found, filling in mRetStringBlock and
      *  mRetData. */
-    @FastNative
     private native final int loadResourceBagValue(int ident, int bagEntryId, TypedValue outValue,
                                                boolean resolve);
     /*package*/ static final int STYLE_NUM_ENTRIES = 6;
@@ -830,24 +826,17 @@
     static final int STYLE_CHANGING_CONFIGURATIONS = 4;
 
     /*package*/ static final int STYLE_DENSITY = 5;
-    @FastNative
     /*package*/ native static final void applyStyle(long theme,
             int defStyleAttr, int defStyleRes, long xmlParser,
             int[] inAttrs, int length, long outValuesAddress, long outIndicesAddress);
-    @FastNative
     /*package*/ native static final boolean resolveAttrs(long theme,
             int defStyleAttr, int defStyleRes, int[] inValues,
             int[] inAttrs, int[] outValues, int[] outIndices);
-    @FastNative
     /*package*/ native final boolean retrieveAttributes(
             long xmlParser, int[] inAttrs, int[] outValues, int[] outIndices);
-    @FastNative
     /*package*/ native final int getArraySize(int resource);
-    @FastNative
     /*package*/ native final int retrieveArray(int resource, int[] outValues);
-    @FastNative
     private native final int getStringBlockCount();
-    @FastNative
     private native final long getNativeStringBlock(int block);
 
     /**
@@ -880,22 +869,17 @@
     /*package*/ native static final void applyThemeStyle(long theme, int styleRes, boolean force);
     /*package*/ native static final void copyTheme(long dest, long source);
     /*package*/ native static final void clearTheme(long theme);
-    @FastNative
     /*package*/ native static final int loadThemeAttributeValue(long theme, int ident,
                                                                 TypedValue outValue,
                                                                 boolean resolve);
     /*package*/ native static final void dumpTheme(long theme, int priority, String tag, String prefix);
-    @FastNative
     /*package*/ native static final @NativeConfig int getThemeChangingConfigurations(long theme);
 
     private native final long openXmlAssetNative(int cookie, String fileName);
 
     private native final String[] getArrayStringResource(int arrayRes);
-    @FastNative
     private native final int[] getArrayStringInfo(int arrayRes);
-    @FastNative
     /*package*/ native final int[] getArrayIntResource(int arrayRes);
-    @FastNative
     /*package*/ native final int[] getStyleAttributes(int themeRes);
 
     private native final void init(boolean isSystem);
diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java
index 273522a..a46db06 100644
--- a/core/java/android/content/res/ColorStateList.java
+++ b/core/java/android/content/res/ColorStateList.java
@@ -508,8 +508,8 @@
     }
 
     /**
-     * Indicates whether this color state list contains more than one state spec
-     * and will change color based on state.
+     * Indicates whether this color state list contains at least one state spec
+     * and the first spec is not empty (e.g. match-all).
      *
      * @return True if this color state list changes color based on state, false
      *         otherwise.
@@ -517,7 +517,7 @@
      */
     @Override
     public boolean isStateful() {
-        return mStateSpecs.length > 1;
+        return mStateSpecs.length >= 1 && mStateSpecs[0].length > 0;
     }
 
     /**
diff --git a/core/java/android/content/res/CompatResources.java b/core/java/android/content/res/CompatResources.java
new file mode 100644
index 0000000..829b6b7
--- /dev/null
+++ b/core/java/android/content/res/CompatResources.java
@@ -0,0 +1,69 @@
+/*
+ * 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 android.content.res;
+
+import android.annotation.ColorRes;
+import android.annotation.DrawableRes;
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * Version of resources generated for apps targeting <26.
+ * @hide
+ */
+public class CompatResources extends Resources {
+
+    private WeakReference<Context> mContext;
+
+    public CompatResources(ClassLoader cls) {
+        super(cls);
+        mContext = new WeakReference<>(null);
+    }
+
+    /**
+     * @hide
+     */
+    public void setContext(Context context) {
+        mContext = new WeakReference<>(context);
+    }
+
+    @Override
+    public Drawable getDrawable(@DrawableRes int id) throws NotFoundException {
+        return getDrawable(id, getTheme());
+    }
+
+    @Override
+    public Drawable getDrawableForDensity(@DrawableRes int id, int density)
+            throws NotFoundException {
+        return getDrawableForDensity(id, density, getTheme());
+    }
+
+    @Override
+    public int getColor(@ColorRes int id) throws NotFoundException {
+        return getColor(id, getTheme());
+    }
+
+    @Override
+    public ColorStateList getColorStateList(@ColorRes int id) throws NotFoundException {
+        return getColorStateList(id, getTheme());
+    }
+
+    private Theme getTheme() {
+        Context c = mContext.get();
+        return c != null ? c.getTheme() : null;
+    }
+}
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index da35ee9..781e235 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -21,6 +21,8 @@
 import android.graphics.PointF;
 import android.graphics.Rect;
 import android.graphics.Region;
+import android.os.Build;
+import android.os.Build.VERSION_CODES;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.DisplayMetrics;
@@ -78,6 +80,11 @@
     private static final int NEEDS_SCREEN_COMPAT = 8;
 
     /**
+     * Set if the application needs to run in with compat resources.
+     */
+    private static final int NEEDS_COMPAT_RES = 16;
+
+    /**
      * The effective screen density we have selected for this application.
      */
     public final int applicationDensity;
@@ -96,6 +103,9 @@
             boolean forceCompat) {
         int compatFlags = 0;
 
+        if (appInfo.targetSdkVersion < VERSION_CODES.O) {
+            compatFlags |= NEEDS_COMPAT_RES;
+        }
         if (appInfo.requiresSmallestWidthDp != 0 || appInfo.compatibleWidthLimitDp != 0
                 || appInfo.largestWidthLimitDp != 0) {
             // New style screen requirements spec.
@@ -274,6 +284,10 @@
         return (mCompatibilityFlags&NEVER_NEEDS_COMPAT) != 0;
     }
 
+    public boolean needsCompatResources() {
+        return (mCompatibilityFlags&NEEDS_COMPAT_RES) != 0;
+    }
+
     /**
      * Returns the translator which translates the coordinates in compatibility mode.
      * @param params the window's parameter
diff --git a/core/java/android/content/res/FontResourcesParser.java b/core/java/android/content/res/FontResourcesParser.java
index 3f8f90e..50fc344 100644
--- a/core/java/android/content/res/FontResourcesParser.java
+++ b/core/java/android/content/res/FontResourcesParser.java
@@ -67,13 +67,14 @@
         AttributeSet attrs = Xml.asAttributeSet(parser);
         TypedArray array = resources.obtainAttributes(attrs, R.styleable.FontFamily);
         String authority = array.getString(R.styleable.FontFamily_fontProviderAuthority);
+        String providerPackage = array.getString(R.styleable.FontFamily_fontProviderPackage);
         String query = array.getString(R.styleable.FontFamily_fontProviderQuery);
         array.recycle();
-        if (authority != null && query != null) {
+        if (authority != null && providerPackage != null && query != null) {
             while (parser.next() != XmlPullParser.END_TAG) {
                 skip(parser);
             }
-            return new FontConfig.Family(authority, query);
+            return new FontConfig.Family(authority, providerPackage, query);
         }
         List<FontConfig.Font> fonts = new ArrayList<>();
         while (parser.next() != XmlPullParser.END_TAG) {
diff --git a/core/java/android/hardware/SensorDirectChannel.java b/core/java/android/hardware/SensorDirectChannel.java
index 0efd62b..a65d57d 100644
--- a/core/java/android/hardware/SensorDirectChannel.java
+++ b/core/java/android/hardware/SensorDirectChannel.java
@@ -135,8 +135,8 @@
     }
 
     /**
-     * This function encode handle information in {@link android.os.Memory} into a long array to be
-     * passed down to native methods.
+     * This function encode handle information in {@link android.os.MemoryFile} into a long array to
+     * be passed down to native methods.
      *
      * @hide */
     static long[] encodeData(MemoryFile ashmem) {
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index cfda2f4..a6930b0 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -895,7 +895,7 @@
      * @see #configureDirectChannel(SensorDirectChannel, Sensor, int)
      */
     public SensorDirectChannel createDirectChannel(MemoryFile mem) {
-        return createDirectChannelImpl(mem.length(), mem, null);
+        return createDirectChannelImpl(mem, null);
     }
 
     /**
@@ -913,12 +913,12 @@
      * @see #configureDirectChannel(SensorDirectChannel, Sensor, int)
      */
     public SensorDirectChannel createDirectChannel(HardwareBuffer mem) {
-        return null;
+        return createDirectChannelImpl(null, mem);
     }
 
     /** @hide */
-    protected abstract SensorDirectChannel createDirectChannelImpl(long size,
-            MemoryFile ashmemFile, HardwareBuffer hardwareBuffer);
+    protected abstract SensorDirectChannel createDirectChannelImpl(
+            MemoryFile memoryFile, HardwareBuffer hardwareBuffer);
 
     /** @hide */
     void destroyDirectChannel(SensorDirectChannel channel) {
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index 4992def..7029847 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -34,6 +34,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 
+import java.io.IOException;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -50,6 +51,7 @@
 public class SystemSensorManager extends SensorManager {
     //TODO: disable extra logging before release
     private static boolean DEBUG_DYNAMIC_SENSOR = true;
+    private static int MIN_DIRECT_CHANNEL_BUFFER_SIZE = 104;
 
     private static native void nativeClassInit();
     private static native long nativeCreate(String opPackageName);
@@ -59,7 +61,7 @@
     private static native boolean nativeIsDataInjectionEnabled(long nativeInstance);
 
     private static native int nativeCreateDirectChannel(
-            long nativeInstance, long size, int channelType, long [] channelData);
+            long nativeInstance, long size, int channelType, int fd, HardwareBuffer buffer);
     private static native void nativeDestroyDirectChannel(
             long nativeInstance, int channelHandle);
     private static native int nativeConfigDirectChannel(
@@ -525,24 +527,54 @@
     }
 
     /** @hide */
-    protected SensorDirectChannel createDirectChannelImpl(long size,
-            MemoryFile ashmemFile, HardwareBuffer grallocMemObject) {
+    protected SensorDirectChannel createDirectChannelImpl(
+            MemoryFile memoryFile, HardwareBuffer hardwareBuffer) {
         SensorDirectChannel ch = null;
-
-        if (size <= 0) throw new IllegalArgumentException("size has to be greater than 0");
-
-        if (ashmemFile != null) {
-            if (size != ashmemFile.length()) {
-                throw new IllegalArgumentException("size has to match MemoryFile.length()");
+        long size;
+        if (memoryFile != null) {
+            int fd;
+            try {
+                fd = memoryFile.getFileDescriptor().getInt$();
+            } catch (IOException e) {
+                throw new IllegalArgumentException("MemoryFile object is not valid");
             }
+
+            if (memoryFile.length() < MIN_DIRECT_CHANNEL_BUFFER_SIZE) {
+                throw new IllegalArgumentException(
+                        "Size of MemoryFile has to be greater than "
+                        + MIN_DIRECT_CHANNEL_BUFFER_SIZE);
+            }
+
+            size = memoryFile.length();
             int id = nativeCreateDirectChannel(
-                    mNativeInstance, size, SensorDirectChannel.TYPE_ASHMEM,
-                    SensorDirectChannel.encodeData(ashmemFile));
+                    mNativeInstance, size, SensorDirectChannel.TYPE_ASHMEM, fd, null);
             if (id > 0) {
                 ch = new SensorDirectChannel(this, id, SensorDirectChannel.TYPE_ASHMEM, size);
             }
-        } else if (grallocMemObject != null) {
-            Log.wtf(TAG, "Implement GRALLOC or remove GRALLOC support entirely");
+        } else if (hardwareBuffer != null) {
+            if (hardwareBuffer.getFormat() != HardwareBuffer.BLOB) {
+                throw new IllegalArgumentException("Format of HardwareBuffer must be BLOB");
+            }
+            if (hardwareBuffer.getHeight() != 1) {
+                throw new IllegalArgumentException("Height of HardwareBuffer must be 1");
+            }
+            if (hardwareBuffer.getWidth() < MIN_DIRECT_CHANNEL_BUFFER_SIZE) {
+                throw new IllegalArgumentException(
+                        "Width if HaradwareBuffer must be greater than "
+                        + MIN_DIRECT_CHANNEL_BUFFER_SIZE);
+            }
+            if ((hardwareBuffer.getUsage() & HardwareBuffer.USAGE0_SENSOR_DIRECT_DATA) == 0) {
+                throw new IllegalArgumentException(
+                        "HardwareBuffer must set usage flag USAGE0_SENSOR_DIRECT_DATA");
+            }
+            size = hardwareBuffer.getWidth();
+            int id = nativeCreateDirectChannel(
+                    mNativeInstance, size, SensorDirectChannel.TYPE_HARDWARE_BUFFER,
+                    -1, hardwareBuffer);
+            if (id > 0) {
+                ch = new SensorDirectChannel(
+                        this, id, SensorDirectChannel.TYPE_HARDWARE_BUFFER, size);
+            }
         } else {
             throw new IllegalArgumentException("Invalid parameter");
         }
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 45cd084..7bfb5d0 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -19,6 +19,10 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.IntDef;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import static android.hardware.camera2.ICameraDeviceUser.NORMAL_MODE;
+import static android.hardware.camera2.ICameraDeviceUser.CONSTRAINED_HIGH_SPEED_MODE;
 import android.hardware.camera2.params.InputConfiguration;
 import android.hardware.camera2.params.StreamConfigurationMap;
 import android.hardware.camera2.params.OutputConfiguration;
@@ -719,6 +723,84 @@
             throws CameraAccessException;
 
     /**
+     * Standard camera operation mode.
+     *
+     * @see #createCustomCaptureSession
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    public static final int SESSION_OPERATION_MODE_NORMAL =
+            0; // ICameraDeviceUser.NORMAL_MODE;
+
+    /**
+     * Constrained high-speed operation mode.
+     *
+     * @see #createCustomCaptureSession
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    public static final int SESSION_OPERATION_MODE_CONSTRAINED_HIGH_SPEED =
+            1; // ICameraDeviceUser.CONSTRAINED_HIGH_SPEED_MODE;
+
+    /**
+     * First vendor-specific operating mode
+     *
+     * @see #createCustomCaptureSession
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    public static final int SESSION_OPERATION_MODE_VENDOR_START =
+            0x8000; // ICameraDeviceUser.VENDOR_MODE_START;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(
+            {SESSION_OPERATION_MODE_NORMAL,
+             SESSION_OPERATION_MODE_CONSTRAINED_HIGH_SPEED,
+             SESSION_OPERATION_MODE_VENDOR_START})
+    public @interface SessionOperatingMode {};
+
+    /**
+     * Create a new camera capture session with a custom operating mode.
+     *
+     * @param inputConfig The configuration for the input {@link Surface} if a reprocessing session
+     *                is desired, or {@code null} otherwise.
+     * @param outputs The new set of {@link OutputConfiguration OutputConfigurations} that should be
+     *                made available as targets for captured image data.
+     * @param operatingMode The custom operating mode to use; a nonnegative value, either a custom
+     *                vendor value or one of the SESSION_OPERATION_MODE_* values.
+     * @param callback The callback to notify about the status of the new capture session.
+     * @param handler The handler on which the callback should be invoked, or {@code null} to use
+     *                the current thread's {@link android.os.Looper looper}.
+     *
+     * @throws IllegalArgumentException if the input configuration is null or not supported, the set
+     *                                  of output Surfaces do not meet the requirements, the
+     *                                  callback is null, or the handler is null but the current
+     *                                  thread has no looper.
+     * @throws CameraAccessException if the camera device is no longer connected or has
+     *                               encountered a fatal error
+     * @throws IllegalStateException if the camera device has been closed
+     *
+     * @see #createCaptureSession
+     * @see #createReprocessableCaptureSession
+     * @see CameraCaptureSession
+     * @see OutputConfiguration
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    public abstract void createCustomCaptureSession(
+            InputConfiguration inputConfig,
+            @NonNull List<OutputConfiguration> outputs,
+            @SessionOperatingMode int operatingMode,
+            @NonNull CameraCaptureSession.StateCallback callback,
+            @Nullable Handler handler)
+            throws CameraAccessException;
+
+    /**
      * <p>Create a {@link CaptureRequest.Builder} for new capture requests,
      * initialized with template for a target use case. The settings are chosen
      * to be the best options for the specific camera device, so it is not
diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
index 891df63..16ffee0 100644
--- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
@@ -19,6 +19,7 @@
 import android.hardware.camera2.CameraCaptureSession;
 import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.ICameraDeviceUser;
 import android.hardware.camera2.dispatch.ArgumentReplacingDispatcher;
 import android.hardware.camera2.dispatch.BroadcastDispatcher;
 import android.hardware.camera2.dispatch.DuckTypingDispatcher;
@@ -742,7 +743,7 @@
                     try {
                         // begin transition to unconfigured
                         mDeviceImpl.configureStreamsChecked(/*inputConfig*/null, /*outputs*/null,
-                                /*isConstrainedHighSpeed*/false);
+                                /*operatingMode*/ ICameraDeviceUser.NORMAL_MODE);
                     } catch (CameraAccessException e) {
                         // OK: do not throw checked exceptions.
                         Log.e(TAG, mIdString + "Exception while unconfiguring outputs: ", e);
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index 2364ebe..8bc65af 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -356,7 +356,7 @@
             outputConfigs.add(new OutputConfiguration(s));
         }
         configureStreamsChecked(/*inputConfig*/null, outputConfigs,
-                /*isConstrainedHighSpeed*/false);
+                /*operatingMode*/ICameraDeviceUser.NORMAL_MODE);
 
     }
 
@@ -374,13 +374,14 @@
      *
      * @param inputConfig input configuration or {@code null} for no input
      * @param outputs a list of one or more surfaces, or {@code null} to unconfigure
-     * @param isConstrainedHighSpeed If the streams configuration is for constrained high speed output.
+     * @param operatingMode If the stream configuration is for a normal session,
+     *     a constrained high speed session, or something else.
      * @return whether or not the configuration was successful
      *
      * @throws CameraAccessException if there were any unexpected problems during configuration
      */
     public boolean configureStreamsChecked(InputConfiguration inputConfig,
-            List<OutputConfiguration> outputs, boolean isConstrainedHighSpeed)
+            List<OutputConfiguration> outputs, int operatingMode)
                     throws CameraAccessException {
         // Treat a null input the same an empty list
         if (outputs == null) {
@@ -456,7 +457,7 @@
                     }
                 }
 
-                mRemoteDevice.endConfigure(isConstrainedHighSpeed);
+                mRemoteDevice.endConfigure(operatingMode);
 
                 success = true;
             } catch (IllegalArgumentException e) {
@@ -492,7 +493,7 @@
             outConfigurations.add(new OutputConfiguration(surface));
         }
         createCaptureSessionInternal(null, outConfigurations, callback, handler,
-                /*isConstrainedHighSpeed*/false);
+                /*operatingMode*/ICameraDeviceUser.NORMAL_MODE);
     }
 
     @Override
@@ -508,7 +509,7 @@
         List<OutputConfiguration> currentOutputs = new ArrayList<>(outputConfigurations);
 
         createCaptureSessionInternal(null, currentOutputs, callback, handler,
-                /*isConstrainedHighSpeed*/false);
+                /*operatingMode*/ICameraDeviceUser.NORMAL_MODE);
     }
 
     @Override
@@ -528,7 +529,7 @@
             outConfigurations.add(new OutputConfiguration(surface));
         }
         createCaptureSessionInternal(inputConfig, outConfigurations, callback, handler,
-                /*isConstrainedHighSpeed*/false);
+                /*operatingMode*/ICameraDeviceUser.NORMAL_MODE);
     }
 
     @Override
@@ -556,7 +557,7 @@
             currentOutputs.add(new OutputConfiguration(output));
         }
         createCaptureSessionInternal(inputConfig, currentOutputs,
-                callback, handler, /*isConstrainedHighSpeed*/false);
+                callback, handler, /*operatingMode*/ICameraDeviceUser.NORMAL_MODE);
     }
 
     @Override
@@ -576,13 +577,26 @@
             outConfigurations.add(new OutputConfiguration(surface));
         }
         createCaptureSessionInternal(null, outConfigurations, callback, handler,
-                /*isConstrainedHighSpeed*/true);
+                /*operatingMode*/ICameraDeviceUser.CONSTRAINED_HIGH_SPEED_MODE);
+    }
+
+    @Override
+    public void createCustomCaptureSession(InputConfiguration inputConfig,
+            List<OutputConfiguration> outputs,
+            int operatingMode,
+            android.hardware.camera2.CameraCaptureSession.StateCallback callback,
+            Handler handler) throws CameraAccessException {
+        List<OutputConfiguration> currentOutputs = new ArrayList<OutputConfiguration>();
+        for (OutputConfiguration output : outputs) {
+            currentOutputs.add(new OutputConfiguration(output));
+        }
+        createCaptureSessionInternal(inputConfig, currentOutputs, callback, handler, operatingMode);
     }
 
     private void createCaptureSessionInternal(InputConfiguration inputConfig,
             List<OutputConfiguration> outputConfigurations,
             CameraCaptureSession.StateCallback callback, Handler handler,
-            boolean isConstrainedHighSpeed) throws CameraAccessException {
+            int operatingMode) throws CameraAccessException {
         synchronized(mInterfaceLock) {
             if (DEBUG) {
                 Log.d(TAG, "createCaptureSessionInternal");
@@ -590,6 +604,8 @@
 
             checkIfCameraClosedOrInError();
 
+            boolean isConstrainedHighSpeed =
+                    (operatingMode == ICameraDeviceUser.CONSTRAINED_HIGH_SPEED_MODE);
             if (isConstrainedHighSpeed && inputConfig != null) {
                 throw new IllegalArgumentException("Constrained high speed session doesn't support"
                         + " input configuration yet.");
@@ -608,7 +624,7 @@
             try {
                 // configure streams and then block until IDLE
                 configureSuccess = configureStreamsChecked(inputConfig, outputConfigurations,
-                        isConstrainedHighSpeed);
+                        operatingMode);
                 if (configureSuccess == true && inputConfig != null) {
                     input = mRemoteDevice.getInputSurface();
                 }
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index 0e450d7..4d92ab1 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -1097,7 +1097,6 @@
             throws IllegalArgumentException;
     private static native int nativeGetTypeFromTag(int tag)
             throws IllegalArgumentException;
-    private static native void nativeClassInit();
 
     /**
      * <p>Perform a 0-copy swap of the internal metadata with another object.</p>
@@ -1289,10 +1288,6 @@
     }
 
     static {
-        /*
-         * We use a class initializer to allow the native code to cache some field offsets
-         */
-        nativeClassInit();
         registerAllMarshalers();
     }
 }
diff --git a/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java b/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
index d9f666e..27087a2 100644
--- a/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
+++ b/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
@@ -106,9 +106,9 @@
         }
     }
 
-    public void endConfigure(boolean isConstrainedHighSpeed) throws CameraAccessException {
+    public void endConfigure(int operatingMode) throws CameraAccessException {
         try {
-            mRemoteDevice.endConfigure(isConstrainedHighSpeed);
+            mRemoteDevice.endConfigure(operatingMode);
         } catch (Throwable t) {
             CameraManager.throwAsPublicException(t);
             throw new UnsupportedOperationException("Unexpected exception", t);
diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
index d8ec4df..f87d8c1 100644
--- a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
+++ b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
@@ -497,7 +497,7 @@
     }
 
     @Override
-    public void endConfigure(boolean isConstrainedHighSpeed) {
+    public void endConfigure(int operatingMode) {
         if (DEBUG) {
             Log.d(TAG, "endConfigure called.");
         }
@@ -507,6 +507,12 @@
             throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
         }
 
+        if (operatingMode != ICameraDeviceUser.NORMAL_MODE) {
+            String err = "LEGACY devices do not support this operating mode";
+            Log.e(TAG, err);
+            throw new ServiceSpecificException(ICameraService.ERROR_ILLEGAL_ARGUMENT, err);
+        }
+
         SparseArray<Surface> surfaces = null;
         synchronized(mConfigureLock) {
             if (!mConfiguring) {
diff --git a/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableString.java b/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableString.java
index d2c3908..c81e18d 100644
--- a/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableString.java
+++ b/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableString.java
@@ -33,7 +33,9 @@
     private static final String TAG = MarshalQueryableString.class.getSimpleName();
     private static final boolean DEBUG = false;
 
-    private static final Charset UTF8_CHARSET = Charset.forName("UTF-8");
+    private static class PreloadHolder {
+        public static final Charset UTF8_CHARSET = Charset.forName("UTF-8");
+    }
     private static final byte NUL = (byte)'\0'; // used as string terminator
 
     private class MarshalerString extends Marshaler<String> {
@@ -44,7 +46,7 @@
 
         @Override
         public void marshal(String value, ByteBuffer buffer) {
-            byte[] arr = value.getBytes(UTF8_CHARSET);
+            byte[] arr = value.getBytes(PreloadHolder.UTF8_CHARSET);
 
             buffer.put(arr);
             buffer.put(NUL); // metadata strings are NUL-terminated
@@ -52,7 +54,7 @@
 
         @Override
         public int calculateMarshalSize(String value) {
-            byte[] arr = value.getBytes(UTF8_CHARSET);
+            byte[] arr = value.getBytes(PreloadHolder.UTF8_CHARSET);
 
             return arr.length + 1; // metadata strings are NUL-terminated
         }
@@ -88,7 +90,7 @@
             buffer.get(strBytes, /*dstOffset*/0, stringLength + 1); // including null character
 
             // not including null character
-            return new String(strBytes, /*offset*/0, stringLength, UTF8_CHARSET);
+            return new String(strBytes, /*offset*/0, stringLength, PreloadHolder.UTF8_CHARSET);
         }
 
         @Override
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 33a9f5e..a529c2f 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -339,8 +339,7 @@
     private Display getOrCreateDisplayLocked(int displayId, boolean assumeValid) {
         Display display = mDisplays.get(displayId);
         if (display == null) {
-            display = mGlobal.getCompatibleDisplay(displayId,
-                    mContext.getDisplayAdjustments(displayId));
+            display = mGlobal.getCompatibleDisplay(displayId, mContext.getResources());
             if (display != null) {
                 mDisplays.put(displayId, display);
             }
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index 826eb74..341754c 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.hardware.display.DisplayManager.DisplayListener;
 import android.media.projection.MediaProjection;
 import android.media.projection.IMediaProjection;
@@ -181,6 +182,24 @@
     }
 
     /**
+     * Gets information about a logical display.
+     *
+     * The display metrics may be adjusted to provide compatibility
+     * for legacy applications or limited screen areas.
+     *
+     * @param displayId The logical display id.
+     * @param resources Resources providing compatibility info.
+     * @return The display object, or null if there is no display with the given id.
+     */
+    public Display getCompatibleDisplay(int displayId, Resources resources) {
+        DisplayInfo displayInfo = getDisplayInfo(displayId);
+        if (displayInfo == null) {
+            return null;
+        }
+        return new Display(this, displayId, displayInfo, resources);
+    }
+
+    /**
      * Gets information about a logical display without applying any compatibility metrics.
      *
      * @param displayId The logical display id.
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 98a5749..b276008 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -213,6 +213,10 @@
         // If true, scales the brightness to half of desired.
         public boolean lowPowerMode;
 
+        // The factor to adjust the screen brightness in low power mode in the range
+        // 0 (screen off) to 1 (no change)
+        public float screenLowPowerBrightnessFactor;
+
         // If true, applies a brightness boost.
         public boolean boostScreenBrightness;
 
@@ -235,6 +239,7 @@
             useProximitySensor = false;
             screenBrightness = PowerManager.BRIGHTNESS_ON;
             screenAutoBrightnessAdjustment = 0.0f;
+            screenLowPowerBrightnessFactor = 0.5f;
             useAutoBrightness = false;
             blockScreenOn = false;
             dozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
@@ -258,6 +263,7 @@
             useProximitySensor = other.useProximitySensor;
             screenBrightness = other.screenBrightness;
             screenAutoBrightnessAdjustment = other.screenAutoBrightnessAdjustment;
+            screenLowPowerBrightnessFactor = other.screenLowPowerBrightnessFactor;
             brightnessSetByUser = other.brightnessSetByUser;
             useAutoBrightness = other.useAutoBrightness;
             blockScreenOn = other.blockScreenOn;
@@ -279,6 +285,8 @@
                     && useProximitySensor == other.useProximitySensor
                     && screenBrightness == other.screenBrightness
                     && screenAutoBrightnessAdjustment == other.screenAutoBrightnessAdjustment
+                    && screenLowPowerBrightnessFactor
+                    == other.screenLowPowerBrightnessFactor
                     && brightnessSetByUser == other.brightnessSetByUser
                     && useAutoBrightness == other.useAutoBrightness
                     && blockScreenOn == other.blockScreenOn
@@ -299,6 +307,7 @@
                     + ", useProximitySensor=" + useProximitySensor
                     + ", screenBrightness=" + screenBrightness
                     + ", screenAutoBrightnessAdjustment=" + screenAutoBrightnessAdjustment
+                    + ", screenLowPowerBrightnessFactor=" + screenLowPowerBrightnessFactor
                     + ", brightnessSetByUser=" + brightnessSetByUser
                     + ", useAutoBrightness=" + useAutoBrightness
                     + ", blockScreenOn=" + blockScreenOn
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index ff87b67..27e2a50 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -338,6 +338,20 @@
     }
 
     /**
+     * Controls standby mode of the system. It will also try to turn on/off the connected devices if
+     * necessary.
+     *
+     * @param isStandbyModeOn target status of the system's standby mode
+     */
+    public void setStandbyMode(boolean isStandbyModeOn) {
+        try {
+            mService.setStandbyMode(isStandbyModeOn);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Listener used to get hotplug event from HDMI port.
      */
     public interface HotplugEventListener {
diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
index c1e924e..67e2d18 100644
--- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
@@ -71,4 +71,5 @@
     void clearTimerRecording(int recorderAddress, int sourceType, in byte[] recordSource);
     void sendMhlVendorCommand(int portId, int offset, int length, in byte[] data);
     void addHdmiMhlVendorCommandListener(IHdmiMhlVendorCommandListener listener);
+    void setStandbyMode(boolean isStandbyModeOn);
 }
diff --git a/core/java/android/hardware/location/NanoApp.java b/core/java/android/hardware/location/NanoApp.java
index 03ac4a2..d5d428e 100644
--- a/core/java/android/hardware/location/NanoApp.java
+++ b/core/java/android/hardware/location/NanoApp.java
@@ -39,7 +39,7 @@
     private String mPublisher;
     private String mName;
 
-    private int mAppId;
+    private long mAppId;
     private boolean mAppIdSet;
     private int mAppVersion;
 
@@ -53,7 +53,7 @@
 
     /**
      * If this version of the constructor is used, the methods
-     * {@link #setAppBinary(byte[])} and {@link #setAppId(int)} must be called
+     * {@link #setAppBinary(byte[])} and {@link #setAppId(long)} must be called
      * prior to passing this object to any managers.
      *
      * @see #NanoApp(int, byte[])
@@ -77,8 +77,29 @@
      * @see #setNeededExecMemBytes(int)
      * @see #setNeededSensors(int[])
      * @see #setOutputEvents(int[])
+     *
+     * @deprecated Use NanoApp(long, byte[]) instead
      */
-    public NanoApp(int appId, byte[] appBinary) {
+    @Deprecated public NanoApp(int appId, byte[] appBinary) {
+        Log.w(TAG, "NanoApp(int, byte[]) is deprecated, please use NanoApp(long, byte[]) instead.");
+    }
+
+    /**
+     * Initialize a NanoApp with the given id and binary.
+     *
+     * While this sets defaults for other fields, users will want to provide
+     * other values for those fields in most cases.
+     *
+     * @see #setPublisher(String)
+     * @see #setName(String)
+     * @see #setAppVersion(int)
+     * @see #setNeededReadMemBytes(int)
+     * @see #setNeededWriteMemBytes(int)
+     * @see #setNeededExecMemBytes(int)
+     * @see #setNeededSensors(int[])
+     * @see #setOutputEvents(int[])
+     */
+    public NanoApp(long appId, byte[] appBinary) {
         mPublisher = UNKNOWN;
         mName = UNKNOWN;
 
@@ -116,9 +137,9 @@
     /**
      * set the app identifier
      *
-     * @param appId  add identifier
+     * @param appId  app identifier
      */
-    public void setAppId(int appId) {
+    public void setAppId(long appId) {
         mAppId = appId;
         mAppIdSet = true;
     }
@@ -209,7 +230,7 @@
      *
      * @return identifier for this app
      */
-    public int getAppId() {
+    public long getAppId() {
         return mAppId;
     }
 
@@ -280,7 +301,7 @@
         mPublisher = in.readString();
         mName = in.readString();
 
-        mAppId = in.readInt();
+        mAppId = in.readLong();
         mAppVersion = in.readInt();
         mNeededReadMemBytes = in.readInt();
         mNeededWriteMemBytes = in.readInt();
@@ -313,7 +334,7 @@
 
         out.writeString(mPublisher);
         out.writeString(mName);
-        out.writeInt(mAppId);
+        out.writeLong(mAppId);
         out.writeInt(mAppVersion);
         out.writeInt(mNeededReadMemBytes);
         out.writeInt(mNeededWriteMemBytes);
diff --git a/core/java/android/inputmethodservice/KeyboardView.java b/core/java/android/inputmethodservice/KeyboardView.java
index d1000ad..13b9206 100644
--- a/core/java/android/inputmethodservice/KeyboardView.java
+++ b/core/java/android/inputmethodservice/KeyboardView.java
@@ -988,49 +988,31 @@
         if (mAccessibilityManager.isEnabled()) {
             AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
             onInitializeAccessibilityEvent(event);
-            String text = null;
-            // This is very efficient since the properties are cached.
-            final boolean speakPassword = Settings.Secure.getIntForUser(
-                    mContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD, 0,
-                    UserHandle.USER_CURRENT_OR_SELF) != 0;
-            // Add text only if password announcement is enabled or if headset is
-            // used to avoid leaking passwords.
-            if (speakPassword || mAudioManager.isBluetoothA2dpOn()
-                    || mAudioManager.isWiredHeadsetOn()) {
-                switch (code) {
-                    case Keyboard.KEYCODE_ALT:
-                        text = mContext.getString(R.string.keyboardview_keycode_alt);
-                        break;
-                    case Keyboard.KEYCODE_CANCEL:
-                        text = mContext.getString(R.string.keyboardview_keycode_cancel);
-                        break;
-                    case Keyboard.KEYCODE_DELETE:
-                        text = mContext.getString(R.string.keyboardview_keycode_delete);
-                        break;
-                    case Keyboard.KEYCODE_DONE:
-                        text = mContext.getString(R.string.keyboardview_keycode_done);
-                        break;
-                    case Keyboard.KEYCODE_MODE_CHANGE:
-                        text = mContext.getString(R.string.keyboardview_keycode_mode_change);
-                        break;
-                    case Keyboard.KEYCODE_SHIFT:
-                        text = mContext.getString(R.string.keyboardview_keycode_shift);
-                        break;
-                    case '\n':
-                        text = mContext.getString(R.string.keyboardview_keycode_enter);
-                        break;
-                    default:
-                        text = String.valueOf((char) code);
-                }
-            } else if (!mHeadsetRequiredToHearPasswordsAnnounced) {
-                // We want the waring for required head set to be send with both the
-                // hover enter and hover exit event, so set the flag after the exit.
-                if (eventType == AccessibilityEvent.TYPE_VIEW_HOVER_EXIT) {
-                    mHeadsetRequiredToHearPasswordsAnnounced = true;
-                }
-                text = mContext.getString(R.string.keyboard_headset_required_to_hear_password);
-            } else {
-                text = mContext.getString(R.string.keyboard_password_character_no_headset);
+            final String text;
+            switch (code) {
+                case Keyboard.KEYCODE_ALT:
+                    text = mContext.getString(R.string.keyboardview_keycode_alt);
+                    break;
+                case Keyboard.KEYCODE_CANCEL:
+                    text = mContext.getString(R.string.keyboardview_keycode_cancel);
+                    break;
+                case Keyboard.KEYCODE_DELETE:
+                    text = mContext.getString(R.string.keyboardview_keycode_delete);
+                    break;
+                case Keyboard.KEYCODE_DONE:
+                    text = mContext.getString(R.string.keyboardview_keycode_done);
+                    break;
+                case Keyboard.KEYCODE_MODE_CHANGE:
+                    text = mContext.getString(R.string.keyboardview_keycode_mode_change);
+                    break;
+                case Keyboard.KEYCODE_SHIFT:
+                    text = mContext.getString(R.string.keyboardview_keycode_shift);
+                    break;
+                case '\n':
+                    text = mContext.getString(R.string.keyboardview_keycode_enter);
+                    break;
+                default:
+                    text = String.valueOf((char) code);
             }
             event.getText().add(text);
             mAccessibilityManager.sendAccessibilityEvent(event);
diff --git a/core/java/android/metrics/LogMaker.java b/core/java/android/metrics/LogMaker.java
index 0ee2574..612b135 100644
--- a/core/java/android/metrics/LogMaker.java
+++ b/core/java/android/metrics/LogMaker.java
@@ -60,26 +60,51 @@
         return this;
     }
 
+    public LogMaker clearCategory() {
+        entries.remove(MetricsEvent.RESERVED_FOR_LOGBUILDER_CATEGORY);
+        return this;
+    }
+
     public LogMaker setType(int type) {
         entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_TYPE, type);
         return this;
     }
 
+    public LogMaker clearType() {
+        entries.remove(MetricsEvent.RESERVED_FOR_LOGBUILDER_TYPE);
+        return this;
+    }
+
     public LogMaker setSubtype(int subtype) {
         entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_SUBTYPE, subtype);
         return this;
     }
 
+    public LogMaker clearSubtype() {
+        entries.remove(MetricsEvent.RESERVED_FOR_LOGBUILDER_SUBTYPE);
+        return this;
+    }
+
     public LogMaker setTimestamp(long timestamp) {
         entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_TIMESTAMP, timestamp);
         return this;
     }
 
+    public LogMaker clearTimestamp() {
+        entries.remove(MetricsEvent.RESERVED_FOR_LOGBUILDER_TIMESTAMP);
+        return this;
+    }
+
     public LogMaker setPackageName(String packageName) {
         entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_PACKAGENAME, packageName);
         return this;
     }
 
+    public LogMaker clearPackageName() {
+        entries.remove(MetricsEvent.RESERVED_FOR_LOGBUILDER_PACKAGENAME);
+        return this;
+    }
+
     public LogMaker setCounterName(String name) {
         entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_NAME, name);
         return this;
diff --git a/core/java/android/metrics/MetricsReader.java b/core/java/android/metrics/MetricsReader.java
index 079c2c9..dd8a74d 100644
--- a/core/java/android/metrics/MetricsReader.java
+++ b/core/java/android/metrics/MetricsReader.java
@@ -16,10 +16,15 @@
 package android.metrics;
 
 import android.annotation.SystemApi;
+import android.util.EventLog;
+import android.util.EventLog.Event;
+import android.util.Log;
 
-import com.android.internal.logging.legacy.LegacyConversionLogger;
-import com.android.internal.logging.legacy.EventLogCollector;
+import com.android.internal.logging.MetricsLogger;
 
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.LinkedList;
 import java.util.Queue;
 
 /**
@@ -28,41 +33,87 @@
  */
 @SystemApi
 public class MetricsReader {
-    private EventLogCollector mReader;
-    private Queue<LogMaker> mEventQueue;
+    private Queue<LogMaker> mEventQueue = new LinkedList<>();
     private long mLastEventMs;
     private long mCheckpointMs;
+    private int[] LOGTAGS = { MetricsLogger.LOGTAG };
 
-    /** Open a new session and start reading logs.
+    /**
+     * Read the available logs into a new session.
      *
-     * Starts reading from the oldest log not already read by this reader object.
-     * On first invocation starts from the oldest available log ion the system.
+     * The session will contain events starting from the oldest available
+     * log on the system up to the most recent at the time of this call.
+     *
+     * A call to {@link #checkpoint()} will cause the session to contain
+     * only events that occured after that call.
+     *
+     * This call will not return until the system buffer overflows the
+     * specified timestamp. If the specified timestamp is 0, then the
+     * call will return immediately since any logs 1970 have already been
+     * overwritten (n.b. if the underlying system has the capability to
+     * store many decades of system logs, this call may fail in
+     * interesting ways.)
+     *
+     * @param horizonMs block until this timestamp is overwritten, 0 for non-blocking read.
      */
-    public void read(long startMs) {
-        EventLogCollector reader = EventLogCollector.getInstance();
-        LegacyConversionLogger logger = new LegacyConversionLogger();
-        mLastEventMs = reader.collect(logger, startMs);
-        mEventQueue = logger.getEvents();
+    public void read(long horizonMs) {
+        ArrayList<Event> nativeEvents = new ArrayList<>();
+        try {
+            EventLog.readEventsOnWrapping(LOGTAGS, horizonMs, nativeEvents);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        mEventQueue.clear();
+        for (EventLog.Event event : nativeEvents) {
+            final long eventTimestampMs = event.getTimeNanos() / 1000000;
+            if (eventTimestampMs > mCheckpointMs) {
+                Object data = event.getData();
+                Object[] objects;
+                if (data instanceof Object[]) {
+                    objects = (Object[]) data;
+                } else {
+                    // wrap scalar objects
+                    objects = new Object[1];
+                    objects[0] = data;
+                }
+                mEventQueue.add(new LogMaker(objects)
+                        .setTimestamp(eventTimestampMs));
+                mLastEventMs = eventTimestampMs;
+            }
+        }
     }
 
+    /** Cause this session to only contain events that occur after this call. */
     public void checkpoint() {
+        // read the log to find the most recent event.
         read(0L);
+        // any queued event is now too old, so drop them.
+        mEventQueue.clear();
         mCheckpointMs = mLastEventMs;
-        mEventQueue = null;
     }
 
+    /**
+     * Rewind the session to the beginning of time and read all available logs.
+     *
+     * A prior call to {@link #checkpoint()} will cause the reader to ignore
+     * any event with a timestamp before the time of that call.
+     *
+     * The underlying log buffer is live: between calls to {@link #reset()}, older
+     * events may be lost from the beginning of the session, and new events may
+     * appear at the end.
+     */
     public void reset() {
-        read(mCheckpointMs);
+        read(0l);
     }
 
     /* Does the current log session have another entry? */
     public boolean hasNext() {
-        return mEventQueue == null ? false : !mEventQueue.isEmpty();
+        return !mEventQueue.isEmpty();
     }
 
-    /* Next entry in the current log session. */
+    /* Return the next entry in the current log session. */
     public LogMaker next() {
-        return mEventQueue == null ? null : mEventQueue.remove();
+        return mEventQueue.poll();
     }
 
 }
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 719a957..14333f7 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -1069,26 +1069,6 @@
     }
 
     /**
-     * Request that this callback be invoked at ConnectivityService's earliest
-     * convenience with the current satisfying network's LinkProperties.
-     * If no such network exists no callback invocation is performed.
-     *
-     * The callback must have been registered with #requestNetwork() or
-     * #registerDefaultNetworkCallback(); callbacks registered with
-     * registerNetworkCallback() are not specific to any particular Network so
-     * do not cause any updates.
-     *
-     * @hide
-     */
-    public void requestLinkProperties(NetworkCallback networkCallback) {
-        try {
-            mService.requestLinkProperties(networkCallback.networkRequest);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
      * Get the {@link android.net.NetworkCapabilities} for the given {@link Network}.  This
      * will return {@code null} if the network is unknown.
      * <p>This method requires the caller to hold the permission
@@ -1106,26 +1086,6 @@
     }
 
     /**
-     * Request that this callback be invoked at ConnectivityService's earliest
-     * convenience with the current satisfying network's NetworkCapabilities.
-     * If no such network exists no callback invocation is performed.
-     *
-     * The callback must have been registered with #requestNetwork() or
-     * #registerDefaultNetworkCallback(); callbacks registered with
-     * registerNetworkCallback() are not specific to any particular Network so
-     * do not cause any updates.
-     *
-     * @hide
-     */
-    public void requestNetworkCapabilities(NetworkCallback networkCallback) {
-        try {
-            mService.requestNetworkCapabilities(networkCallback.networkRequest);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
      * Gets the URL that should be used for resolving whether a captive portal is present.
      * 1. This URL should respond with a 204 response to a GET request to indicate no captive
      *    portal is present.
@@ -1442,8 +1402,8 @@
         l.networkCapabilities = netCap;
         l.delay = delay;
         l.expireSequenceNumber = 0;
-        l.networkRequest = sendRequestForNetwork(netCap, l.networkCallback, 0,
-                REQUEST, type);
+        l.networkRequest = sendRequestForNetwork(
+                netCap, l.networkCallback, 0, REQUEST, type, getDefaultHandler());
         if (l.networkRequest == null) return null;
         sLegacyRequests.put(netCap, l);
         sendExpireMsgForFeature(netCap, l.expireSequenceNumber, delay);
@@ -1453,7 +1413,7 @@
     private void sendExpireMsgForFeature(NetworkCapabilities netCap, int seqNum, int delay) {
         if (delay >= 0) {
             Log.d(TAG, "sending expire msg with seqNum " + seqNum + " and delay " + delay);
-            CallbackHandler handler = getHandler();
+            CallbackHandler handler = getDefaultHandler();
             Message msg = handler.obtainMessage(EXPIRE_LEGACY_REQUEST, seqNum, 0, netCap);
             handler.sendMessageDelayed(msg, delay);
         }
@@ -2676,10 +2636,12 @@
         public void onLost(Network network) {}
 
         /**
-         * Called if no network is found in the given timeout time.  If no timeout is given,
-         * this will not be called. The associated {@link NetworkRequest} will have already
-         * been removed and released, as if {@link #unregisterNetworkCallback} had been called.
-         * @hide
+         * Called if no network is found in the timeout time specified in
+         * {@link #requestNetwork(NetworkRequest, int, NetworkCallback)} call. This callback is not
+         * called for the version of {@link #requestNetwork(NetworkRequest, NetworkCallback)}
+         * without timeout. When this callback is invoked the associated
+         * {@link NetworkRequest} will have already been removed and released, as if
+         * {@link #unregisterNetworkCallback(NetworkCallback)} had been called.
          */
         public void onUnavailable() {}
 
@@ -2780,6 +2742,10 @@
             super(looper);
         }
 
+        CallbackHandler(Handler handler) {
+            this(handler.getLooper());
+        }
+
         @Override
         public void handleMessage(Message message) {
             NetworkRequest request = getObject(message, NetworkRequest.class);
@@ -2889,7 +2855,7 @@
         }
     }
 
-    private CallbackHandler getHandler() {
+    private CallbackHandler getDefaultHandler() {
         synchronized (sCallbacks) {
             if (sCallbackHandler == null) {
                 sCallbackHandler = new CallbackHandler(ConnectivityThread.getInstanceLooper());
@@ -2904,11 +2870,6 @@
     private static final int LISTEN  = 1;
     private static final int REQUEST = 2;
 
-    private NetworkRequest sendRequestForNetwork(NetworkCapabilities need,
-            NetworkCallback callback, int timeoutMs, int action, int legacyType) {
-        return sendRequestForNetwork(need, callback, timeoutMs, action, legacyType, getHandler());
-    }
-
     private NetworkRequest sendRequestForNetwork(NetworkCapabilities need, NetworkCallback callback,
             int timeoutMs, int action, int legacyType, CallbackHandler handler) {
         if (callback == null) {
@@ -2953,16 +2914,19 @@
      * @hide
      */
     public void requestNetwork(NetworkRequest request, NetworkCallback networkCallback,
-            int timeoutMs, int legacyType) {
-        sendRequestForNetwork(request.networkCapabilities, networkCallback, timeoutMs, REQUEST,
-                legacyType);
+            int timeoutMs, int legacyType, Handler handler) {
+        CallbackHandler cbHandler = new CallbackHandler(handler);
+        NetworkCapabilities nc = request.networkCapabilities;
+        sendRequestForNetwork(nc, networkCallback, timeoutMs, REQUEST, legacyType, cbHandler);
     }
 
     /**
      * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}.
      *
      * This {@link NetworkRequest} will live until released via
-     * {@link #unregisterNetworkCallback(NetworkCallback)} or the calling application exits.
+     * {@link #unregisterNetworkCallback(NetworkCallback)} or the calling application exits. A
+     * version of the method which takes a timeout is
+     * {@link #requestNetwork(NetworkRequest, int, NetworkCallback)}.
      * Status of the request can be followed by listening to the various
      * callbacks described in {@link NetworkCallback}.  The {@link Network}
      * can be used to direct traffic to the network.
@@ -2981,25 +2945,75 @@
      * {@link android.provider.Settings.System#canWrite}.</p>
      *
      * @param request {@link NetworkRequest} describing this request.
-     * @param networkCallback The {@link NetworkCallback} to be utilized for this
-     *                        request.  Note the callback must not be shared - they
-     *                        uniquely specify this request.
+     * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note
+     *                        the callback must not be shared - it uniquely specifies this request.
+     *                        The callback is invoked on the default internal Handler.
      * @throws IllegalArgumentException if {@code request} specifies any mutable
      *         {@code NetworkCapabilities}.
      */
     public void requestNetwork(NetworkRequest request, NetworkCallback networkCallback) {
-        requestNetwork(request, networkCallback, 0,
-                inferLegacyTypeForNetworkCapabilities(request.networkCapabilities));
+        requestNetwork(request, networkCallback, getDefaultHandler());
     }
 
     /**
+     * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}.
+     *
+     * This {@link NetworkRequest} will live until released via
+     * {@link #unregisterNetworkCallback(NetworkCallback)} or the calling application exits. A
+     * version of the method which takes a timeout is
+     * {@link #requestNetwork(NetworkRequest, int, NetworkCallback)}.
+     * Status of the request can be followed by listening to the various
+     * callbacks described in {@link NetworkCallback}.  The {@link Network}
+     * can be used to direct traffic to the network.
+     * <p>It is presently unsupported to request a network with mutable
+     * {@link NetworkCapabilities} such as
+     * {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED} or
+     * {@link NetworkCapabilities#NET_CAPABILITY_CAPTIVE_PORTAL}
+     * as these {@code NetworkCapabilities} represent states that a particular
+     * network may never attain, and whether a network will attain these states
+     * is unknown prior to bringing up the network so the framework does not
+     * know how to go about satisfing a request with these capabilities.
+     *
+     * <p>This method requires the caller to hold either the
+     * {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission
+     * or the ability to modify system settings as determined by
+     * {@link android.provider.Settings.System#canWrite}.</p>
+     *
+     * @param request {@link NetworkRequest} describing this request.
+     * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note
+     *                        the callback must not be shared - it uniquely specifies this request.
+     * @param handler {@link Handler} to specify the thread upon which the callback will be invoked.
+     * @throws IllegalArgumentException if {@code request} specifies any mutable
+     *         {@code NetworkCapabilities}.
+     * @hide
+     */
+    public void requestNetwork(
+            NetworkRequest request, NetworkCallback networkCallback, Handler handler) {
+        int legacyType = inferLegacyTypeForNetworkCapabilities(request.networkCapabilities);
+        CallbackHandler cbHandler = new CallbackHandler(handler);
+        requestNetwork(request, networkCallback, 0, legacyType, cbHandler);
+    }
+
+    /**
+     * Note: this is a deprecated version of
+     * {@link #requestNetwork(NetworkRequest, int, NetworkCallback)} - please transition code to use
+     * the unhidden version of the function.
+     * TODO: replace all callers with the new version of the API
+     *
      * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}, limited
      * by a timeout.
      *
-     * This function behaves identically to the non-timedout version, but if a suitable
-     * network is not found within the given time (in milliseconds) the
-     * {@link NetworkCallback#onUnavailable()} callback is called.  The request must
-     * still be released normally by calling {@link #unregisterNetworkCallback(NetworkCallback)}.
+     * This function behaves identically to the non-timed-out version
+     * {@link #requestNetwork(NetworkRequest, NetworkCallback)}, but if a suitable network
+     * is not found within the given time (in milliseconds) the
+     * {@link NetworkCallback#onUnavailable()} callback is called. The request can still be
+     * released normally by calling {@link #unregisterNetworkCallback(NetworkCallback)} but does
+     * not have to be released if timed-out (it is automatically released). Unregistering a
+     * request that timed out is not an error.
+     *
+     * <p>Do not use this method to poll for the existence of specific networks (e.g. with a small
+     * timeout) - the {@link #registerNetworkCallback(NetworkRequest, NetworkCallback)} is provided
+     * for that purpose. Calling this method will attempt to bring up the requested network.
      *
      * <p>This method requires the caller to hold either the
      * {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission
@@ -3011,13 +3025,94 @@
      *                        the callbacks must not be shared - they uniquely specify
      *                        this request.
      * @param timeoutMs The time in milliseconds to attempt looking for a suitable network
-     *                  before {@link NetworkCallback#onUnavailable()} is called.
+     *                  before {@link NetworkCallback#onUnavailable()} is called. The timeout must
+     *                  be a positive value (i.e. >0).
      * @hide
      */
     public void requestNetwork(NetworkRequest request, NetworkCallback networkCallback,
             int timeoutMs) {
-        requestNetwork(request, networkCallback, timeoutMs,
-                inferLegacyTypeForNetworkCapabilities(request.networkCapabilities));
+        if (timeoutMs <= 0) {
+            throw new IllegalArgumentException("Non-positive timeoutMs: " + timeoutMs);
+        }
+        int legacyType = inferLegacyTypeForNetworkCapabilities(request.networkCapabilities);
+        requestNetwork(request, networkCallback, timeoutMs, legacyType, getDefaultHandler());
+    }
+
+    /**
+     * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}, limited
+     * by a timeout.
+     *
+     * This function behaves identically to the non-timed-out version
+     * {@link #requestNetwork(NetworkRequest, NetworkCallback)}, but if a suitable network
+     * is not found within the given time (in milliseconds) the
+     * {@link NetworkCallback#onUnavailable()} callback is called. The request can still be
+     * released normally by calling {@link #unregisterNetworkCallback(NetworkCallback)} but does
+     * not have to be released if timed-out (it is automatically released). Unregistering a
+     * request that timed out is not an error.
+     *
+     * <p>Do not use this method to poll for the existence of specific networks (e.g. with a small
+     * timeout) - {@link #registerNetworkCallback(NetworkRequest, NetworkCallback)} is provided
+     * for that purpose. Calling this method will attempt to bring up the requested network.
+     *
+     * <p>This method requires the caller to hold either the
+     * {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission
+     * or the ability to modify system settings as determined by
+     * {@link android.provider.Settings.System#canWrite}.</p>
+     *
+     * @param request {@link NetworkRequest} describing this request.
+     * @param timeoutMs The time in milliseconds to attempt looking for a suitable network
+     *                  before {@link NetworkCallback#onUnavailable()} is called. The timeout must
+     *                  be a positive value (i.e. >0).
+     * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note
+     *                        the callback must not be shared - it uniquely specifies this request.
+     */
+    public void requestNetwork(NetworkRequest request, int timeoutMs,
+            NetworkCallback networkCallback) {
+        if (timeoutMs <= 0) {
+            throw new IllegalArgumentException("Non-positive timeoutMs: " + timeoutMs);
+        }
+        int legacyType = inferLegacyTypeForNetworkCapabilities(request.networkCapabilities);
+        requestNetwork(request, networkCallback, timeoutMs, legacyType, getDefaultHandler());
+    }
+
+
+    /**
+     * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}, limited
+     * by a timeout.
+     *
+     * This function behaves identically to the non-timedout version, but if a suitable
+     * network is not found within the given time (in milliseconds) the
+     * {@link NetworkCallback#onUnavailable} callback is called. The request can still be
+     * released normally by calling {@link #unregisterNetworkCallback(NetworkCallback)} but does
+     * not have to be released if timed-out (it is automatically released). Unregistering a
+     * request that timed out is not an error.
+     *
+     * <p>Do not use this method to poll for the existence of specific networks (e.g. with a small
+     * timeout) - {@link #registerNetworkCallback(NetworkRequest, NetworkCallback)} is provided
+     * for that purpose. Calling this method will attempt to bring up the requested network.
+     *
+     * <p>This method requires the caller to hold either the
+     * {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission
+     * or the ability to modify system settings as determined by
+     * {@link android.provider.Settings.System#canWrite}.</p>
+     *
+     * @param request {@link NetworkRequest} describing this request.
+     * @param timeoutMs The time in milliseconds to attempt looking for a suitable network
+     *                  before {@link NetworkCallback#onUnavailable} is called.
+     * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note
+     *                        the callback must not be shared - it uniquely specifies this request.
+     * @param handler {@link Handler} to specify the thread upon which the callback will be invoked.
+     *
+     * @hide
+     */
+    public void requestNetwork(NetworkRequest request, int timeoutMs,
+            NetworkCallback networkCallback, Handler handler) {
+        if (timeoutMs <= 0) {
+            throw new IllegalArgumentException("Non-positive timeoutMs");
+        }
+        int legacyType = inferLegacyTypeForNetworkCapabilities(request.networkCapabilities);
+        CallbackHandler cbHandler = new CallbackHandler(handler);
+        requestNetwork(request, networkCallback, timeoutMs, legacyType, cbHandler);
     }
 
     /**
@@ -3131,9 +3226,30 @@
      * @param request {@link NetworkRequest} describing this request.
      * @param networkCallback The {@link NetworkCallback} that the system will call as suitable
      *                        networks change state.
+     *                        The callback is invoked on the default internal Handler.
      */
     public void registerNetworkCallback(NetworkRequest request, NetworkCallback networkCallback) {
-        sendRequestForNetwork(request.networkCapabilities, networkCallback, 0, LISTEN, TYPE_NONE);
+        registerNetworkCallback(request, networkCallback, getDefaultHandler());
+    }
+
+    /**
+     * Registers to receive notifications about all networks which satisfy the given
+     * {@link NetworkRequest}.  The callbacks will continue to be called until
+     * either the application exits or link #unregisterNetworkCallback(NetworkCallback)} is called.
+     * <p>This method requires the caller to hold the permission
+     * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
+     *
+     * @param request {@link NetworkRequest} describing this request.
+     * @param networkCallback The {@link NetworkCallback} that the system will call as suitable
+     *                        networks change state.
+     * @param handler {@link Handler} to specify the thread upon which the callback will be invoked.
+     * @hide
+     */
+    public void registerNetworkCallback(
+            NetworkRequest request, NetworkCallback networkCallback, Handler handler) {
+        CallbackHandler cbHandler = new CallbackHandler(handler);
+        NetworkCapabilities nc = request.networkCapabilities;
+        sendRequestForNetwork(nc, networkCallback, 0, LISTEN, TYPE_NONE, cbHandler);
     }
 
     /**
@@ -3185,8 +3301,25 @@
      *
      * @param networkCallback The {@link NetworkCallback} that the system will call as the
      *                        system default network changes.
+     *                        The callback is invoked on the default internal Handler.
      */
     public void registerDefaultNetworkCallback(NetworkCallback networkCallback) {
+        registerDefaultNetworkCallback(networkCallback, getDefaultHandler());
+    }
+
+    /**
+     * Registers to receive notifications about changes in the system default network. The callbacks
+     * will continue to be called until either the application exits or
+     * {@link #unregisterNetworkCallback(NetworkCallback)} is called.
+     * <p>This method requires the caller to hold the permission
+     * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
+     *
+     * @param networkCallback The {@link NetworkCallback} that the system will call as the
+     *                        system default network changes.
+     * @param handler {@link Handler} to specify the thread upon which the callback will be invoked.
+     * @hide
+     */
+    public void registerDefaultNetworkCallback(NetworkCallback networkCallback, Handler handler) {
         // This works because if the NetworkCapabilities are null,
         // ConnectivityService takes them from the default request.
         //
@@ -3194,7 +3327,8 @@
         // capabilities, this request is guaranteed, at all times, to be
         // satisfied by the same network, if any, that satisfies the default
         // request, i.e., the system default network.
-        sendRequestForNetwork(null, networkCallback, 0, REQUEST, TYPE_NONE);
+        CallbackHandler cbHandler = new CallbackHandler(handler);
+        sendRequestForNetwork(null, networkCallback, 0, REQUEST, TYPE_NONE, cbHandler);
     }
 
     /**
diff --git a/core/java/android/net/ConnectivityMetricsEvent.aidl b/core/java/android/net/ConnectivityMetricsEvent.aidl
index a027d7c..1c541dc 100644
--- a/core/java/android/net/ConnectivityMetricsEvent.aidl
+++ b/core/java/android/net/ConnectivityMetricsEvent.aidl
@@ -16,5 +16,5 @@
 
 package android.net;
 
+/** {@hide} */
 parcelable ConnectivityMetricsEvent;
-parcelable ConnectivityMetricsEvent.Reference;
diff --git a/core/java/android/net/ConnectivityMetricsEvent.java b/core/java/android/net/ConnectivityMetricsEvent.java
index eaaef7f..6fdc739 100644
--- a/core/java/android/net/ConnectivityMetricsEvent.java
+++ b/core/java/android/net/ConnectivityMetricsEvent.java
@@ -16,12 +16,10 @@
 
 package android.net;
 
-import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
 /** {@hide} */
-@SystemApi
 public final class ConnectivityMetricsEvent implements Parcelable {
 
     /**  The time when this event was collected, as returned by System.currentTimeMillis(). */
@@ -67,7 +65,6 @@
         return 0;
     }
 
-    /** Implement the Parcelable interface */
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeLong(timestamp);
@@ -80,51 +77,4 @@
         return String.format("ConnectivityMetricsEvent(%tT.%tL, %d, %d): %s",
                 timestamp, timestamp, componentTag, eventTag, data);
     }
-
-    /** {@hide} */
-    @SystemApi
-    public final static class Reference implements Parcelable {
-
-        private long mValue;
-
-        public Reference(long ref) {
-            this.mValue = ref;
-        }
-
-        /** Implement the Parcelable interface */
-        public static final Parcelable.Creator<Reference> CREATOR
-                = new Parcelable.Creator<Reference> (){
-            public Reference createFromParcel(Parcel source) {
-                return new Reference(source.readLong());
-            }
-
-            public Reference[] newArray(int size) {
-                return new Reference[size];
-            }
-        };
-
-        /** Implement the Parcelable interface */
-        @Override
-        public int describeContents() {
-            return 0;
-        }
-
-        /** Implement the Parcelable interface */
-        @Override
-        public void writeToParcel(Parcel dest, int flags) {
-            dest.writeLong(mValue);
-        }
-
-        public void readFromParcel(Parcel in) {
-            mValue = in.readLong();
-        }
-
-        public long getValue() {
-            return mValue;
-        }
-
-        public void setValue(long val) {
-            mValue = val;
-        }
-    }
 }
diff --git a/core/java/android/net/ConnectivityMetricsLogger.java b/core/java/android/net/ConnectivityMetricsLogger.java
deleted file mode 100644
index 67b6908..0000000
--- a/core/java/android/net/ConnectivityMetricsLogger.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.net;
-
-import android.annotation.SystemApi;
-import android.app.PendingIntent;
-import android.os.Bundle;
-import android.os.Parcelable;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-/** {@hide} */
-@SystemApi
-public class ConnectivityMetricsLogger {
-    private static String TAG = "ConnectivityMetricsLogger";
-    private static final boolean DBG = true;
-
-    public static final String CONNECTIVITY_METRICS_LOGGER_SERVICE = "connectivity_metrics_logger";
-
-    // Component Tags
-    public static final int COMPONENT_TAG_CONNECTIVITY = 0;
-    public static final int COMPONENT_TAG_BLUETOOTH    = 1;
-    public static final int COMPONENT_TAG_WIFI         = 2;
-    public static final int COMPONENT_TAG_TELECOM      = 3;
-    public static final int COMPONENT_TAG_TELEPHONY    = 4;
-    public static final int NUMBER_OF_COMPONENTS       = 5;
-
-    // Event Tag
-    public static final int TAG_SKIPPED_EVENTS = -1;
-
-    public static final String DATA_KEY_EVENTS_COUNT = "count";
-
-    public ConnectivityMetricsLogger() {
-    }
-
-    /**
-     * Log a ConnectivityMetricsEvent.
-     *
-     * This method keeps track of skipped events when MetricsLoggerService throttles input events.
-     * It skips logging when MetricsLoggerService is active. When throttling ends, it logs a
-     * meta-event containing the number of events dropped. It is not safe to call this method
-     * concurrently from different threads.
-     *
-     * @param timestamp is the epoch timestamp of the event in ms.
-     * @param componentTag is the COMPONENT_* constant the event belongs to.
-     * @param eventTag is an event type constant whose meaning is specific to the component tag.
-     * @param data is a Parcelable instance representing the event.
-     */
-    public void logEvent(long timestamp, int componentTag, int eventTag, Parcelable data) {
-    }
-
-    /**
-     * Retrieve events
-     *
-     * @param reference of the last event previously returned. The function will return
-     *                  events following it.
-     *                  If 0 then all events will be returned.
-     *                  After the function call it will contain reference of the
-     *                  last returned event.
-     * @return events
-     */
-    public ConnectivityMetricsEvent[] getEvents(ConnectivityMetricsEvent.Reference reference) {
-        return new ConnectivityMetricsEvent[0];
-    }
-
-    /**
-     * Register PendingIntent which will be sent when new events are ready to be retrieved.
-     */
-    public boolean register(PendingIntent newEventsIntent) {
-        return false;
-    }
-
-    public boolean unregister(PendingIntent newEventsIntent) {
-        return false;
-    }
-}
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 117fa0b..425e494 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -156,8 +156,6 @@
     void pendingListenForNetwork(in NetworkCapabilities networkCapabilities,
             in PendingIntent operation);
 
-    void requestLinkProperties(in NetworkRequest networkRequest);
-    void requestNetworkCapabilities(in NetworkRequest networkRequest);
     void releaseNetworkRequest(in NetworkRequest networkRequest);
 
     void setAcceptUnvalidated(in Network network, boolean accept, boolean always);
diff --git a/core/java/android/net/IConnectivityMetricsLogger.aidl b/core/java/android/net/IConnectivityMetricsLogger.aidl
deleted file mode 100644
index a83a019..0000000
--- a/core/java/android/net/IConnectivityMetricsLogger.aidl
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.app.PendingIntent;
-import android.net.ConnectivityMetricsEvent;
-
-/** {@hide} */
-interface IConnectivityMetricsLogger {
-
-    /**
-     * @return 0 on success
-     *        <0 if error happened
-     *        >0 timestamp after which new events will be accepted
-     */
-    long logEvent(in ConnectivityMetricsEvent event);
-    long logEvents(in ConnectivityMetricsEvent[] events);
-
-    /**
-     * @param reference of the last event previously returned. The function will return
-     *                  events following it.
-     *                  If 0 then all events will be returned.
-     *                  After the function call it will contain reference of the last event.
-     */
-    ConnectivityMetricsEvent[] getEvents(inout ConnectivityMetricsEvent.Reference reference);
-
-    boolean register(in PendingIntent newEventsIntent);
-    void unregister(in PendingIntent newEventsIntent);
-}
diff --git a/core/java/android/net/INetworkScoreService.aidl b/core/java/android/net/INetworkScoreService.aidl
index f249daf..362ea9d 100644
--- a/core/java/android/net/INetworkScoreService.aidl
+++ b/core/java/android/net/INetworkScoreService.aidl
@@ -18,7 +18,7 @@
 
 import android.net.INetworkScoreCache;
 import android.net.NetworkKey;
-import android.net.NetworkScorerAppManager;
+import android.net.NetworkScorerAppData;
 import android.net.RecommendationRequest;
 import android.net.RecommendationResult;
 import android.net.ScoredNetwork;
@@ -135,11 +135,11 @@
     /**
      * Returns metadata about the active scorer or <code>null</code> if there is no active scorer.
      */
-    NetworkScorerAppManager.NetworkScorerAppData getActiveScorer();
+    NetworkScorerAppData getActiveScorer();
 
     /**
      * Returns the list of available scorer apps. The list will be empty if there are
      * no valid scorers.
      */
-    List<NetworkScorerAppManager.NetworkScorerAppData> getAllValidScorers();
+    List<NetworkScorerAppData> getAllValidScorers();
 }
diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java
new file mode 100644
index 0000000..da5cb37
--- /dev/null
+++ b/core/java/android/net/IpSecAlgorithm.java
@@ -0,0 +1,181 @@
+/*
+ * 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 android.net;
+
+import android.annotation.StringDef;
+import android.os.Parcel;
+import android.os.Parcelable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * IpSecAlgorithm specifies a single algorithm that can be applied to an IpSec Transform. Refer to
+ * RFC 4301.
+ */
+public final class IpSecAlgorithm implements Parcelable {
+
+    /**
+     * AES-CBC Encryption/Ciphering Algorithm.
+     *
+     * <p>Valid lengths for this key are {128, 192, 256}.
+     */
+    public static final String ALGO_CRYPT_AES_CBC = "cbc(aes)";
+
+    /**
+     * MD5 HMAC Authentication/Integrity Algorithm. This algorithm is not recommended for use in new
+     * applications and is provided for legacy compatibility with 3gpp infrastructure.
+     *
+     * <p>Valid truncation lengths are multiples of 8 bits from 96 to (default) 128.
+     */
+    public static final String ALGO_AUTH_HMAC_MD5 = "hmac(md5)";
+
+    /**
+     * SHA1 HMAC Authentication/Integrity Algorithm. This algorithm is not recommended for use in
+     * new applications and is provided for legacy compatibility with 3gpp infrastructure.
+     *
+     * <p>Valid truncation lengths are multiples of 8 bits from 96 to (default) 160.
+     */
+    public static final String ALGO_AUTH_HMAC_SHA1 = "hmac(sha1)";
+
+    /**
+     * SHA256 HMAC Authentication/Integrity Algorithm.
+     *
+     * <p>Valid truncation lengths are multiples of 8 bits from 96 to (default) 256.
+     */
+    public static final String ALGO_AUTH_HMAC_SHA256 = "hmac(sha256)";
+
+    /**
+     * SHA384 HMAC Authentication/Integrity Algorithm.
+     *
+     * <p>Valid truncation lengths are multiples of 8 bits from 192 to (default) 384.
+     */
+    public static final String ALGO_AUTH_HMAC_SHA384 = "hmac(sha384)";
+    /**
+     * SHA512 HMAC Authentication/Integrity Algorithm
+     *
+     * <p>Valid truncation lengths are multiples of 8 bits from 256 to (default) 512.
+     */
+    public static final String ALGO_AUTH_HMAC_SHA512 = "hmac(sha512)";
+
+    /** @hide */
+    @StringDef({
+        ALGO_CRYPT_AES_CBC,
+        ALGO_AUTH_HMAC_MD5,
+        ALGO_AUTH_HMAC_SHA1,
+        ALGO_AUTH_HMAC_SHA256,
+        ALGO_AUTH_HMAC_SHA512
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface AlgorithmName {}
+
+    private final String mName;
+    private final byte[] mKey;
+    private final int mTruncLenBits;
+
+    /**
+     * Specify a IpSecAlgorithm of one of the supported types including the truncation length of the
+     * algorithm
+     *
+     * @param algorithm type for IpSec.
+     * @param key non-null Key padded to a multiple of 8 bits.
+     */
+    public IpSecAlgorithm(String algorithm, byte[] key) {
+        this(algorithm, key, key.length * 8);
+    }
+
+    /**
+     * Specify a IpSecAlgorithm of one of the supported types including the truncation length of the
+     * algorithm
+     *
+     * @param algoName precise name of the algorithm to be used.
+     * @param key non-null Key padded to a multiple of 8 bits.
+     * @param truncLenBits the number of bits of output hash to use; only meaningful for
+     *     Authentication.
+     */
+    public IpSecAlgorithm(@AlgorithmName String algoName, byte[] key, int truncLenBits) {
+        if (!isTruncationLengthValid(algoName, truncLenBits)) {
+            throw new IllegalArgumentException("Unknown algorithm or invalid length");
+        }
+        mName = algoName;
+        mKey = key.clone();
+        mTruncLenBits = Math.min(truncLenBits, key.length * 8);
+    }
+
+    /** Retrieve the algorithm name */
+    public String getName() {
+        return mName;
+    }
+
+    /** Retrieve the key for this algorithm */
+    public byte[] getKey() {
+        return mKey.clone();
+    }
+
+    /**
+     * Retrieve the truncation length, in bits, for the key in this algo. By default this will be
+     * the length in bits of the key.
+     */
+    public int getTruncationLengthBits() {
+        return mTruncLenBits;
+    }
+
+    /* Parcelable Implementation */
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Write to parcel */
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeString(mName);
+        out.writeByteArray(mKey);
+        out.writeInt(mTruncLenBits);
+    }
+
+    /** Parcelable Creator */
+    public static final Parcelable.Creator<IpSecAlgorithm> CREATOR =
+            new Parcelable.Creator<IpSecAlgorithm>() {
+                public IpSecAlgorithm createFromParcel(Parcel in) {
+                    return new IpSecAlgorithm(in);
+                }
+
+                public IpSecAlgorithm[] newArray(int size) {
+                    return new IpSecAlgorithm[size];
+                }
+            };
+
+    private IpSecAlgorithm(Parcel in) {
+        mName = in.readString();
+        mKey = in.createByteArray();
+        mTruncLenBits = in.readInt();
+    }
+
+    private static boolean isTruncationLengthValid(String algo, int truncLenBits) {
+        switch (algo) {
+            case ALGO_AUTH_HMAC_MD5:
+                return (truncLenBits >= 96 && truncLenBits <= 128);
+            case ALGO_AUTH_HMAC_SHA1:
+                return (truncLenBits >= 96 && truncLenBits <= 160);
+            case ALGO_AUTH_HMAC_SHA256:
+                return (truncLenBits >= 96 && truncLenBits <= 256);
+            case ALGO_AUTH_HMAC_SHA384:
+                return (truncLenBits >= 192 && truncLenBits <= 384);
+            case ALGO_AUTH_HMAC_SHA512:
+                return (truncLenBits >= 256 && truncLenBits <= 512);
+            default:
+                return false;
+        }
+    }
+};
diff --git a/core/java/com/android/internal/logging/legacy/Util.java b/core/java/android/net/IpSecConfig.aidl
similarity index 77%
copy from core/java/com/android/internal/logging/legacy/Util.java
copy to core/java/android/net/IpSecConfig.aidl
index 99f71ca..eaefca7 100644
--- a/core/java/com/android/internal/logging/legacy/Util.java
+++ b/core/java/android/net/IpSecConfig.aidl
@@ -13,13 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.internal.logging.legacy;
 
-/**
- * Created by cwren on 11/21/16.
- */
-public class Util {
-    public static boolean debug() {
-        return false;
-    }
-}
+package android.net;
+
+/** @hide */
+parcelable IpSecConfig;
diff --git a/core/java/android/net/IpSecConfig.java b/core/java/android/net/IpSecConfig.java
new file mode 100644
index 0000000..b58bf42
--- /dev/null
+++ b/core/java/android/net/IpSecConfig.java
@@ -0,0 +1,197 @@
+/*
+ * 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 android.net;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/** @hide */
+public final class IpSecConfig implements Parcelable {
+    private static final String TAG = IpSecConfig.class.getSimpleName();
+
+    //MODE_TRANSPORT or MODE_TUNNEL
+    int mode;
+
+    // For tunnel mode
+    InetAddress localAddress;
+
+    InetAddress remoteAddress;
+
+    // Limit selection by network interface
+    Network network;
+
+    public static class Flow {
+        // Minimum requirements for identifying a transform
+        // SPI identifying the IPsec flow in packet processing
+        // and a remote IP address
+        int spi;
+
+        // Encryption Algorithm
+        IpSecAlgorithm encryptionAlgo;
+
+        // Authentication Algorithm
+        IpSecAlgorithm authenticationAlgo;
+    }
+
+    Flow[] flow = new Flow[2];
+
+    // For tunnel mode IPv4 UDP Encapsulation
+    // IpSecTransform#ENCAP_ESP_*, such as ENCAP_ESP_OVER_UDP_IKE
+    int encapType;
+    int encapLocalPort;
+    int encapRemotePort;
+
+    // An optional protocol to match with the selector
+    int selectorProto;
+
+    // A bitmask of FEATURE_* indicating which of the fields
+    // of this class are valid.
+    long features;
+
+    // An interval, in seconds between the NattKeepalive packets
+    int nattKeepaliveInterval;
+
+    public InetAddress getLocalIp() {
+        return localAddress;
+    }
+
+    public int getSpi(int direction) {
+        return flow[direction].spi;
+    }
+
+    public InetAddress getRemoteIp() {
+        return remoteAddress;
+    }
+
+    public IpSecAlgorithm getEncryptionAlgo(int direction) {
+        return flow[direction].encryptionAlgo;
+    }
+
+    public IpSecAlgorithm getAuthenticationAlgo(int direction) {
+        return flow[direction].authenticationAlgo;
+    }
+
+    Network getNetwork() {
+        return network;
+    }
+
+    public int getEncapType() {
+        return encapType;
+    }
+
+    public int getEncapLocalPort() {
+        return encapLocalPort;
+    }
+
+    public int getEncapRemotePort() {
+        return encapRemotePort;
+    }
+
+    public int getSelectorProto() {
+        return selectorProto;
+    }
+
+    int getNattKeepaliveInterval() {
+        return nattKeepaliveInterval;
+    }
+
+    public boolean hasProperty(int featureBits) {
+        return (features & featureBits) == featureBits;
+    }
+
+    // Parcelable Methods
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeLong(features);
+        // TODO: Use a byte array or other better method for storing IPs that can also include scope
+        out.writeString((localAddress != null) ? localAddress.getHostAddress() : null);
+        // TODO: Use a byte array or other better method for storing IPs that can also include scope
+        out.writeString((remoteAddress != null) ? remoteAddress.getHostAddress() : null);
+        out.writeParcelable(network, flags);
+        out.writeInt(flow[IpSecTransform.DIRECTION_IN].spi);
+        out.writeParcelable(flow[IpSecTransform.DIRECTION_IN].encryptionAlgo, flags);
+        out.writeParcelable(flow[IpSecTransform.DIRECTION_IN].authenticationAlgo, flags);
+        out.writeInt(flow[IpSecTransform.DIRECTION_OUT].spi);
+        out.writeParcelable(flow[IpSecTransform.DIRECTION_OUT].encryptionAlgo, flags);
+        out.writeParcelable(flow[IpSecTransform.DIRECTION_OUT].authenticationAlgo, flags);
+        out.writeInt(encapType);
+        out.writeInt(encapLocalPort);
+        out.writeInt(encapRemotePort);
+        out.writeInt(selectorProto);
+    }
+
+    // Package Private: Used by the IpSecTransform.Builder;
+    // there should be no public constructor for this object
+    IpSecConfig() {
+        flow[IpSecTransform.DIRECTION_IN].spi = 0;
+        flow[IpSecTransform.DIRECTION_OUT].spi = 0;
+        nattKeepaliveInterval = 0; //FIXME constant
+    }
+
+    private static InetAddress readInetAddressFromParcel(Parcel in) {
+        String addrString = in.readString();
+        if (addrString == null) {
+            return null;
+        }
+        try {
+            return InetAddress.getByName(addrString);
+        } catch (UnknownHostException e) {
+            Log.wtf(TAG, "Invalid IpAddress " + addrString);
+            return null;
+        }
+    }
+
+    private IpSecConfig(Parcel in) {
+        features = in.readLong();
+        localAddress = readInetAddressFromParcel(in);
+        remoteAddress = readInetAddressFromParcel(in);
+        network = (Network) in.readParcelable(Network.class.getClassLoader());
+        flow[IpSecTransform.DIRECTION_IN].spi = in.readInt();
+        flow[IpSecTransform.DIRECTION_IN].encryptionAlgo =
+                (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
+        flow[IpSecTransform.DIRECTION_IN].authenticationAlgo =
+                (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
+        flow[IpSecTransform.DIRECTION_OUT].spi = in.readInt();
+        flow[IpSecTransform.DIRECTION_OUT].encryptionAlgo =
+                (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
+        flow[IpSecTransform.DIRECTION_OUT].authenticationAlgo =
+                (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
+        encapType = in.readInt();
+        encapLocalPort = in.readInt();
+        encapRemotePort = in.readInt();
+        selectorProto = in.readInt();
+    }
+
+    public static final Parcelable.Creator<IpSecConfig> CREATOR =
+            new Parcelable.Creator<IpSecConfig>() {
+                public IpSecConfig createFromParcel(Parcel in) {
+                    return new IpSecConfig(in);
+                }
+
+                public IpSecConfig[] newArray(int size) {
+                    return new IpSecConfig[size];
+                }
+            };
+}
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
new file mode 100644
index 0000000..2c544e9
--- /dev/null
+++ b/core/java/android/net/IpSecManager.java
@@ -0,0 +1,379 @@
+/*
+ * 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 android.net;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import android.annotation.SystemApi;
+import android.content.Context;
+import android.os.INetworkManagementService;
+import android.os.ParcelFileDescriptor;
+import android.util.AndroidException;
+import dalvik.system.CloseGuard;
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.Socket;
+
+/**
+ * This class contains methods for managing IPsec sessions, which will perform kernel-space
+ * encryption and decryption of socket or Network traffic.
+ *
+ * <p>An IpSecManager may be obtained by calling {@link
+ * android.content.Context#getSystemService(String) Context#getSystemService(String)} with {@link
+ * android.content.Context#IPSEC_SERVICE Context#IPSEC_SERVICE}
+ */
+public final class IpSecManager {
+    private static final String TAG = "IpSecManager";
+
+    /**
+     * Indicates that the combination of remote InetAddress and SPI was non-unique for a given
+     * request. If encountered, selection of a new SPI is required before a transform may be
+     * created. Note, this should happen very rarely if the SPI is chosen to be sufficiently random
+     * or reserved using reserveSecurityParameterIndex.
+     */
+    public static final class SpiUnavailableException extends AndroidException {
+        private final int mSpi;
+
+        /**
+         * Construct an exception indicating that a transform with the given SPI is already in use
+         * or otherwise unavailable.
+         *
+         * @param msg Description indicating the colliding SPI
+         * @param spi the SPI that could not be used due to a collision
+         */
+        SpiUnavailableException(String msg, int spi) {
+            super(msg + "(spi: " + spi + ")");
+            mSpi = spi;
+        }
+
+        /** Retrieve the SPI that caused a collision */
+        public int getSpi() {
+            return mSpi;
+        }
+    }
+
+    /**
+     * Indicates that the requested system resource for IPsec, such as a socket or other system
+     * resource is unavailable. If this exception is thrown, try releasing allocated objects of the
+     * type requested.
+     */
+    public static final class ResourceUnavailableException extends AndroidException {
+
+        ResourceUnavailableException(String msg) {
+            super(msg);
+        }
+    }
+
+    private final Context mContext;
+    private final INetworkManagementService mService;
+
+    public static final class SecurityParameterIndex implements AutoCloseable {
+        private final Context mContext;
+        private final InetAddress mDestinationAddress;
+        private final CloseGuard mCloseGuard = CloseGuard.get();
+        private int mSpi;
+
+        /** Return the underlying SPI held by this object */
+        public int getSpi() {
+            return mSpi;
+        }
+
+        private SecurityParameterIndex(Context context, InetAddress destinationAddress, int spi)
+                throws ResourceUnavailableException, SpiUnavailableException {
+            mContext = context;
+            mDestinationAddress = destinationAddress;
+            mSpi = spi;
+            mCloseGuard.open("open");
+        }
+
+        /**
+         * Release an SPI that was previously reserved.
+         *
+         * <p>Release an SPI for use by other users in the system. This will fail if the SPI is
+         * currently in use by an IpSecTransform.
+         *
+         * @param destinationAddress SPIs must be unique for each combination of SPI and destination
+         *     address. Thus, the destinationAddress to which the SPI will communicate must be
+         *     supplied.
+         * @param spi the previously reserved SPI to be freed.
+         */
+        @Override
+        public void close() {
+            mSpi = INVALID_SECURITY_PARAMETER_INDEX; // TODO: Invalid SPI
+            mCloseGuard.close();
+        }
+
+        @Override
+        protected void finalize() {
+            if (mCloseGuard != null) {
+                mCloseGuard.warnIfOpen();
+            }
+
+            close();
+        }
+    }
+
+    /**
+     * The Security Parameter Index, SPI, 0 indicates an unknown or invalid index.
+     *
+     * <p>No IPsec packet may contain an SPI of 0.
+     */
+    public static final int INVALID_SECURITY_PARAMETER_INDEX = 0;
+
+    /**
+     * Reserve an SPI for traffic bound towards the specified destination address.
+     *
+     * <p>If successful, this SPI is guaranteed available until released by a call to {@link
+     * SecurityParameterIndex#close()}.
+     *
+     * @param destinationAddress SPIs must be unique for each combination of SPI and destination
+     *     address.
+     * @param requestedSpi the requested SPI, or '0' to allocate a random SPI.
+     * @return the reserved SecurityParameterIndex
+     * @throws ResourceUnavailableException indicating that too many SPIs are currently allocated
+     *     for this user
+     * @throws SpiUnavailableException indicating that a particular SPI cannot be reserved
+     */
+    public SecurityParameterIndex reserveSecurityParameterIndex(
+            InetAddress destinationAddress, int requestedSpi)
+            throws SpiUnavailableException, ResourceUnavailableException {
+        return new SecurityParameterIndex(mContext, destinationAddress, requestedSpi);
+    }
+
+    /**
+     * Apply an active Transport Mode IPsec Transform to a stream socket to perform IPsec
+     * encapsulation of the traffic flowing between the socket and the remote InetAddress of that
+     * transform. For security reasons, attempts to send traffic to any IP address other than the
+     * address associated with that transform will throw an IOException. In addition, if the
+     * IpSecTransform is later deactivated, the socket will throw an IOException on any calls to
+     * send() or receive() until the transform is removed from the socket by calling {@link
+     * #removeTransportModeTransform(Socket, IpSecTransform)};
+     *
+     * @param socket a stream socket
+     * @param transform an {@link IpSecTransform}, which must be an active Transport Mode transform.
+     */
+    public void applyTransportModeTransform(Socket socket, IpSecTransform transform)
+            throws IOException {
+        applyTransportModeTransform(ParcelFileDescriptor.fromSocket(socket), transform);
+    }
+
+    /**
+     * Apply an active Transport Mode IPsec Transform to a datagram socket to perform IPsec
+     * encapsulation of the traffic flowing between the socket and the remote InetAddress of that
+     * transform. For security reasons, attempts to send traffic to any IP address other than the
+     * address associated with that transform will throw an IOException. In addition, if the
+     * IpSecTransform is later deactivated, the socket will throw an IOException on any calls to
+     * send() or receive() until the transform is removed from the socket by calling {@link
+     * #removeTransportModeTransform(DatagramSocket, IpSecTransform)};
+     *
+     * @param socket a datagram socket
+     * @param transform an {@link IpSecTransform}, which must be an active Transport Mode transform.
+     */
+    public void applyTransportModeTransform(DatagramSocket socket, IpSecTransform transform)
+            throws IOException {
+        applyTransportModeTransform(ParcelFileDescriptor.fromDatagramSocket(socket), transform);
+    }
+
+    /* Call down to activate a transform */
+    private void applyTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) {}
+
+    /**
+     * Apply an active Tunnel Mode IPsec Transform to a network, which will tunnel all traffic to
+     * and from that network's interface with IPsec (applies an outer IP header and IPsec Header to
+     * all traffic, and expects an additional IP header and IPsec Header on all inbound traffic).
+     * Applications should probably not use this API directly. Instead, they should use {@link
+     * VpnService} to provide VPN capability in a more generic fashion.
+     *
+     * @param net a {@link Network} that will be tunneled via IP Sec.
+     * @param transform an {@link IpSecTransform}, which must be an active Tunnel Mode transform.
+     * @hide
+     */
+    @SystemApi
+    public void applyTunnelModeTransform(Network net, IpSecTransform transform) {}
+
+    /**
+     * Remove a transform from a given stream socket. Once removed, traffic on the socket will not
+     * be encypted. This allows sockets that have been used for IPsec to be reclaimed for
+     * communication in the clear in the event socket reuse is desired. This operation will succeed
+     * regardless of the underlying state of a transform. If a transform is removed, communication
+     * on all sockets to which that transform was applied will fail until this method is called.
+     *
+     * @param socket a socket that previously had a transform applied to it.
+     * @param transform the IPsec Transform that was previously applied to the given socket
+     */
+    public void removeTransportModeTransform(Socket socket, IpSecTransform transform) {
+        removeTransportModeTransform(ParcelFileDescriptor.fromSocket(socket), transform);
+    }
+
+    /**
+     * Remove a transform from a given datagram socket. Once removed, traffic on the socket will not
+     * be encypted. This allows sockets that have been used for IPsec to be reclaimed for
+     * communication in the clear in the event socket reuse is desired. This operation will succeed
+     * regardless of the underlying state of a transform. If a transform is removed, communication
+     * on all sockets to which that transform was applied will fail until this method is called.
+     *
+     * @param socket a socket that previously had a transform applied to it.
+     * @param transform the IPsec Transform that was previously applied to the given socket
+     */
+    public void removeTransportModeTransform(DatagramSocket socket, IpSecTransform transform) {
+        removeTransportModeTransform(ParcelFileDescriptor.fromDatagramSocket(socket), transform);
+    }
+
+    /* Call down to activate a transform */
+    private void removeTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) {}
+
+    /**
+     * Remove a Tunnel Mode IPsec Transform from a {@link Network}. This must be used as part of
+     * cleanup if a tunneled Network experiences a change in default route. The Network will drop
+     * all traffic that cannot be routed to the Tunnel's outbound interface. If that interface is
+     * lost, all traffic will drop.
+     *
+     * @param net a network that currently has transform applied to it.
+     * @param transform a Tunnel Mode IPsec Transform that has been previously applied to the given
+     *     network
+     * @hide
+     */
+    @SystemApi
+    public void removeTunnelModeTransform(Network net, IpSecTransform transform) {}
+
+    /**
+     * Class providing access to a system-provided UDP Encapsulation Socket, which may be used for
+     * IKE signalling as well as for inbound and outbound UDP encapsulated IPsec traffic.
+     *
+     * <p>The socket provided by this class cannot be re-bound or closed via the inner
+     * FileDescriptor. Instead, disposing of this socket requires a call to close().
+     */
+    public static final class UdpEncapsulationSocket implements AutoCloseable {
+        private final FileDescriptor mFd;
+        private final Context mContext;
+        private final CloseGuard mCloseGuard = CloseGuard.get();
+
+        private UdpEncapsulationSocket(Context context, int port)
+                throws ResourceUnavailableException {
+            mContext = context;
+            mCloseGuard.open("constructor");
+            // TODO: go down to the kernel and get a socket on the specified
+            mFd = new FileDescriptor();
+        }
+
+        private UdpEncapsulationSocket(Context context) throws ResourceUnavailableException {
+            mContext = context;
+            mCloseGuard.open("constructor");
+            // TODO: go get a random socket on a random port
+            mFd = new FileDescriptor();
+        }
+
+        /** Access the inner UDP Encapsulation Socket */
+        public FileDescriptor getSocket() {
+            return mFd;
+        }
+
+        /** Retrieve the port number of the inner encapsulation socket */
+        public int getPort() {
+            return 0; // TODO get the port number from the Socket;
+        }
+
+        @Override
+        /**
+         * Release the resources that have been reserved for this Socket.
+         *
+         * <p>This method closes the underlying socket, reducing a user's allocated sockets in the
+         * system. This must be done as part of cleanup following use of a socket. Failure to do so
+         * will cause the socket to count against a total allocation limit for IpSec and eventually
+         * fail due to resource limits.
+         *
+         * @param fd a file descriptor previously returned as a UDP Encapsulation socket.
+         */
+        public void close() {
+            // TODO: Go close the socket
+            mCloseGuard.close();
+        }
+
+        @Override
+        protected void finalize() throws Throwable {
+            if (mCloseGuard != null) {
+                mCloseGuard.warnIfOpen();
+            }
+
+            close();
+        }
+    };
+
+    /**
+     * Open a socket that is bound to a free UDP port on the system.
+     *
+     * <p>By binding in this manner and holding the FileDescriptor, the socket cannot be un-bound by
+     * the caller. This provides safe access to a socket on a port that can later be used as a UDP
+     * Encapsulation port.
+     *
+     * <p>This socket reservation works in conjunction with IpSecTransforms, which may re-use the
+     * socket port. Explicitly opening this port is only necessary if communication is desired on
+     * that port.
+     *
+     * @param port a local UDP port to be reserved for UDP Encapsulation. is provided, then this
+     *     method will bind to the specified port or fail. To retrieve the port number, call {@link
+     *     android.system.Os#getsockname(FileDescriptor)}.
+     * @return a {@link UdpEncapsulationSocket} that is bound to the requested port for the lifetime
+     *     of the object.
+     */
+    // Returning a socket in this fashion that has been created and bound by the system
+    // is the only safe way to ensure that a socket is both accessible to the user and
+    // safely usable for Encapsulation without allowing a user to possibly unbind from/close
+    // the port, which could potentially impact the traffic of the next user who binds to that
+    // socket.
+    public UdpEncapsulationSocket openUdpEncapsulationSocket(int port)
+            throws IOException, ResourceUnavailableException {
+        // Temporary code
+        return new UdpEncapsulationSocket(mContext, port);
+    }
+
+    /**
+     * Open a socket that is bound to a port selected by the system.
+     *
+     * <p>By binding in this manner and holding the FileDescriptor, the socket cannot be un-bound by
+     * the caller. This provides safe access to a socket on a port that can later be used as a UDP
+     * Encapsulation port.
+     *
+     * <p>This socket reservation works in conjunction with IpSecTransforms, which may re-use the
+     * socket port. Explicitly opening this port is only necessary if communication is desired on
+     * that port.
+     *
+     * @return a {@link UdpEncapsulationSocket} that is bound to an arbitrarily selected port
+     */
+    // Returning a socket in this fashion that has been created and bound by the system
+    // is the only safe way to ensure that a socket is both accessible to the user and
+    // safely usable for Encapsulation without allowing a user to possibly unbind from/close
+    // the port, which could potentially impact the traffic of the next user who binds to that
+    // socket.
+    public UdpEncapsulationSocket openUdpEncapsulationSocket()
+            throws IOException, ResourceUnavailableException {
+        // Temporary code
+        return new UdpEncapsulationSocket(mContext);
+    }
+
+    /**
+     * Retrieve an instance of an IpSecManager within you application context
+     *
+     * @param context the application context for this manager
+     * @hide
+     */
+    public IpSecManager(Context context, INetworkManagementService service) {
+        mContext = checkNotNull(context, "missing context");
+        mService = checkNotNull(service, "missing service");
+    }
+}
diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java
new file mode 100644
index 0000000..d6dd28b
--- /dev/null
+++ b/core/java/android/net/IpSecTransform.java
@@ -0,0 +1,471 @@
+/*
+ * 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 android.net;
+
+import android.annotation.IntDef;
+import android.annotation.SystemApi;
+import android.content.Context;
+import android.system.ErrnoException;
+import android.util.Log;
+import dalvik.system.CloseGuard;
+import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.net.InetAddress;
+
+/**
+ * This class represents an IpSecTransform, which encapsulates both properties and state of IPsec.
+ *
+ * <p>IpSecTransforms must be built from an IpSecTransform.Builder, and they must persist throughout
+ * the lifetime of the underlying transform. If a transform object leaves scope, the underlying
+ * transform may be disabled automatically, with likely undesirable results.
+ *
+ * <p>An IpSecTransform may either represent a tunnel mode transform that operates on a wide array
+ * of traffic or may represent a transport mode transform operating on a Socket or Sockets.
+ */
+public final class IpSecTransform implements AutoCloseable {
+    private static final String TAG = "IpSecTransform";
+
+    /**
+     * For direction-specific attributes of an IpSecTransform, indicates that an attribute applies
+     * to traffic towards the host.
+     */
+    public static final int DIRECTION_IN = 0;
+
+    /**
+     * For direction-specific attributes of an IpSecTransform, indicates that an attribute applies
+     * to traffic from the host.
+     */
+    public static final int DIRECTION_OUT = 1;
+
+    /** @hide */
+    @IntDef(value = {DIRECTION_IN, DIRECTION_OUT})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface TransformDirection {}
+
+    /** @hide */
+    private static final int MODE_TUNNEL = 0;
+
+    /** @hide */
+    private static final int MODE_TRANSPORT = 1;
+
+    /** @hide */
+    public static final int ENCAP_NONE = 0;
+
+    /**
+     * IpSec traffic will be encapsulated within UDP as per <a
+     * href="https://tools.ietf.org/html/rfc3948">RFC3498</a>.
+     *
+     * @hide
+     */
+    public static final int ENCAP_ESPINUDP = 1;
+
+    /**
+     * IpSec traffic will be encapsulated within a UDP header with an additional 8-byte header pad
+     * (of '0'-value bytes) that prevents traffic from being interpreted as IKE or as ESP over UDP.
+     *
+     * @hide
+     */
+    public static final int ENCAP_ESPINUDP_NONIKE = 2;
+
+    /** @hide */
+    @IntDef(value = {ENCAP_NONE, ENCAP_ESPINUDP, ENCAP_ESPINUDP_NONIKE})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface EncapType {}
+
+    /**
+     * Sentinel for an invalid transform (means that this transform is inactive).
+     *
+     * @hide
+     */
+    public static final int INVALID_TRANSFORM_ID = -1;
+
+    private IpSecTransform(Context context, IpSecConfig config) {
+        mContext = context;
+        mConfig = config;
+        mTransformId = INVALID_TRANSFORM_ID;
+    }
+
+    private IpSecTransform activate()
+            throws IOException, IpSecManager.ResourceUnavailableException,
+                    IpSecManager.SpiUnavailableException {
+        int transformId;
+        synchronized (this) {
+            //try {
+            transformId = INVALID_TRANSFORM_ID;
+            //} catch (RemoteException e) {
+            //    throw e.rethrowFromSystemServer();
+            //}
+
+            if (transformId < 0) {
+                throw new ErrnoException("addTransform", -transformId).rethrowAsIOException();
+            }
+
+            startKeepalive(mContext); // Will silently fail if not required
+            mTransformId = transformId;
+            Log.d(TAG, "Added Transform with Id " + transformId);
+        }
+        mCloseGuard.open("build");
+
+        return this;
+    }
+
+    /**
+     * Deactivate an IpSecTransform and free all resources for that transform that are managed by
+     * the system for this Transform.
+     *
+     * <p>Deactivating a transform while it is still applied to any Socket will result in sockets
+     * refusing to send or receive data. This method will silently succeed if the specified
+     * transform has already been removed; thus, it is always safe to attempt cleanup when a
+     * transform is no longer needed.
+     */
+    public void close() {
+        Log.d(TAG, "Removing Transform with Id " + mTransformId);
+
+        // Always safe to attempt cleanup
+        if (mTransformId == INVALID_TRANSFORM_ID) {
+            return;
+        }
+        //try {
+        stopKeepalive();
+        //} catch (RemoteException e) {
+        //    transform.setTransformId(transformId);
+        //    throw e.rethrowFromSystemServer();
+        //} finally {
+        mTransformId = INVALID_TRANSFORM_ID;
+        //}
+        mCloseGuard.close();
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        if (mCloseGuard != null) {
+            mCloseGuard.warnIfOpen();
+        }
+        close();
+    }
+
+    /* Package */
+    IpSecConfig getConfig() {
+        return mConfig;
+    }
+
+    private final IpSecConfig mConfig;
+    private int mTransformId;
+    private final Context mContext;
+    private final CloseGuard mCloseGuard = CloseGuard.get();
+    private ConnectivityManager.PacketKeepalive mKeepalive;
+    private int mKeepaliveStatus = ConnectivityManager.PacketKeepalive.NO_KEEPALIVE;
+    private Object mKeepaliveSyncLock = new Object();
+    private ConnectivityManager.PacketKeepaliveCallback mKeepaliveCallback =
+            new ConnectivityManager.PacketKeepaliveCallback() {
+
+                @Override
+                public void onStarted() {
+                    synchronized (mKeepaliveSyncLock) {
+                        mKeepaliveStatus = ConnectivityManager.PacketKeepalive.SUCCESS;
+                        mKeepaliveSyncLock.notifyAll();
+                    }
+                }
+
+                @Override
+                public void onStopped() {
+                    synchronized (mKeepaliveSyncLock) {
+                        mKeepaliveStatus = ConnectivityManager.PacketKeepalive.NO_KEEPALIVE;
+                        mKeepaliveSyncLock.notifyAll();
+                    }
+                }
+
+                @Override
+                public void onError(int error) {
+                    synchronized (mKeepaliveSyncLock) {
+                        mKeepaliveStatus = error;
+                        mKeepaliveSyncLock.notifyAll();
+                    }
+                }
+            };
+
+    /* Package */
+    void startKeepalive(Context c) {
+        if (mConfig.getNattKeepaliveInterval() == 0) {
+            return;
+        }
+
+        ConnectivityManager cm =
+                (ConnectivityManager) c.getSystemService(Context.CONNECTIVITY_SERVICE);
+
+        if (mKeepalive != null) {
+            Log.e(TAG, "Keepalive already started for this IpSecTransform.");
+            return;
+        }
+
+        synchronized (mKeepaliveSyncLock) {
+            mKeepalive =
+                    cm.startNattKeepalive(
+                            mConfig.getNetwork(),
+                            mConfig.getNattKeepaliveInterval(),
+                            mKeepaliveCallback,
+                            mConfig.getLocalIp(),
+                            mConfig.getEncapLocalPort(),
+                            mConfig.getRemoteIp());
+            try {
+                mKeepaliveSyncLock.wait(2000);
+            } catch (InterruptedException e) {
+            }
+        }
+        if (mKeepaliveStatus != ConnectivityManager.PacketKeepalive.SUCCESS) {
+            throw new UnsupportedOperationException("Packet Keepalive cannot be started");
+        }
+    }
+
+    /* Package */
+    void stopKeepalive() {
+        if (mKeepalive == null) {
+            return;
+        }
+        mKeepalive.stop();
+        synchronized (mKeepaliveSyncLock) {
+            if (mKeepaliveStatus == ConnectivityManager.PacketKeepalive.SUCCESS) {
+                try {
+                    mKeepaliveSyncLock.wait(2000);
+                } catch (InterruptedException e) {
+                }
+            }
+        }
+    }
+
+    /* Package */
+    void setTransformId(int transformId) {
+        mTransformId = transformId;
+    }
+
+    /* Package */
+    int getTransformId() {
+        return mTransformId;
+    }
+
+    /**
+     * Builder object to facilitate the creation of IpSecTransform objects.
+     *
+     * <p>Apply additional properties to the transform and then call a build() method to return an
+     * IpSecTransform object.
+     *
+     * @see Builder#buildTransportModeTransform(InetAddress)
+     */
+    public static class Builder {
+        private Context mContext;
+        private IpSecConfig mConfig;
+
+        /**
+         * Add an encryption algorithm to the transform for the given direction.
+         *
+         * <p>If encryption is set for a given direction without also providing an SPI for that
+         * direction, creation of an IpSecTransform will fail upon calling a build() method.
+         *
+         * @param direction either {@link #DIRECTION_IN or #DIRECTION_OUT}
+         * @param algo {@link IpSecAlgorithm} specifying the encryption to be applied.
+         */
+        public IpSecTransform.Builder setEncryption(
+                @TransformDirection int direction, IpSecAlgorithm algo) {
+            mConfig.flow[direction].encryptionAlgo = algo;
+            return this;
+        }
+
+        /**
+         * Add an authentication/integrity algorithm to the transform.
+         *
+         * <p>If authentication is set for a given direction without also providing an SPI for that
+         * direction, creation of an IpSecTransform will fail upon calling a build() method.
+         *
+         * @param direction either {@link #DIRECTION_IN or #DIRECTION_OUT}
+         * @param algo {@link IpSecAlgorithm} specifying the authentication to be applied.
+         */
+        public IpSecTransform.Builder setAuthentication(
+                @TransformDirection int direction, IpSecAlgorithm algo) {
+            mConfig.flow[direction].authenticationAlgo = algo;
+            return this;
+        }
+
+        /**
+         * Set the SPI, which uniquely identifies a particular IPsec session from others. Because
+         * IPsec operates at the IP layer, this 32-bit identifier uniquely identifies packets to a
+         * given destination address.
+         *
+         * <p>Care should be chosen when selecting an SPI to ensure that is is as unique as
+         * possible. Random number generation is a reasonable approach to selecting an SPI. For
+         * outbound SPIs, they must be reserved by calling {@link
+         * IpSecManager#reserveSecurityParameterIndex(InetAddress, int)}. Otherwise, Transforms will
+         * fail to build.
+         *
+         * <p>Unless an SPI is set for a given direction, traffic in that direction will be
+         * sent/received without any IPsec applied.
+         *
+         * @param direction either {@link #DIRECTION_IN or #DIRECTION_OUT}
+         * @param spi a unique 32-bit integer to identify transformed traffic
+         */
+        public IpSecTransform.Builder setSpi(@TransformDirection int direction, int spi) {
+            mConfig.flow[direction].spi = spi;
+            return this;
+        }
+
+        /**
+         * Set the SPI, which uniquely identifies a particular IPsec session from others. Because
+         * IPsec operates at the IP layer, this 32-bit identifier uniquely identifies packets to a
+         * given destination address.
+         *
+         * <p>Care should be chosen when selecting an SPI to ensure that is is as unique as
+         * possible. Random number generation is a reasonable approach to selecting an SPI. For
+         * outbound SPIs, they must be reserved by calling {@link
+         * IpSecManager#reserveSecurityParameterIndex(InetAddress, int)}. Otherwise, Transforms will
+         * fail to activate.
+         *
+         * <p>Unless an SPI is set for a given direction, traffic in that direction will be
+         * sent/received without any IPsec applied.
+         *
+         * @param direction either {@link #DIRECTION_IN or #DIRECTION_OUT}
+         * @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed
+         *     traffic
+         */
+        public IpSecTransform.Builder setSpi(
+                @TransformDirection int direction, IpSecManager.SecurityParameterIndex spi) {
+            mConfig.flow[direction].spi = spi.getSpi();
+            return this;
+        }
+
+        /**
+         * Specify the network on which this transform will emit its traffic; (otherwise it will
+         * emit on the default network).
+         *
+         * <p>Restricts the transformed traffic to a particular {@link Network}. This is required in
+         * tunnel mode.
+         *
+         * @hide
+         */
+        @SystemApi
+        public IpSecTransform.Builder setUnderlyingNetwork(Network net) {
+            mConfig.network = net;
+            return this;
+        }
+
+        /**
+         * Add UDP encapsulation to an IPv4 transform
+         *
+         * <p>This option allows IPsec traffic to pass through NAT. Refer to RFC 3947 and 3948 for
+         * details on how UDP should be applied to IPsec.
+         *
+         * @param localSocket a {@link IpSecManager.UdpEncapsulationSocket} for sending and
+         *     receiving encapsulating traffic.
+         * @param remotePort the UDP port number of the remote that will send and receive
+         *     encapsulated traffic. In the case of IKE, this is likely port 4500.
+         */
+        public IpSecTransform.Builder setIpv4Encapsulation(
+                IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) {
+            // TODO: check encap type is valid.
+            mConfig.encapType = ENCAP_ESPINUDP;
+            mConfig.encapLocalPort = localSocket.getPort(); // TODO: plug in the encap socket
+            mConfig.encapRemotePort = remotePort;
+            return this;
+        }
+
+        // TODO: Decrease the minimum keepalive to maybe 10?
+        // TODO: Probably a better exception to throw for NATTKeepalive failure
+        // TODO: Specify the needed NATT keepalive permission.
+        /**
+         * Send a NATT Keepalive packet with a given maximum interval. This will create an offloaded
+         * request to do power-efficient NATT Keepalive. If NATT keepalive is requested but cannot
+         * be activated, then the transform will fail to activate and throw an IOException.
+         *
+         * @param intervalSeconds the maximum number of seconds between keepalive packets, no less
+         *     than 20s and no more than 3600s.
+         * @hide
+         */
+        @SystemApi
+        public IpSecTransform.Builder setNattKeepalive(int intervalSeconds) {
+            mConfig.nattKeepaliveInterval = intervalSeconds;
+            return this;
+        }
+
+        /**
+         * Build and return an active {@link IpSecTransform} object as a Transport Mode Transform.
+         * Some parameters have interdependencies that are checked at build time. If a well-formed
+         * transform cannot be created from the supplied parameters, this method will throw an
+         * Exception.
+         *
+         * <p>Upon a successful return from this call, the provided IpSecTransform will be active
+         * and may be applied to sockets. If too many IpSecTransform objects are active for a given
+         * user this operation will fail and throw ResourceUnavailableException. To avoid these
+         * exceptions, unused Transform objects must be cleaned up by calling {@link
+         * IpSecTransform#close()} when they are no longer needed.
+         *
+         * @param remoteAddress the {@link InetAddress} that, when matched on traffic to/from this
+         *     socket will cause the transform to be applied.
+         *     <p>Note that an active transform will not impact any network traffic until it has
+         *     been applied to one or more Sockets. Calling this method is a necessary precondition
+         *     for applying it to a socket, but is not sufficient to actually apply IPsec.
+         * @throws IllegalArgumentException indicating that a particular combination of transform
+         *     properties is invalid.
+         * @throws IpSecManager.ResourceUnavailableException in the event that no more Transforms
+         *     may be allocated
+         * @throws SpiUnavailableException if the SPI collides with an existing transform
+         *     (unlikely).
+         * @throws ResourceUnavailableException if the current user currently has exceeded the
+         *     number of allowed active transforms.
+         */
+        public IpSecTransform buildTransportModeTransform(InetAddress remoteAddress)
+                throws IpSecManager.ResourceUnavailableException,
+                        IpSecManager.SpiUnavailableException, IOException {
+            //FIXME: argument validation here
+            //throw new IllegalArgumentException("Natt Keepalive requires UDP Encapsulation");
+            mConfig.mode = MODE_TRANSPORT;
+            mConfig.remoteAddress = remoteAddress;
+            return new IpSecTransform(mContext, mConfig).activate();
+        }
+
+        /**
+         * Build and return an {@link IpSecTransform} object as a Tunnel Mode Transform. Some
+         * parameters have interdependencies that are checked at build time.
+         *
+         * @param localAddress the {@link InetAddress} that provides the local endpoint for this
+         *     IPsec tunnel. This is almost certainly an address belonging to the {@link Network}
+         *     that will originate the traffic, which is set as the {@link #setUnderlyingNetwork}.
+         * @param remoteAddress the {@link InetAddress} representing the remote endpoint of this
+         *     IPsec tunnel.
+         * @throws IllegalArgumentException indicating that a particular combination of transform
+         *     properties is invalid.
+         * @hide
+         */
+        @SystemApi
+        public IpSecTransform buildTunnelModeTransform(
+                InetAddress localAddress, InetAddress remoteAddress) {
+            //FIXME: argument validation here
+            //throw new IllegalArgumentException("Natt Keepalive requires UDP Encapsulation");
+            mConfig.localAddress = localAddress;
+            mConfig.remoteAddress = remoteAddress;
+            mConfig.mode = MODE_TUNNEL;
+            return new IpSecTransform(mContext, mConfig);
+        }
+
+        /**
+         * Create a new IpSecTransform.Builder to construct an IpSecTransform
+         *
+         * @param context current Context
+         */
+        public Builder(Context context) {
+            mContext = context;
+            mConfig = new IpSecConfig();
+        }
+    }
+}
diff --git a/core/java/android/net/NetworkBadging.java b/core/java/android/net/NetworkBadging.java
index 5cf2f96..4409d0a 100644
--- a/core/java/android/net/NetworkBadging.java
+++ b/core/java/android/net/NetworkBadging.java
@@ -17,6 +17,7 @@
 package android.net;
 
 import android.annotation.DrawableRes;
+import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -25,19 +26,29 @@
 import android.content.res.Resources.Theme;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.LayerDrawable;
-import android.net.ScoredNetwork.Badging;
 import android.net.wifi.WifiManager;
 import android.view.View;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * Utility methods for working with network badging.
  *
- * TODO: move ScoredNetwork.Badging and related constants to this class.
- *
  * @hide
  */
 @SystemApi
 public class NetworkBadging {
+
+    @IntDef({BADGING_NONE, BADGING_SD, BADGING_HD, BADGING_4K})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Badging {}
+
+    public static final int BADGING_NONE = 0;
+    public static final int BADGING_SD = 10;
+    public static final int BADGING_HD = 20;
+    public static final int BADGING_4K = 30;
+
     private NetworkBadging() {}
 
     /**
@@ -55,7 +66,7 @@
     @NonNull public static Drawable getWifiIcon(
             @IntRange(from=0, to=4) int signalLevel, @Badging int badging, @Nullable Theme theme) {
         Resources resources = Resources.getSystem();
-        if (badging == ScoredNetwork.BADGING_NONE) {
+        if (badging == BADGING_NONE) {
             return resources.getDrawable(getWifiSignalResource(signalLevel), theme);
         }
         Drawable[] layers = new Drawable[] {
@@ -131,19 +142,19 @@
      *
      * @param badging {@see ScoredNetwork#Badging} from {@link ScoredNetwork#calculateBadge(int)}.
      * @return the @DrawableRes for the icon or {@link View#NO_ID} for
-     *         {@link ScoredNetwork#BADGING_NONE}
+     *         {@link NetworkBadging#BADGING_NONE}
      * @throws IllegalArgumentException for an invalid badging value.
      * @hide
      */
     @DrawableRes private static int getWifiBadgeResource(@Badging int badging) {
         switch (badging) {
-            case ScoredNetwork.BADGING_NONE:
+            case BADGING_NONE:
                 return View.NO_ID;
-            case ScoredNetwork.BADGING_SD:
+            case BADGING_SD:
                 return com.android.internal.R.drawable.ic_signal_wifi_badged_sd;
-            case ScoredNetwork.BADGING_HD:
+            case BADGING_HD:
                 return com.android.internal.R.drawable.ic_signal_wifi_badged_hd;
-            case ScoredNetwork.BADGING_4K:
+            case BADGING_4K:
                 return com.android.internal.R.drawable.ic_signal_wifi_badged_4k;
             default:
                 throw new IllegalArgumentException("No resource found for badge: " + badging);
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 4b184f1..43fab03 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -66,8 +66,6 @@
      *
      * See network-policy-restrictions.md for more info.
      */
-    /** Not a valid rule */
-    public static final int RULE_INVALID = -1;
     /** No specific rule was set */
     public static final int RULE_NONE = 0;
     /** Allow traffic on metered networks. */
@@ -363,8 +361,6 @@
         final StringBuilder string = new StringBuilder().append(uidRules).append(" (");
         if (uidRules == RULE_NONE) {
             string.append("NONE");
-        } else if (uidRules == RULE_INVALID) {
-            string.append("INVALID");
         } else {
             string.append(DebugUtils.flagsToString(NetworkPolicyManager.class, "RULE_", uidRules));
         }
@@ -388,23 +384,18 @@
     }
 
     /**
-     * @hide
+     * Returns true if {@param procState} is considered foreground and as such will be allowed
+     * to access network when the device is idle or in battery saver mode. Otherwise, false.
      */
     public static boolean isProcStateAllowedWhileIdleOrPowerSaveMode(int procState) {
         return procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
     }
 
     /**
-     * @hide
+     * Returns true if {@param procState} is considered foreground and as such will be allowed
+     * to access network when the device is in data saver mode. Otherwise, false.
      */
-    public static boolean isProcStateAllowedWhileRestrictBackgroundOn(int procState) {
+    public static boolean isProcStateAllowedWhileOnRestrictBackground(int procState) {
         return procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
     }
-
-    /**
-     * @hide
-     */
-    public interface UidStateWithSeqObserver {
-        void onUidStateChangedWithSeq(int uid, int procState, long seq);
-    }
 }
diff --git a/core/java/android/net/NetworkRecommendationProvider.java b/core/java/android/net/NetworkRecommendationProvider.java
index 8395864..271b0a7 100644
--- a/core/java/android/net/NetworkRecommendationProvider.java
+++ b/core/java/android/net/NetworkRecommendationProvider.java
@@ -1,6 +1,8 @@
 package android.net;
 
+import android.Manifest.permission;
 import android.annotation.SystemApi;
+import android.content.Context;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
@@ -10,8 +12,10 @@
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
 
 import java.util.Objects;
+import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
@@ -32,6 +36,7 @@
     /**
      * Constructs a new instance.
      * @param handler indicates which thread to use when handling requests. Cannot be {@code null}.
+     * @deprecated use {@link #NetworkRecommendationProvider(Context, Executor)}
      */
     public NetworkRecommendationProvider(Handler handler) {
         if (handler == null) {
@@ -41,6 +46,17 @@
     }
 
     /**
+     * Constructs a new instance.
+     * @param context the current context instance. Cannot be {@code null}.
+     * @param executor used to execute the incoming requests. Cannot be {@code null}.
+     */
+    public NetworkRecommendationProvider(Context context, Executor executor) {
+        Preconditions.checkNotNull(context);
+        Preconditions.checkNotNull(executor);
+        mService = new ServiceWrapper(context, executor);
+    }
+
+    /**
      * Invoked when a recommendation has been requested.
      *
      * @param request a {@link RecommendationRequest} instance containing additional
@@ -130,17 +146,28 @@
      * A wrapper around INetworkRecommendationProvider that dispatches to the provided Handler.
      */
     private final class ServiceWrapper extends INetworkRecommendationProvider.Stub {
+        private final Context mContext;
+        private final Executor mExecutor;
         private final Handler mHandler;
 
         ServiceWrapper(Handler handler) {
             mHandler = handler;
+            mExecutor = null;
+            mContext = null;
+        }
+
+        ServiceWrapper(Context context, Executor executor) {
+            mContext = context;
+            mExecutor = executor;
+            mHandler = null;
         }
 
         @Override
         public void requestRecommendation(final RecommendationRequest request,
                 final IRemoteCallback callback, final int sequence) throws RemoteException {
+            enforceCallingPermission();
             if (VERBOSE) Log.v(TAG, "requestRecommendation(seq=" + sequence + ")");
-            mHandler.post(new Runnable() {
+            execute(new Runnable() {
                 @Override
                 public void run() {
                     if (VERBOSE) {
@@ -154,8 +181,9 @@
 
         @Override
         public void requestScores(final NetworkKey[] networks) throws RemoteException {
+            enforceCallingPermission();
             if (networks != null && networks.length > 0) {
-                mHandler.post(new Runnable() {
+                execute(new Runnable() {
                     @Override
                     public void run() {
                         onRequestScores(networks);
@@ -163,5 +191,20 @@
                 });
             }
         }
+
+        private void execute(Runnable command) {
+            if (mExecutor != null) {
+                mExecutor.execute(command);
+            } else {
+                mHandler.post(command);
+            }
+        }
+
+        private void enforceCallingPermission() {
+            if (mContext != null) {
+                mContext.enforceCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES,
+                        "Permission denied.");
+            }
+        }
     }
 }
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index 8f3af66..e6fe0d0 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -18,7 +18,6 @@
 
 import static android.net.NetworkRecommendationProvider.EXTRA_RECOMMENDATION_RESULT;
 
-import android.Manifest;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -26,7 +25,6 @@
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
 import android.content.Context;
-import android.net.NetworkScorerAppManager.NetworkScorerAppData;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.RemoteCallback;
@@ -96,17 +94,32 @@
     public static final String EXTRA_NETWORKS_TO_SCORE = "networksToScore";
 
     /**
-     * Activity action: launch a custom activity for configuring a scorer before enabling it.
-     * Scorer applications may choose to specify an activity for this action, in which case the
-     * framework will launch that activity which should return RESULT_OK if scoring was enabled.
-     *
-     * <p>If no activity is included in a scorer which implements this action, the system dialog for
-     * selecting a scorer will be shown instead.
+     * Activity action: launch an activity for configuring a provider for the feature that connects
+     * and secures open wifi networks available before enabling it. Applications that enable this
+     * feature must provide an activity for this action. The framework will launch this activity
+     * which must return RESULT_OK if the feature should be enabled.
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_CUSTOM_ENABLE = "android.net.scoring.CUSTOM_ENABLE";
 
     /**
+     * Meta-data specified on a {@link NetworkRecommendationProvider} that provides a user-visible
+     * label of the recommendation service.
+     * @hide
+     */
+    public static final String RECOMMENDATION_SERVICE_LABEL_META_DATA =
+            "android.net.scoring.recommendation_service_label";
+
+    /**
+     * Meta-data specified on a {@link NetworkRecommendationProvider} that specified the package
+     * name of the application that connects and secures open wifi networks automatically. The
+     * specified package must provide an Activity for {@link #ACTION_CUSTOM_ENABLE}.
+     * @hide
+     */
+    public static final String USE_OPEN_WIFI_PACKAGE_META_DATA =
+            "android.net.wifi.use_open_wifi_package";
+
+    /**
      * Broadcast action: the active scorer has been changed. Scorer apps may listen to this to
      * perform initialization once selected as the active scorer, or clean up unneeded resources
      * if another scorer has been selected. This is an explicit broadcast only sent to the
@@ -158,6 +171,43 @@
      */
     public static final int CACHE_FILTER_SCAN_RESULTS = 2;
 
+    /** @hide */
+    @IntDef({RECOMMENDATIONS_ENABLED_FORCED_OFF, RECOMMENDATIONS_ENABLED_OFF,
+            RECOMMENDATIONS_ENABLED_ON})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface RecommendationsEnabledSetting {}
+
+    /**
+     * Recommendations have been forced off.
+     * <p>
+     * This value is never set by any of the NetworkScore classes, it must be set via other means.
+     * This state is also "sticky" and we won't transition out of this state once entered. To move
+     * to a different state this value has to be explicitly set to a different value via
+     * other means.
+     * @hide
+     */
+    public static final int RECOMMENDATIONS_ENABLED_FORCED_OFF = -1;
+
+    /**
+     * Recommendations are not enabled.
+     * <p>
+     * This is a transient state that can be entered when the default recommendation app is enabled
+     * but no longer valid. This state will transition to RECOMMENDATIONS_ENABLED_ON when a valid
+     * recommendation app is enabled.
+     * @hide
+     */
+    public static final int RECOMMENDATIONS_ENABLED_OFF = 0;
+
+    /**
+     * Recommendations are enabled.
+     * <p>
+     * This is a transient state that means a valid recommendation app is active. This state will
+     * transition to RECOMMENDATIONS_ENABLED_OFF if the current and default recommendation apps
+     * become invalid.
+     * @hide
+     */
+    public static final int RECOMMENDATIONS_ENABLED_ON = 1;
+
     private final Context mContext;
     private final INetworkScoreService mService;
 
@@ -260,8 +310,8 @@
      * the {@link #ACTION_CHANGE_ACTIVE} broadcast, or using a custom configuration activity.
      *
      * @return true if the operation succeeded, or false if the new package is not a valid scorer.
-     * @throws SecurityException if the caller does not hold the
-     *         {@link android.Manifest.permission#SCORE_NETWORKS} permission.
+     * @throws SecurityException if the caller is not a system process or does not hold the
+     *         {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission
      * @hide
      */
     @SystemApi
diff --git a/core/java/android/net/NetworkScorerAppManager.aidl b/core/java/android/net/NetworkScorerAppData.aidl
similarity index 91%
rename from core/java/android/net/NetworkScorerAppManager.aidl
rename to core/java/android/net/NetworkScorerAppData.aidl
index d968343..ee7f1d1 100644
--- a/core/java/android/net/NetworkScorerAppManager.aidl
+++ b/core/java/android/net/NetworkScorerAppData.aidl
@@ -16,4 +16,4 @@
 
 package android.net;
 
-parcelable NetworkScorerAppManager.NetworkScorerAppData;
+parcelable NetworkScorerAppData;
diff --git a/core/java/android/net/NetworkScorerAppData.java b/core/java/android/net/NetworkScorerAppData.java
new file mode 100644
index 0000000..5bf1e10
--- /dev/null
+++ b/core/java/android/net/NetworkScorerAppData.java
@@ -0,0 +1,112 @@
+package android.net;
+
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * Holds metadata about a discovered network scorer/recommendation application.
+ *
+ * @hide
+ */
+public final class NetworkScorerAppData implements Parcelable {
+    /** UID of the scorer app. */
+    public final int packageUid;
+    private final ComponentName mRecommendationService;
+    /** User visible label in Settings for the recommendation service. */
+    private final String mRecommendationServiceLabel;
+    /**
+     * The {@link ComponentName} of the Activity to start before enabling the "connect to open
+     * wifi networks automatically" feature.
+     */
+    private final ComponentName mEnableUseOpenWifiActivity;
+
+    public NetworkScorerAppData(int packageUid, ComponentName recommendationServiceComp,
+            String recommendationServiceLabel, ComponentName enableUseOpenWifiActivity) {
+        this.packageUid = packageUid;
+        this.mRecommendationService = recommendationServiceComp;
+        this.mRecommendationServiceLabel = recommendationServiceLabel;
+        this.mEnableUseOpenWifiActivity = enableUseOpenWifiActivity;
+    }
+
+    protected NetworkScorerAppData(Parcel in) {
+        packageUid = in.readInt();
+        mRecommendationService = ComponentName.readFromParcel(in);
+        mRecommendationServiceLabel = in.readString();
+        mEnableUseOpenWifiActivity = ComponentName.readFromParcel(in);
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(packageUid);
+        ComponentName.writeToParcel(mRecommendationService, dest);
+        dest.writeString(mRecommendationServiceLabel);
+        ComponentName.writeToParcel(mEnableUseOpenWifiActivity, dest);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    public static final Creator<NetworkScorerAppData> CREATOR =
+            new Creator<NetworkScorerAppData>() {
+                @Override
+                public NetworkScorerAppData createFromParcel(Parcel in) {
+                    return new NetworkScorerAppData(in);
+                }
+
+                @Override
+                public NetworkScorerAppData[] newArray(int size) {
+                    return new NetworkScorerAppData[size];
+                }
+            };
+
+    public String getRecommendationServicePackageName() {
+        return mRecommendationService.getPackageName();
+    }
+
+    public ComponentName getRecommendationServiceComponent() {
+        return mRecommendationService;
+    }
+
+    @Nullable
+    public ComponentName getEnableUseOpenWifiActivity() {
+        return mEnableUseOpenWifiActivity;
+    }
+
+    @Nullable
+    public String getRecommendationServiceLabel() {
+        return mRecommendationServiceLabel;
+    }
+
+    @Override
+    public String toString() {
+        return "NetworkScorerAppData{" +
+                "packageUid=" + packageUid +
+                ", mRecommendationService=" + mRecommendationService +
+                ", mRecommendationServiceLabel=" + mRecommendationServiceLabel +
+                ", mEnableUseOpenWifiActivity=" + mEnableUseOpenWifiActivity +
+                '}';
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        NetworkScorerAppData that = (NetworkScorerAppData) o;
+        return packageUid == that.packageUid &&
+                Objects.equals(mRecommendationService, that.mRecommendationService) &&
+                Objects.equals(mRecommendationServiceLabel, that.mRecommendationServiceLabel) &&
+                Objects.equals(mEnableUseOpenWifiActivity, that.mEnableUseOpenWifiActivity);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(packageUid, mRecommendationService, mRecommendationServiceLabel,
+                mEnableUseOpenWifiActivity);
+    }
+}
diff --git a/core/java/android/net/NetworkScorerAppManager.java b/core/java/android/net/NetworkScorerAppManager.java
deleted file mode 100644
index a166c7f..0000000
--- a/core/java/android/net/NetworkScorerAppManager.java
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package android.net;
-
-import android.Manifest.permission;
-import android.annotation.Nullable;
-import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.internal.R;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * Internal class for discovering and managing the network scorer/recommendation application.
- *
- * @hide
- */
-public class NetworkScorerAppManager {
-    private static final String TAG = "NetworkScorerAppManager";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
-    private final Context mContext;
-
-    public NetworkScorerAppManager(Context context) {
-      mContext = context;
-    }
-
-    /**
-     * Holds metadata about a discovered network scorer/recommendation application.
-     */
-    public static final class NetworkScorerAppData implements Parcelable {
-        /** UID of the scorer app. */
-        public final int packageUid;
-        private final ComponentName mRecommendationService;
-
-        public NetworkScorerAppData(int packageUid, ComponentName recommendationServiceComp) {
-            this.packageUid = packageUid;
-            this.mRecommendationService = recommendationServiceComp;
-        }
-
-        protected NetworkScorerAppData(Parcel in) {
-            packageUid = in.readInt();
-            mRecommendationService = ComponentName.readFromParcel(in);
-        }
-
-        @Override
-        public void writeToParcel(Parcel dest, int flags) {
-            dest.writeInt(packageUid);
-            ComponentName.writeToParcel(mRecommendationService, dest);
-        }
-
-        @Override
-        public int describeContents() {
-            return 0;
-        }
-
-        public static final Creator<NetworkScorerAppData> CREATOR =
-                new Creator<NetworkScorerAppData>() {
-                    @Override
-                    public NetworkScorerAppData createFromParcel(Parcel in) {
-                        return new NetworkScorerAppData(in);
-                    }
-
-                    @Override
-                    public NetworkScorerAppData[] newArray(int size) {
-                        return new NetworkScorerAppData[size];
-                    }
-                };
-
-        public String getRecommendationServicePackageName() {
-            return mRecommendationService.getPackageName();
-        }
-
-        public ComponentName getRecommendationServiceComponent() {
-            return mRecommendationService;
-        }
-
-        @Override
-        public String toString() {
-            return "NetworkScorerAppData{" +
-                    "packageUid=" + packageUid +
-                    ", mRecommendationService=" + mRecommendationService +
-                    '}';
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (o == null || getClass() != o.getClass()) return false;
-            NetworkScorerAppData that = (NetworkScorerAppData) o;
-            return packageUid == that.packageUid &&
-                    Objects.equals(mRecommendationService, that.mRecommendationService);
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(packageUid, mRecommendationService);
-        }
-    }
-
-    /**
-     * Returns the list of available scorer apps. The list will be empty if there are
-     * no valid scorers.
-     */
-    public List<NetworkScorerAppData> getAllValidScorers() {
-        return Collections.emptyList();
-    }
-
-    /**
-     * @return A {@link NetworkScorerAppData} instance containing information about the
-     *         best configured network recommendation provider installed or {@code null}
-     *         if none of the configured packages can recommend networks.
-     *
-     * <p>A network recommendation provider is any application which:
-     * <ul>
-     * <li>Is listed in the <code>config_networkRecommendationPackageNames</code> config.
-     * <li>Declares the {@link android.Manifest.permission#SCORE_NETWORKS} permission.
-     * <li>Includes a Service for {@link NetworkScoreManager#ACTION_RECOMMEND_NETWORKS}.
-     * </ul>
-     */
-    public NetworkScorerAppData getNetworkRecommendationProviderData() {
-        // Network recommendation apps can only run as the primary user right now.
-        // http://b/23422763
-        if (UserHandle.getCallingUserId() != UserHandle.USER_SYSTEM) {
-            return null;
-        }
-
-        final List<String> potentialPkgs = getPotentialRecommendationProviderPackages();
-        if (potentialPkgs.isEmpty()) {
-            if (DEBUG) {
-                Log.d(TAG, "No Network Recommendation Providers specified.");
-            }
-            return null;
-        }
-
-        for (int i = 0; i < potentialPkgs.size(); i++) {
-            final String potentialPkg = potentialPkgs.get(i);
-
-            // Look for the recommendation service class and required receiver.
-            final ResolveInfo resolveServiceInfo = findRecommendationService(potentialPkg);
-            if (resolveServiceInfo != null) {
-                final ComponentName componentName =
-                        new ComponentName(potentialPkg, resolveServiceInfo.serviceInfo.name);
-                return new NetworkScorerAppData(resolveServiceInfo.serviceInfo.applicationInfo.uid,
-                        componentName);
-            } else {
-                if (DEBUG) {
-                    Log.d(TAG, potentialPkg + " does not have the required components, skipping.");
-                }
-            }
-        }
-
-        // None of the configured packages are valid.
-        return null;
-    }
-
-    /**
-     * @return A priority order list of package names that have been granted the
-     *         permission needed for them to act as a network recommendation provider.
-     *         The packages in the returned list may not contain the other required
-     *         network recommendation provider components so additional checks are required
-     *         before making a package the network recommendation provider.
-     */
-    public List<String> getPotentialRecommendationProviderPackages() {
-        final String[] packageArray = mContext.getResources().getStringArray(
-                R.array.config_networkRecommendationPackageNames);
-        if (packageArray == null || packageArray.length == 0) {
-            if (DEBUG) {
-                Log.d(TAG, "No Network Recommendation Providers specified.");
-            }
-            return Collections.emptyList();
-        }
-
-        if (VERBOSE) {
-            Log.d(TAG, "Configured packages: " + TextUtils.join(", ", packageArray));
-        }
-
-        List<String> packages = new ArrayList<>();
-        final PackageManager pm = mContext.getPackageManager();
-        for (String potentialPkg : packageArray) {
-            if (pm.checkPermission(permission.SCORE_NETWORKS, potentialPkg)
-                    == PackageManager.PERMISSION_GRANTED) {
-                packages.add(potentialPkg);
-            } else {
-                if (DEBUG) {
-                    Log.d(TAG, potentialPkg + " has not been granted " + permission.SCORE_NETWORKS
-                            + ", skipping.");
-                }
-            }
-        }
-
-        return packages;
-    }
-
-    private ResolveInfo findRecommendationService(String packageName) {
-        final PackageManager pm = mContext.getPackageManager();
-        final int resolveFlags = 0;
-
-        final Intent serviceIntent = new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS);
-        serviceIntent.setPackage(packageName);
-        final ResolveInfo resolveServiceInfo =
-                pm.resolveService(serviceIntent, resolveFlags);
-
-        if (VERBOSE) {
-            Log.d(TAG, "Resolved " + serviceIntent + " to " + resolveServiceInfo);
-        }
-
-        if (resolveServiceInfo != null && resolveServiceInfo.serviceInfo != null) {
-            return resolveServiceInfo;
-        }
-
-        if (VERBOSE) {
-            Log.v(TAG, packageName + " does not have a service for " + serviceIntent);
-        }
-        return null;
-    }
-
-    /**
-     * Get the application to use for scoring networks.
-     *
-     * @return the scorer app info or null if scoring is disabled (including if no scorer was ever
-     *     selected) or if the previously-set scorer is no longer a valid scorer app (e.g. because
-     *     it was disabled or uninstalled).
-     */
-    @Nullable
-    public NetworkScorerAppData getActiveScorer() {
-        if (isNetworkRecommendationsDisabled()) {
-            // If recommendations are disabled then there can't be an active scorer.
-            return null;
-        }
-
-        // Otherwise return the recommendation provider (which may be null).
-        return getNetworkRecommendationProviderData();
-    }
-
-    /**
-     * Set the specified package as the default scorer application.
-     *
-     * <p>The caller must have permission to write to {@link android.provider.Settings.Global}.
-     *
-     * @param packageName the packageName of the new scorer to use. If null, scoring will be
-     *     disabled. Otherwise, the scorer will only be set if it is a valid scorer application.
-     * @return true if the scorer was changed, or false if the package is not a valid scorer or
-     *         a valid network recommendation provider exists.
-     * @deprecated Scorers are now selected from a configured list.
-     */
-    @Deprecated
-    public boolean setActiveScorer(String packageName) {
-        return false;
-    }
-
-    private boolean isNetworkRecommendationsDisabled() {
-        final ContentResolver cr = mContext.getContentResolver();
-        // A value of 1 indicates enabled.
-        return Settings.Global.getInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0) != 1;
-    }
-}
diff --git a/core/java/android/net/ScoredNetwork.java b/core/java/android/net/ScoredNetwork.java
index ba0a8b5..a664a8b 100644
--- a/core/java/android/net/ScoredNetwork.java
+++ b/core/java/android/net/ScoredNetwork.java
@@ -41,7 +41,7 @@
      * Key used with the {@link #attributes} bundle to define the badging curve.
      *
      * <p>The badging curve is a {@link RssiCurve} used to map different RSSI values to {@link
-     * Badging} enums.
+     * NetworkBadging.Badging} enums.
      */
     public static final String ATTRIBUTES_KEY_BADGING_CURVE =
             "android.net.attributes.key.BADGING_CURVE";
@@ -70,17 +70,31 @@
     public static final String ATTRIBUTES_KEY_RANKING_SCORE_OFFSET =
             "android.net.attributes.key.RANKING_SCORE_OFFSET";
 
+    /** A {@link NetworkKey} uniquely identifying this network. */
+    public final NetworkKey networkKey;
+
+    // TODO(b/35323372): Delete these once external references are switched.
+    /** @deprecated Use {@link NetworkBadging#Badging} instead. */
+    @Deprecated
     @IntDef({BADGING_NONE, BADGING_SD, BADGING_HD, BADGING_4K})
     @Retention(RetentionPolicy.SOURCE)
     public @interface Badging {}
 
+    /** @deprecated Use {@link NetworkBadging#BADGING_NONE} instead. */
+    @Deprecated
     public static final int BADGING_NONE = 0;
-    public static final int BADGING_SD = 10;
-    public static final int BADGING_HD = 20;
-    public static final int BADGING_4K = 30;
 
-    /** A {@link NetworkKey} uniquely identifying this network. */
-    public final NetworkKey networkKey;
+    /** @deprecated Use {@link NetworkBadging#BADGING_SD} instead. */
+    @Deprecated
+    public static final int BADGING_SD = 10;
+
+    /** @deprecated Use {@link NetworkBadging#BADGING_HD} instead. */
+    @Deprecated
+    public static final int BADGING_HD = 20;
+
+    /** @deprecated Use {@link NetworkBadging#BADGING_4K} instead. */
+    @Deprecated
+    public static final int BADGING_4K = 30;
 
     /**
      * The {@link RssiCurve} representing the scores for this network based on the RSSI.
@@ -276,14 +290,14 @@
     }
 
     /**
-     * Return the {@link Badging} enum for this network for the given RSSI, derived from the
+     * Return the {@link NetworkBadging.Badging} enum for this network for the given RSSI, derived from the
      * badging curve.
      *
      * <p>If no badging curve is present, {@link #BADGE_NONE} will be returned.
      *
      * @param rssi The rssi level for which the badge should be calculated
      */
-    @Badging
+    @NetworkBadging.Badging
     public int calculateBadge(int rssi) {
         if (attributes != null && attributes.containsKey(ATTRIBUTES_KEY_BADGING_CURVE)) {
             RssiCurve badgingCurve =
@@ -291,7 +305,7 @@
             return badgingCurve.lookupScore(rssi);
         }
 
-        return BADGING_NONE;
+        return NetworkBadging.BADGING_NONE;
     }
 
     public static final Parcelable.Creator<ScoredNetwork> CREATOR =
diff --git a/core/java/android/net/http/SslCertificate.java b/core/java/android/net/http/SslCertificate.java
index 2715af0..4c0f418 100644
--- a/core/java/android/net/http/SslCertificate.java
+++ b/core/java/android/net/http/SslCertificate.java
@@ -506,6 +506,6 @@
         if (certificateDate == null) {
             return "";
         }
-        return DateFormat.getDateFormat(context).format(certificateDate);
+        return DateFormat.getMediumDateFormat(context).format(certificateDate);
     }
 }
diff --git a/core/java/android/net/metrics/ApfProgramEvent.java b/core/java/android/net/metrics/ApfProgramEvent.java
index 258d8e1..c2795a2a 100644
--- a/core/java/android/net/metrics/ApfProgramEvent.java
+++ b/core/java/android/net/metrics/ApfProgramEvent.java
@@ -17,7 +17,6 @@
 package android.net.metrics;
 
 import android.annotation.IntDef;
-import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -36,7 +35,6 @@
  * the APF program in place with a new APF program.
  * {@hide}
  */
-@SystemApi
 public final class ApfProgramEvent implements Parcelable {
 
     // Bitflag constants describing what an Apf program filters.
@@ -55,7 +53,6 @@
     public final int programLength; // Length of the APF program in bytes
     public final int flags;         // Bitfield compound of FLAG_* constants
 
-    /** {@hide} */
     public ApfProgramEvent(
             long lifetime, int filteredRas, int currentRas, int programLength, @Flags int flags) {
         this.lifetime = lifetime;
@@ -105,7 +102,6 @@
         }
     };
 
-    /** {@hide} */
     public static @Flags int flagsFor(boolean hasIPv4, boolean multicastFilterOn) {
         int bitfield = 0;
         if (hasIPv4) {
diff --git a/core/java/android/net/metrics/ApfStats.java b/core/java/android/net/metrics/ApfStats.java
index 8451e53..f8d7fa9 100644
--- a/core/java/android/net/metrics/ApfStats.java
+++ b/core/java/android/net/metrics/ApfStats.java
@@ -16,7 +16,6 @@
 
 package android.net.metrics;
 
-import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -24,7 +23,6 @@
  * An event logged for an interface with APF capabilities when its IpManager state machine exits.
  * {@hide}
  */
-@SystemApi
 public final class ApfStats implements Parcelable {
 
     public final long durationMs;     // time interval in milliseconds these stastistics covers
@@ -36,7 +34,6 @@
     public final int programUpdates;  // number of APF program updates
     public final int maxProgramSize;  // maximum APF program size advertised by hardware
 
-    /** {@hide} */
     public ApfStats(long durationMs, int receivedRas, int matchingRas, int droppedRas,
             int zeroLifetimeRas, int parseErrors, int programUpdates, int maxProgramSize) {
         this.durationMs = durationMs;
diff --git a/core/java/android/net/metrics/DefaultNetworkEvent.java b/core/java/android/net/metrics/DefaultNetworkEvent.java
index 9f0bad7..28cf42f 100644
--- a/core/java/android/net/metrics/DefaultNetworkEvent.java
+++ b/core/java/android/net/metrics/DefaultNetworkEvent.java
@@ -16,7 +16,6 @@
 
 package android.net.metrics;
 
-import android.annotation.SystemApi;
 import android.net.NetworkCapabilities;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -25,7 +24,6 @@
  * An event recorded by ConnectivityService when there is a change in the default network.
  * {@hide}
  */
-@SystemApi
 public final class DefaultNetworkEvent implements Parcelable {
     // The ID of the network that has become the new default or NETID_UNSET if none.
     public final int netId;
@@ -38,7 +36,6 @@
     public final boolean prevIPv4;
     public final boolean prevIPv6;
 
-    /** {@hide} */
     public DefaultNetworkEvent(int netId, int[] transportTypes,
                 int prevNetId, boolean prevIPv4, boolean prevIPv6) {
         this.netId = netId;
@@ -106,8 +103,4 @@
             return new DefaultNetworkEvent[size];
         }
     };
-
-    public static void logEvent(
-            int netId, int[] transports, int prevNetId, boolean hadIPv4, boolean hadIPv6) {
-    }
 }
diff --git a/core/java/android/net/metrics/DhcpClientEvent.java b/core/java/android/net/metrics/DhcpClientEvent.java
index 4a9ff05..7e30ab5 100644
--- a/core/java/android/net/metrics/DhcpClientEvent.java
+++ b/core/java/android/net/metrics/DhcpClientEvent.java
@@ -16,7 +16,6 @@
 
 package android.net.metrics;
 
-import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -24,7 +23,6 @@
  * An event recorded when a DhcpClient state machine transitions to a new state.
  * {@hide}
  */
-@SystemApi
 public final class DhcpClientEvent implements Parcelable {
 
     // Names for recording DhcpClient pseudo-state transitions.
@@ -37,7 +35,6 @@
     public final String msg;
     public final int durationMs;
 
-    /** {@hide} */
     public DhcpClientEvent(String ifName, String msg, int durationMs) {
         this.ifName = ifName;
         this.msg = msg;
@@ -77,7 +74,4 @@
             return new DhcpClientEvent[size];
         }
     };
-
-    public static void logStateEvent(String ifName, String state) {
-    }
 }
diff --git a/core/java/android/net/metrics/DhcpErrorEvent.java b/core/java/android/net/metrics/DhcpErrorEvent.java
index c3abcf7..f34ffdf 100644
--- a/core/java/android/net/metrics/DhcpErrorEvent.java
+++ b/core/java/android/net/metrics/DhcpErrorEvent.java
@@ -16,7 +16,6 @@
 
 package android.net.metrics;
 
-import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.SparseArray;
@@ -27,7 +26,6 @@
  * Event class used to record error events when parsing DHCP response packets.
  * {@hide}
  */
-@SystemApi
 public final class DhcpErrorEvent implements Parcelable {
     public static final int L2_ERROR   = 1;
     public static final int L3_ERROR   = 2;
@@ -50,12 +48,10 @@
     public static final int DHCP_INVALID_OPTION_LENGTH = makeErrorCode(DHCP_ERROR, 3);
     public static final int DHCP_NO_MSG_TYPE           = makeErrorCode(DHCP_ERROR, 4);
     public static final int DHCP_UNKNOWN_MSG_TYPE      = makeErrorCode(DHCP_ERROR, 5);
-    /** {@hide} */
     public static final int DHCP_NO_COOKIE             = makeErrorCode(DHCP_ERROR, 6);
 
     public static final int BUFFER_UNDERFLOW           = makeErrorCode(MISC_ERROR, 1);
     public static final int RECEIVE_ERROR              = makeErrorCode(MISC_ERROR, 2);
-    /** {@hide} */
     public static final int PARSING_ERROR              = makeErrorCode(MISC_ERROR, 3);
 
     public final String ifName;
@@ -66,7 +62,6 @@
     // byte 3: optional code
     public final int errorCode;
 
-    /** {@hide} */
     public DhcpErrorEvent(String ifName, int errorCode) {
         this.ifName = ifName;
         this.errorCode = errorCode;
@@ -99,12 +94,6 @@
         }
     };
 
-    public static void logParseError(String ifName, int errorCode) {
-    }
-
-    public static void logReceiveError(String ifName) {
-    }
-
     public static int errorCodeWithOption(int errorCode, int option) {
         return (0xFFFF0000 & errorCode) | (0xFF & option);
     }
diff --git a/core/java/android/net/metrics/DnsEvent.java b/core/java/android/net/metrics/DnsEvent.java
index 6176b2c..89ae1c2 100644
--- a/core/java/android/net/metrics/DnsEvent.java
+++ b/core/java/android/net/metrics/DnsEvent.java
@@ -16,7 +16,6 @@
 
 package android.net.metrics;
 
-import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -24,7 +23,6 @@
  * A DNS event recorded by NetdEventListenerService.
  * {@hide}
  */
-@SystemApi
 final public class DnsEvent implements Parcelable {
     public final int netId;
 
@@ -38,7 +36,6 @@
     // queries.
     public final int[] latenciesMs;
 
-    /** {@hide} */
     public DnsEvent(int netId, byte[] eventTypes, byte[] returnCodes, int[] latenciesMs) {
         this.netId = netId;
         this.eventTypes = eventTypes;
@@ -82,8 +79,4 @@
             return new DnsEvent[size];
         }
     };
-
-    public static void logEvent(
-            int netId, byte[] eventTypes, byte[] returnCodes, int[] latenciesMs) {
-    }
 }
diff --git a/core/java/android/net/metrics/IpManagerEvent.java b/core/java/android/net/metrics/IpManagerEvent.java
index e0a026e..50dda7c 100644
--- a/core/java/android/net/metrics/IpManagerEvent.java
+++ b/core/java/android/net/metrics/IpManagerEvent.java
@@ -17,7 +17,6 @@
 package android.net.metrics;
 
 import android.annotation.IntDef;
-import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.SparseArray;
@@ -32,17 +31,15 @@
  * when a network disconnects.
  * {@hide}
  */
-@SystemApi
 public final class IpManagerEvent implements Parcelable {
 
-    public static final int PROVISIONING_OK    = 1;
-    public static final int PROVISIONING_FAIL  = 2;
-    public static final int COMPLETE_LIFECYCLE = 3;
-    /** @hide */ public static final int ERROR_STARTING_IPV4 = 4;
-    /** @hide */ public static final int ERROR_STARTING_IPV6 = 5;
-    /** @hide */ public static final int ERROR_STARTING_IPREACHABILITYMONITOR = 6;
+    public static final int PROVISIONING_OK                       = 1;
+    public static final int PROVISIONING_FAIL                     = 2;
+    public static final int COMPLETE_LIFECYCLE                    = 3;
+    public static final int ERROR_STARTING_IPV4                   = 4;
+    public static final int ERROR_STARTING_IPV6                   = 5;
+    public static final int ERROR_STARTING_IPREACHABILITYMONITOR  = 6;
 
-    /** {@hide} */
     @IntDef(value = {
             PROVISIONING_OK, PROVISIONING_FAIL, COMPLETE_LIFECYCLE,
             ERROR_STARTING_IPV4, ERROR_STARTING_IPV6, ERROR_STARTING_IPREACHABILITYMONITOR,
@@ -54,7 +51,6 @@
     public final @EventType int eventType;
     public final long durationMs;
 
-    /** {@hide} */
     public IpManagerEvent(String ifName, @EventType int eventType, long duration) {
         this.ifName = ifName;
         this.eventType = eventType;
@@ -90,9 +86,6 @@
         }
     };
 
-    public static void logEvent(int eventType, String ifName, long durationMs) {
-    }
-
     @Override
     public String toString() {
         return String.format("IpManagerEvent(%s, %s, %dms)",
diff --git a/core/java/android/net/metrics/IpReachabilityEvent.java b/core/java/android/net/metrics/IpReachabilityEvent.java
index ee09e22..d69e806 100644
--- a/core/java/android/net/metrics/IpReachabilityEvent.java
+++ b/core/java/android/net/metrics/IpReachabilityEvent.java
@@ -16,7 +16,6 @@
 
 package android.net.metrics;
 
-import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.SparseArray;
@@ -28,7 +27,6 @@
  * a neighbor probe result.
  * {@hide}
  */
-@SystemApi
 public final class IpReachabilityEvent implements Parcelable {
 
     // Event types.
@@ -38,9 +36,9 @@
     public static final int NUD_FAILED                = 2 << 8;
     /** Neighbor unreachable after a forced probe, IP provisioning is also lost. */
     public static final int PROVISIONING_LOST         = 3 << 8;
-    /** {@hide} Neighbor unreachable notification from kernel. */
+    /** Neighbor unreachable notification from kernel. */
     public static final int NUD_FAILED_ORGANIC        = 4 << 8;
-    /** {@hide} Neighbor unreachable notification from kernel, IP provisioning is also lost. */
+    /** Neighbor unreachable notification from kernel, IP provisioning is also lost. */
     public static final int PROVISIONING_LOST_ORGANIC = 5 << 8;
 
     public final String ifName;
@@ -51,7 +49,6 @@
     // byte 3: when byte 2 == PROBE, errno code from RTNetlink or IpReachabilityMonitor.
     public final int eventType;
 
-    /** {@hide} */
     public IpReachabilityEvent(String ifName, int eventType) {
         this.ifName = ifName;
         this.eventType = eventType;
@@ -84,18 +81,8 @@
         }
     };
 
-    public static void logProbeEvent(String ifName, int nlErrorCode) {
-    }
-
-    public static void logNudFailed(String ifName) {
-    }
-
-    public static void logProvisioningLost(String ifName) {
-    }
-
     /**
      * Returns the NUD failure event type code corresponding to the given conditions.
-     * {@hide}
      */
     public static int nudFailureEventType(boolean isFromProbe, boolean isProvisioningLost) {
         if (isFromProbe) {
diff --git a/core/java/android/net/metrics/NetworkEvent.java b/core/java/android/net/metrics/NetworkEvent.java
index 0667495..4df3bf0 100644
--- a/core/java/android/net/metrics/NetworkEvent.java
+++ b/core/java/android/net/metrics/NetworkEvent.java
@@ -17,7 +17,6 @@
 package android.net.metrics;
 
 import android.annotation.IntDef;
-import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.SparseArray;
@@ -30,7 +29,6 @@
 /**
  * {@hide}
  */
-@SystemApi
 public final class NetworkEvent implements Parcelable {
 
     public static final int NETWORK_CONNECTED            = 1;
@@ -41,16 +39,11 @@
     public static final int NETWORK_UNLINGER             = 6;
     public static final int NETWORK_DISCONNECTED         = 7;
 
-    /** {@hide} */
     public static final int NETWORK_FIRST_VALIDATION_SUCCESS      = 8;
-    /** {@hide} */
     public static final int NETWORK_REVALIDATION_SUCCESS          = 9;
-    /** {@hide} */
     public static final int NETWORK_FIRST_VALIDATION_PORTAL_FOUND = 10;
-    /** {@hide} */
     public static final int NETWORK_REVALIDATION_PORTAL_FOUND     = 11;
 
-    /** {@hide} */
     @IntDef(value = {
             NETWORK_CONNECTED,
             NETWORK_VALIDATED,
@@ -71,14 +64,12 @@
     public final @EventType int eventType;
     public final long durationMs;
 
-    /** {@hide} */
     public NetworkEvent(int netId, @EventType int eventType, long durationMs) {
         this.netId = netId;
         this.eventType = eventType;
         this.durationMs = durationMs;
     }
 
-    /** {@hide} */
     public NetworkEvent(int netId, @EventType int eventType) {
         this(netId, eventType, 0);
     }
@@ -112,15 +103,6 @@
         }
     };
 
-    public static void logEvent(int netId, int eventType) {
-    }
-
-    public static void logValidated(int netId, long durationMs) {
-    }
-
-    public static void logCaptivePortalFound(int netId, long durationMs) {
-    }
-
     @Override
     public String toString() {
         return String.format("NetworkEvent(%d, %s, %dms)",
diff --git a/core/java/android/net/metrics/RaEvent.java b/core/java/android/net/metrics/RaEvent.java
index 91bd023..3249f80 100644
--- a/core/java/android/net/metrics/RaEvent.java
+++ b/core/java/android/net/metrics/RaEvent.java
@@ -16,7 +16,6 @@
 
 package android.net.metrics;
 
-import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -24,10 +23,8 @@
  * An event logged when the APF packet socket receives an RA packet.
  * {@hide}
  */
-@SystemApi
 public final class RaEvent implements Parcelable {
 
-    /** {@hide} */
     public static final long NO_LIFETIME = -1L;
 
     // Lifetime in seconds of options found in a single RA packet.
@@ -39,7 +36,6 @@
     public final long rdnssLifetime;
     public final long dnsslLifetime;
 
-    /** {@hide} */
     public RaEvent(long routerLifetime, long prefixValidLifetime, long prefixPreferredLifetime,
             long routeInfoLifetime, long rdnssLifetime, long dnsslLifetime) {
         this.routerLifetime = routerLifetime;
@@ -96,7 +92,6 @@
         }
     };
 
-    /** {@hide} */
     public static class Builder {
 
         long routerLifetime          = NO_LIFETIME;
diff --git a/core/java/android/net/metrics/ValidationProbeEvent.java b/core/java/android/net/metrics/ValidationProbeEvent.java
index a724ec1..70c6e84 100644
--- a/core/java/android/net/metrics/ValidationProbeEvent.java
+++ b/core/java/android/net/metrics/ValidationProbeEvent.java
@@ -17,7 +17,6 @@
 package android.net.metrics;
 
 import android.annotation.IntDef;
-import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.SparseArray;
@@ -31,14 +30,12 @@
  * An event recorded by NetworkMonitor when sending a probe for finding captive portals.
  * {@hide}
  */
-@SystemApi
 public final class ValidationProbeEvent implements Parcelable {
 
     public static final int PROBE_DNS       = 0;
     public static final int PROBE_HTTP      = 1;
     public static final int PROBE_HTTPS     = 2;
     public static final int PROBE_PAC       = 3;
-    /** {@hide} */
     public static final int PROBE_FALLBACK  = 4;
 
     public static final int DNS_FAILURE = 0;
@@ -47,7 +44,6 @@
     private static final int FIRST_VALIDATION  = 1 << 8;
     private static final int REVALIDATION      = 2 << 8;
 
-    /** {@hide} */
     @IntDef(value = {DNS_FAILURE, DNS_SUCCESS})
     @Retention(RetentionPolicy.SOURCE)
     public @interface ReturnCode {}
@@ -62,7 +58,6 @@
     public final int probeType;
     public final @ReturnCode int returnCode;
 
-    /** {@hide} */
     public ValidationProbeEvent(
             int netId, long durationMs, int probeType, @ReturnCode int returnCode) {
         this.netId = netId;
@@ -102,24 +97,18 @@
         }
     };
 
-    /** @hide */
     public static int makeProbeType(int probeType, boolean firstValidation) {
         return (probeType & 0xff) | (firstValidation ? FIRST_VALIDATION : REVALIDATION);
     }
 
-    /** @hide */
     public static String getProbeName(int probeType) {
         return Decoder.constants.get(probeType & 0xff, "PROBE_???");
     }
 
-    /** @hide */
     public static String getValidationStage(int probeType) {
         return Decoder.constants.get(probeType & 0xff00, "UNKNOWN");
     }
 
-    public static void logEvent(int netId, long durationMs, int probeType, int returnCode) {
-    }
-
     @Override
     public String toString() {
         return String.format("ValidationProbeEvent(%d, %s:%d %s, %dms)", netId,
diff --git a/core/java/android/nfc/NdefRecord.java b/core/java/android/nfc/NdefRecord.java
index bd32314..2c9ce3f 100644
--- a/core/java/android/nfc/NdefRecord.java
+++ b/core/java/android/nfc/NdefRecord.java
@@ -839,7 +839,7 @@
 
                 if (cf && !inChunk) {
                     // first chunk
-                    if (typeLength == 0) {
+                    if (typeLength == 0 && tnf != NdefRecord.TNF_UNKNOWN) {
                         throw new FormatException("expected non-zero type length in first chunk");
                     }
                     chunks.clear();
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index 14760ab..e82fe03 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -341,7 +341,7 @@
                     final int N = fromMap.size();
                     mMap = new ArrayMap<>(N);
                     for (int i = 0; i < N; i++) {
-                        mMap.append(fromMap.keyAt(i), deepcopyValue(fromMap.valueAt(i)));
+                        mMap.append(fromMap.keyAt(i), deepCopyValue(fromMap.valueAt(i)));
                     }
                 }
             } else {
@@ -352,14 +352,14 @@
         }
     }
 
-    Object deepcopyValue(Object value) {
+    Object deepCopyValue(Object value) {
         if (value == null) {
             return null;
         }
         if (value instanceof Bundle) {
-            return ((Bundle)value).deepcopy();
+            return ((Bundle)value).deepCopy();
         } else if (value instanceof PersistableBundle) {
-            return ((PersistableBundle)value).deepcopy();
+            return ((PersistableBundle)value).deepCopy();
         } else if (value instanceof ArrayList) {
             return deepcopyArrayList((ArrayList) value);
         } else if (value.getClass().isArray()) {
@@ -388,7 +388,7 @@
         final int N = from.size();
         ArrayList out = new ArrayList(N);
         for (int i=0; i<N; i++) {
-            out.add(deepcopyValue(from.get(i)));
+            out.add(deepCopyValue(from.get(i)));
         }
         return out;
     }
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index 3a441c7..734d89e 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -118,6 +118,13 @@
      */
      public static final String EXTRA_CHARGE_COUNTER = "charge_counter";
 
+    /**
+     * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
+     * Current int sequence number of the update.
+     * {@hide}
+     */
+    public static final String EXTRA_SEQUENCE = "seq";
+
     // values for "status" field in the ACTION_BATTERY_CHANGED Intent
     public static final int BATTERY_STATUS_UNKNOWN = Constants.BATTERY_STATUS_UNKNOWN;
     public static final int BATTERY_STATUS_CHARGING = Constants.BATTERY_STATUS_CHARGING;
@@ -204,7 +211,7 @@
     /**
      * Battery charge status, from a BATTERY_STATUS_* value.
      */
-    public static final int BATTERY_PROPERTY_BATTERY_STATUS = 6;
+    public static final int BATTERY_PROPERTY_STATUS = 6;
 
     private final IBatteryStats mBatteryStats;
     private final IBatteryPropertiesRegistrar mBatteryPropertiesRegistrar;
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 013972d..dc170ed 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -2186,7 +2186,11 @@
     public static final int NETWORK_WIFI_TX_DATA = 3;
     public static final int NETWORK_BT_RX_DATA = 4;
     public static final int NETWORK_BT_TX_DATA = 5;
-    public static final int NUM_NETWORK_ACTIVITY_TYPES = NETWORK_BT_TX_DATA + 1;
+    public static final int NETWORK_MOBILE_BG_RX_DATA = 6;
+    public static final int NETWORK_MOBILE_BG_TX_DATA = 7;
+    public static final int NETWORK_WIFI_BG_RX_DATA = 8;
+    public static final int NETWORK_WIFI_BG_TX_DATA = 9;
+    public static final int NUM_NETWORK_ACTIVITY_TYPES = NETWORK_WIFI_BG_TX_DATA + 1;
 
     public abstract long getNetworkActivityBytes(int type, int which);
     public abstract long getNetworkActivityPackets(int type, int which);
@@ -2406,6 +2410,10 @@
     // Step duration mode: the screen is on, off, dozed, etc; value is Display.STATE_* - 1.
     public static final int STEP_LEVEL_MODE_SCREEN_STATE = 0x03;
 
+    // The largest value for screen state that is tracked in battery states. Any values above
+    // this should be mapped back to one of the tracked values before being tracked here.
+    public static final int MAX_TRACKED_SCREEN_STATE = Display.STATE_DOZE_SUSPEND;
+
     // Step duration mode: power save is on.
     public static final int STEP_LEVEL_MODE_POWER_SAVE = 0x04;
 
@@ -3133,8 +3141,8 @@
                 for (Map.Entry<String, ? extends Timer> ent : kernelWakelocks.entrySet()) {
                     sb.setLength(0);
                     printWakeLockCheckin(sb, ent.getValue(), rawRealtime, null, which, "");
-                    dumpLine(pw, 0 /* uid */, category, KERNEL_WAKELOCK_DATA, ent.getKey(),
-                            sb.toString());
+                    dumpLine(pw, 0 /* uid */, category, KERNEL_WAKELOCK_DATA,
+                            "\"" + ent.getKey() + "\"", sb.toString());
                 }
             }
             final Map<String, ? extends Timer> wakeupReasons = getWakeupReasonStats();
@@ -3233,16 +3241,39 @@
             final long wifiWakeup = u.getWifiRadioApWakeupCount(which);
             final long btBytesRx = u.getNetworkActivityBytes(NETWORK_BT_RX_DATA, which);
             final long btBytesTx = u.getNetworkActivityBytes(NETWORK_BT_TX_DATA, which);
+            // Background data transfers
+            final long mobileBytesBgRx = u.getNetworkActivityBytes(NETWORK_MOBILE_BG_RX_DATA,
+                    which);
+            final long mobileBytesBgTx = u.getNetworkActivityBytes(NETWORK_MOBILE_BG_TX_DATA,
+                    which);
+            final long wifiBytesBgRx = u.getNetworkActivityBytes(NETWORK_WIFI_BG_RX_DATA, which);
+            final long wifiBytesBgTx = u.getNetworkActivityBytes(NETWORK_WIFI_BG_TX_DATA, which);
+            final long mobilePacketsBgRx = u.getNetworkActivityPackets(NETWORK_MOBILE_BG_RX_DATA,
+                    which);
+            final long mobilePacketsBgTx = u.getNetworkActivityPackets(NETWORK_MOBILE_BG_TX_DATA,
+                    which);
+            final long wifiPacketsBgRx = u.getNetworkActivityPackets(NETWORK_WIFI_BG_RX_DATA,
+                    which);
+            final long wifiPacketsBgTx = u.getNetworkActivityPackets(NETWORK_WIFI_BG_TX_DATA,
+                    which);
+
             if (mobileBytesRx > 0 || mobileBytesTx > 0 || wifiBytesRx > 0 || wifiBytesTx > 0
                     || mobilePacketsRx > 0 || mobilePacketsTx > 0 || wifiPacketsRx > 0
                     || wifiPacketsTx > 0 || mobileActiveTime > 0 || mobileActiveCount > 0
-                    || btBytesRx > 0 || btBytesTx > 0 || mobileWakeup > 0 || wifiWakeup > 0) {
+                    || btBytesRx > 0 || btBytesTx > 0 || mobileWakeup > 0 || wifiWakeup > 0
+                    || mobileBytesBgRx > 0 || mobileBytesBgTx > 0 || wifiBytesBgRx > 0
+                    || wifiBytesBgTx > 0
+                    || mobilePacketsBgRx > 0 || mobilePacketsBgTx > 0 || wifiPacketsBgRx > 0
+                    || wifiPacketsBgTx > 0) {
                 dumpLine(pw, uid, category, NETWORK_DATA, mobileBytesRx, mobileBytesTx,
                         wifiBytesRx, wifiBytesTx,
                         mobilePacketsRx, mobilePacketsTx,
                         wifiPacketsRx, wifiPacketsTx,
                         mobileActiveTime, mobileActiveCount,
-                        btBytesRx, btBytesTx, mobileWakeup, wifiWakeup);
+                        btBytesRx, btBytesTx, mobileWakeup, wifiWakeup,
+                        mobileBytesBgRx, mobileBytesBgTx, wifiBytesBgRx, wifiBytesBgTx,
+                        mobilePacketsBgRx, mobilePacketsBgTx, wifiPacketsBgRx, wifiPacketsBgTx
+                        );
             }
 
             // Dump modem controller data, per UID.
@@ -3312,7 +3343,8 @@
                 final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
                 final int count = timer.getCountLocked(which);
                 if (totalTime != 0) {
-                    dumpLine(pw, uid, category, SYNC_DATA, syncs.keyAt(isy), totalTime, count);
+                    dumpLine(pw, uid, category, SYNC_DATA, "\"" + syncs.keyAt(isy) + "\"",
+                            totalTime, count);
                 }
             }
 
@@ -3323,7 +3355,8 @@
                 final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
                 final int count = timer.getCountLocked(which);
                 if (totalTime != 0) {
-                    dumpLine(pw, uid, category, JOB_DATA, jobs.keyAt(ij), totalTime, count);
+                    dumpLine(pw, uid, category, JOB_DATA, "\"" + jobs.keyAt(ij) + "\"",
+                            totalTime, count);
                 }
             }
 
@@ -3395,8 +3428,8 @@
 
                 if (userMillis != 0 || systemMillis != 0 || foregroundMillis != 0
                         || starts != 0 || numAnrs != 0 || numCrashes != 0) {
-                    dumpLine(pw, uid, category, PROCESS_DATA, processStats.keyAt(ipr), userMillis,
-                            systemMillis, foregroundMillis, starts, numAnrs, numCrashes);
+                    dumpLine(pw, uid, category, PROCESS_DATA, "\"" + processStats.keyAt(ipr) + "\"",
+                            userMillis, systemMillis, foregroundMillis, starts, numAnrs, numCrashes);
                 }
             }
 
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 817cb5b..0610499 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -275,7 +275,7 @@
          * Magic version number for a current development build, which has
          * not yet turned into an official release.
          */
-        public static final int CUR_DEVELOPMENT = 10000;
+        public static final int CUR_DEVELOPMENT = VMRuntime.SDK_VERSION_CUR_DEVELOPMENT;
 
         /**
          * October 2008: The original, first, version of Android.  Yay!
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index d04d6c2..c1292e7 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -98,9 +98,12 @@
 
     /**
      * Constructs a Bundle containing a copy of the mappings from the given
-     * Bundle.
+     * Bundle.  Does only a shallow copy of the original Bundle -- see
+     * {@link #deepCopy()} if that is not what you want.
      *
      * @param b a Bundle to be copied.
+     *
+     * @see #deepCopy()
      */
     public Bundle(Bundle b) {
         super(b);
@@ -109,9 +112,10 @@
 
     /**
      * Constructs a Bundle containing a copy of the mappings from the given
-     * PersistableBundle.
+     * PersistableBundle.  Does only a shallow copy of the PersistableBundle -- see
+     * {@link PersistableBundle#deepCopy()} if you don't want that.
      *
-     * @param b a Bundle to be copied.
+     * @param b a PersistableBundle to be copied.
      */
     public Bundle(PersistableBundle b) {
         super(b);
@@ -209,7 +213,7 @@
      * primitive arrays.  Other types of objects (such as Parcelable or Serializable)
      * are referenced as-is and not copied in any way.
      */
-    public Bundle deepcopy() {
+    public Bundle deepCopy() {
         Bundle b = new Bundle(false);
         b.copyInternal(this, true);
         return b;
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 39f4d42..5b0e5bbc 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -301,11 +301,6 @@
     }
 
     /** {@hide} */
-    public static File getDataProfilesDeForeignDexDirectory(int userId) {
-        return buildPath(getDataProfilesDeDirectory(userId), "foreign-dex");
-    }
-
-    /** {@hide} */
     public static File getDataAppDirectory(String volumeUuid) {
         return new File(getDataDirectory(volumeUuid), "app");
     }
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 7c015de..50b4f8c 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -432,14 +432,13 @@
      */
     public static boolean contains(File dir, File file) {
         if (dir == null || file == null) return false;
+        return contains(dir.getAbsolutePath(), file.getAbsolutePath());
+    }
 
-        String dirPath = dir.getAbsolutePath();
-        String filePath = file.getAbsolutePath();
-
+    public static boolean contains(String dirPath, String filePath) {
         if (dirPath.equals(filePath)) {
             return true;
         }
-
         if (!dirPath.endsWith("/")) {
             dirPath += "/";
         }
@@ -771,4 +770,22 @@
 
         return dir.mkdir() ? dir : null;
     }
+
+    /**
+     * Round the given size of a storage device to a nice round power-of-two
+     * value, such as 256MB or 32GB. This avoids showing weird values like
+     * "29.5GB" in UI.
+     */
+    public static long roundStorageSize(long size) {
+        long val = 1;
+        long pow = 1;
+        while ((val * pow) < size) {
+            val <<= 1;
+            if (val > 512) {
+                val = 1;
+                pow *= 1000;
+            }
+        }
+        return val * pow;
+    }
 }
diff --git a/core/java/android/os/HwBinder.java b/core/java/android/os/HwBinder.java
index e025494..b09c51c 100644
--- a/core/java/android/os/HwBinder.java
+++ b/core/java/android/os/HwBinder.java
@@ -43,9 +43,7 @@
             int code, HwParcel request, HwParcel reply, int flags)
         throws RemoteException;
 
-    public native final void registerService(
-            ArrayList<String> interfaceChain,
-            String serviceName)
+    public native final void registerService(String serviceName)
         throws RemoteException;
 
     public static native final IHwBinder getService(
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 1d464c0..b715780 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -2,22 +2,23 @@
 **
 ** Copyright 2007, The Android Open Source Project
 **
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
 **
-**     http://www.apache.org/licenses/LICENSE-2.0 
+**     http://www.apache.org/licenses/LICENSE-2.0
 **
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
 ** limitations under the License.
 */
 
 package android.os;
 
 import android.os.WorkSource;
+import android.os.PowerSaveState;
 
 /** @hide */
 
@@ -45,6 +46,7 @@
     void nap(long time);
     boolean isInteractive();
     boolean isPowerSaveMode();
+    PowerSaveState getPowerSaveState(int serviceType);
     boolean setPowerSaveMode(boolean mode);
     boolean isDeviceIdleMode();
     boolean isLightDeviceIdleMode();
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
index d299672..63d3e7a 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -18,8 +18,10 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.os.LooperProto;
 import android.util.Log;
 import android.util.Printer;
+import android.util.proto.ProtoOutputStream;
 
 /**
   * Class used to run a message loop for a thread.  Threads by default do
@@ -289,6 +291,16 @@
         mQueue.dump(pw, prefix + "  ");
     }
 
+    /** @hide */
+    public void writeToProto(ProtoOutputStream proto, long fieldId) {
+        final long looperToken = proto.start(fieldId);
+        proto.write(LooperProto.THREAD_NAME, mThread.getName());
+        proto.write(LooperProto.THREAD_ID, mThread.getId());
+        proto.write(LooperProto.IDENTITY_HASH_CODE, System.identityHashCode(this));
+        mQueue.writeToProto(proto, LooperProto.QUEUE);
+        proto.end(looperToken);
+    }
+
     @Override
     public String toString() {
         return "Looper (" + mThread.getName() + ", tid " + mThread.getId()
diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java
index 8c75847..d066db1 100644
--- a/core/java/android/os/Message.java
+++ b/core/java/android/os/Message.java
@@ -16,13 +16,15 @@
 
 package android.os;
 
+import android.os.MessageProto;
 import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
 
 /**
- * 
+ *
  * Defines a message containing a description and arbitrary data object that can be
  * sent to a {@link Handler}.  This object contains two extra int fields and an
- * extra object field that allow you to not do allocations in many cases.  
+ * extra object field that allow you to not do allocations in many cases.
  *
  * <p class="note">While the constructor of Message is public, the best way to get
  * one of these is to call {@link #obtain Message.obtain()} or one of the
@@ -31,7 +33,7 @@
  */
 public final class Message implements Parcelable {
     /**
-     * User-defined message code so that the recipient can identify 
+     * User-defined message code so that the recipient can identify
      * what this message is about. Each {@link Handler} has its own name-space
      * for message codes, so you do not need to worry about yours conflicting
      * with other handlers.
@@ -43,7 +45,7 @@
      * {@link #setData(Bundle) setData()} if you only need to store a
      * few integer values.
      */
-    public int arg1; 
+    public int arg1;
 
     /**
      * arg1 and arg2 are lower-cost alternatives to using
@@ -58,7 +60,7 @@
      * be non-null if it contains a Parcelable of a framework class (not one
      * implemented by the application).   For other data transfer use
      * {@link #setData}.
-     * 
+     *
      * <p>Note that Parcelable objects here are not supported prior to
      * the {@link android.os.Build.VERSION_CODES#FROYO} release.
      */
@@ -97,13 +99,13 @@
     /*package*/ int flags;
 
     /*package*/ long when;
-    
+
     /*package*/ Bundle data;
-    
+
     /*package*/ Handler target;
-    
+
     /*package*/ Runnable callback;
-    
+
     // sometimes we store linked lists of these things
     /*package*/ Message next;
 
@@ -216,9 +218,9 @@
     }
 
     /**
-     * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, 
+     * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>,
      * <em>arg1</em>, and <em>arg2</em> members.
-     * 
+     *
      * @param h  The <em>target</em> value to set.
      * @param what  The <em>what</em> value to set.
      * @param arg1  The <em>arg1</em> value to set.
@@ -236,9 +238,9 @@
     }
 
     /**
-     * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, 
+     * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>,
      * <em>arg1</em>, <em>arg2</em>, and <em>obj</em> members.
-     * 
+     *
      * @param h  The <em>target</em> value to set.
      * @param what  The <em>what</em> value to set.
      * @param arg1  The <em>arg1</em> value to set.
@@ -246,7 +248,7 @@
      * @param obj  The <em>obj</em> value to set.
      * @return  A Message object from the global pool.
      */
-    public static Message obtain(Handler h, int what, 
+    public static Message obtain(Handler h, int what,
             int arg1, int arg2, Object obj) {
         Message m = obtain();
         m.target = h;
@@ -339,7 +341,7 @@
     public long getWhen() {
         return when;
     }
-    
+
     public void setTarget(Handler target) {
         this.target = target;
     }
@@ -367,8 +369,8 @@
     public Runnable getCallback() {
         return callback;
     }
-    
-    /** 
+
+    /**
      * Obtains a Bundle of arbitrary data associated with this
      * event, lazily creating it if necessary. Set this value by calling
      * {@link #setData(Bundle)}.  Note that when transferring data across
@@ -383,11 +385,11 @@
         if (data == null) {
             data = new Bundle();
         }
-        
+
         return data;
     }
 
-    /** 
+    /**
      * Like getData(), but does not lazily create the Bundle.  A null
      * is returned if the Bundle does not already exist.  See
      * {@link #getData} for further information on this.
@@ -401,7 +403,7 @@
     /**
      * Sets a Bundle of arbitrary data values. Use arg1 and arg2 members
      * as a lower cost way to send a few simple integer values, if you can.
-     * @see #getData() 
+     * @see #getData()
      * @see #peekData()
      */
     public void setData(Bundle data) {
@@ -520,6 +522,37 @@
         return b.toString();
     }
 
+    void writeToProto(ProtoOutputStream proto, long fieldId) {
+        final long messageToken = proto.start(fieldId);
+        proto.write(MessageProto.WHEN, when);
+
+        if (target != null) {
+            if (callback != null) {
+                proto.write(MessageProto.CALLBACK, callback.getClass().getName());
+            } else {
+                proto.write(MessageProto.WHAT, what);
+            }
+
+            if (arg1 != 0) {
+                proto.write(MessageProto.ARG1, arg1);
+            }
+
+            if (arg2 != 0) {
+                proto.write(MessageProto.ARG2, arg2);
+            }
+
+            if (obj != null) {
+                proto.write(MessageProto.OBJ, obj.toString());
+            }
+
+            proto.write(MessageProto.TARGET, target.getClass().getName());
+        } else {
+            proto.write(MessageProto.BARRIER, arg1);
+        }
+
+        proto.end(messageToken);
+    }
+
     public static final Parcelable.Creator<Message> CREATOR
             = new Parcelable.Creator<Message>() {
         public Message createFromParcel(Parcel source) {
@@ -527,12 +560,12 @@
             msg.readFromParcel(source);
             return msg;
         }
-        
+
         public Message[] newArray(int size) {
             return new Message[size];
         }
     };
-        
+
     public int describeContents() {
         return 0;
     }
diff --git a/core/java/android/os/MessageQueue.java b/core/java/android/os/MessageQueue.java
index 4f2e968..2a8c52e 100644
--- a/core/java/android/os/MessageQueue.java
+++ b/core/java/android/os/MessageQueue.java
@@ -18,9 +18,11 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.os.MessageQueueProto;
 import android.util.Log;
 import android.util.Printer;
 import android.util.SparseArray;
+import android.util.proto.ProtoOutputStream;
 
 import java.io.FileDescriptor;
 import java.lang.annotation.Retention;
@@ -31,7 +33,7 @@
  * Low-level class holding the list of messages to be dispatched by a
  * {@link Looper}.  Messages are not added directly to a MessageQueue,
  * but rather through {@link Handler} objects associated with the Looper.
- * 
+ *
  * <p>You can retrieve the MessageQueue for the current thread with
  * {@link Looper#myQueue() Looper.myQueue()}.
  */
@@ -770,6 +772,18 @@
         }
     }
 
+    void writeToProto(ProtoOutputStream proto, long fieldId) {
+        final long messageQueueToken = proto.start(fieldId);
+        synchronized (this) {
+            for (Message msg = mMessages; msg != null; msg = msg.next) {
+                msg.writeToProto(proto, MessageQueueProto.MESSAGES);
+            }
+            proto.write(MessageQueueProto.IS_POLLING_LOCKED, isPollingLocked());
+            proto.write(MessageQueueProto.IS_QUITTING, mQuitting);
+        }
+        proto.end(messageQueueToken);
+    }
+
     /**
      * Callback interface for discovering when a thread is going to block
      * waiting for more messages.
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index 7702c17..8882672 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -546,6 +546,25 @@
     }
 
     /**
+     * Return the filesystem path of the real file on disk that is represented
+     * by the given {@link FileDescriptor}.
+     *
+     * @hide
+     */
+    public static File getFile(FileDescriptor fd) throws IOException {
+        try {
+            final String path = Os.readlink("/proc/self/fd/" + fd.getInt$());
+            if (OsConstants.S_ISREG(Os.stat(path).st_mode)) {
+                return new File(path);
+            } else {
+                throw new IOException("Not a regular file: " + path);
+            }
+        } catch (ErrnoException e) {
+            throw e.rethrowAsIOException();
+        }
+    }
+
+    /**
      * Retrieve the actual FileDescriptor associated with this object.
      *
      * @return Returns the FileDescriptor associated with this object.
diff --git a/core/java/android/os/PatternMatcher.java b/core/java/android/os/PatternMatcher.java
index 3890fbf..1f3a1e6 100644
--- a/core/java/android/os/PatternMatcher.java
+++ b/core/java/android/os/PatternMatcher.java
@@ -56,10 +56,8 @@
      * with full support for character ranges and the not ({@code ^}) modifier.
      * Supported modifiers include star ({@code *}) for zero-or-more, plus ({@code +})
      * for one-or-more and full range ({@code {...}}) support. This is a simple
-     * evaulation implementation in which matching is done against the pattern in
-     * realtime with no backtracking support.
-     *
-     * {@hide} Pending approval for public API
+     * evaluation implementation in which matching is done against the pattern in
+     * real time with no backtracking support.
      */
     public static final int PATTERN_ADVANCED_GLOB = 3;
 
diff --git a/core/java/android/os/PersistableBundle.java b/core/java/android/os/PersistableBundle.java
index 9b607837..75f9c11 100644
--- a/core/java/android/os/PersistableBundle.java
+++ b/core/java/android/os/PersistableBundle.java
@@ -76,9 +76,12 @@
 
     /**
      * Constructs a PersistableBundle containing a copy of the mappings from the given
-     * PersistableBundle.
+     * PersistableBundle.  Does only a shallow copy of the original PersistableBundle -- see
+     * {@link #deepCopy()} if that is not what you want.
      *
      * @param b a PersistableBundle to be copied.
+     *
+     * @see #deepCopy()
      */
     public PersistableBundle(PersistableBundle b) {
         super(b);
@@ -87,7 +90,7 @@
 
 
     /**
-     * Constructs a PersistableBundle from a Bundle.
+     * Constructs a PersistableBundle from a Bundle.  Does only a shallow copy of the Bundle.
      *
      * @param b a Bundle to be copied.
      *
@@ -167,7 +170,7 @@
      * primitive arrays.  Other types of objects (such as Parcelable or Serializable)
      * are referenced as-is and not copied in any way.
      */
-    public PersistableBundle deepcopy() {
+    public PersistableBundle deepCopy() {
         PersistableBundle b = new PersistableBundle(false);
         b.copyInternal(this, true);
         return b;
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 31b3bc9..a713eef 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -971,6 +971,24 @@
     }
 
     /**
+     * Get data about the battery saver mode for a specific service
+     * @param serviceType unique key for the service, one of
+     *             {@link com.android.server.power.BatterySaverPolicy.ServiceType}
+     * @return Battery saver state data.
+     *
+     * @hide
+     * @see com.android.server.power.BatterySaverPolicy
+     * @see PowerSaveState
+     */
+    public PowerSaveState getPowerSaveState(int serviceType) {
+        try {
+            return mService.getPowerSaveState(serviceType);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Returns true if the device is currently in idle mode.  This happens when a device
      * has been sitting unused and unmoving for a sufficiently long period of time, so that
      * it decides to go into a lower power-use state.  This may involve things like turning
diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java
index d0db255..44addfc 100644
--- a/core/java/android/os/PowerManagerInternal.java
+++ b/core/java/android/os/PowerManagerInternal.java
@@ -131,12 +131,13 @@
     public abstract void setDozeOverrideFromDreamManager(
             int screenState, int screenBrightness);
 
-    public abstract boolean getLowPowerModeEnabled();
+    public abstract PowerSaveState getLowPowerState(int serviceType);
 
     public abstract void registerLowPowerModeObserver(LowPowerModeListener listener);
 
     public interface LowPowerModeListener {
-        public void onLowPowerModeChanged(boolean enabled);
+        int getServiceType();
+        void onLowPowerModeChanged(PowerSaveState state);
     }
 
     public abstract boolean setDeviceIdleMode(boolean enabled);
diff --git a/graphics/tests/graphicstests/res/values/colors.xml b/core/java/android/os/PowerSaveState.aidl
similarity index 67%
copy from graphics/tests/graphicstests/res/values/colors.xml
copy to core/java/android/os/PowerSaveState.aidl
index 7559e65..e3f572d 100644
--- a/graphics/tests/graphicstests/res/values/colors.xml
+++ b/core/java/android/os/PowerSaveState.aidl
@@ -1,7 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2006, The Android Open Source Project
+/*
+** 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.
@@ -15,10 +13,7 @@
 ** See the License for the specific language governing permissions and
 ** limitations under the License.
 */
--->
-<resources>
-    <color name="testcolor1">#ff00ff00</color>
-    <color name="testcolor2">#ffff0000</color>
-    <color name="failColor">#ff0000ff</color>
-</resources>
 
+package android.os;
+
+parcelable PowerSaveState;
\ No newline at end of file
diff --git a/core/java/android/os/PowerSaveState.java b/core/java/android/os/PowerSaveState.java
new file mode 100644
index 0000000..9269e76
--- /dev/null
+++ b/core/java/android/os/PowerSaveState.java
@@ -0,0 +1,95 @@
+/* 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.
+*/
+
+package android.os;
+
+/**
+ * Data class for battery saver state. It contains the data
+ * <p>
+ * 1. Whether battery saver mode is enabled
+ * 2. Specific parameters to use in battery saver mode(i.e. screen brightness, gps mode)
+ *
+ * @hide
+ */
+public class PowerSaveState implements Parcelable {
+    public final boolean batterySaverEnabled;
+    public final int gpsMode;
+    public final float brightnessFactor;
+
+    public PowerSaveState(Builder builder) {
+        batterySaverEnabled = builder.mBatterySaverEnabled;
+        gpsMode = builder.mGpsMode;
+        brightnessFactor = builder.mBrightnessFactor;
+    }
+
+    public PowerSaveState(Parcel in) {
+        batterySaverEnabled = in.readByte() != 0;
+        gpsMode = in.readInt();
+        brightnessFactor = in.readFloat();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeByte((byte) (batterySaverEnabled ? 1 : 0));
+        dest.writeInt(gpsMode);
+        dest.writeFloat(brightnessFactor);
+    }
+
+    public static final class Builder {
+        private boolean mBatterySaverEnabled = false;
+        private int mGpsMode = 0;
+        private float mBrightnessFactor = 0.5f;
+
+        public Builder() {}
+
+        public Builder setBatterySaverEnabled(boolean enabled) {
+            mBatterySaverEnabled = enabled;
+            return this;
+        }
+
+        public Builder setGpsMode(int mode) {
+            mGpsMode = mode;
+            return this;
+        }
+
+        public Builder setBrightnessFactor(float factor) {
+            mBrightnessFactor = factor;
+            return this;
+        }
+
+        public PowerSaveState build() {
+            return new PowerSaveState(this);
+        }
+    }
+
+    public static final Parcelable.Creator<PowerSaveState>
+            CREATOR = new Parcelable.Creator<PowerSaveState>() {
+
+        @Override
+        public PowerSaveState createFromParcel(Parcel source) {
+            return new PowerSaveState(source);
+        }
+
+        @Override
+        public PowerSaveState[] newArray(int size) {
+            return new PowerSaveState[size];
+        }
+    };
+}
\ No newline at end of file
diff --git a/core/java/android/os/RemoteCallbackList.java b/core/java/android/os/RemoteCallbackList.java
index 819afb4..9db58ee 100644
--- a/core/java/android/os/RemoteCallbackList.java
+++ b/core/java/android/os/RemoteCallbackList.java
@@ -329,15 +329,38 @@
     }
 
     /**
-     * Return the cookies associated with a currently registered callback.  Note that this is
-     * <em>not</em> the same as {@link #getBroadcastCookie} and should not be used
-     * interchangeably with it.  This method returns the current cookied registered at the given
+     * Return a currently registered callback.  Note that this is
+     * <em>not</em> the same as {@link #getBroadcastItem} and should not be used
+     * interchangeably with it.  This method returns the registered callback at the given
      * index, not the current broadcast state.  This means that it is not itself thread-safe:
      * any call to {@link #register} or {@link #unregister} will change these indices, so you
      * must do your own thread safety between these to protect from such changes.
      *
-     * @param index Index of which registration cookie to return from 0 to
-     * {@link #getRegisteredCallbackCount()}.
+     * @param index Index of which callback registration to return, from 0 to
+     * {@link #getRegisteredCallbackCount()} - 1.
+     *
+     * @return Returns whatever callback is associated with this index, or null if
+     * {@link #kill()} has been called.
+     */
+    public E getRegisteredCallbackItem(int index) {
+        synchronized (mCallbacks) {
+            if (mKilled) {
+                return null;
+            }
+            return mCallbacks.valueAt(index).mCallback;
+        }
+    }
+
+    /**
+     * Return any cookie associated with a currently registered callback.  Note that this is
+     * <em>not</em> the same as {@link #getBroadcastCookie} and should not be used
+     * interchangeably with it.  This method returns the current cookie registered at the given
+     * index, not the current broadcast state.  This means that it is not itself thread-safe:
+     * any call to {@link #register} or {@link #unregister} will change these indices, so you
+     * must do your own thread safety between these to protect from such changes.
+     *
+     * @param index Index of which registration cookie to return, from 0 to
+     * {@link #getRegisteredCallbackCount()} - 1.
      *
      * @return Returns whatever cookie object is associated with this index, or null if
      * {@link #kill()} has been called.
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index b9e4bad..caea202 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -506,7 +506,7 @@
             }
 
             /**
-             * Detect unbuffered input/output operations.
+             * Disable detection of unbuffered input/output operations.
              */
             public Builder permitUnbufferedIo() {
                 return disable(DETECT_UNBUFFERED_IO);
diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java
index 78820b5..b525193 100644
--- a/core/java/android/os/SystemProperties.java
+++ b/core/java/android/os/SystemProperties.java
@@ -35,7 +35,6 @@
     private static final String TAG = "SystemProperties";
     private static final boolean TRACK_KEY_ACCESS = false;
 
-    public static final int PROP_NAME_MAX = 31;
     public static final int PROP_VALUE_MAX = 91;
 
     private static final ArrayList<Runnable> sChangeCallbacks = new ArrayList<Runnable>();
@@ -82,12 +81,8 @@
     /**
      * Get the value for the given key.
      * @return an empty string if the key isn't found
-     * @throws IllegalArgumentException if the key exceeds 32 characters
      */
     public static String get(String key) {
-        if (key.length() > PROP_NAME_MAX) {
-            throw newKeyTooLargeException(key);
-        }
         if (TRACK_KEY_ACCESS) onKeyAccess(key);
         return native_get(key);
     }
@@ -95,12 +90,8 @@
     /**
      * Get the value for the given key.
      * @return if the key isn't found, return def if it isn't null, or an empty string otherwise
-     * @throws IllegalArgumentException if the key exceeds 32 characters
      */
     public static String get(String key, String def) {
-        if (key.length() > PROP_NAME_MAX) {
-            throw newKeyTooLargeException(key);
-        }
         if (TRACK_KEY_ACCESS) onKeyAccess(key);
         return native_get(key, def);
     }
@@ -111,12 +102,8 @@
      * @param def a default value to return
      * @return the key parsed as an integer, or def if the key isn't found or
      *         cannot be parsed
-     * @throws IllegalArgumentException if the key exceeds 32 characters
      */
     public static int getInt(String key, int def) {
-        if (key.length() > PROP_NAME_MAX) {
-            throw newKeyTooLargeException(key);
-        }
         if (TRACK_KEY_ACCESS) onKeyAccess(key);
         return native_get_int(key, def);
     }
@@ -127,12 +114,8 @@
      * @param def a default value to return
      * @return the key parsed as a long, or def if the key isn't found or
      *         cannot be parsed
-     * @throws IllegalArgumentException if the key exceeds 32 characters
      */
     public static long getLong(String key, long def) {
-        if (key.length() > PROP_NAME_MAX) {
-            throw newKeyTooLargeException(key);
-        }
         if (TRACK_KEY_ACCESS) onKeyAccess(key);
         return native_get_long(key, def);
     }
@@ -148,25 +131,17 @@
      * @param def a default value to return
      * @return the key parsed as a boolean, or def if the key isn't found or is
      *         not able to be parsed as a boolean.
-     * @throws IllegalArgumentException if the key exceeds 32 characters
      */
     public static boolean getBoolean(String key, boolean def) {
-        if (key.length() > PROP_NAME_MAX) {
-            throw newKeyTooLargeException(key);
-        }
         if (TRACK_KEY_ACCESS) onKeyAccess(key);
         return native_get_boolean(key, def);
     }
 
     /**
      * Set the value for the given key.
-     * @throws IllegalArgumentException if the key exceeds 32 characters
      * @throws IllegalArgumentException if the value exceeds 92 characters
      */
     public static void set(String key, String val) {
-        if (key.length() > PROP_NAME_MAX) {
-            throw newKeyTooLargeException(key);
-        }
         if (val != null && val.length() > PROP_VALUE_MAX) {
             throw newValueTooLargeException(key, val);
         }
@@ -196,11 +171,6 @@
         }
     }
 
-    private static IllegalArgumentException newKeyTooLargeException(String key) {
-        return new IllegalArgumentException("system property key '" + key + "' is longer than "
-                + PROP_NAME_MAX + " characters");
-    }
-
     private static IllegalArgumentException newValueTooLargeException(String key, String value) {
         return new IllegalArgumentException("value of system property '" + key + "' is longer than "
                 + PROP_VALUE_MAX + " characters: " + value);
diff --git a/core/java/android/os/UpdateEngine.java b/core/java/android/os/UpdateEngine.java
index bf03cce..8549cff 100644
--- a/core/java/android/os/UpdateEngine.java
+++ b/core/java/android/os/UpdateEngine.java
@@ -26,7 +26,18 @@
 /**
  * UpdateEngine handles calls to the update engine which takes care of A/B OTA
  * updates. It wraps up the update engine Binder APIs and exposes them as
- * SystemApis, which will be called by system apps like GmsCore.
+ * SystemApis, which will be called by the system app responsible for OTAs.
+ * On a Google device, this will be GmsCore.
+ *
+ * The minimal flow is:
+ * <ol>
+ * <li>Create a new UpdateEngine instance.
+ * <li>Call {@link #bind}, optionally providing callbacks.
+ * <li>Call {@link #applyPayload}.
+ * </ol>
+ *
+ * In addition, methods are provided to {@link #cancel} or
+ * {@link #suspend}/{@link #resume} application of an update.
  *
  * The APIs defined in this class and UpdateEngineCallback class must be in
  * sync with the ones in
@@ -80,12 +91,20 @@
 
     private IUpdateEngine mUpdateEngine;
 
+    /**
+     * Creates a new instance.
+     */
     @SystemApi
     public UpdateEngine() {
         mUpdateEngine = IUpdateEngine.Stub.asInterface(
                 ServiceManager.getService(UPDATE_ENGINE_SERVICE));
     }
 
+    /**
+     * Prepares this instance for use. The callback will be notified on any
+     * status change, and when the update completes. A handler can be supplied
+     * to control which thread runs the callback, or null.
+     */
     @SystemApi
     public boolean bind(final UpdateEngineCallback callback, final Handler handler) {
         IUpdateEngineCallback updateEngineCallback = new IUpdateEngineCallback.Stub() {
@@ -125,11 +144,42 @@
         }
     }
 
+    /**
+     * Equivalent to {@code bind(callback, null)}.
+     */
     @SystemApi
     public boolean bind(final UpdateEngineCallback callback) {
         return bind(callback, null);
     }
 
+    /**
+     * Applies the payload found at the given {@code url}. For non-streaming
+     * updates, the URL can be a local file using the {@code file://} scheme.
+     *
+     * <p>The {@code offset} and {@code size} parameters specify the location
+     * of the payload within the file represented by the URL. This is useful
+     * if the downloadable package at the URL contains more than just the
+     * update_engine payload (such as extra metadata). This is true for
+     * Google's OTA system, where the URL points to a zip file in which the
+     * payload is stored uncompressed within the zip file alongside other
+     * data.
+     *
+     * <p>The {@code headerKeyValuePairs} parameter is used to pass metadata
+     * to update_engine. In Google's implementation, this is stored as
+     * {@code payload_properties.txt} in the zip file. It's generated by the
+     * script {@code system/update_engine/scripts/brillo_update_payload}.
+     * The complete list of keys and their documentation is in
+     * {@code system/update_engine/common/constants.cc}, but an example
+     * might be:
+     * <pre>
+     * String[] pairs = {
+     *   "FILE_HASH=lURPCIkIAjtMOyB/EjQcl8zDzqtD6Ta3tJef6G/+z2k=",
+     *   "FILE_SIZE=871903868",
+     *   "METADATA_HASH=tBvj43QOB0Jn++JojcpVdbRLz0qdAuL+uTkSy7hokaw=",
+     *   "METADATA_SIZE=70604"
+     * };
+     * </pre>
+     */
     @SystemApi
     public void applyPayload(String url, long offset, long size, String[] headerKeyValuePairs) {
         try {
@@ -139,6 +189,15 @@
         }
     }
 
+    /**
+     * Permanently cancels an in-progress update.
+     *
+     * <p>See {@link #resetStatus} to undo a finshed update (only available
+     * before the updated system has been rebooted).
+     *
+     * <p>See {@link #suspend} for a way to temporarily stop an in-progress
+     * update with the ability to resume it later.
+     */
     @SystemApi
     public void cancel() {
         try {
@@ -148,6 +207,10 @@
         }
     }
 
+    /**
+     * Suspends an in-progress update. This can be undone by calling
+     * {@link #resume}.
+     */
     @SystemApi
     public void suspend() {
         try {
@@ -157,6 +220,9 @@
         }
     }
 
+    /**
+     * Resumes a suspended update.
+     */
     @SystemApi
     public void resume() {
         try {
@@ -166,6 +232,15 @@
         }
     }
 
+    /**
+     * Resets the bootable flag on the non-current partition and all internal
+     * update_engine state. This can be used after an unwanted payload has been
+     * successfully applied and the device has not yet been rebooted to signal
+     * that we no longer want to boot into that updated system. After this call
+     * completes, update_engine will no longer report
+     * {@code UPDATED_NEED_REBOOT}, so your callback can remove any outstanding
+     * notification that rebooting into the new system is possible.
+     */
     @SystemApi
     public void resetStatus() {
         try {
diff --git a/core/java/android/os/UpdateEngineCallback.java b/core/java/android/os/UpdateEngineCallback.java
index b3b856f..afff60a 100644
--- a/core/java/android/os/UpdateEngineCallback.java
+++ b/core/java/android/os/UpdateEngineCallback.java
@@ -19,7 +19,8 @@
 import android.annotation.SystemApi;
 
 /**
- * Callback function for UpdateEngine.
+ * Callback function for UpdateEngine. Used to keep the caller up to date
+ * with progress, so the UI (if any) can be updated.
  *
  * The APIs defined in this class and UpdateEngine class must be in sync with
  * the ones in
@@ -31,9 +32,19 @@
 @SystemApi
 public abstract class UpdateEngineCallback {
 
+    /**
+     * Invoked when anything changes. The value of {@code status} will
+     * be one of the values from {@link UpdateEngine.UpdateStatusConstants},
+     * and {@code percent} will be valid [TODO: in which cases?].
+     */
     @SystemApi
     public abstract void onStatusUpdate(int status, float percent);
 
+    /**
+     * Invoked when the payload has been applied, whether successfully or
+     * unsuccessfully. The value of {@code errorCode} will be one of the
+     * values from {@link UpdateEngine.ErrorCodeConstants}.
+     */
     @SystemApi
     public abstract void onPayloadApplicationComplete(int errorCode);
 }
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 21c70f9..a638cd4 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1057,12 +1057,17 @@
      * allowed to run code through scheduled alarms, receiving broadcasts,
      * etc.  A started user may be either the current foreground user or a
      * background user; the result here does not distinguish between the two.
-     * <p>Requires {@code android.permission.MANAGE_USERS} or
-     * {@code android.permission.INTERACT_ACROSS_USERS}, otherwise specified {@link UserHandle user}
-     * must be the calling user or a managed profile associated with it.
+     *
+     * <p>Note prior to Android Nougat MR1 (SDK version <= 24;
+     * {@link android.os.Build.VERSION_CODES#N), this API required a system permission
+     * in order to check other profile's status.
+     * Since Android Nougat MR1 (SDK version >= 25;
+     * {@link android.os.Build.VERSION_CODES#N_MR1)), the restriction has been relaxed, and now
+     * it'll accept any {@link UserHandle} within the same profile group as the caller.
      *
      * @param user The user to retrieve the running state for.
      */
+    // Note this requires either INTERACT_ACROSS_USERS or MANAGE_USERS.
     public boolean isUserRunning(UserHandle user) {
         return isUserRunning(user.getIdentifier());
     }
@@ -1081,12 +1086,17 @@
      * This is like {@link #isUserRunning(UserHandle)}, but will also return
      * true if the user had been running but is in the process of being stopped
      * (but is not yet fully stopped, and still running some code).
-     * <p>Requires {@code android.permission.MANAGE_USERS} or
-     * {@code android.permission.INTERACT_ACROSS_USERS}, otherwise specified {@link UserHandle user}
-     * must be the calling user or a managed profile associated with it.
+     *
+     * <p>Note prior to Android Nougat MR1 (SDK version <= 24;
+     * {@link android.os.Build.VERSION_CODES#N), this API required a system permission
+     * in order to check other profile's status.
+     * Since Android Nougat MR1 (SDK version >= 25;
+     * {@link android.os.Build.VERSION_CODES#N_MR1)), the restriction has been relaxed, and now
+     * it'll accept any {@link UserHandle} within the same profile group as the caller.
      *
      * @param user The user to retrieve the running state for.
      */
+    // Note this requires either INTERACT_ACROSS_USERS or MANAGE_USERS.
     public boolean isUserRunningOrStopping(UserHandle user) {
         try {
             // TODO: reconcile stopped vs stopping?
@@ -1097,40 +1107,6 @@
         }
     }
 
-    /** @removed */
-    @Deprecated
-    public boolean isUserRunningAndLocked() {
-        return isUserRunningAndLocked(Process.myUserHandle());
-    }
-
-    /** @removed */
-    @Deprecated
-    public boolean isUserRunningAndLocked(UserHandle user) {
-        try {
-            return ActivityManager.getService().isUserRunning(
-                    user.getIdentifier(), ActivityManager.FLAG_AND_LOCKED);
-        } catch (RemoteException re) {
-            throw re.rethrowFromSystemServer();
-        }
-    }
-
-    /** @removed */
-    @Deprecated
-    public boolean isUserRunningAndUnlocked() {
-        return isUserRunningAndUnlocked(Process.myUserHandle());
-    }
-
-    /** @removed */
-    @Deprecated
-    public boolean isUserRunningAndUnlocked(UserHandle user) {
-        try {
-            return ActivityManager.getService().isUserRunning(
-                    user.getIdentifier(), ActivityManager.FLAG_AND_UNLOCKED);
-        } catch (RemoteException re) {
-            throw re.rethrowFromSystemServer();
-        }
-    }
-
     /**
      * Return whether the calling user is running in an "unlocked" state.
      * <p>
diff --git a/core/java/android/os/WorkSource.java b/core/java/android/os/WorkSource.java
index f8da87a..ecec448 100644
--- a/core/java/android/os/WorkSource.java
+++ b/core/java/android/os/WorkSource.java
@@ -1,6 +1,8 @@
 package android.os;
 
+import android.os.WorkSourceProto;
 import android.util.Log;
+import android.util.proto.ProtoOutputStream;
 
 import java.util.Arrays;
 
@@ -296,7 +298,7 @@
                 break;
             }
             if (mUids[i] == uid) {
-                int diff = mNames[i].compareTo(name); 
+                int diff = mNames[i].compareTo(name);
                 if (diff > 0) {
                     break;
                 }
@@ -692,6 +694,20 @@
         return result.toString();
     }
 
+    /** @hide */
+    public void writeToProto(ProtoOutputStream proto, long fieldId) {
+        final long workSourceToken = proto.start(fieldId);
+        for (int i = 0; i < mNum; i++) {
+            final long contentProto = proto.start(WorkSourceProto.WORK_SOURCE_CONTENTS);
+            proto.write(WorkSourceProto.WorkSourceContentProto.UID, mUids[i]);
+            if (mNames != null) {
+                proto.write(WorkSourceProto.WorkSourceContentProto.NAME, mNames[i]);
+            }
+            proto.end(contentProto);
+        }
+        proto.end(workSourceToken);
+    }
+
     public static final Parcelable.Creator<WorkSource> CREATOR
             = new Parcelable.Creator<WorkSource>() {
         public WorkSource createFromParcel(Parcel in) {
diff --git a/core/java/android/os/storage/IStorageManager.aidl b/core/java/android/os/storage/IStorageManager.aidl
index 9e35bf6..2cc4b71 100644
--- a/core/java/android/os/storage/IStorageManager.aidl
+++ b/core/java/android/os/storage/IStorageManager.aidl
@@ -293,6 +293,6 @@
     ParcelFileDescriptor openProxyFileDescriptor(int mountPointId, int fileId, int mode) = 74;
     long getCacheQuotaBytes(String volumeUuid, int uid) = 75;
     long getCacheSizeBytes(String volumeUuid, int uid) = 76;
-    long getAllocatableBytes(String path, int flags) = 77;
-    void allocateBytes(String path, long bytes, int flags) = 78;
+    long getAllocatableBytes(String volumeUuid, int flags) = 77;
+    void allocateBytes(String volumeUuid, long bytes, int flags) = 78;
 }
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 2a3c03d..e1fb37b 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -16,6 +16,7 @@
 
 package android.os.storage;
 
+import static android.net.TrafficStats.GB_IN_BYTES;
 import static android.net.TrafficStats.MB_IN_BYTES;
 
 import android.annotation.IntDef;
@@ -55,6 +56,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.MetricsLogger;
 import com.android.internal.os.AppFuseMount;
 import com.android.internal.os.FuseAppLoop;
 import com.android.internal.os.RoSystemProperties;
@@ -675,6 +677,36 @@
     }
 
     /** {@hide} */
+    public @Nullable String findUuidForPath(File path) {
+        Preconditions.checkNotNull(path);
+        final String pathString = path.getAbsolutePath();
+        if (FileUtils.contains(Environment.getDataDirectory().getAbsolutePath(), pathString)) {
+            return StorageManager.UUID_PRIVATE_INTERNAL;
+        }
+        try {
+            for (VolumeInfo vol : mStorageManager.getVolumes(0)) {
+                if (vol.path != null && FileUtils.contains(vol.path, pathString)) {
+                    // TODO: verify that emulated adopted devices have UUID of
+                    // underlying volume
+                    return vol.fsUuid;
+                }
+            }
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+        throw new IllegalStateException("Failed to find a storage device for " + path);
+    }
+
+    /** {@hide} */
+    public @Nullable File findPathForUuid(String volumeUuid) {
+        final VolumeInfo vol = findVolumeByQualifiedUuid(volumeUuid);
+        if (vol != null) {
+            return vol.getPath();
+        }
+        throw new IllegalStateException("Failed to find a storage device for " + volumeUuid);
+    }
+
+    /** {@hide} */
     public @NonNull List<VolumeInfo> getVolumes() {
         try {
             return Arrays.asList(mStorageManager.getVolumes(0));
@@ -975,7 +1007,8 @@
         for (String path : INTERNAL_STORAGE_SIZE_PATHS) {
             final long numberBlocks = readLong(path);
             if (numberBlocks > 0) {
-                return new Pair<>(path, Long.valueOf(numberBlocks * INTERNAL_STORAGE_SECTOR_SIZE));
+                return new Pair<>(path,
+                        FileUtils.roundStorageSize(numberBlocks * INTERNAL_STORAGE_SECTOR_SIZE));
             }
         }
         return null;
@@ -1069,9 +1102,12 @@
         throw new IllegalStateException("Missing primary storage");
     }
 
-    /** {@hide} */
-    private static final int DEFAULT_THRESHOLD_PERCENTAGE = 10;
+    private static final int DEFAULT_THRESHOLD_PERCENTAGE = 5;
     private static final long DEFAULT_THRESHOLD_MAX_BYTES = 500 * MB_IN_BYTES;
+
+    private static final int DEFAULT_CACHE_PERCENTAGE = 10;
+    private static final long DEFAULT_CACHE_MAX_BYTES = 5 * GB_IN_BYTES;
+
     private static final long DEFAULT_FULL_THRESHOLD_BYTES = MB_IN_BYTES;
 
     /**
@@ -1102,6 +1138,23 @@
     }
 
     /**
+     * Return the minimum number of bytes of storage on the device that should
+     * be reserved for cached data.
+     *
+     * @hide
+     */
+    public long getStorageCacheBytes(File path) {
+        final long cachePercent = Settings.Global.getInt(mResolver,
+                Settings.Global.SYS_STORAGE_CACHE_PERCENTAGE, DEFAULT_CACHE_PERCENTAGE);
+        final long cacheBytes = (path.getTotalSpace() * cachePercent) / 100;
+
+        final long maxCacheBytes = Settings.Global.getLong(mResolver,
+                Settings.Global.SYS_STORAGE_CACHE_MAX_BYTES, DEFAULT_CACHE_MAX_BYTES);
+
+        return Math.min(cacheBytes, maxCacheBytes);
+    }
+
+    /**
      * Return the number of available bytes at which the given path is
      * considered full.
      *
@@ -1335,6 +1388,7 @@
     public @NonNull ParcelFileDescriptor openProxyFileDescriptor(
             int mode, ProxyFileDescriptorCallback callback, ThreadFactory factory)
                     throws IOException {
+        MetricsLogger.count(mContext, "storage_open_proxy_file_descriptor", 1);
         // Retry is needed because the mount point mFuseAppLoop is using may be unmounted before
         // invoking StorageManagerService#openProxyFileDescriptor. In this case, we need to re-mount
         // the bridge by calling mountProxyFileDescriptorBridge.
@@ -1409,40 +1463,37 @@
     }
 
     /**
-     * Return quota size in bytes for cached data belonging to the calling app.
+     * Return quota size in bytes for all cached data belonging to the calling
+     * app on the filesystem that hosts the given path.
      * <p>
      * If your app goes above this quota, your cached files will be some of the
      * first to be deleted when additional disk space is needed. Conversely, if
      * your app stays under this quota, your cached files will be some of the
      * last to be deleted when additional disk space is needed.
      * <p>
-     * This quota may change over time depending on how frequently the user
+     * This quota will change over time depending on how frequently the user
      * interacts with your app, and depending on how much disk space is used.
-     * <p>
-     * Cached data tracked by this method always includes
-     * {@link Context#getCacheDir()} and {@link Context#getCodeCacheDir()}, and
-     * it also includes {@link Context#getExternalCacheDir()} if the primary
-     * shared/external storage is hosted on the same storage device as your
-     * private data.
      * <p class="note">
      * Note: if your app uses the {@code android:sharedUserId} manifest feature,
      * then cached data for all packages in your shared UID is tracked together
      * as a single unit.
      * </p>
      *
-     * @see #getCacheSizeBytes()
+     * @see #getCacheSizeBytes(File)
      */
-    public long getCacheQuotaBytes() {
+    public long getCacheQuotaBytes(File path) {
         try {
+            final String volumeUuid = findUuidForPath(path);
             final ApplicationInfo app = mContext.getApplicationInfo();
-            return mStorageManager.getCacheQuotaBytes(app.volumeUuid, app.uid);
+            return mStorageManager.getCacheQuotaBytes(volumeUuid, app.uid);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
     /**
-     * Return total size in bytes of cached data belonging to the calling app.
+     * Return total size in bytes of all cached data belonging to the calling
+     * app on the filesystem that hosts the given path.
      * <p>
      * Cached data tracked by this method always includes
      * {@link Context#getCacheDir()} and {@link Context#getCodeCacheDir()}, and
@@ -1457,67 +1508,38 @@
      *
      * @see #getCacheQuotaBytes()
      */
-    public long getCacheSizeBytes() {
+    public long getCacheSizeBytes(File path) {
         try {
+            final String volumeUuid = findUuidForPath(path);
             final ApplicationInfo app = mContext.getApplicationInfo();
-            return mStorageManager.getCacheSizeBytes(app.volumeUuid, app.uid);
+            return mStorageManager.getCacheSizeBytes(volumeUuid, app.uid);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
-    /**
-     * Return quota size in bytes for cached data on primary shared/external
-     * storage belonging to the calling app.
-     * <p>
-     * If primary shared/external storage is hosted on the same storage device
-     * as your private data, this method will return -1, since all data stored
-     * under {@link Context#getExternalCacheDir()} will be counted under
-     * {@link #getCacheQuotaBytes()}.
-     * <p class="note">
-     * Note: if your app uses the {@code android:sharedUserId} manifest feature,
-     * then cached data for all packages in your shared UID is tracked together
-     * as a single unit.
-     * </p>
-     */
+    /** @removed */
+    @Deprecated
+    public long getCacheQuotaBytes() {
+        return getCacheQuotaBytes(mContext.getCacheDir());
+    }
+
+    /** @removed */
+    @Deprecated
+    public long getCacheSizeBytes() {
+        return getCacheSizeBytes(mContext.getCacheDir());
+    }
+
+    /** @removed */
+    @Deprecated
     public long getExternalCacheQuotaBytes() {
-        final ApplicationInfo app = mContext.getApplicationInfo();
-        final String primaryUuid = getPrimaryStorageUuid();
-        if (Objects.equals(app.volumeUuid, primaryUuid)) {
-            return -1;
-        }
-        try {
-            return mStorageManager.getCacheQuotaBytes(primaryUuid, app.uid);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return getCacheQuotaBytes(mContext.getExternalCacheDir());
     }
 
-    /**
-     * Return total size in bytes of cached data on primary shared/external
-     * storage belonging to the calling app.
-     * <p>
-     * If primary shared/external storage is hosted on the same storage device
-     * as your private data, this method will return -1, since all data stored
-     * under {@link Context#getExternalCacheDir()} will be counted under
-     * {@link #getCacheQuotaBytes()}.
-     * <p class="note">
-     * Note: if your app uses the {@code android:sharedUserId} manifest feature,
-     * then cached data for all packages in your shared UID is tracked together
-     * as a single unit.
-     * </p>
-     */
+    /** @removed */
+    @Deprecated
     public long getExternalCacheSizeBytes() {
-        final ApplicationInfo app = mContext.getApplicationInfo();
-        final String primaryUuid = getPrimaryStorageUuid();
-        if (Objects.equals(app.volumeUuid, primaryUuid)) {
-            return -1;
-        }
-        try {
-            return mStorageManager.getCacheSizeBytes(primaryUuid, app.uid);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return getCacheSizeBytes(mContext.getExternalCacheDir());
     }
 
     /**
@@ -1551,28 +1573,30 @@
      * Return the maximum number of new bytes that your app can allocate for
      * itself using {@link #allocateBytes(File, long, int)} at the given path.
      * This value is typically larger than {@link File#getUsableSpace()}, since
-     * the system may automatically delete cached files to satisfy your request.
+     * the system may be willing to delete cached files to satisfy an allocation
+     * request.
      * <p>
      * This method is best used as a pre-flight check, such as deciding if there
      * is enough space to store an entire music album before you allocate space
      * for each audio file in the album. Attempts to allocate disk space beyond
-     * this value will fail.
+     * the returned value will fail.
      * <p class="note">
      * Note: if your app uses the {@code android:sharedUserId} manifest feature,
      * then allocatable space for all packages in your shared UID is tracked
      * together as a single unit.
      * </p>
      *
-     * @param file the directory where you're considering allocating disk space,
+     * @param path the path where you're considering allocating disk space,
      *            since allocatable space can vary widely depending on the
      *            underlying storage device.
      * @param flags to apply to the request.
      * @return the maximum number of new bytes that the calling app can allocate
      *         using {@link #allocateBytes(File, long, int)}.
      */
-    public long getAllocatableBytes(File file, @AllocateFlags int flags) throws IOException {
+    public long getAllocatableBytes(File path, @AllocateFlags int flags) throws IOException {
         try {
-            return mStorageManager.getAllocatableBytes(file.getAbsolutePath(), flags);
+            final String volumeUuid = findUuidForPath(path);
+            return mStorageManager.getAllocatableBytes(volumeUuid, flags);
         } catch (ParcelableException e) {
             e.maybeRethrow(IOException.class);
             throw new RuntimeException(e);
@@ -1594,14 +1618,15 @@
      * {@link #allocateBytes(FileDescriptor, long, int)} which will guarantee
      * that bytes are allocated to an opened file.
      *
-     * @param file the directory where you'd like to allocate disk space.
+     * @param path the path where you'd like to allocate disk space.
      * @param bytes the number of bytes to allocate.
      * @param flags to apply to the request.
      * @see #getAllocatableBytes(File, int)
      */
-    public void allocateBytes(File file, long bytes, @AllocateFlags int flags) throws IOException {
+    public void allocateBytes(File path, long bytes, @AllocateFlags int flags) throws IOException {
         try {
-            mStorageManager.allocateBytes(file.getAbsolutePath(), bytes, flags);
+            final String volumeUuid = findUuidForPath(path);
+            mStorageManager.allocateBytes(volumeUuid, bytes, flags);
         } catch (ParcelableException e) {
             e.maybeRethrow(IOException.class);
         } catch (RemoteException e) {
@@ -1610,37 +1635,39 @@
     }
 
     /**
-     * Allocate the requested number of bytes for your application to use at the
-     * given path. This will cause the system to delete any cached files
+     * Allocate the requested number of bytes for your application to use in the
+     * given open file. This will cause the system to delete any cached files
      * necessary to satisfy your request.
      * <p>
      * Attempts to allocate disk space beyond the value returned by
      * {@link #getAllocatableBytes(File, int)} will fail.
      * <p>
-     * This method guarantees that bytes are allocated to the opened file,
-     * otherwise it will throw if fast allocation not possible. Fast allocation
-     * is typically only supported in private app data directories, and on
-     * shared/external storage devices which are emulated.
+     * This method guarantees that bytes have been allocated to the opened file,
+     * otherwise it will throw if fast allocation is not possible. Fast
+     * allocation is typically only supported in private app data directories,
+     * and on shared/external storage devices which are emulated.
      *
-     * @param fd the directory where you'd like to allocate disk space.
-     * @param bytes the number of bytes to allocate.
+     * @param fd the open file that you'd like to allocate disk space for.
+     * @param bytes the number of bytes to allocate. This is the desired final
+     *            size of the open file.
      * @param flags to apply to the request.
      * @see #getAllocatableBytes(File, int)
      * @see Environment#isExternalStorageEmulated(File)
      */
     public void allocateBytes(FileDescriptor fd, long bytes, @AllocateFlags int flags)
             throws IOException {
-        final File file;
-        try {
-            file = new File(Os.readlink("/proc/self/fd/" + fd.getInt$()));
-        } catch (ErrnoException e) {
-            throw e.rethrowAsIOException();
-        }
+        final File file = ParcelFileDescriptor.getFile(fd);
         for (int i = 0; i < 3; i++) {
-            allocateBytes(file, bytes, flags);
-
             try {
+                final long haveBytes = Os.fstat(fd).st_blocks * 512;
+                final long needBytes = bytes - haveBytes;
+
+                if (needBytes > 0) {
+                    allocateBytes(file, needBytes, flags);
+                }
+
                 Os.posix_fallocate(fd, 0, bytes);
+                return;
             } catch (ErrnoException e) {
                 if (e.errno == OsConstants.ENOSPC) {
                     Log.w(TAG, "Odd, not enough space; let's try again?");
@@ -1653,8 +1680,8 @@
                 "Well this is embarassing; we can't allocate " + bytes + " for " + file);
     }
 
-    private static final String XATTR_ATOMIC = "user.atomic";
-    private static final String XATTR_TOMBSTONE = "user.tombstone";
+    private static final String XATTR_CACHE_ATOMIC = "user.cache_atomic";
+    private static final String XATTR_CACHE_TOMBSTONE = "user.cache_tombstone";
 
     /** {@hide} */
     private static void setCacheBehavior(File path, String name, boolean enabled)
@@ -1712,7 +1739,7 @@
      * to all contained files and directories.
      */
     public void setCacheBehaviorAtomic(File path, boolean atomic) throws IOException {
-        setCacheBehavior(path, XATTR_ATOMIC, atomic);
+        setCacheBehavior(path, XATTR_CACHE_ATOMIC, atomic);
     }
 
     /**
@@ -1720,7 +1747,7 @@
      * {@link #setCacheBehaviorAtomic(File, boolean)}.
      */
     public boolean isCacheBehaviorAtomic(File path) throws IOException {
-        return isCacheBehavior(path, XATTR_ATOMIC);
+        return isCacheBehavior(path, XATTR_CACHE_ATOMIC);
     }
 
     /**
@@ -1740,7 +1767,7 @@
      * </p>
      */
     public void setCacheBehaviorTombstone(File path, boolean tombstone) throws IOException {
-        setCacheBehavior(path, XATTR_TOMBSTONE, tombstone);
+        setCacheBehavior(path, XATTR_CACHE_TOMBSTONE, tombstone);
     }
 
     /**
@@ -1748,7 +1775,7 @@
      * {@link #setCacheBehaviorTombstone(File, boolean)}.
      */
     public boolean isCacheBehaviorTombstone(File path) throws IOException {
-        return isCacheBehavior(path, XATTR_TOMBSTONE);
+        return isCacheBehavior(path, XATTR_CACHE_TOMBSTONE);
     }
 
     private final Object mFuseAppLoopLock = new Object();
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index 7b63b62..a21e05e 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -435,7 +435,7 @@
             return null;
         }
 
-        final Intent intent = new Intent(DocumentsContract.ACTION_BROWSE);
+        final Intent intent = new Intent(Intent.ACTION_VIEW);
         intent.addCategory(Intent.CATEGORY_DEFAULT);
         intent.setDataAndType(uri, DocumentsContract.Root.MIME_TYPE_ITEM);
 
diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java
index 089eaec..443a3e9 100644
--- a/core/java/android/preference/Preference.java
+++ b/core/java/android/preference/Preference.java
@@ -410,11 +410,13 @@
     /**
      * Sets a {@link PreferenceDataStore} to be used by this Preference instead of using
      * {@link android.content.SharedPreferences}.
-     * <p>
-     * The data store will remain assigned even if the Preference is moved between multiple
-     * instances of {@link PreferenceFragment}.
+     *
+     * <p>The data store will remain assigned even if the Preference is moved around the preference
+     * hierarchy. It will also override a data store propagated from the {@link PreferenceManager}
+     * that owns this Preference.
      *
      * @param dataStore The {@link PreferenceDataStore} to be used by this Preference.
+     * @see PreferenceManager#setPreferenceDataStore(PreferenceDataStore)
      */
     public void setPreferenceDataStore(PreferenceDataStore dataStore) {
         mPreferenceDataStore = dataStore;
@@ -424,6 +426,12 @@
      * Returns {@link PreferenceDataStore} used by this Preference. Returns {@code null} if
      * {@link android.content.SharedPreferences} is used instead.
      *
+     * <p>By default preferences always use {@link android.content.SharedPreferences}. To make this
+     * preference to use the {@link PreferenceDataStore} you need to assign your implementation
+     * to the Preference itself via {@link #setPreferenceDataStore(PreferenceDataStore)} or to its
+     * {@link PreferenceManager} via
+     * {@link PreferenceManager#setPreferenceDataStore(PreferenceDataStore)}.
+     *
      * @return The {@link PreferenceDataStore} used by this Preference or {@code null} if none.
      */
     @Nullable
@@ -892,8 +900,8 @@
     }
 
     /**
-     * Sets the key for this Preference, which is used as a key to the
-     * {@link SharedPreferences}. This should be unique for the package.
+     * Sets the key for this Preference, which is used as a key to the {@link SharedPreferences} or
+     * {@link PreferenceDataStore}. This should be unique for the package.
      *
      * @param key The key for the preference.
      */
@@ -906,8 +914,8 @@
     }
 
     /**
-     * Gets the key for this Preference, which is also the key used for storing
-     * values into SharedPreferences.
+     * Gets the key for this Preference, which is also the key used for storing values into
+     * {@link SharedPreferences} or {@link PreferenceDataStore}.
      *
      * @return The key.
      */
@@ -917,8 +925,7 @@
 
     /**
      * Checks whether the key is present, and if it isn't throws an
-     * exception. This should be called by subclasses that store preferences in
-     * the {@link SharedPreferences}.
+     * exception. This should be called by subclasses that persist their preferences.
      *
      * @throws IllegalStateException If there is no key assigned.
      */
@@ -941,7 +948,8 @@
 
     /**
      * Checks whether this Preference is persistent. If it is, it stores its value(s) into
-     * the persistent {@link SharedPreferences} storage.
+     * the persistent {@link SharedPreferences} storage by default or into
+     * {@link PreferenceDataStore} if assigned.
      *
      * @return True if it is persistent.
      */
@@ -950,11 +958,10 @@
     }
 
     /**
-     * Checks whether, at the given time this method is called,
-     * this Preference should store/restore its value(s) into the
-     * {@link SharedPreferences}. This, at minimum, checks whether this
-     * Preference is persistent and it currently has a key. Before you
-     * save/restore from the {@link SharedPreferences}, check this first.
+     * Checks whether, at the given time this method is called, this Preference should store/restore
+     * its value(s) into the {@link SharedPreferences} or into {@link PreferenceDataStore} if
+     * assigned. This, at minimum, checks whether this Preference is persistent and it currently has
+     * a key. Before you save/restore from the storage, check this first.
      *
      * @return True if it should persist the value.
      */
@@ -963,9 +970,9 @@
     }
 
     /**
-     * Sets whether this Preference is persistent. When persistent,
-     * it stores its value(s) into the persistent {@link SharedPreferences}
-     * storage.
+     * Sets whether this Preference is persistent. When persistent, it stores its value(s) into
+     * the persistent {@link SharedPreferences} storage by default or into
+     * {@link PreferenceDataStore} if assigned.
      *
      * @param persistent Set true if it should store its value(s) into the {@link SharedPreferences}.
      */
@@ -982,7 +989,7 @@
      *         value (and persisted).
      */
     protected boolean callChangeListener(Object newValue) {
-        return mOnChangeListener == null ? true : mOnChangeListener.onPreferenceChange(this, newValue);
+        return mOnChangeListener == null || mOnChangeListener.onPreferenceChange(this, newValue);
     }
 
     /**
@@ -1071,7 +1078,7 @@
     }
 
     /**
-     * Returns the {@link android.content.Context} of this Preference. 
+     * Returns the {@link android.content.Context} of this Preference.
      * Each Preference in a Preference hierarchy can be
      * from different Context (for example, if multiple activities provide preferences into a single
      * {@link PreferenceActivity}). This Context will be used to save the Preference values.
@@ -1095,12 +1102,14 @@
      * {@link SharedPreferences}, this is intended behavior to improve
      * performance.
      *
-     * @return The {@link SharedPreferences} where this Preference reads its
-     *         value(s), or null if it isn't attached to a Preference hierarchy.
+     * @return The {@link SharedPreferences} where this Preference reads its value(s), or null if it
+     *         isn't attached to a Preference hierarchy or if {@link PreferenceDataStore} is used
+     *         instead.
      * @see #getEditor()
+     * @see #setPreferenceDataStore(PreferenceDataStore)
      */
     public SharedPreferences getSharedPreferences() {
-        if (mPreferenceManager == null) {
+        if (mPreferenceManager == null || getPreferenceDataStore() != null) {
             return null;
         }
 
@@ -1120,14 +1129,15 @@
      * not show up in the SharedPreferences, this is intended behavior to
      * improve performance.
      *
-     * @return A {@link SharedPreferences.Editor} where this preference saves
-     *         its value(s), or null if it isn't attached to a Preference
-     *         hierarchy.
+     * @return A {@link SharedPreferences.Editor} where this preference saves its value(s), or null
+     *         if it isn't attached to a Preference hierarchy or if {@link PreferenceDataStore} is
+     *         used instead.
      * @see #shouldCommit()
      * @see #getSharedPreferences()
+     * @see #setPreferenceDataStore(PreferenceDataStore)
      */
     public SharedPreferences.Editor getEditor() {
-        if (mPreferenceManager == null) {
+        if (mPreferenceManager == null || getPreferenceDataStore() != null) {
             return null;
         }
 
@@ -1139,6 +1149,8 @@
      * {@link #getEditor()}. This may return false in situations where batch
      * committing is being done (by the manager) to improve performance.
      *
+     * <p>If this preference is using {@link PreferenceDataStore} this value should be irrelevant.
+     *
      * @return Whether the Preference should commit its saved value(s).
      * @see #getEditor()
      */
@@ -1445,6 +1457,11 @@
     }
 
     private void dispatchSetInitialValue() {
+        if (getPreferenceDataStore() != null) {
+            onSetInitialValue(true, mDefaultValue);
+            return;
+        }
+
         // By now, we know if we are persistent.
         final boolean shouldPersist = shouldPersist();
         if (!shouldPersist || !getSharedPreferences().contains(mKey)) {
@@ -1457,15 +1474,18 @@
     }
 
     /**
-     * Implement this to set the initial value of the Preference. 
-     * <p>
-     * If <var>restorePersistedValue</var> is true, you should restore the 
-     * Preference value from the {@link android.content.SharedPreferences}. If 
-     * <var>restorePersistedValue</var> is false, you should set the Preference 
-     * value to defaultValue that is given (and possibly store to SharedPreferences 
+     * Implement this to set the initial value of the Preference.
+     *
+     * <p>If <var>restorePersistedValue</var> is true, you should restore the
+     * Preference value from the {@link android.content.SharedPreferences}. If
+     * <var>restorePersistedValue</var> is false, you should set the Preference
+     * value to defaultValue that is given (and possibly store to SharedPreferences
      * if {@link #shouldPersist()} is true).
-     * <p>
-     * This may not always be called. One example is if it should not persist
+     *
+     * <p>In case of using {@link PreferenceDataStore}, the <var>restorePersistedValue</var> is
+     * always false. But the default value (if provided) is set.
+     *
+     * <p>This may not always be called. One example is if it should not persist
      * but there is no default value given.
      *
      * @param restorePersistedValue True to restore the persisted value;
@@ -1861,8 +1881,8 @@
     }
 
     /**
-     * Called by {@link #saveHierarchyState} to store the instance for this Preference and its children.
-     * May be overridden to modify how the save happens for children. For example, some
+     * Called by {@link #saveHierarchyState} to store the instance for this Preference and its
+     * children. May be overridden to modify how the save happens for children. For example, some
      * Preference objects may want to not store an instance for their children.
      *
      * @param container The Bundle in which to save the instance of this Preference.
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index 600d82f..02fa7ed 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -40,6 +40,7 @@
 import android.util.TypedValue;
 import android.util.Xml;
 import android.view.LayoutInflater;
+import android.view.MenuItem;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
@@ -75,12 +76,11 @@
  * however vary; currently there are two major approaches it may take:
  *
  * <ul>
- * <li>On a small screen it may display only the headers as a single list
- * when first launched.  Selecting one of the header items will re-launch
- * the activity with it only showing the PreferenceFragment of that header.
- * <li>On a large screen in may display both the headers and current
- * PreferenceFragment together as panes.  Selecting a header item switches
- * to showing the correct PreferenceFragment for that item.
+ * <li>On a small screen it may display only the headers as a single list when first launched.
+ * Selecting one of the header items will only show the PreferenceFragment of that header (on
+ * Android N and lower a new Activity is launched).
+ * <li>On a large screen in may display both the headers and current PreferenceFragment together as
+ * panes. Selecting a header item switches to showing the correct PreferenceFragment for that item.
  * </ul>
  *
  * <p>Subclasses of PreferenceActivity should implement
@@ -200,6 +200,10 @@
 
     private ViewGroup mPrefsContainer;
 
+    // Backup of the original activity title. This is used when navigating back to the headers list
+    // in onBackPress to restore the title.
+    private CharSequence mActivityTitle;
+
     // Null if in legacy mode.
     private ViewGroup mHeadersContainer;
 
@@ -536,6 +540,16 @@
     }
 
     @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        if (item.getItemId() == android.R.id.home) {
+            // Override home navigation button to call onBackPressed (b/35152749).
+            onBackPressed();
+            return true;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+    @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
@@ -569,6 +583,7 @@
         Bundle initialArguments = getIntent().getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
         int initialTitle = getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_TITLE, 0);
         int initialShortTitle = getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_SHORT_TITLE, 0);
+        mActivityTitle = getTitle();
 
         if (savedInstanceState != null) {
             // We are restarting from a previous saved state; used that to
@@ -704,6 +719,9 @@
 
             mPrefsContainer.setVisibility(View.GONE);
             mHeadersContainer.setVisibility(View.VISIBLE);
+            if (mActivityTitle != null) {
+                showBreadCrumbs(mActivityTitle, null);
+            }
             getListView().clearChoices();
         } else {
             super.onBackPressed();
diff --git a/core/java/android/preference/PreferenceDataStore.java b/core/java/android/preference/PreferenceDataStore.java
index e1a08ac..8caa404 100644
--- a/core/java/android/preference/PreferenceDataStore.java
+++ b/core/java/android/preference/PreferenceDataStore.java
@@ -21,16 +21,32 @@
 import java.util.Set;
 
 /**
- * A data store interface to be implemented and provided to the Preferences framework.
+ * A data store interface to be implemented and provided to the Preferences framework. This can be
+ * used to replace the default {@link android.content.SharedPreferences}, if needed.
  *
- * Use this to replace the default {@link android.content.SharedPreferences}. By default, all "put"
- * methods throw {@link UnsupportedOperationException}.
+ * <p>In most cases you want to use {@link android.content.SharedPreferences} as it is automatically
+ * backed up and migrated to new devices. However, providing custom data store to preferences can be
+ * useful if your app stores its preferences in a local db, cloud or they are device specific like
+ * "Developer settings". It might be also useful when you want to use the preferences UI but
+ * the data are not supposed to be stored at all because they are valid per session only.
+ *
+ * <p>Once a put method is called it is full responsibility of the data store implementation to
+ * safely store the given values. Time expensive operations need to be done in the background to
+ * prevent from blocking the UI. You also need to have a plan on how to serialize the data in case
+ * the activity holding this object gets destroyed.
+ *
+ * <p>By default, all "put" methods throw {@link UnsupportedOperationException}.
+ *
+ * @see Preference#setPreferenceDataStore(PreferenceDataStore)
+ * @see PreferenceManager#setPreferenceDataStore(PreferenceDataStore)
  */
 public interface PreferenceDataStore {
 
     /**
      * Set a String value to the data store.
      *
+     * <p>Once the value is set the data store is responsible for holding it.
+     *
      * @param key The name of the preference to modify.
      * @param value The new value for the preference.
      * @see #getString(String, String)
@@ -42,6 +58,8 @@
     /**
      * Set a set of String value to the data store.
      *
+     * <p>Once the value is set the data store is responsible for holding it.
+     *
      * @param key The name of the preference to modify.
      * @param values The set of new values for the preference.
      * @see #getStringSet(String, Set)
@@ -53,6 +71,8 @@
     /**
      * Set an int value to the data store.
      *
+     * <p>Once the value is set the data store is responsible for holding it.
+     *
      * @param key The name of the preference to modify.
      * @param value The new value for the preference.
      * @see #getInt(String, int)
@@ -64,6 +84,8 @@
     /**
      * Set a long value to the data store.
      *
+     * <p>Once the value is set the data store is responsible for holding it.
+     *
      * @param key The name of the preference to modify.
      * @param value The new value for the preference.
      * @see #getLong(String, long)
@@ -75,6 +97,8 @@
     /**
      * Set a float value to the data store.
      *
+     * <p>Once the value is set the data store is responsible for holding it.
+     *
      * @param key The name of the preference to modify.
      * @param value The new value for the preference.
      * @see #getFloat(String, float)
@@ -86,6 +110,8 @@
     /**
      * Set a boolean value to the data store.
      *
+     * <p>Once the value is set the data store is responsible for holding it.
+     *
      * @param key The name of the preference to modify.
      * @param value The new value for the preference.
      * @see #getBoolean(String, boolean)
diff --git a/core/java/android/preference/PreferenceManager.java b/core/java/android/preference/PreferenceManager.java
index a2f4db6..14b748a 100644
--- a/core/java/android/preference/PreferenceManager.java
+++ b/core/java/android/preference/PreferenceManager.java
@@ -208,10 +208,13 @@
 
     /**
      * Sets a {@link PreferenceDataStore} to be used by all Preferences associated with this manager
-     * that don't have a custom {@link PreferenceDataStore} assigned. Also if the data store is set,
-     * the Preferences will no longer use {@link android.content.SharedPreferences}.
+     * that don't have a custom {@link PreferenceDataStore} assigned via
+     * {@link Preference#setPreferenceDataStore(PreferenceDataStore)}. Also if the data store is
+     * set, the child preferences won't use {@link android.content.SharedPreferences} as long as
+     * they are assigned to this manager.
      *
      * @param dataStore The {@link PreferenceDataStore} to be used by this manager.
+     * @see Preference#setPreferenceDataStore(PreferenceDataStore)
      */
     public void setPreferenceDataStore(PreferenceDataStore dataStore) {
         mPreferenceDataStore = dataStore;
@@ -219,9 +222,10 @@
 
     /**
      * Returns the {@link PreferenceDataStore} associated with this manager or {@code null} if
-     * {@link android.content.SharedPreferences} are used instead.
+     * the default {@link android.content.SharedPreferences} are used instead.
      *
      * @return The {@link PreferenceDataStore} associated with this manager or {@code null} if none.
+     * @see #setPreferenceDataStore(PreferenceDataStore)
      */
     @Nullable
     public PreferenceDataStore getPreferenceDataStore() {
@@ -281,7 +285,7 @@
                     context = mContext.createPackageContext(activityInfo.packageName, 0);
                 } catch (NameNotFoundException e) {
                     Log.w(TAG, "Could not create context for " + activityInfo.packageName + ": "
-                        + Log.getStackTraceString(e));
+                            + Log.getStackTraceString(e));
                     continue;
                 }
 
@@ -358,8 +362,11 @@
      * Sets the name of the SharedPreferences file that preferences managed by this
      * will use.
      *
+     * <p>If custom {@link PreferenceDataStore} is set, this won't override its usage.
+     *
      * @param sharedPreferencesName The name of the SharedPreferences file.
      * @see Context#getSharedPreferences(String, int)
+     * @see #setPreferenceDataStore(PreferenceDataStore)
      */
     public void setSharedPreferencesName(String sharedPreferencesName) {
         mSharedPreferencesName = sharedPreferencesName;
@@ -420,12 +427,6 @@
         mSharedPreferences = null;
     }
 
-    /** @removed */
-    @Deprecated
-    public void setStorageDeviceEncrypted() {
-        setStorageDeviceProtected();
-    }
-
     /**
      * Explicitly set the storage location used internally by this class to be
      * credential-protected storage. This is the default storage area for apps
@@ -445,12 +446,6 @@
         mSharedPreferences = null;
     }
 
-    /** @removed */
-    @Deprecated
-    public void setStorageCredentialEncrypted() {
-        setStorageCredentialProtected();
-    }
-
     /**
      * Indicates if the storage location used internally by this class is the
      * default provided by the hosting {@link Context}.
@@ -487,14 +482,13 @@
     }
 
     /**
-     * Gets a SharedPreferences instance that preferences managed by this will
-     * use.
+     * Gets a {@link SharedPreferences} instance that preferences managed by this will use.
      *
-     * @return A SharedPreferences instance pointing to the file that contains
-     *         the values of preferences that are managed by this.
+     * @return A {@link SharedPreferences} instance pointing to the file that contains the values of
+     * preferences that are managed by this or null if {@link PreferenceDataStore} is used instead.
      */
     public SharedPreferences getSharedPreferences() {
-        if (mSharedPreferences == null) {
+        if (mSharedPreferences == null && getPreferenceDataStore() == null) {
             final Context storageContext;
             switch (mStorage) {
                 case STORAGE_DEVICE_PROTECTED:
@@ -516,12 +510,12 @@
     }
 
     /**
-     * Gets a SharedPreferences instance that points to the default file that is
-     * used by the preference framework in the given context.
+     * Gets a {@link SharedPreferences} instance that points to the default file that is used by
+     * the preference framework in the given context.
      *
      * @param context The context of the preferences whose values are wanted.
-     * @return A SharedPreferences instance that can be used to retrieve and
-     *         listen to values of the preferences.
+     * @return A {@link SharedPreferences} instance that can be used to retrieve and listen
+     *         to values of the preferences.
      */
     public static SharedPreferences getDefaultSharedPreferences(Context context) {
         return context.getSharedPreferences(getDefaultSharedPreferencesName(context),
@@ -668,10 +662,14 @@
      * <p>
      * Do NOT commit unless {@link #shouldCommit()} returns true.
      *
-     * @return An editor to use to write to shared preferences.
+     * @return An editor to use to write to shared preferences or null if
+     * {@link PreferenceDataStore} is used instead.
      * @see #shouldCommit()
      */
     SharedPreferences.Editor getEditor() {
+        if (mPreferenceDataStore != null) {
+            return null;
+        }
 
         if (mNoCommit) {
             if (mEditor == null) {
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index a6e6fda..33b5903 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -119,6 +119,9 @@
      * <p>Location should specify a document URI or a tree URI with document ID. If
      * this URI identifies a non-directory, document navigator will attempt to use the parent
      * of the document as the initial location.
+     *
+     * <p>The initial location is system specific if this extra is missing or document navigator
+     * failed to locate the desired initial location.
      */
     public static final String EXTRA_INITIAL_URI = "android.provider.extra.INITIAL_URI";
 
@@ -162,9 +165,6 @@
     public static final String ACTION_MANAGE_DOCUMENT = "android.provider.action.MANAGE_DOCUMENT";
 
     /** {@hide} */
-    public static final String ACTION_BROWSE = "android.provider.action.BROWSE";
-
-    /** {@hide} */
     public static final String
             ACTION_DOCUMENT_ROOT_SETTINGS = "android.provider.action.DOCUMENT_ROOT_SETTINGS";
 
@@ -538,7 +538,9 @@
          */
         public static final String COLUMN_MIME_TYPES = "mime_types";
 
-        /** {@hide} */
+        /**
+         * MIME type for a root.
+         */
         public static final String MIME_TYPE_ITEM = "vnd.android.document/root";
 
         /**
diff --git a/core/java/android/provider/FontsContract.java b/core/java/android/provider/FontsContract.java
index 90e710f..96dd76b 100644
--- a/core/java/android/provider/FontsContract.java
+++ b/core/java/android/provider/FontsContract.java
@@ -19,9 +19,12 @@
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.Context;
+import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ProviderInfo;
+import android.content.pm.Signature;
 import android.database.Cursor;
+import android.graphics.Typeface;
 import android.graphics.fonts.FontRequest;
 import android.graphics.fonts.FontResult;
 import android.net.Uri;
@@ -34,9 +37,13 @@
 import android.util.Log;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 
 import java.io.FileNotFoundException;
 import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
 
 /**
  * Utility class to deal with Font ContentProviders.
@@ -107,6 +114,13 @@
         mPackageManager = mContext.getPackageManager();
     }
 
+    /** @hide */
+    @VisibleForTesting
+    public FontsContract(Context context, PackageManager packageManager) {
+        mContext = context;
+        mPackageManager = packageManager;
+    }
+
     // We use a background thread to post the content resolving work for all requests on. This
     // thread should be quit/stopped after all requests are done.
     private final Runnable mReplaceDispatcherThreadRunnable = new Runnable() {
@@ -133,31 +147,79 @@
                 mHandler = new Handler(mThread.getLooper());
             }
             mHandler.post(() -> {
-                String providerAuthority = request.getProviderAuthority();
-                // TODO: Implement cert checking for non-system apps
-                ProviderInfo providerInfo = mPackageManager.resolveContentProvider(
-                        providerAuthority, PackageManager.MATCH_SYSTEM_ONLY);
+                ProviderInfo providerInfo = getProvider(request);
                 if (providerInfo == null) {
                     receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null);
                     return;
                 }
-                Bundle result = getFontFromProvider(request, receiver, providerInfo);
-                if (result == null) {
-                    receiver.send(RESULT_CODE_FONT_NOT_FOUND, null);
-                    return;
-                }
-                receiver.send(RESULT_CODE_OK, result);
+                getFontFromProvider(request, receiver, providerInfo.authority);
             });
             mHandler.removeCallbacks(mReplaceDispatcherThreadRunnable);
             mHandler.postDelayed(mReplaceDispatcherThreadRunnable, THREAD_RENEWAL_THRESHOLD_MS);
         }
     }
 
-    private Bundle getFontFromProvider(FontRequest request, ResultReceiver receiver,
-            ProviderInfo providerInfo) {
+    /** @hide */
+    @VisibleForTesting
+    public ProviderInfo getProvider(FontRequest request) {
+        String providerAuthority = request.getProviderAuthority();
+        ProviderInfo info = mPackageManager.resolveContentProvider(providerAuthority, 0);
+        if (info == null) {
+            Log.e(TAG, "Can't find content provider " + providerAuthority);
+            return null;
+        }
+
+        if (!info.packageName.equals(request.getProviderPackage())) {
+            Log.e(TAG, "Found content provider " + providerAuthority + ", but package was not "
+                    + request.getProviderPackage());
+            return null;
+        }
+        // Trust system apps without signature checks
+        if (info.applicationInfo.isSystemApp()) {
+            return info;
+        }
+
+        Set<byte[]> signatures;
+        try {
+            PackageInfo packageInfo = mPackageManager.getPackageInfo(info.packageName,
+                    PackageManager.GET_SIGNATURES);
+            signatures = convertToSet(packageInfo.signatures);
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.e(TAG, "Can't find content provider " + providerAuthority, e);
+            return null;
+        }
+        List<List<byte[]>> requestCertificatesList = request.getCertificates();
+        for (int i = 0; i < requestCertificatesList.size(); ++i) {
+            final Set<byte[]> requestCertificates = convertToSet(requestCertificatesList.get(i));
+            if (signatures.equals(requestCertificates)) {
+                return info;
+            }
+        }
+        Log.e(TAG, "Certificates don't match for given provider " + providerAuthority);
+        return null;
+    }
+
+    private Set<byte[]> convertToSet(Signature[] signatures) {
+        Set<byte[]> shas = new HashSet<>();
+        for (int i = 0; i < signatures.length; ++i) {
+            shas.add(signatures[i].toByteArray());
+        }
+        return shas;
+    }
+
+    private Set<byte[]> convertToSet(List<byte[]> certs) {
+        Set<byte[]> shas = new HashSet<>();
+        shas.addAll(certs);
+        return shas;
+    }
+
+    /** @hide */
+    @VisibleForTesting
+    public void getFontFromProvider(FontRequest request, ResultReceiver receiver,
+            String authority) {
         ArrayList<FontResult> result = null;
         Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
-                .authority(providerInfo.authority)
+                .authority(authority)
                 .build();
         try (Cursor cursor = mContext.getContentResolver().query(uri, new String[] { Columns._ID,
                         Columns.TTC_INDEX, Columns.VARIATION_SETTINGS, Columns.STYLE },
@@ -176,13 +238,16 @@
                     try {
                         ParcelFileDescriptor pfd =
                                 mContext.getContentResolver().openFileDescriptor(fileUri, "r");
-                        final int ttcIndex = cursor.getInt(ttcIndexColumnIndex);
-                        final String variationSettings = cursor.getString(vsColumnIndex);
-                        final int style = cursor.getInt(styleColumnIndex);
+                        final int ttcIndex = ttcIndexColumnIndex != -1
+                                ? cursor.getInt(ttcIndexColumnIndex) : 0;
+                        final String variationSettings = vsColumnIndex != -1
+                                ? cursor.getString(vsColumnIndex) : null;
+                        final int style = styleColumnIndex != -1
+                                ? cursor.getInt(styleColumnIndex) : Typeface.NORMAL;
                         result.add(new FontResult(pfd, ttcIndex, variationSettings, style));
                     } catch (FileNotFoundException e) {
                         Log.e(TAG, "FileNotFoundException raised when interacting with content "
-                                + "provider " + providerInfo.authority, e);
+                                + "provider " + authority, e);
                     }
                 }
             }
@@ -190,8 +255,9 @@
         if (result != null && !result.isEmpty()) {
             Bundle bundle = new Bundle();
             bundle.putParcelableArrayList(PARCEL_FONT_RESULTS, result);
-            return bundle;
+            receiver.send(RESULT_CODE_OK, bundle);
+            return;
         }
-        return null;
+        receiver.send(RESULT_CODE_FONT_NOT_FOUND, null);
     }
 }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index c9b1c9c..e3a9d80 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -295,7 +295,9 @@
      * In some cases, a matching Activity may not exist, so ensure you
      * safeguard against this.
      * <p>
-     * Input: Nothing.
+     * Input: Optionally, the Intent's data URI can specify the application package name to
+     * directly invoke the management GUI specific to the package name. For example
+     * "package:com.my.app".
      * <p>
      * Output: Nothing.
      */
@@ -1121,7 +1123,7 @@
     public static final String ACTION_ZEN_MODE_SETTINGS = "android.settings.ZEN_MODE_SETTINGS";
 
     /**
-     * Activity Action: Show Zen Mode priority configuration settings.
+     * Activity Action: Show Zen Mode (aka Do Not Disturb) priority configuration settings.
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_ZEN_MODE_PRIORITY_SETTINGS
@@ -4635,7 +4637,7 @@
                 return setLocationModeForUser(resolver, Integer.parseInt(value), userHandle);
             }
             if (MOVED_TO_GLOBAL.contains(name)) {
-                Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System"
+                Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.Secure"
                         + " to android.provider.Settings.Global");
                 return Global.putStringForUser(resolver, name, value,
                         tag, makeDefault, userHandle);
@@ -5217,6 +5219,18 @@
         public static final String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
 
         /**
+         * A flag to tell {@link com.android.server.devicepolicy.DevicePolicyManagerService} that
+         * the default for {@link #INSTALL_NON_MARKET_APPS} is reversed for this user on OTA. So it
+         * can set the restriction {@link android.os.UserManager#DISALLOW_INSTALL_UNKNOWN_SOURCES}
+         * on behalf of the profile owner if needed to make the change transparent for profile
+         * owners.
+         *
+         * @hide
+         */
+        public static final String UNKNOWN_SOURCES_DEFAULT_REVERSED =
+                "unknown_sources_default_reversed";
+
+        /**
          * Comma-separated list of location providers that activities may access. Do not rely on
          * this value being present in settings.db or on ContentObserver notifications on the
          * corresponding Uri.
@@ -5492,7 +5506,12 @@
 
         /**
          * Whether to speak passwords while in accessibility mode.
+         *
+         * @deprecated The speaking of passwords is controlled by individual accessibility services.
+         * Apps should ignore this setting and provide complete information to accessibility
+         * at all times, which was the behavior when this value was {@code true}.
          */
+        @Deprecated
         public static final String ACCESSIBILITY_SPEAK_PASSWORD = "speak_password";
 
         /**
@@ -6888,6 +6907,12 @@
         public static final String PACKAGE_VERIFIER_STATE = "package_verifier_state";
 
         /**
+         * Specifies additional package name for broadcasting the CMAS messages.
+         * @hide
+         */
+        public static final String CMAS_ADDITIONAL_BROADCAST_PKG = "cmas_additional_broadcast_pkg";
+
+        /**
          * This are the settings to be backed up.
          *
          * NOTE: Settings are backed up and restored in the order they appear
@@ -6975,7 +7000,8 @@
             DOZE_PULSE_ON_DOUBLE_TAP,
             NFC_PAYMENT_DEFAULT_COMPONENT,
             AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
-            ASSIST_GESTURE_ENABLED
+            ASSIST_GESTURE_ENABLED,
+            VR_DISPLAY_MODE
         };
 
         /**
@@ -8210,7 +8236,14 @@
          * Value to specify if network recommendations from
          * {@link com.android.server.NetworkScoreService} are enabled.
          *
-         * Type: int (0 for false, 1 for true)
+         * Type: int
+         * Valid values:
+         *   -1 = Forced off
+         *    0 = Disabled
+         *    1 = Enabled
+         *
+         * Most readers of this setting should simply check if value == 1 to determined the
+         * enabled state.
          * @hide
          */
         @SystemApi
@@ -8241,6 +8274,15 @@
         public static final String CURATE_SAVED_OPEN_NETWORKS = "curate_saved_open_networks";
 
         /**
+         * The package name of the application that connect and secures high quality open wifi
+         * networks automatically.
+         *
+         * Type: string package name or null if the feature is either not provided or disabled.
+         * @hide
+         */
+        public static final String USE_OPEN_WIFI_PACKAGE = "use_open_wifi_package";
+
+        /**
          * The number of milliseconds the {@link com.android.server.NetworkScoreService}
          * will give a recommendation request to complete before returning a default response.
          *
@@ -8250,6 +8292,16 @@
         public static final String NETWORK_RECOMMENDATION_REQUEST_TIMEOUT_MS =
                 "network_recommendation_request_timeout_ms";
 
+        /**
+         * The expiration time in milliseconds for the {@link android.net.WifiKey} request cache in
+         * {@link com.android.server.wifi.RecommendedNetworkEvaluator}.
+         *
+         * Type: long
+         * @hide
+         */
+        public static final String RECOMMENDED_NETWORK_EVALUATOR_CACHE_EXPIRY_MS =
+                "recommended_network_evaluator_cache_expiry_ms";
+
        /**
         * Settings to allow BLE scans to be enabled even when Bluetooth is turned off for
         * connectivity.
@@ -8578,6 +8630,24 @@
                 SYS_STORAGE_FULL_THRESHOLD_BYTES = "sys_storage_full_threshold_bytes";
 
         /**
+         * Minimum percentage of storage on the device that is reserved for
+         * cached data.
+         *
+         * @hide
+         */
+        public static final String
+                SYS_STORAGE_CACHE_PERCENTAGE = "sys_storage_cache_percentage";
+
+        /**
+         * Maximum bytes of storage on the device that is reserved for cached
+         * data.
+         *
+         * @hide
+         */
+        public static final String
+                SYS_STORAGE_CACHE_MAX_BYTES = "sys_storage_cache_max_bytes";
+
+        /**
          * The maximum reconnect delay for short network outages or when the
          * network is suspended due to phone use.
          *
@@ -8895,6 +8965,30 @@
         public static final String DEVICE_IDLE_CONSTANTS_WATCH = "device_idle_constants_watch";
 
         /**
+         * Battery Saver specific settings
+         * This is encoded as a key=value list, separated by commas. Ex:
+         *
+         * "vibration_disabled=true,adjust_brightness_factor=0.5"
+         *
+         * The following keys are supported:
+         *
+         * <pre>
+         * vibration_disabled                (boolean)
+         * animation_disabled                (boolean)
+         * soundtrigger_disabled             (boolean)
+         * fullbackup_deferred               (boolean)
+         * keyvaluebackup_deferred           (boolean)
+         * firewall_disabled                 (boolean)
+         * gps_mode                          (int)
+         * adjust_brightness_disabled        (boolean)
+         * adjust_brightness_factor          (float)
+         * </pre>
+         * @hide
+         * @see com.android.server.power.BatterySaverPolicy
+         */
+        public static final String BATTERY_SAVER_CONSTANTS = "battery_saver_constants";
+
+        /**
          * App standby (app idle) specific settings.
          * This is encoded as a key=value list, separated by commas. Ex:
          *
@@ -9590,16 +9684,6 @@
         public static final String RETAIL_DEMO_MODE_CONSTANTS = "retail_demo_mode_constants";
 
         /**
-         * When blocked for the network policy rules to get updated, the maximum time that the
-         * {@link ActivityThread} have to wait before unblocking.
-         *
-         * Type: long
-         *
-         * @hide
-         */
-        public static final String WAIT_FOR_NETWORK_TIMEOUT_MS = "wait_for_network_timeout_ms";
-
-        /**
          * The reason for the settings database being downgraded. This is only for
          * troubleshooting purposes and its value should not be interpreted in any way.
          *
@@ -9654,6 +9738,7 @@
             CURATE_SAVED_OPEN_NETWORKS,
             WIFI_WAKEUP_ENABLED,
             WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
+            USE_OPEN_WIFI_PACKAGE,
             WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED,
             EMERGENCY_TONE,
             CALL_AUTO_RETRY,
@@ -10182,6 +10267,13 @@
          * @hide
          */
         public static final String ENABLE_DISKSTATS_LOGGING = "enable_diskstats_logging";
+
+        /**
+         * Whether the cache quota calculation task is enabled/disabled.
+         * @hide
+         */
+        public static final String ENABLE_CACHE_QUOTA_CALCULATION =
+                "enable_cache_quota_calculation";
     }
 
     /**
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index 5461e6b..ad8ad69 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -138,8 +138,6 @@
     public static final int KM_PURPOSE_DECRYPT = 1;
     public static final int KM_PURPOSE_SIGN = 2;
     public static final int KM_PURPOSE_VERIFY = 3;
-    public static final int KM_PURPOSE_DERIVE_KEY = 4;
-    public static final int KM_PURPOSE_WRAP_KEY = 5;
 
     // Key formats.
     public static final int KM_KEY_FORMAT_X509 = 0;
diff --git a/core/java/android/service/autofill/AutoFillService.java b/core/java/android/service/autofill/AutoFillService.java
index 4099f59..3c211eb 100644
--- a/core/java/android/service/autofill/AutoFillService.java
+++ b/core/java/android/service/autofill/AutoFillService.java
@@ -15,9 +15,12 @@
  */
 package android.service.autofill;
 
+import android.accessibilityservice.IAccessibilityServiceConnection;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.os.Message;
 import android.os.RemoteException;
+import android.view.accessibility.AccessibilityInteractionClient;
 import com.android.internal.os.HandlerCaller;
 import android.annotation.SdkConstant;
 import android.app.Activity;
@@ -79,6 +82,15 @@
 
     private final IAutoFillService mInterface = new IAutoFillService.Stub() {
         @Override
+        public void onInit(IAutoFillServiceConnection connection) {
+            if (connection != null) {
+                mHandlerCaller.obtainMessageO(MSG_CONNECT, connection).sendToTarget();
+            } else {
+                mHandlerCaller.obtainMessage(MSG_DISCONNECT).sendToTarget();
+            }
+        }
+
+        @Override
         public void onFillRequest(AssistStructure structure, Bundle extras,
                 IFillCallback callback) {
             ICancellationSignal transport = CancellationSignal.createTransport();
@@ -98,21 +110,12 @@
             mHandlerCaller.obtainMessageOOO(MSG_ON_SAVE_REQUEST, structure,
                     extras, callback).sendToTarget();
         }
-
-        @Override
-        public void onConnected() {
-            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessage(MSG_CONNECT));
-        }
-
-        @Override
-        public void onDisconnected() {
-            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessage(MSG_DISCONNECT));
-        }
     };
 
     private final HandlerCaller.Callback mHandlerCallback = (msg) -> {
         switch (msg.what) {
             case MSG_CONNECT: {
+                mConnection = (IAutoFillServiceConnection) msg.obj;
                 onConnected();
                 break;
             } case MSG_ON_FILL_REQUEST: {
@@ -136,6 +139,7 @@
                 break;
             } case MSG_DISCONNECT: {
                 onDisconnected();
+                mConnection = null;
                 break;
             } default: {
                 Log.w(TAG, "MyCallbacks received invalid message type: " + msg);
@@ -145,6 +149,8 @@
 
     private HandlerCaller mHandlerCaller;
 
+    private IAutoFillServiceConnection mConnection;
+
     /**
      * {@inheritDoc}
      *
@@ -223,4 +229,22 @@
     public void onDisconnected() {
         //TODO(b/33197203): is not called anymore, fix it!
     }
+
+    /**
+     * Disables the service. After calling this method, the service will
+     * be disabled and settings will show that it is turned off.
+     *
+     * <p>You should call this method only after a call to {@link #onConnected()}
+     * and before the corresponding call to {@link #onDisconnected()}. In other words
+     * you can disable your service only while the system is connected to it.</p>
+     */
+    public final void disableSelf() {
+        if (mConnection != null) {
+            try {
+                mConnection.disableSelf();
+            } catch (RemoteException re) {
+                throw re.rethrowFromSystemServer();
+            }
+        }
+    }
 }
diff --git a/core/java/android/service/autofill/Dataset.java b/core/java/android/service/autofill/Dataset.java
index bd38c7f..d76d444 100644
--- a/core/java/android/service/autofill/Dataset.java
+++ b/core/java/android/service/autofill/Dataset.java
@@ -16,6 +16,8 @@
 
 package android.service.autofill;
 
+import static android.view.autofill.Helper.DEBUG;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.IntentSender;
@@ -23,6 +25,7 @@
 import android.os.Parcelable;
 import android.view.autofill.AutoFillId;
 import android.view.autofill.AutoFillValue;
+import android.widget.RemoteViews;
 import com.android.internal.util.Preconditions;
 
 import java.util.ArrayList;
@@ -33,34 +36,28 @@
  * <p>It contains:
  *
  * <ol>
- *   <li>A name used to identify the dataset in the UI.
- *   <li>A list of id/value pairs for the fields that can be auto-filled.
- *   <li>A list of savable ids in addition to the ones with a provided value.
+ *   <li>A list of values for input fields.
+ *   <li>A presentation view to visualize.
+ *   <li>An optional intent to authenticate.
  * </ol>
  *
  * @see android.service.autofill.FillResponse for examples.
  */
 public final class Dataset implements Parcelable {
-    private static final boolean DEBUG = false;
 
-    private final CharSequence mName;
     private final ArrayList<AutoFillId> mFieldIds;
     private final ArrayList<AutoFillValue> mFieldValues;
+    private final RemoteViews mPresentation;
     private final IntentSender mAuthentication;
 
     private Dataset(Builder builder) {
-        mName = builder.mName;
         mFieldIds = builder.mFieldIds;
         mFieldValues = builder.mFieldValues;
+        mPresentation = builder.mPresentation;
         mAuthentication = builder.mAuthentication;
     }
 
     /** @hide */
-    public @NonNull CharSequence getName() {
-        return mName;
-    }
-
-    /** @hide */
     public @Nullable ArrayList<AutoFillId> getFieldIds() {
         return mFieldIds;
     }
@@ -71,6 +68,11 @@
     }
 
     /** @hide */
+    public @Nullable RemoteViews getPresentation() {
+        return mPresentation;
+    }
+
+    /** @hide */
     public @Nullable IntentSender getAuthentication() {
         return mAuthentication;
     }
@@ -84,11 +86,12 @@
     public String toString() {
         if (!DEBUG) return super.toString();
 
-        final StringBuilder builder = new StringBuilder("Dataset [name=").append(mName)
+        return new StringBuilder("Dataset [")
                 .append(", fieldIds=").append(mFieldIds)
                 .append(", fieldValues=").append(mFieldValues)
-                .append(", hasAuthentication=").append(mAuthentication != null);
-        return builder.append(']').toString();
+                .append(", hasPresentation=").append(mPresentation != null)
+                .append(", hasAuthentication=").append(mAuthentication != null)
+                .append(']').toString();
     }
 
     /**
@@ -96,21 +99,20 @@
      * one value for a field or set an authentication intent.
      */
     public static final class Builder {
-        private CharSequence mName;
         private ArrayList<AutoFillId> mFieldIds;
         private ArrayList<AutoFillValue> mFieldValues;
+        private RemoteViews mPresentation;
         private IntentSender mAuthentication;
         private boolean mDestroyed;
 
         /**
          * Creates a new builder.
          *
-         * @param name Name used to identify the dataset in the UI. Typically it's the same value as
-         * the first field in the dataset (like username or email address) or a user-provided name
-         * (like "My Work Address").
+         * @param presentation The presentation used to visualize this dataset.
          */
-        public Builder(@NonNull CharSequence name) {
-            mName = Preconditions.checkStringNotEmpty(name, "name cannot be empty or null");
+        public Builder(@NonNull RemoteViews presentation) {
+            Preconditions.checkNotNull(presentation, "presentation must be non-null");
+            mPresentation = presentation;
         }
 
         /**
@@ -119,7 +121,7 @@
          * <p>This method is called when you need to provide an authentication
          * UI for the data set. For example, when a data set contains credit card information
          * (such as number, expiration date, and verification code), you can display UI
-         * asking for the verification code to before filing in the data). Even if the
+         * asking for the verification code before filing in the data. Even if the
          * data set is completely populated the system will launch the specified authentication
          * intent and will need your approval to fill it in. Since the data set is "locked"
          * until the user authenticates it, typically this data set name is masked
@@ -136,7 +138,7 @@
          * android.app.Activity#RESULT_OK} and provide the fully populated {@link Dataset
          * dataset} by setting it to the {@link
          * android.view.autofill.AutoFillManager#EXTRA_AUTHENTICATION_RESULT} extra. For example,
-         * if you provided an credit card information without the CVV for the data set in the
+         * if you provided 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>
          *
@@ -145,6 +147,7 @@
          * platform needs to fill in the authentication arguments.</p>
          *
          * @param authentication Intent to an activity with your authentication flow.
+         * @return This builder.
          *
          * @see android.app.PendingIntent
          */
@@ -160,6 +163,7 @@
          * @param id id returned by {@link
          *         android.app.assist.AssistStructure.ViewNode#getAutoFillId()}.
          * @param value value to be auto filled.
+         * @return This builder.
          */
         public @NonNull Builder setValue(@NonNull AutoFillId id, @NonNull AutoFillValue value) {
             throwIfDestroyed();
@@ -182,14 +186,18 @@
 
         /**
          * Creates a new {@link Dataset} instance. You should not interact
-         * with this builder once this method is called.
+         * 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.
+         *
+         * @return The built dataset.
          */
         public @NonNull Dataset build() {
             throwIfDestroyed();
             mDestroyed = true;
-            if (mFieldIds == null && mAuthentication == null) {
+            if (mFieldIds == null) {
                 throw new IllegalArgumentException(
-                        "at least one value or an authentication must be set");
+                        "at least one value must be set");
             }
             return new Dataset(this);
         }
@@ -212,9 +220,9 @@
 
     @Override
     public void writeToParcel(Parcel parcel, int flags) {
-        parcel.writeCharSequence(mName);
-        parcel.writeTypedArrayList(mFieldIds, 0);
-        parcel.writeTypedArrayList(mFieldValues, 0);
+        parcel.writeParcelable(mPresentation, flags);
+        parcel.writeTypedArrayList(mFieldIds, flags);
+        parcel.writeTypedArrayList(mFieldValues, flags);
         parcel.writeParcelable(mAuthentication, flags);
     }
 
@@ -224,7 +232,7 @@
             // Always go through the builder to ensure the data ingested by
             // the system obeys the contract of the builder to avoid attacks
             // using specially crafted parcels.
-            final Builder builder = new Builder(parcel.readCharSequence());
+            final Builder builder = new Builder(parcel.readParcelable(null));
             final ArrayList<AutoFillId> ids = parcel.readTypedArrayList(null);
             final ArrayList<AutoFillValue> values = parcel.readTypedArrayList(null);
             final int idCount = (ids != null) ? ids.size() : 0;
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index ea36e64..c457c56 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -15,21 +15,24 @@
  */
 package android.service.autofill;
 
+import static android.view.autofill.Helper.DEBUG;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.IntentSender;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.util.ArraySet;
 import android.view.autofill.AutoFillId;
 import android.view.autofill.AutoFillManager;
+import android.widget.RemoteViews;
+
+import java.util.ArrayList;
 
 /**
  * Response for a {@link
  * AutoFillService#onFillRequest(android.app.assist.AssistStructure,
- * Bundle, android.os.CancellationSignal, FillCallback)} and
- * authentication requests.
+ * Bundle, android.os.CancellationSignal, FillCallback)}.
  *
  * <p>The response typically contains one or more {@link Dataset}s, each representing a set of
  * fields that can be auto-filled together, and the Android system displays a dataset picker UI
@@ -41,7 +44,7 @@
  *
  * <pre class="prettyprint">
  *  new FillResponse.Builder()
- *      .add(new Dataset.Builder("homer")
+ *      .add(new Dataset.Builder(createPresentation())
  *          .setTextFieldValue(id1, "homer")
  *          .setTextFieldValue(id2, "D'OH!")
  *          .build())
@@ -52,11 +55,11 @@
  *
  * <pre class="prettyprint">
  *  new FillResponse.Builder()
- *      .add(new Dataset.Builder("Homer's Account")
+ *      .add(new Dataset.Builder(createFirstPresentation())
  *          .setTextFieldValue(id1, "homer")
  *          .setTextFieldValue(id2, "D'OH!")
  *          .build())
- *      .add(new Dataset.Builder("Bart's Account")
+ *      .add(new Dataset.Builder(createSecondPresentation())
  *          .setTextFieldValue(id1, "elbarto")
  *          .setTextFieldValue(id2, "cowabonga")
  *          .build())
@@ -65,28 +68,30 @@
  *
  * <p>If the user does not have any data associated with this {@link android.app.Activity} but
  * the service wants to offer the user the option to save the data that was entered, then the
- * service could populate the response with {@code savableIds} instead of {@link Dataset}s:
+ * service could populate the response with a {@link SaveInfo} instead of {@link Dataset}s:
  *
  * <pre class="prettyprint">
  *  new FillResponse.Builder()
- *      .addSavableFields(id1, id2)
+ *      .setSaveInfo(new SaveInfo.Builder(SaveInfo.SAVE_INFO_TYPE_CREDENTIALS)
+ *                   .addSavableFields(id1, id2))
  *      .build();
  * </pre>
  *
  * <p>Similarly, there might be cases where the user data on the service 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 populate the response with both {@link Dataset}s and {@code
- * savableIds}:
+ * scenario, the service could populate the response with both {@link Dataset}s and
+ * {@link SaveInfo}:
  *
  * <pre class="prettyprint">
  *   new FillResponse.Builder()
- *       .add(new Dataset.Builder("Homer")
+ *       .add(new Dataset.Builder(createPresentation())
  *          .setTextFieldValue(id1, "Homer")                  // first name
  *          .setTextFieldValue(id2, "Simpson")                // last name
  *          .setTextFieldValue(id3, "742 Evergreen Terrace")  // street
  *          .setTextFieldValue(id4, "Springfield")            // city
  *          .build())
- *       .addSavableFields(id5, id6) // state and zipcode
+ *       .setSaveInfo(new SaveInfo.Builder(SaveInfo.SAVE_INFO_TYPE_ADDRESS)
+ *                   .addSavableFields(id5, id6)) // state and zipcode
  *       .build();
  *
  * </pre>
@@ -108,27 +113,27 @@
  *
  * <pre class="prettyprint">
  *  new FillResponse.Builder()
- *      .add(new Dataset.Builder("Homer")
+ *      .add(new Dataset.Builder(createFirstPresentation())
  *          .setTextFieldValue(id1, "Homer")
  *          .setTextFieldValue(id2, "Simpson")
  *          .build())
- *      .add(new Dataset.Builder("Bart")
+ *      .add(new Dataset.Builder(createSecondPresentation())
  *          .setTextFieldValue(id1, "Bart")
  *          .setTextFieldValue(id2, "Simpson")
  *          .build())
  *      .build();
  * </pre>
  *
- * <p>Then after the user picks the {@code Homer} dataset and taps the {@code Street} field to
+ * <p>Then after the user picks the second dataset and taps the street field to
  * trigger another auto-fill request, the second response could be:
  *
  * <pre class="prettyprint">
  *  new FillResponse.Builder()
- *      .add(new Dataset.Builder("Home")
+ *      .add(new Dataset.Builder(createThirdPresentation())
  *          .setTextFieldValue(id3, "742 Evergreen Terrace")
  *          .setTextFieldValue(id4, "Springfield")
  *          .build())
- *      .add(new Dataset.Builder("Work")
+ *      .add(new Dataset.Builder(createFourthPresentation())
  *          .setTextFieldValue(id3, "Springfield Power Plant")
  *          .setTextFieldValue(id4, "Springfield")
  *          .build())
@@ -136,33 +141,47 @@
  * </pre>
  *
  * <p>The service could require user authentication at the {@link FillResponse} or the
- * {@link Dataset} level, prior to auto-filling an activity - see {@link FillResponse.Builder
- * #setAuthentication(IntentSender)} and {@link Dataset.Builder#setAuthentication(IntentSender)}.
- * It is recommended that you encrypt only the sensitive data but leave the labels unencrypted
- * which would allow you to provide the dataset names to the user and if they choose one
- * them challenge the user to onAuthenticate. 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 Home and Work options which will trigger your auth
- * flow and after successfully authenticating the user will be presented with the Home and
- * Work options where they can 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>
+ * {@link Dataset} level, prior to auto-filling an activity - see
+ * {@link FillResponse.Builder#setAuthentication(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>
  */
 public final class FillResponse implements Parcelable {
-    private static final boolean DEBUG = false;
 
-    private final ArraySet<Dataset> mDatasets;
-    private final ArraySet<AutoFillId> mSavableIds;
+    private final ArrayList<Dataset> mDatasets;
+    private final SaveInfo mSaveInfo;
     private final Bundle mExtras;
+    private final RemoteViews mPresentation;
     private final IntentSender mAuthentication;
 
     private FillResponse(@NonNull Builder builder) {
         mDatasets = builder.mDatasets;
-        mSavableIds = builder.mSavableIds;
+
+        // TODO(b/33197203, 35727295): this is how mSaveInfo will be set once we don't support
+        // FillResponse.addSavableIds()
+        mSaveInfo = builder.mSaveInfo;
+        if (mSaveInfo != null) {
+            mSaveInfo.addSavableIds(mDatasets);
+            if (mSaveInfo.getSavableIds() == null) {
+                throw new IllegalArgumentException(
+                        "need to provide at least one savable id on SaveInfo");
+            }
+        }
+
         mExtras = builder.mExtras;
+        mPresentation = builder.mPresentation;
         mAuthentication = builder.mAuthentication;
     }
 
@@ -172,13 +191,18 @@
     }
 
     /** @hide */
-    public @Nullable ArraySet<Dataset> getDatasets() {
+    public @Nullable ArrayList<Dataset> getDatasets() {
         return mDatasets;
     }
 
     /** @hide */
-    public @Nullable ArraySet<AutoFillId> getSavableIds() {
-        return mSavableIds;
+    public @Nullable SaveInfo getSaveInfo() {
+        return mSaveInfo;
+    }
+
+    /** @hide */
+    public @Nullable RemoteViews getPresentation() {
+        return mPresentation;
     }
 
     /** @hide */
@@ -188,23 +212,17 @@
 
     /**
      * Builder for {@link FillResponse} objects. You must to provide at least
-     * one dataset or set an authentication intent.
+     * one dataset or set an authentication intent with a presentation view.
      */
     public static final class Builder {
-        private ArraySet<Dataset> mDatasets;
-        private ArraySet<AutoFillId> mSavableIds;
+        private ArrayList<Dataset> mDatasets;
+        private SaveInfo mSaveInfo;
         private Bundle mExtras;
+        private RemoteViews mPresentation;
         private IntentSender mAuthentication;
         private boolean mDestroyed;
 
         /**
-         * Creates a new {@link FillResponse} builder.
-         */
-        public Builder() {
-
-        }
-
-        /**
          * Requires a fill response authentication before auto-filling the activity with
          * any data set in this response.
          *
@@ -214,14 +232,15 @@
          * 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.</p>
+         * 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>
          *
          * <p>When a user triggers auto-fill, the system launches the provided intent
-         * whose extras will have the {@link
-         * AutoFillManager#EXTRA_ASSIST_STRUCTURE screen
+         * whose extras will have the {@link AutoFillManager#EXTRA_ASSIST_STRUCTURE screen
          * content}. 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
+         * 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
@@ -229,25 +248,36 @@
          * available data sets some of which may need to be further authenticated, for
          * example a credit card whose CVV needs to be entered.</p>
          *
+         * <p>If you provide an authentication intent you must also provide a presentation
+         * which is used to visualize visualize the response for triggering the authentication
+         * flow.</p>
+         *
          * <p></><strong>Note:</strong> 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>
          *
          * @param authentication Intent to an activity with your authentication flow.
+         * @param presentation The presentation to visualize the response.
+         * @return This builder.
          *
          * @see android.app.PendingIntent#getIntentSender()
          */
-        public @NonNull Builder setAuthentication(@Nullable IntentSender authentication) {
+        public @NonNull Builder setAuthentication(@Nullable IntentSender authentication,
+                @Nullable RemoteViews presentation) {
             throwIfDestroyed();
+            if (authentication == null ^ presentation == null) {
+                throw new IllegalArgumentException("authentication and presentation"
+                        + " must be both non-null or null");
+            }
             mAuthentication = authentication;
+            mPresentation = presentation;
             return this;
         }
 
         /**
-         * Adds a new {@link Dataset} to this response. Adding a dataset with the
-         * same id updates the existing one.
+         * Adds a new {@link Dataset} to this response.
          *
-         * @throws IllegalArgumentException if a dataset with same {@code name} already exists.
+         * @return This builder.
          */
         public@NonNull Builder addDataset(@Nullable Dataset dataset) {
             throwIfDestroyed();
@@ -255,48 +285,24 @@
                 return this;
             }
             if (mDatasets == null) {
-                mDatasets = new ArraySet<>();
-            }
-            final int datasetCount = mDatasets.size();
-            for (int i = 0; i < datasetCount; i++) {
-                if (mDatasets.valueAt(i).getName().equals(dataset.getName())) {
-                    throw new IllegalArgumentException("Duplicate dataset name: "
-                            + dataset.getName());
-                }
+                mDatasets = new ArrayList<>();
             }
             if (!mDatasets.add(dataset)) {
                 return this;
             }
-            final int fieldCount = dataset.getFieldIds().size();
-            for (int i = 0; i < fieldCount; i++) {
-                final AutoFillId id = dataset.getFieldIds().get(i);
-                if (mSavableIds == null) {
-                    mSavableIds = new ArraySet<>();
-                }
-                mSavableIds.add(id);
-            }
             return this;
         }
 
         /**
-         * Adds ids of additional fields that the service would be interested to save (through
-         * {@link AutoFillService#onSaveRequest(
-         * android.app.assist.AssistStructure, Bundle, SaveCallback)})
-         * but were not indirectly set through {@link #addDataset(Dataset)}.
+         * Sets the {@link SaveInfo} associated with this response.
          *
-         * <p>See {@link FillResponse} for examples.
+         * <p>See {@link FillResponse} for more info.
+         *
+         * @return This builder.
          */
-        public @NonNull Builder addSavableFields(@Nullable AutoFillId... ids) {
+        public @NonNull Builder setSaveInfo(@NonNull SaveInfo saveInfo) {
             throwIfDestroyed();
-            if (ids == null) {
-                return this;
-            }
-            for (AutoFillId id : ids) {
-                if (mSavableIds == null) {
-                    mSavableIds = new ArraySet<>();
-                }
-                mSavableIds.add(id);
-            }
+            mSaveInfo = saveInfo;
             return this;
         }
 
@@ -305,10 +311,11 @@
          * manipulate this response. For example, they are passed to subsequent
          * calls to {@link AutoFillService#onFillRequest(
          * android.app.assist.AssistStructure, Bundle, android.os.CancellationSignal,
-         * FillCallback)} and {@link
-         * AutoFillService#onSaveRequest(
-         * android.app.assist.AssistStructure, Bundle,
-         * SaveCallback)}.
+         * FillCallback)} and {@link AutoFillService#onSaveRequest(
+         * android.app.assist.AssistStructure, Bundle, SaveCallback)}.
+         *
+         * @param extras The response extras.
+         * @return This builder.
          */
         public Builder setExtras(Bundle extras) {
             throwIfDestroyed();
@@ -317,10 +324,19 @@
         }
 
         /**
-         * Builds a new {@link FillResponse} instance.
+         * Builds a new {@link FillResponse} instance. You must provide at least
+         * one dataset or some savable ids or an authentication with a presentation
+         * view.
+         *
+         * @return A built response.
          */
         public FillResponse build() {
             throwIfDestroyed();
+
+            if (mAuthentication == null && mDatasets == null && mSaveInfo == null) {
+                throw new IllegalArgumentException("need to provide at least one DataSet or a "
+                        + "SaveInfo or an authentication with a presentation");
+            }
             mDestroyed = true;
             return new FillResponse(this);
         }
@@ -338,12 +354,14 @@
     @Override
     public String toString() {
         if (!DEBUG) return super.toString();
-        final StringBuilder builder = new StringBuilder(
+
+        return new StringBuilder(
                 "FillResponse: [datasets=").append(mDatasets)
-                .append(", savableIds=").append(mSavableIds)
+                .append(", saveInfo=").append(mSaveInfo)
                 .append(", hasExtras=").append(mExtras != null)
-                .append(", hasAuthentication=").append(mAuthentication != null);
-        return builder.append(']').toString();
+                .append(", hasPresentation=").append(mPresentation != null)
+                .append(", hasAuthentication=").append(mAuthentication != null)
+                .toString();
     }
 
     /////////////////////////////////////
@@ -357,10 +375,11 @@
 
     @Override
     public void writeToParcel(Parcel parcel, int flags) {
-        parcel.writeTypedArraySet(mDatasets, 0);
-        parcel.writeTypedArraySet(mSavableIds, 0);
-        parcel.writeParcelable(mExtras, 0);
-        parcel.writeParcelable(mAuthentication, 0);
+        parcel.writeTypedArrayList(mDatasets, flags);
+        parcel.writeParcelable(mSaveInfo, flags);
+        parcel.writeParcelable(mExtras, flags);
+        parcel.writeParcelable(mAuthentication, flags);
+        parcel.writeParcelable(mPresentation, flags);
     }
 
     public static final Parcelable.Creator<FillResponse> CREATOR =
@@ -371,18 +390,15 @@
             // the system obeys the contract of the builder to avoid attacks
             // using specially crafted parcels.
             final Builder builder = new Builder();
-            final ArraySet<Dataset> datasets = parcel.readTypedArraySet(null);
+            final ArrayList<Dataset> datasets = parcel.readTypedArrayList(null);
             final int datasetCount = (datasets != null) ? datasets.size() : 0;
             for (int i = 0; i < datasetCount; i++) {
-                builder.addDataset(datasets.valueAt(i));
+                builder.addDataset(datasets.get(i));
             }
-            final ArraySet<AutoFillId> fillIds = parcel.readTypedArraySet(null);
-            final int fillIdCount = (fillIds != null) ? fillIds.size() : 0;
-            for (int i = 0; i < fillIdCount; i++) {
-                builder.addSavableFields(fillIds.valueAt(i));
-            }
+            builder.setSaveInfo(parcel.readParcelable(null));
             builder.setExtras(parcel.readParcelable(null));
-            builder.setAuthentication(parcel.readParcelable(null));
+            builder.setAuthentication(parcel.readParcelable(null),
+                    parcel.readParcelable(null));
             return builder.build();
         }
 
diff --git a/core/java/android/service/autofill/IAutoFillService.aidl b/core/java/android/service/autofill/IAutoFillService.aidl
index fa1ea65..80685d8 100644
--- a/core/java/android/service/autofill/IAutoFillService.aidl
+++ b/core/java/android/service/autofill/IAutoFillService.aidl
@@ -18,6 +18,7 @@
 
 import android.app.assist.AssistStructure;
 import android.os.Bundle;
+import android.service.autofill.IAutoFillServiceConnection;
 import android.service.autofill.IFillCallback;
 import android.service.autofill.ISaveCallback;
 import com.android.internal.os.IResultReceiver;
@@ -28,10 +29,9 @@
  * @hide
  */
 oneway interface IAutoFillService {
+    void onInit(in IAutoFillServiceConnection connection);
     void onFillRequest(in AssistStructure structure, in Bundle extras,
             in IFillCallback callback);
     void onSaveRequest(in AssistStructure structure, in Bundle extras,
             in ISaveCallback callback);
-    void onConnected();
-    void onDisconnected();
 }
diff --git a/core/java/com/android/internal/logging/legacy/Util.java b/core/java/android/service/autofill/IAutoFillServiceConnection.aidl
similarity index 78%
rename from core/java/com/android/internal/logging/legacy/Util.java
rename to core/java/android/service/autofill/IAutoFillServiceConnection.aidl
index 99f71ca..cf73a10 100644
--- a/core/java/com/android/internal/logging/legacy/Util.java
+++ b/core/java/android/service/autofill/IAutoFillServiceConnection.aidl
@@ -13,13 +13,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.internal.logging.legacy;
+
+package android.service.autofill;
 
 /**
- * Created by cwren on 11/21/16.
+ * Interface from an auto fill service to the system.
+ *
+ * @hide
  */
-public class Util {
-    public static boolean debug() {
-        return false;
-    }
+interface IAutoFillServiceConnection {
+    void disableSelf();
 }
diff --git a/core/java/android/net/NetworkScorerAppManager.aidl b/core/java/android/service/autofill/SaveInfo.aidl
similarity index 88%
copy from core/java/android/net/NetworkScorerAppManager.aidl
copy to core/java/android/service/autofill/SaveInfo.aidl
index d968343..8cda608 100644
--- a/core/java/android/net/NetworkScorerAppManager.aidl
+++ b/core/java/android/service/autofill/SaveInfo.aidl
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package android.net;
+package android.service.autofill;
 
-parcelable NetworkScorerAppManager.NetworkScorerAppData;
+parcelable SaveInfo;
diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java
new file mode 100644
index 0000000..a8f9aee
--- /dev/null
+++ b/core/java/android/service/autofill/SaveInfo.java
@@ -0,0 +1,319 @@
+/*
+ * 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 android.service.autofill;
+
+import static android.view.autofill.Helper.DEBUG;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.IntentSender;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArraySet;
+import android.view.autofill.AutoFillId;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+
+/**
+ * Information used to indicate that a service is interested on saving the user-inputed data for
+ * future use.
+ *
+ * <p>A {@link SaveInfo} is always associated with a {@link FillResponse}.
+ *
+ * <p>A {@link SaveInfo} must define the type it represents, and contain at least one
+ * {@code savableId}. A {@code savableId} is the {@link AutoFillId} of a view the service is
+ * interested to save in a {@code onSaveRequest()}; the ids of all {@link Dataset} present in the
+ * {@link FillResponse} associated with this {@link SaveInfo} are already marked as savable,
+ * but additional ids can be added through {@link Builder#addSavableIds(AutoFillId...)}.
+ *
+ * <p>See {@link AutoFillService#onSaveRequest(android.app.assist.AssistStructure, Bundle,
+ * SaveCallback)} and {@link FillResponse} for more info.
+ */
+public final class SaveInfo implements Parcelable {
+
+    /**
+     * Type used on when the service can save the contents of an activity, but cannot describe what
+     * the content is for.
+     */
+    public static final int SAVE_DATA_TYPE_GENERIC = 0;
+
+    /**
+     * Type used when the {@link FillResponse} represents user credentials that have a password.
+     */
+    public static final int SAVE_DATA_TYPE_PASSWORD = 1;
+
+
+    /**
+     * Type used on when the {@link FillResponse} represents a physical address (such as street,
+     * city, state, etc).
+     */
+    public static final int SAVE_DATA_TYPE_ADDRESS = 2;
+
+    /**
+     * Type used when the {@link FillResponse} represents a credit card.
+     */
+    public static final int SAVE_DATA_TYPE_CREDIT_CARD = 3;
+
+    private final @SaveDataType int mType;
+    private CharSequence mNegativeActionTitle;
+    private IntentSender mNegativeActionListener;
+    private ArraySet<AutoFillId> mSavableIds;
+    private final CharSequence mDescription;
+
+    /** @hide */
+    @IntDef({
+        SAVE_DATA_TYPE_GENERIC,
+        SAVE_DATA_TYPE_PASSWORD,
+        SAVE_DATA_TYPE_ADDRESS,
+        SAVE_DATA_TYPE_CREDIT_CARD
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SaveDataType {
+    }
+
+    private SaveInfo(Builder builder) {
+        mType = builder.mType;
+        mNegativeActionTitle = builder.mNegativeActionTitle;
+        mNegativeActionListener = builder.mNegativeActionListener;
+        mSavableIds = builder.mSavableIds;
+        mDescription = builder.mDescription;
+    }
+
+    /** @hide */
+    public @Nullable CharSequence getNegativeActionTitle() {
+        return mNegativeActionTitle;
+    }
+
+    /** @hide */
+    public @Nullable IntentSender getNegativeActionListener() {
+        return mNegativeActionListener;
+    }
+
+    /** @hide */
+    public @Nullable ArraySet<AutoFillId> getSavableIds() {
+        return mSavableIds;
+    }
+
+    /** @hide */
+    public int getType() {
+        return mType;
+    }
+
+    /** @hide */
+    public CharSequence getDescription() {
+        return mDescription;
+    }
+
+    /** @hide */
+    public void addSavableIds(@Nullable ArrayList<Dataset> datasets) {
+        if (datasets != null) {
+            for (Dataset dataset : datasets) {
+                final ArrayList<AutoFillId> ids = dataset.getFieldIds();
+                if (ids != null) {
+                    final int fieldCount = ids.size();
+                    for (int i = 0; i < fieldCount; i++) {
+                        final AutoFillId id = ids.get(i);
+                        if (mSavableIds == null) {
+                            mSavableIds = new ArraySet<>();
+                        }
+                        mSavableIds.add(id);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * A builder for {@link SaveInfo} objects.
+     */
+    public static final class Builder {
+
+        private final @SaveDataType int mType;
+        private CharSequence mNegativeActionTitle;
+        private IntentSender mNegativeActionListener;
+        private ArraySet<AutoFillId> mSavableIds;
+        private CharSequence mDescription;
+        private boolean mDestroyed;
+
+        /**
+         * Creates a new builder.
+         *
+         * @param type the type of information the associated {@link FillResponse} represents. Must
+         * be {@link SaveInfo#SAVE_DATA_TYPE_GENERIC}, {@link SaveInfo#SAVE_DATA_TYPE_PASSWORD},
+         * {@link SaveInfo#SAVE_DATA_TYPE_ADDRESS}, or {@link SaveInfo#SAVE_DATA_TYPE_CREDIT_CARD};
+         * otherwise it will assume {@link SaveInfo#SAVE_DATA_TYPE_GENERIC}.
+         */
+        public Builder(@SaveDataType int type) {
+            switch (type) {
+                case SAVE_DATA_TYPE_PASSWORD:
+                case SAVE_DATA_TYPE_ADDRESS:
+                case SAVE_DATA_TYPE_CREDIT_CARD:
+                    mType = type;
+                    break;
+                default:
+                    mType = SAVE_DATA_TYPE_GENERIC;
+            }
+        }
+
+        /**
+         * Adds ids of additional views the service would be interested to save, but were not
+         * indirectly set through {@link FillResponse.Builder#addDataset(Dataset)}.
+         *
+         * @param ids The savable ids.
+         * @return This builder.
+         *
+         * @see FillResponse
+         */
+        public @NonNull Builder addSavableIds(@Nullable AutoFillId... ids) {
+            throwIfDestroyed();
+
+            if (ids == null) {
+                return this;
+            }
+            for (AutoFillId id : ids) {
+                if (mSavableIds == null) {
+                    mSavableIds = new ArraySet<>();
+                }
+                mSavableIds.add(id);
+            }
+            return this;
+        }
+
+        /**
+         * Sets an optional description to be shown in the UI when the user is asked to save.
+         *
+         * <p>Typically, it describes how the data will be stored by the service, so it can help
+         * users to decide whether they can trust the service to save their data.
+         *
+         * @param description a succint description.
+         * @return This Builder.
+         */
+        public @NonNull Builder setDescription(@Nullable CharSequence description) {
+            mDescription = description;
+            return this;
+        }
+
+        /**
+         * Sets the title and listener for the negative save action.
+         *
+         * <p>This allows a fill-provider to customize the text and be
+         * notified when the user selects the negative action in the save
+         * UI. Note that selecting the negative action regardless of its text
+         * and listener being customized would dismiss the save UI and if a
+         * custom listener intent is provided then this intent will be
+         * started.</p>
+         *
+         * <p>This customization could be useful for providing additional
+         * semantics to the negative action. For example, a fill-provider
+         * can use this mechanism to add a "Disable" function or a "More info"
+         * function, etc. Note that the save action is exclusively controlled
+         * by the platform to ensure user consent is collected to release
+         * data from the filled app to the fill-provider.</p>
+         *
+         * @param title The action title.
+         * @param listener The action listener.
+         * @return This builder.
+         *
+         * @throws IllegalArgumentException If the title and the listener
+         *     are not both either null or non-null.
+         */
+        public @NonNull Builder setNegativeAction(@Nullable CharSequence title,
+                @Nullable IntentSender listener) {
+            throwIfDestroyed();
+            if (title == null ^ listener == null) {
+                throw new IllegalArgumentException("title and listener"
+                        + " must be both non-null or null");
+            }
+            mNegativeActionTitle = title;
+            mNegativeActionListener = listener;
+            return this;
+        }
+
+        /**
+         * Builds a new {@link SaveInfo} instance.
+         */
+        public SaveInfo build() {
+            throwIfDestroyed();
+            mDestroyed = true;
+            return new SaveInfo(this);
+        }
+
+        private void throwIfDestroyed() {
+            if (mDestroyed) {
+                throw new IllegalStateException("Already called #build()");
+            }
+        }
+
+    }
+
+    /////////////////////////////////////
+    // Object "contract" methods. //
+    /////////////////////////////////////
+    @Override
+    public String toString() {
+        if (!DEBUG) return super.toString();
+
+        return new StringBuilder("SaveInfo: [type=").append(mType)
+                .append(", savableIds=").append(mSavableIds)
+                .append("]").toString();
+    }
+
+    /////////////////////////////////////
+    // Parcelable "contract" methods. //
+    /////////////////////////////////////
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeInt(mType);
+        parcel.writeCharSequence(mNegativeActionTitle);
+        parcel.writeParcelable(mNegativeActionListener, flags);
+        parcel.writeTypedArraySet(mSavableIds, flags);
+        parcel.writeCharSequence(mDescription);
+    }
+
+    public static final Parcelable.Creator<SaveInfo> CREATOR = new Parcelable.Creator<SaveInfo>() {
+        @Override
+        public SaveInfo createFromParcel(Parcel parcel) {
+            // Always go through the builder to ensure the data ingested by
+            // the system obeys the contract of the builder to avoid attacks
+            // using specially crafted parcels.
+            final Builder builder = new Builder(parcel.readInt());
+            builder.setNegativeAction(parcel.readCharSequence(), parcel.readParcelable(null));
+            final ArraySet<AutoFillId> savableIds = parcel.readTypedArraySet(null);
+            final int savableIdsCount = (savableIds != null) ? savableIds.size() : 0;
+            for (int i = 0; i < savableIdsCount; i++) {
+                builder.addSavableIds(savableIds.valueAt(i));
+            }
+            builder.setDescription(parcel.readCharSequence());
+            return builder.build();
+        }
+
+        @Override
+        public SaveInfo[] newArray(int size) {
+            return new SaveInfo[size];
+        }
+    };
+}
diff --git a/core/java/android/service/notification/ConditionProviderService.java b/core/java/android/service/notification/ConditionProviderService.java
index c8358a6..3e992ec 100644
--- a/core/java/android/service/notification/ConditionProviderService.java
+++ b/core/java/android/service/notification/ConditionProviderService.java
@@ -127,7 +127,7 @@
     }
 
     /**
-     * Request that the provider be rebound, after a previous call to (@link requestUnbind).
+     * Request that the provider be rebound, after a previous call to (@link #requestUnbind).
      *
      * <p>This method will fail for providers that have not been granted the permission by the user.
      */
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 5f7ff67..70e0461 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -148,7 +148,7 @@
 
     // Notification cancellation reasons
 
-    /** Notification was canceled by the status bar reporting a click. */
+    /** Notification was canceled by the status bar reporting a notification click. */
     public static final int REASON_DELEGATE_CLICK = 1;
     /** Notification was canceled by the status bar reporting a user dismissal. */
     public static final int REASON_DELEGATE_CANCEL = 2;
@@ -547,20 +547,20 @@
      * Inform the notification manager about snoozing a specific notification.
      * <p>
      * Use this if your listener has a user interface that allows the user to snooze a notification
-     * until a given time. It should be called after the user snoozes a single notification using
+     * for a time. It should be called after the user snoozes a single notification using
      * your UI; upon being informed, the notification manager will actually remove the notification
      * and you will get an {@link #onNotificationRemoved(StatusBarNotification)} callback. When the
      * snoozing period expires, you will get a
      * {@link #onNotificationPosted(StatusBarNotification, RankingMap)} callback for the
      * notification.
      * @param key The key of the notification to snooze
-     * @param snoozeUntil A time in the future, in milliseconds.
+     * @param durationMs A duration to snooze the notification for, in milliseconds.
      */
-    public final void snoozeNotification(String key, long snoozeUntil) {
+    public final void snoozeNotification(String key, long durationMs) {
         if (!isBound()) return;
         try {
             getNotificationInterface().snoozeNotificationUntilFromListener(
-                    mWrapper, key, snoozeUntil);
+                    mWrapper, key, durationMs);
         } catch (android.os.RemoteException ex) {
             Log.v(TAG, "Unable to contact notification manager", ex);
         }
@@ -636,7 +636,7 @@
      * <p>The service should wait for the {@link #onListenerConnected()} event
      * before performing this operation.
      *
-     * @return An array of active notifications, sorted in natural order.
+     * @return An array of snoozed notifications, sorted in natural order.
      */
     public final StatusBarNotification[] getSnoozedNotifications() {
         try {
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index 85bccf7..6a24aa4 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -67,6 +67,9 @@
         this.groupKey = groupKey();
     }
 
+    /**
+     * @deprecated Non-system apps should not need to create StatusBarNotifications.
+     */
     @Deprecated
     public StatusBarNotification(String pkg, String opPkg, int id, String tag, int uid,
             int initialPid, int score, Notification notification, UserHandle user,
diff --git a/core/java/android/service/quicksettings/TileService.java b/core/java/android/service/quicksettings/TileService.java
index 1781c2a..2116847 100644
--- a/core/java/android/service/quicksettings/TileService.java
+++ b/core/java/android/service/quicksettings/TileService.java
@@ -126,7 +126,9 @@
     public static final String EXTRA_TOKEN = "token";
 
     /**
-     * @hide
+     * May be included when {@link #ACTION_QS_TILE_PREFERENCES} is launched from a tile.
+     * This extra may contain the {@link ComponentName} of the tile that triggered
+     * the preferences to be opened.
      */
     public static final String EXTRA_COMPONENT = "android.service.quicksettings.extra.COMPONENT";
 
diff --git a/core/java/android/service/trust/ITrustAgentService.aidl b/core/java/android/service/trust/ITrustAgentService.aidl
index 22b4d09..21661db 100644
--- a/core/java/android/service/trust/ITrustAgentService.aidl
+++ b/core/java/android/service/trust/ITrustAgentService.aidl
@@ -16,6 +16,7 @@
 package android.service.trust;
 
 import android.os.PersistableBundle;
+import android.os.UserHandle;
 import android.service.trust.ITrustAgentServiceCallback;
 
 /**
@@ -30,4 +31,7 @@
     oneway void onDeviceUnlocked();
     oneway void onConfigure(in List<PersistableBundle> options, IBinder token);
     oneway void setCallback(ITrustAgentServiceCallback callback);
+    oneway void onEscrowTokenAdded(in byte[] token, long handle, in UserHandle user);
+    oneway void onTokenStateReceived(long handle, int tokenState);
+    oneway void onEscrowTokenRemoved(long handle, boolean successful);
 }
diff --git a/core/java/android/service/trust/ITrustAgentServiceCallback.aidl b/core/java/android/service/trust/ITrustAgentServiceCallback.aidl
index ec66cc8..14df7cb 100644
--- a/core/java/android/service/trust/ITrustAgentServiceCallback.aidl
+++ b/core/java/android/service/trust/ITrustAgentServiceCallback.aidl
@@ -28,4 +28,8 @@
     void revokeTrust();
     void setManagingTrust(boolean managingTrust);
     void onConfigureCompleted(boolean result, IBinder token);
+    void addEscrowToken(in byte[] token, int userId);
+    void isEscrowTokenActive(long handle, int userId);
+    void removeEscrowToken(long handle, int userId);
+    void unlockUserWithToken(long handle, in byte[] token, int userId);
 }
diff --git a/core/java/android/service/trust/TrustAgentService.java b/core/java/android/service/trust/TrustAgentService.java
index 0d5177d..2b37a23 100644
--- a/core/java/android/service/trust/TrustAgentService.java
+++ b/core/java/android/service/trust/TrustAgentService.java
@@ -23,16 +23,20 @@
 import android.app.Service;
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
+import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.Message;
 import android.os.PersistableBundle;
 import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
 import android.util.Log;
 import android.util.Slog;
-
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.List;
@@ -118,13 +122,44 @@
     public @interface GrantTrustFlags {}
 
 
+    /**
+     * Int enum indicating that escrow token is active.
+     * See {@link #onEscrowTokenStateReceived(long, int)}
+     *
+     */
+    public static final int TOKEN_STATE_ACTIVE = 1;
+
+    /**
+     * Int enum indicating that escow token is inactive.
+     * See {@link #onEscrowTokenStateReceived(long, int)}
+     *
+     */
+    public static final int TOKEN_STATE_INACTIVE = 0;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(flag = true,
+            value = {
+                TOKEN_STATE_ACTIVE,
+                TOKEN_STATE_INACTIVE,
+            })
+    public @interface TokenState {}
+
     private static final int MSG_UNLOCK_ATTEMPT = 1;
     private static final int MSG_CONFIGURE = 2;
     private static final int MSG_TRUST_TIMEOUT = 3;
     private static final int MSG_DEVICE_LOCKED = 4;
     private static final int MSG_DEVICE_UNLOCKED = 5;
     private static final int MSG_UNLOCK_LOCKOUT = 6;
+    private static final int MSG_ESCROW_TOKEN_ADDED = 7;
+    private static final int MSG_ESCROW_TOKEN_STATE_RECEIVED = 8;
+    private static final int MSG_ESCROW_TOKEN_REMOVED = 9;
 
+    private static final String EXTRA_TOKEN = "token";
+    private static final String EXTRA_TOKEN_HANDLE = "token_handle";
+    private static final String EXTRA_USER_HANDLE = "user_handle";
+    private static final String EXTRA_TOKEN_STATE = "token_state";
+    private static final String EXTRA_TOKEN_REMOVED_RESULT = "token_removed_result";
     /**
      * Class containing raw data for a given configuration request.
      */
@@ -155,7 +190,7 @@
                 case MSG_UNLOCK_LOCKOUT:
                     onDeviceUnlockLockout(msg.arg1);
                     break;
-                case MSG_CONFIGURE:
+                case MSG_CONFIGURE: {
                     ConfigurationData data = (ConfigurationData) msg.obj;
                     boolean result = onConfigure(data.options);
                     if (data.token != null) {
@@ -168,6 +203,7 @@
                         }
                     }
                     break;
+                }
                 case MSG_TRUST_TIMEOUT:
                     onTrustTimeout();
                     break;
@@ -177,6 +213,28 @@
                 case MSG_DEVICE_UNLOCKED:
                     onDeviceUnlocked();
                     break;
+                case MSG_ESCROW_TOKEN_ADDED: {
+                    Bundle data = msg.getData();
+                    byte[] token = data.getByteArray(EXTRA_TOKEN);
+                    long handle = data.getLong(EXTRA_TOKEN_HANDLE);
+                    UserHandle user = (UserHandle) data.getParcelable(EXTRA_USER_HANDLE);
+                    onEscrowTokenAdded(token, handle, user);
+                    break;
+                }
+                case MSG_ESCROW_TOKEN_STATE_RECEIVED: {
+                    Bundle data = msg.getData();
+                    long handle = data.getLong(EXTRA_TOKEN_HANDLE);
+                    int tokenState = data.getInt(EXTRA_TOKEN_STATE, TOKEN_STATE_INACTIVE);
+                    onEscrowTokenStateReceived(handle, tokenState);
+                    break;
+                }
+                case MSG_ESCROW_TOKEN_REMOVED: {
+                    Bundle data = msg.getData();
+                    long handle = data.getLong(EXTRA_TOKEN_HANDLE);
+                    boolean success = data.getBoolean(EXTRA_TOKEN_REMOVED_RESULT);
+                    onEscrowTokenRemoved(handle, success);
+                    break;
+                }
             }
         }
     };
@@ -245,6 +303,38 @@
     public void onDeviceUnlockLockout(long timeoutMs) {
     }
 
+  /**
+     * Called when an escrow token is added for user userId.
+     *
+     * @param token the added token
+     * @param handle the handle to the corresponding internal synthetic password. A user is unlocked
+     * by presenting both handle and escrow token.
+     * @param user the user to which the escrow token is added.
+     *
+     */
+    public void onEscrowTokenAdded(byte[] token, long handle, UserHandle user) {
+    }
+
+    /**
+     * Called when an escrow token state is received upon request.
+     *
+     * @param handle the handle to the internal synthetic password.
+     * @param state the state of the requested escrow token, see {@link TokenState}.
+     *
+     */
+    public void onEscrowTokenStateReceived(long handle, @TokenState int tokenState) {
+    }
+
+    /**
+     * Called when an escrow token is removed.
+     *
+     * @param handle the handle to the removed the synthetic password.
+     * @param successful whether the removing operaiton is achieved.
+     *
+     */
+    public void onEscrowTokenRemoved(long handle, boolean successful) {
+    }
+
     private void onError(String msg) {
         Slog.v(TAG, "Remote exception while " + msg);
     }
@@ -257,7 +347,7 @@
      * <p>Agents that support configuration options should overload this method and return 'true'.
      *
      * @param options The aggregated list of options or an empty list if no restrictions apply.
-     * @return true if the {@link TrustAgentService} supports configuration options.
+     * @return true if the {@link } supports configuration options.
      */
     public boolean onConfigure(List<PersistableBundle> options) {
         return false;
@@ -373,6 +463,106 @@
         }
     }
 
+    /**
+     * Call to add an escrow token to derive a synthetic password. A synthetic password is an
+     * alternaive to the user-set password/pin/pattern in order to unlock encrypted disk. An escrow
+     * token can be taken and internally derive the synthetic password. The new added token will not
+     * be acivated until the user input the correct PIN/Passcode/Password once.
+     *
+     * Result will be return by callback {@link #onEscrowTokenAdded(long, int)}
+     *
+     * @param token an escrow token of high entropy.
+     * @param user the user which the escrow token will be added to.
+     *
+     */
+    public final void addEscrowToken(byte[] token, UserHandle user) {
+        synchronized (mLock) {
+            if (mCallback == null) {
+                Slog.w(TAG, "Cannot add escrow token if the agent is not connecting to framework");
+                throw new IllegalStateException("Trust agent is not connected");
+            }
+            try {
+                mCallback.addEscrowToken(token, user.getIdentifier());
+            } catch (RemoteException e) {
+                onError("calling addEscrowToken");
+            }
+        }
+    }
+
+    /**
+     * Call to check the active state of an escrow token.
+     *
+     * Result will be return in callback {@link #onEscrowTokenStateReceived(long, boolean)}
+     *
+     * @param handle the handle of escrow token to the internal synthetic password.
+     * @param user the user which the escrow token is added to.
+     *
+     */
+    public final void isEscrowTokenActive(long handle, UserHandle user) {
+        synchronized (mLock) {
+            if (mCallback == null) {
+                Slog.w(TAG, "Cannot add escrow token if the agent is not connecting to framework");
+                throw new IllegalStateException("Trust agent is not connected");
+            }
+            try {
+                mCallback.isEscrowTokenActive(handle, user.getIdentifier());
+            } catch (RemoteException e) {
+                onError("calling isEscrowTokenActive");
+            }
+        }
+    }
+
+    /**
+     * Call to remove the escrow token.
+     *
+     * Result will be return in callback {@link #onEscrowTokenRemoved(long, boolean)}
+     *
+     * @param handle the handle of escrow tokent to the internal synthetic password.
+     * @param user the user id which the escrow token is added to.
+     *
+     */
+    public final void removeEscrowToken(long handle, UserHandle user) {
+        synchronized (mLock) {
+            if (mCallback == null) {
+                Slog.w(TAG, "Cannot add escrow token if the agent is not connecting to framework");
+                throw new IllegalStateException("Trust agent is not connected");
+            }
+            try {
+                mCallback.removeEscrowToken(handle, user.getIdentifier());
+            } catch (RemoteException e) {
+                onError("callling removeEscrowToken");
+            }
+        }
+    }
+
+    /**
+     * Call to unlock user's FBE.
+     *
+     * @param handle the handle of escrow tokent to the internal synthetic password.
+     * @param token the escrow token
+     * @param user the user about to be unlocked.
+     *
+     */
+    public final void unlockUserWithToken(long handle, byte[] token, UserHandle user) {
+        UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
+        if (um.isUserUnlocked()) {
+            Slog.i(TAG, "User already unlocked");
+            return;
+        }
+
+        synchronized (mLock) {
+            if (mCallback == null) {
+                Slog.w(TAG, "Cannot add escrow token if the agent is not connecting to framework");
+                throw new IllegalStateException("Trust agent is not connected");
+            }
+            try {
+                mCallback.unlockUserWithToken(handle, token, user.getIdentifier());
+            } catch (RemoteException e) {
+                onError("calling unlockUserWithToken");
+            }
+        }
+    }
+
     @Override
     public final IBinder onBind(Intent intent) {
         if (DEBUG) Slog.v(TAG, "onBind() intent = " + intent);
@@ -430,6 +620,28 @@
                 }
             }
         }
-    }
 
+        @Override
+        public void onEscrowTokenAdded(byte[] token, long handle, UserHandle user) {
+            Message msg = mHandler.obtainMessage(MSG_ESCROW_TOKEN_ADDED);
+            msg.getData().putByteArray(EXTRA_TOKEN, token);
+            msg.getData().putLong(EXTRA_TOKEN_HANDLE, handle);
+            msg.getData().putParcelable(EXTRA_USER_HANDLE, user);
+            msg.sendToTarget();
+        }
+
+        public void onTokenStateReceived(long handle, int tokenState) {
+            Message msg = mHandler.obtainMessage(MSG_ESCROW_TOKEN_STATE_RECEIVED);
+            msg.getData().putLong(EXTRA_TOKEN_HANDLE, handle);
+            msg.getData().putInt(EXTRA_TOKEN_STATE, tokenState);
+            msg.sendToTarget();
+        }
+
+        public void onEscrowTokenRemoved(long handle, boolean successful) {
+            Message msg = mHandler.obtainMessage(MSG_ESCROW_TOKEN_REMOVED);
+            msg.getData().putLong(EXTRA_TOKEN_HANDLE, handle);
+            msg.getData().putBoolean(EXTRA_TOKEN_REMOVED_RESULT, successful);
+            msg.sendToTarget();
+        }
+    }
 }
diff --git a/core/java/android/text/FontConfig.java b/core/java/android/text/FontConfig.java
index 82e44dc..1087851 100644
--- a/core/java/android/text/FontConfig.java
+++ b/core/java/android/text/FontConfig.java
@@ -403,6 +403,7 @@
         private final String mLanguage;
         private final String mVariant;
         private final String mProviderAuthority;
+        private final String mProviderPackage;
         private final String mQuery;
 
         public Family(String name, List<Font> fonts, String language, String variant) {
@@ -411,18 +412,20 @@
             mLanguage = language;
             mVariant = variant;
             mProviderAuthority = null;
+            mProviderPackage = null;
             mQuery = null;
         }
 
         /**
          * @hide
          */
-        public Family(String providerAuthority, String query) {
+        public Family(String providerAuthority, String providerPackage, String query) {
             mName = null;
             mFonts = null;
             mLanguage = null;
             mVariant = null;
             mProviderAuthority = providerAuthority;
+            mProviderPackage = providerPackage;
             mQuery = query;
         }
 
@@ -435,6 +438,7 @@
                 mFonts.add(new Font(origin.mFonts.get(i)));
             }
             mProviderAuthority = origin.mProviderAuthority;
+            mProviderPackage = origin.mProviderPackage;
             mQuery = origin.mQuery;
         }
 
@@ -476,6 +480,13 @@
         /**
          * @hide
          */
+        public String getProviderPackage() {
+            return mProviderPackage;
+        }
+
+        /**
+         * @hide
+         */
         public String getQuery() {
             return mQuery;
         }
@@ -498,6 +509,11 @@
                 mProviderAuthority = null;
             }
             if (in.readInt() == 1) {
+                mProviderPackage = in.readString();
+            } else {
+                mProviderPackage = null;
+            }
+            if (in.readInt() == 1) {
                 mQuery = in.readString();
             } else {
                 mQuery = null;
@@ -517,6 +533,10 @@
             if (mProviderAuthority != null) {
                 out.writeString(mProviderAuthority);
             }
+            out.writeInt(mProviderPackage == null ? 0 : 1);
+            if (mProviderPackage != null) {
+                out.writeString(mProviderPackage);
+            }
             out.writeInt(mQuery == null ? 0 : 1);
             if (mQuery != null) {
                 out.writeString(mQuery);
diff --git a/core/java/android/text/Hyphenator.java b/core/java/android/text/Hyphenator.java
index 356804e..c2508a6 100644
--- a/core/java/android/text/Hyphenator.java
+++ b/core/java/android/text/Hyphenator.java
@@ -42,13 +42,24 @@
 
     private static String TAG = "Hyphenator";
 
+    // TODO: Confirm that these are the best values. Various sources suggest (1, 1), but
+    // that appears too small.
+    private static final int INDIC_MIN_PREFIX = 2;
+    private static final int INDIC_MIN_SUFFIX = 2;
+
     private final static Object sLock = new Object();
 
     @GuardedBy("sLock")
     final static HashMap<Locale, Hyphenator> sMap = new HashMap<Locale, Hyphenator>();
 
+    // Reasonable enough values for cases where we have no hyphenation patterns but may be able to
+    // do some automatic hyphenation based on characters. These values would be used very rarely.
+    private static final int DEFAULT_MIN_PREFIX = 2;
+    private static final int DEFAULT_MIN_SUFFIX = 2;
     final static Hyphenator sEmptyHyphenator =
-            new Hyphenator(StaticLayout.nLoadHyphenator(null, 0), null);
+            new Hyphenator(StaticLayout.nLoadHyphenator(
+                                   null, 0, DEFAULT_MIN_PREFIX, DEFAULT_MIN_SUFFIX),
+                           null);
 
     final private long mNativePtr;
 
@@ -111,15 +122,26 @@
         return sEmptyHyphenator;
     }
 
-    private static Hyphenator loadHyphenator(String languageTag) {
-        String patternFilename = "hyph-" + languageTag.toLowerCase(Locale.US) + ".hyb";
+    private static class HyphenationData {
+        final String mLanguageTag;
+        final int mMinPrefix, mMinSuffix;
+        HyphenationData(String languageTag, int minPrefix, int minSuffix) {
+            this.mLanguageTag = languageTag;
+            this.mMinPrefix = minPrefix;
+            this.mMinSuffix = minSuffix;
+        }
+    }
+
+    private static Hyphenator loadHyphenator(HyphenationData data) {
+        String patternFilename = "hyph-" + data.mLanguageTag.toLowerCase(Locale.US) + ".hyb";
         File patternFile = new File(getSystemHyphenatorLocation(), patternFilename);
         try {
             RandomAccessFile f = new RandomAccessFile(patternFile, "r");
             try {
                 FileChannel fc = f.getChannel();
                 MappedByteBuffer buf = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
-                long nativePtr = StaticLayout.nLoadHyphenator(buf, 0);
+                long nativePtr = StaticLayout.nLoadHyphenator(
+                        buf, 0, data.mMinPrefix, data.mMinSuffix);
                 return new Hyphenator(nativePtr, buf);
             } finally {
                 f.close();
@@ -176,6 +198,46 @@
         {"wal", "und-Ethi"}, // Wolaytta
     };
 
+    private static final HyphenationData[] AVAILABLE_LANGUAGES = {
+        new HyphenationData("as", INDIC_MIN_PREFIX, INDIC_MIN_SUFFIX), // Assamese
+        new HyphenationData("bg", 2, 2), // Bulgarian
+        new HyphenationData("bn", INDIC_MIN_PREFIX, INDIC_MIN_SUFFIX), // Bengali
+        new HyphenationData("cu", 1, 2), // Church Slavonic
+        new HyphenationData("cy", 2, 3), // Welsh
+        new HyphenationData("da", 2, 2), // Danish
+        new HyphenationData("de-1901", 2, 2), // German 1901 orthography
+        new HyphenationData("de-1996", 2, 2), // German 1996 orthography
+        new HyphenationData("de-CH-1901", 2, 2), // Swiss High German 1901 orthography
+        new HyphenationData("en-GB", 2, 3), // British English
+        new HyphenationData("en-US", 2, 3), // American English
+        new HyphenationData("es", 2, 2), // Spanish
+        new HyphenationData("et", 2, 3), // Estonian
+        new HyphenationData("eu", 2, 2), // Basque
+        new HyphenationData("fr", 2, 3), // French
+        new HyphenationData("ga", 2, 3), // Irish
+        new HyphenationData("gu", INDIC_MIN_PREFIX, INDIC_MIN_SUFFIX), // Gujarati
+        new HyphenationData("hi", INDIC_MIN_PREFIX, INDIC_MIN_SUFFIX), // Hindi
+        new HyphenationData("hr", 2, 2), // Croatian
+        new HyphenationData("hu", 2, 2), // Hungarian
+        // texhyphen sources say Armenian may be (1, 2), but that it needs confirmation.
+        // Going with a more conservative value of (2, 2) for now.
+        new HyphenationData("hy", 2, 2), // Armenian
+        new HyphenationData("kn", INDIC_MIN_PREFIX, INDIC_MIN_SUFFIX), // Kannada
+        new HyphenationData("ml", INDIC_MIN_PREFIX, INDIC_MIN_SUFFIX), // Malayalam
+        new HyphenationData("mn-Cyrl", 2, 2), // Mongolian in Cyrillic script
+        new HyphenationData("mr", INDIC_MIN_PREFIX, INDIC_MIN_SUFFIX), // Marathi
+        new HyphenationData("nb", 2, 2), // Norwegian Bokmål
+        new HyphenationData("nn", 2, 2), // Norwegian Nynorsk
+        new HyphenationData("or", INDIC_MIN_PREFIX, INDIC_MIN_SUFFIX), // Oriya
+        new HyphenationData("pa", INDIC_MIN_PREFIX, INDIC_MIN_SUFFIX), // Punjabi
+        new HyphenationData("pt", 2, 3), // Portuguese
+        new HyphenationData("sl", 2, 2), // Slovenian
+        new HyphenationData("ta", INDIC_MIN_PREFIX, INDIC_MIN_SUFFIX), // Tamil
+        new HyphenationData("te", INDIC_MIN_PREFIX, INDIC_MIN_SUFFIX), // Telugu
+        new HyphenationData("tk", 2, 2), // Turkmen
+        new HyphenationData("und-Ethi", 1, 1), // Any language in Ethiopic script
+    };
+
     /**
      * Load hyphenation patterns at initialization time. We want to have patterns
      * for all locales loaded and ready to use so we don't have to do any file IO
@@ -186,44 +248,11 @@
     public static void init() {
         sMap.put(null, null);
 
-        // TODO: replace this with a discovery-based method that looks into /system/usr/hyphen-data
-        String[] availableLanguages = {
-            "as",
-            "bn",
-            "cy",
-            "da",
-            "de-1901", "de-1996", "de-CH-1901",
-            "en-GB", "en-US",
-            "es",
-            "et",
-            "eu",
-            "fr",
-            "ga",
-            "gu",
-            "hi",
-            "hr",
-            "hu",
-            "hy",
-            "kn",
-            "ml",
-            "mn-Cyrl",
-            "mr",
-            "nb",
-            "nn",
-            "or",
-            "pa",
-            "pt",
-            "sl",
-            "ta",
-            "te",
-            "tk",
-            "und-Ethi",
-        };
-        for (int i = 0; i < availableLanguages.length; i++) {
-            String languageTag = availableLanguages[i];
-            Hyphenator h = loadHyphenator(languageTag);
+        for (int i = 0; i < AVAILABLE_LANGUAGES.length; i++) {
+            HyphenationData data = AVAILABLE_LANGUAGES[i];
+            Hyphenator h = loadHyphenator(data);
             if (h != null) {
-                sMap.put(Locale.forLanguageTag(languageTag), h);
+                sMap.put(Locale.forLanguageTag(data.mLanguageTag), h);
             }
         }
 
diff --git a/core/java/android/text/SpannableStringInternal.java b/core/java/android/text/SpannableStringInternal.java
index 60d8a0f..4b02df86 100644
--- a/core/java/android/text/SpannableStringInternal.java
+++ b/core/java/android/text/SpannableStringInternal.java
@@ -53,16 +53,12 @@
      * @param end End index in the source object.
      */
     private final void copySpans(Spanned src, int start, int end) {
-        final Object[] spans = src.getSpans(start, end, Object.class);
+        Object[] spans = src.getSpans(start, end, Object.class);
 
         for (int i = 0; i < spans.length; i++) {
-            if (spans[i] instanceof NoCopySpan) {
-                continue;
-            }
-
             int st = src.getSpanStart(spans[i]);
             int en = src.getSpanEnd(spans[i]);
-            final int fl = src.getSpanFlags(spans[i]);
+            int fl = src.getSpanFlags(spans[i]);
 
             if (st < start)
                 st = start;
@@ -82,42 +78,33 @@
      * @param end End index in the source object.
      */
     private final void copySpans(SpannableStringInternal src, int start, int end) {
-        int count = 0;
-        boolean includesNoCopySpan = false;
-        final int[] srcData = src.mSpanData;
-        final Object[] srcSpans = src.mSpans;
-        final int limit = src.mSpanCount;
-
-        for (int i = 0; i < limit; i++) {
-            int spanStart = srcData[i * COLUMNS + START];
-            int spanEnd = srcData[i * COLUMNS + END];
-            if (isOutOfCopyRange(start, end, spanStart, spanEnd)) continue;
-            if (srcSpans[i] instanceof NoCopySpan) {
-                includesNoCopySpan = true;
-                continue;
-            }
-            count++;
-        }
-
-        if (count == 0) return;
-
-        if (!includesNoCopySpan && start == 0 && end == src.length()) {
+        if (start == 0 && end == src.length()) {
             mSpans = ArrayUtils.newUnpaddedObjectArray(src.mSpans.length);
             mSpanData = new int[src.mSpanData.length];
             mSpanCount = src.mSpanCount;
             System.arraycopy(src.mSpans, 0, mSpans, 0, src.mSpans.length);
             System.arraycopy(src.mSpanData, 0, mSpanData, 0, mSpanData.length);
         } else {
+            int count = 0;
+            int[] srcData = src.mSpanData;
+            int limit = src.mSpanCount;
+            for (int i = 0; i < limit; i++) {
+                int spanStart = srcData[i * COLUMNS + START];
+                int spanEnd = srcData[i * COLUMNS + END];
+                if (isOutOfCopyRange(start, end, spanStart, spanEnd)) continue;
+                count++;
+            }
+
+            if (count == 0) return;
+
+            Object[] srcSpans = src.mSpans;
             mSpanCount = count;
             mSpans = ArrayUtils.newUnpaddedObjectArray(mSpanCount);
             mSpanData = new int[mSpans.length * COLUMNS];
             for (int i = 0, j = 0; i < limit; i++) {
                 int spanStart = srcData[i * COLUMNS + START];
                 int spanEnd = srcData[i * COLUMNS + END];
-                if (isOutOfCopyRange(start, end, spanStart, spanEnd)
-                        || srcSpans[i] instanceof NoCopySpan) {
-                    continue;
-                }
+                if (isOutOfCopyRange(start, end, spanStart, spanEnd)) continue;
                 if (spanStart < start) spanStart = start;
                 if (spanEnd > end) spanEnd = end;
 
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index cb5b073..94c463c 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -1290,7 +1290,8 @@
     private static native void nFreeBuilder(long nativePtr);
     private static native void nFinishBuilder(long nativePtr);
 
-    /* package */ static native long nLoadHyphenator(ByteBuffer buf, int offset);
+    /* package */ static native long nLoadHyphenator(ByteBuffer buf, int offset,
+            int minPrefix, int minSuffix);
 
     private static native void nSetLocale(long nativePtr, String locale, long nativeHyphenator);
 
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index fcff9a2..756e9a0 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -852,6 +852,18 @@
         return runIsRtl ? -ret : ret;
     }
 
+    private int adjustHyphenEdit(int start, int limit, int hyphenEdit) {
+        int result = hyphenEdit;
+        // Only draw hyphens on first or last run in line. Disable them otherwise.
+        if (start > 0) { // not the first run
+            result &= ~Paint.HYPHENEDIT_MASK_START_OF_LINE;
+        }
+        if (limit < mLen) { // not the last run
+            result &= ~Paint.HYPHENEDIT_MASK_END_OF_LINE;
+        }
+        return result;
+    }
+
     /**
      * Utility function for handling a unidirectional run.  The run must not
      * contain tabs but can contain styles.
@@ -893,9 +905,9 @@
         if (mSpanned == null) {
             TextPaint wp = mWorkPaint;
             wp.set(mPaint);
-            final int mlimit = measureLimit;
+            wp.setHyphenEdit(adjustHyphenEdit(start, limit, wp.getHyphenEdit()));
             return handleText(wp, start, limit, start, limit, runIsRtl, c, x, top,
-                    y, bottom, fmi, needWidth || mlimit < measureLimit, mlimit);
+                    y, bottom, fmi, needWidth, measureLimit);
         }
 
         mMetricAffectingSpanSpanSet.init(mSpanned, mStart + start, mStart + limit);
@@ -953,10 +965,8 @@
                     span.updateDrawState(wp);
                 }
 
-                // Only draw hyphen on last run in line
-                if (jnext < mLen) {
-                    wp.setHyphenEdit(0);
-                }
+                wp.setHyphenEdit(adjustHyphenEdit(j, jnext, wp.getHyphenEdit()));
+
                 x += handleText(wp, j, jnext, i, inext, runIsRtl, c, x,
                         top, y, bottom, fmi, needWidth || jnext < measureLimit, offset);
             }
diff --git a/core/java/android/transition/Fade.java b/core/java/android/transition/Fade.java
index b0de711..38b89dc 100644
--- a/core/java/android/transition/Fade.java
+++ b/core/java/android/transition/Fade.java
@@ -103,6 +103,7 @@
         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Fade);
         int fadingMode = a.getInt(R.styleable.Fade_fadingMode, getMode());
         setMode(fadingMode);
+        a.recycle();
     }
 
     @Override
diff --git a/core/java/android/transition/TransitionInflater.java b/core/java/android/transition/TransitionInflater.java
index 4c5a717..0cc981e 100644
--- a/core/java/android/transition/TransitionInflater.java
+++ b/core/java/android/transition/TransitionInflater.java
@@ -276,9 +276,11 @@
                             transition.addTarget(clazz);
                         }
                     } catch (ClassNotFoundException e) {
+                        a.recycle();
                         throw new RuntimeException("Could not create " + className, e);
                     }
                 }
+                a.recycle();
             } else {
                 throw new RuntimeException("Unknown scene name: " + parser.getName());
             }
diff --git a/core/java/android/util/AtomicFile.java b/core/java/android/util/AtomicFile.java
index 3aa3447..2f1abe9 100644
--- a/core/java/android/util/AtomicFile.java
+++ b/core/java/android/util/AtomicFile.java
@@ -17,13 +17,15 @@
 package android.util;
 
 import android.os.FileUtils;
-import android.util.Log;
+
+import libcore.io.IoUtils;
 
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.util.function.Consumer;
 
 /**
  * Helper class for performing atomic operations on a file by creating a
@@ -244,4 +246,19 @@
             stream.close();
         }
     }
+
+    /** @hide */
+    public void write(Consumer<FileOutputStream> writeContent) {
+        FileOutputStream out = null;
+        try {
+            out = startWrite();
+            writeContent.accept(out);
+            finishWrite(out);
+        } catch (Throwable t) {
+            failWrite(out);
+            throw ExceptionUtils.propagate(t);
+        } finally {
+            IoUtils.closeQuietly(out);
+        }
+    }
 }
diff --git a/core/java/android/util/ExceptionUtils.java b/core/java/android/util/ExceptionUtils.java
index da0b609..87231e1 100644
--- a/core/java/android/util/ExceptionUtils.java
+++ b/core/java/android/util/ExceptionUtils.java
@@ -16,8 +16,11 @@
 
 package android.util;
 
+import android.annotation.NonNull;
 import android.os.ParcelableException;
 
+import com.android.internal.util.Preconditions;
+
 import java.io.IOException;
 
 /**
@@ -51,4 +54,11 @@
     public static String getCompleteMessage(Throwable t) {
         return getCompleteMessage(null, t);
     }
+
+    public static RuntimeException propagate(@NonNull Throwable t) {
+        Preconditions.checkNotNull(t);
+        if (t instanceof Error) throw (Error)t;
+        if (t instanceof RuntimeException) throw (RuntimeException)t;
+        throw new RuntimeException(t);
+    }
 }
diff --git a/core/java/android/util/Half.java b/core/java/android/util/Half.java
index e4f8dd1..84c2e83 100644
--- a/core/java/android/util/Half.java
+++ b/core/java/android/util/Half.java
@@ -17,9 +17,13 @@
 package android.util;
 
 import android.annotation.HalfFloat;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import sun.misc.FloatingDecimal;
 
 /**
- * <p>Half is a utility class to manipulate half-precision 16-bit
+ * <p>The {@code Half} class is a wrapper and a utility class to manipulate half-precision 16-bit
  * <a href="https://en.wikipedia.org/wiki/Half-precision_floating-point_format">IEEE 754</a>
  * floating point data types (also called fp16 or binary16). A half-precision float can be
  * created from or converted to single-precision floats, and is stored in a short data type.
@@ -88,7 +92,7 @@
  * <p>This table shows that numbers higher than 1024 lose all fractional precision.</p>
  */
 @SuppressWarnings("SimplifiableIfStatement")
-public final class Half {
+public final class Half extends Number implements Comparable<Half> {
     /**
      * The number of bits used to represent a half-precision float value.
      */
@@ -164,7 +168,332 @@
     private static final int FP32_DENORMAL_MAGIC = 126 << 23;
     private static final float FP32_DENORMAL_FLOAT = Float.intBitsToFloat(FP32_DENORMAL_MAGIC);
 
-    private Half() {
+    private final @HalfFloat short mValue;
+
+    /**
+     * Constructs a newly allocated {@code Half} object that represents the
+     * half-precision float type argument.
+     *
+     * @param value The value to be represented by the {@code Half}
+     */
+    public Half(@HalfFloat short value) {
+        mValue = value;
+    }
+
+    /**
+     * Constructs a newly allocated {@code Half} object that represents the
+     * argument converted to a half-precision float.
+     *
+     * @param value The value to be represented by the {@code Half}
+     *
+     * @see #toHalf(float)
+     */
+    public Half(float value) {
+        mValue = toHalf(value);
+    }
+
+    /**
+     * Constructs a newly allocated {@code Half} object that
+     * represents the argument converted to a half-precision float.
+     *
+     * @param value The value to be represented by the {@code Half}
+     *
+     * @see #toHalf(float)
+     */
+    public Half(double value) {
+        mValue = toHalf((float) value);
+    }
+
+    /**
+     * <p>Constructs a newly allocated {@code Half} object that represents the
+     * half-precision float value represented by the string.
+     * The string is converted to a half-precision float value as if by the
+     * {@link #valueOf(String)} method.</p>
+     *
+     * <p>Calling this constructor is equivalent to calling:</p>
+     * <pre>
+     *     new Half(Float.parseFloat(value))
+     * </pre>
+     *
+     * @param value A string to be converted to a {@code Half}
+     * @throws NumberFormatException if the string does not contain a parsable number
+     *
+     * @see Float#valueOf(java.lang.String)
+     * @see #toHalf(float)
+     */
+    public Half(@NonNull String value) throws NumberFormatException {
+        mValue = toHalf(Float.parseFloat(value));
+    }
+
+    /**
+     * Returns the half-precision value of this {@code Half} as a {@code short}
+     * containing the bit representation described in {@link Half}.
+     *
+     * @return The half-precision float value represented by this object
+     */
+    public @HalfFloat short halfValue() {
+        return mValue;
+    }
+
+    /**
+     * Returns the value of this {@code Half} as a {@code byte} after
+     * a narrowing primitive conversion.
+     *
+     * @return The half-precision float value represented by this object
+     *         converted to type {@code byte}
+     */
+    @Override
+    public byte byteValue() {
+        return (byte) toFloat(mValue);
+    }
+
+    /**
+     * Returns the value of this {@code Half} as a {@code short} after
+     * a narrowing primitive conversion.
+     *
+     * @return The half-precision float value represented by this object
+     *         converted to type {@code short}
+     */
+    @Override
+    public short shortValue() {
+        return (short) toFloat(mValue);
+    }
+
+    /**
+     * Returns the value of this {@code Half} as a {@code int} after
+     * a narrowing primitive conversion.
+     *
+     * @return The half-precision float value represented by this object
+     *         converted to type {@code int}
+     */
+    @Override
+    public int intValue() {
+        return (int) toFloat(mValue);
+    }
+
+    /**
+     * Returns the value of this {@code Half} as a {@code long} after
+     * a narrowing primitive conversion.
+     *
+     * @return The half-precision float value represented by this object
+     *         converted to type {@code long}
+     */
+    @Override
+    public long longValue() {
+        return (long) toFloat(mValue);
+    }
+
+    /**
+     * Returns the value of this {@code Half} as a {@code float} after
+     * a widening primitive conversion.
+     *
+     * @return The half-precision float value represented by this object
+     *         converted to type {@code float}
+     */
+    @Override
+    public float floatValue() {
+        return toFloat(mValue);
+    }
+
+    /**
+     * Returns the value of this {@code Half} as a {@code double} after
+     * a widening primitive conversion.
+     *
+     * @return The half-precision float value represented by this object
+     *         converted to type {@code double}
+     */
+    @Override
+    public double doubleValue() {
+        return toFloat(mValue);
+    }
+
+    /**
+     * Returns true if this {@code Half} value represents a Not-a-Number,
+     * false otherwise.
+     *
+     * @return True if the value is a NaN, false otherwise
+     */
+    public boolean isNaN() {
+        return isNaN(mValue);
+    }
+
+    /**
+     * Compares this object against the specified object. The result is {@code true}
+     * if and only if the argument is not {@code null} and is a {@code Half} object
+     * that represents the same half-precision value as the this object. Two
+     * half-precision values are considered to be the same if and only if the method
+     * {@link #halfToIntBits(short)} returns an identical {@code int} value for both.
+     *
+     * @param o The object to compare
+     * @return True if the objects are the same, false otherwise
+     *
+     * @see #halfToIntBits(short)
+     */
+    @Override
+    public boolean equals(@Nullable Object o) {
+        return (o instanceof Half) &&
+                (halfToIntBits(((Half) o).mValue) == halfToIntBits(mValue));
+    }
+
+    /**
+     * Returns a hash code for this {@code Half} object. The result is the
+     * integer bit representation, exactly as produced by the method
+     * {@link #halfToIntBits(short)}, of the primitive half-precision float
+     * value represented by this {@code Half} object.
+     *
+     * @return A hash code value for this object
+     */
+    @Override
+    public int hashCode() {
+        return hashCode(mValue);
+    }
+
+    /**
+     * Returns a string representation of the specified half-precision
+     * float value. See {@link #toString(short)} for more information.
+     *
+     * @return A string representation of this {@code Half} object
+     */
+    @NonNull
+    @Override
+    public String toString() {
+        return toString(mValue);
+    }
+
+    /**
+     * <p>Compares the two specified half-precision float values. The following
+     * conditions apply during the comparison:</p>
+     *
+     * <ul>
+     * <li>{@link #NaN} is considered by this method to be equal to itself and greater
+     * than all other half-precision float values (including {@code #POSITIVE_INFINITY})</li>
+     * <li>{@link #POSITIVE_ZERO} is considered by this method to be greater than
+     * {@link #NEGATIVE_ZERO}.</li>
+     * </ul>
+     *
+     * @param h The half-precision float value to compare to the half-precision value
+     *          represented by this {@code Half} object
+     *
+     * @return  The value {@code 0} if {@code x} is numerically equal to {@code y}; a
+     *          value less than {@code 0} if {@code x} is numerically less than {@code y};
+     *          and a value greater than {@code 0} if {@code x} is numerically greater
+     *          than {@code y}
+     */
+    @Override
+    public int compareTo(@NonNull Half h) {
+        return compare(mValue, h.mValue);
+    }
+
+    /**
+     * Returns a hash code for a half-precision float value.
+     *
+     * @param h The value to hash
+     *
+     * @return A hash code value for a half-precision float value
+     */
+    public static int hashCode(@HalfFloat short h) {
+        return halfToIntBits(h);
+    }
+
+    /**
+     * <p>Compares the two specified half-precision float values. The following
+     * conditions apply during the comparison:</p>
+     *
+     * <ul>
+     * <li>{@link #NaN} is considered by this method to be equal to itself and greater
+     * than all other half-precision float values (including {@code #POSITIVE_INFINITY})</li>
+     * <li>{@link #POSITIVE_ZERO} is considered by this method to be greater than
+     * {@link #NEGATIVE_ZERO}.</li>
+     * </ul>
+     *
+     * @param x The first half-precision float value to compare.
+     * @param y The second half-precision float value to compare
+     *
+     * @return  The value {@code 0} if {@code x} is numerically equal to {@code y}, a
+     *          value less than {@code 0} if {@code x} is numerically less than {@code y},
+     *          and a value greater than {@code 0} if {@code x} is numerically greater
+     *          than {@code y}
+     */
+    public static int compare(@HalfFloat short x, @HalfFloat short y) {
+        if (less(x, y)) return -1;
+        if (greater(x, y)) return 1;
+
+        // Collapse NaNs, akin to halfToIntBits(), but we want to keep
+        // (signed) short value types to preserve the ordering of -0.0
+        // and +0.0
+        short xBits = (x & FP16_COMBINED) > FP16_EXPONENT_MAX ? NaN : x;
+        short yBits = (y & FP16_COMBINED) > FP16_EXPONENT_MAX ? NaN : y;
+
+        return (xBits == yBits ? 0 : (xBits < yBits ? -1 : 1));
+    }
+
+    /**
+     * <p>Returns a representation of the specified half-precision float value
+     * according to the bit layout described in {@link Half}.</p>
+     *
+     * <p>Similar to {@link #halfToIntBits(short)}, this method collapses all
+     * possible Not-a-Number values to a single canonical Not-a-Number value
+     * defined by {@link #NaN}.</p>
+     *
+     * @param h A half-precision float value
+     * @return The bits that represent the half-precision float value
+     *
+     * @see #halfToIntBits(short)
+     */
+    public static @HalfFloat short halfToShortBits(@HalfFloat short h) {
+        return (h & FP16_COMBINED) > FP16_EXPONENT_MAX ? NaN : h;
+    }
+
+    /**
+     * <p>Returns a representation of the specified half-precision float value
+     * according to the bit layout described in {@link Half}.</p>
+     *
+     * <p>Unlike {@link #halfToRawIntBits(short)}, this method collapses all
+     * possible Not-a-Number values to a single canonical Not-a-Number value
+     * defined by {@link #NaN}.</p>
+     *
+     * @param h A half-precision float value
+     * @return The bits that represent the half-precision float value
+     *
+     * @see #halfToRawIntBits(short)
+     * @see #halfToShortBits(short)
+     * @see #intBitsToHalf(int)
+     */
+    public static int halfToIntBits(@HalfFloat short h) {
+        return (h & FP16_COMBINED) > FP16_EXPONENT_MAX ? NaN : h & 0xffff;
+    }
+
+    /**
+     * <p>Returns a representation of the specified half-precision float value
+     * according to the bit layout described in {@link Half}.</p>
+     *
+     * <p>The argument is considered to be a representation of a half-precision
+     * float value according to the bit layout described in {@link Half}. The 16
+     * most significant bits of the returned value are set to 0.</p>
+     *
+     * @param h A half-precision float value
+     * @return The bits that represent the half-precision float value
+     *
+     * @see #halfToIntBits(short)
+     * @see #intBitsToHalf(int)
+     */
+    public static int halfToRawIntBits(@HalfFloat short h) {
+        return h & 0xffff;
+    }
+
+    /**
+     * <p>Returns the half-precision float value corresponding to a given
+     * bit representation.</p>
+     *
+     * <p>The argument is considered to be a representation of a half-precision
+     * float value according to the bit layout described in {@link Half}. The 16
+     * most significant bits of the argument are ignored.</p>
+     *
+     * @param bits An integer
+     * @return The half-precision float value with the same bit pattern
+     */
+    public static @HalfFloat short intBitsToHalf(int bits) {
+        return (short) (bits & 0xffff);
     }
 
     /**
@@ -509,7 +838,7 @@
      * infinity, false otherwise.
      *
      * @param h A half-precision float value
-     * @return true if the value is positive infinity or negative infinity,
+     * @return True if the value is positive infinity or negative infinity,
      *         false otherwise
      */
     public static boolean isInfinite(@HalfFloat short h) {
@@ -521,7 +850,7 @@
      * a Not-a-Number, false otherwise.
      *
      * @param h A half-precision float value
-     * @return true if the value is a NaN, false otherwise
+     * @return True if the value is a NaN, false otherwise
      */
     public static boolean isNaN(@HalfFloat short h) {
         return (h & FP16_COMBINED) > FP16_EXPONENT_MAX;
@@ -535,7 +864,7 @@
      * number, this method returns false.
      *
      * @param h A half-precision float value
-     * @return true if the value is normalized, false otherwise
+     * @return True if the value is normalized, false otherwise
      */
     public static boolean isNormalized(@HalfFloat short h) {
         return (h & FP16_EXPONENT_MAX) != 0 && (h & FP16_EXPONENT_MAX) != FP16_EXPONENT_MAX;
@@ -608,7 +937,7 @@
      * @return A half-precision float value
      */
     @SuppressWarnings("StatementWithEmptyBody")
-    public static @HalfFloat short valueOf(float f) {
+    public static @HalfFloat short toHalf(float f) {
         int bits = Float.floatToRawIntBits(f);
         int s = (bits >>> FP32_SIGN_SHIFT    );
         int e = (bits >>> FP32_EXPONENT_SHIFT) & FP32_EXPONENT_MASK;
@@ -650,6 +979,57 @@
     }
 
     /**
+     * Returns a {@code Half} instance representing the specified
+     * half-precision float value.
+     *
+     * @param h A half-precision float value
+     * @return a {@code Half} instance representing {@code h}
+     */
+    public static @NonNull Half valueOf(@HalfFloat short h) {
+        return new Half(h);
+    }
+
+    /**
+     * Returns a {@code Half} instance representing the specified float value.
+     *
+     * @param f A float value
+     * @return a {@code Half} instance representing {@code f}
+     */
+    public static @NonNull Half valueOf(float f) {
+        return new Half(f);
+    }
+
+    /**
+     * Returns a {@code Half} instance representing the specified string value.
+     * Calling this method is equivalent to calling
+     * <code>toHalf(Float.parseString(h))</code>. See {@link Float#valueOf(String)}
+     * for more information on the format of the string representation.
+     *
+     * @param s The string to be parsed
+     * @return a {@code Half} instance representing {@code h}
+     * @throws NumberFormatException if the string does not contain a parsable
+     *         half-precision float value
+     */
+    public static @NonNull Half valueOf(@NonNull String s) {
+        return new Half(s);
+    }
+
+    /**
+     * Returns the half-precision float value represented by the specified string.
+     * Calling this method is equivalent to calling
+     * <code>toHalf(Float.parseString(h))</code>. See {@link Float#valueOf(String)}
+     * for more information on the format of the string representation.
+     *
+     * @param s The string to be parsed
+     * @return A half-precision float value represented by the string
+     * @throws NumberFormatException if the string does not contain a parsable
+     *         half-precision float value
+     */
+    public static @HalfFloat short parseHalf(@NonNull String s) throws NumberFormatException {
+        return toHalf(FloatingDecimal.parseFloat(s));
+    }
+
+    /**
      * Returns a string representation of the specified half-precision
      * float value. Calling this method is equivalent to calling
      * <code>Float.toString(toFloat(h))</code>. See {@link Float#toString(float)}
@@ -658,6 +1038,7 @@
      * @param h A half-precision float value
      * @return A string representation of the specified value
      */
+    @NonNull
     public static String toString(@HalfFloat short h) {
         return Float.toString(toFloat(h));
     }
@@ -688,6 +1069,7 @@
      * @param h A half-precision float value
      * @return A hexadecimal string representation of the specified value
      */
+    @NonNull
     public static String toHexString(@HalfFloat short h) {
         StringBuilder o = new StringBuilder();
 
diff --git a/core/java/android/util/MapCollections.java b/core/java/android/util/MapCollections.java
index 28b788b..80ab23c 100644
--- a/core/java/android/util/MapCollections.java
+++ b/core/java/android/util/MapCollections.java
@@ -22,6 +22,7 @@
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.Map;
+import java.util.NoSuchElementException;
 import java.util.Set;
 
 /**
@@ -52,6 +53,7 @@
 
         @Override
         public T next() {
+            if (!hasNext()) throw new NoSuchElementException();
             Object res = colGetEntry(mIndex, mOffset);
             mIndex++;
             mCanRemove = true;
@@ -87,6 +89,7 @@
 
         @Override
         public Map.Entry<K, V> next() {
+            if (!hasNext()) throw new NoSuchElementException();
             mIndex++;
             mEntryValid = true;
             return this;
diff --git a/core/java/android/util/MathUtils.java b/core/java/android/util/MathUtils.java
index 32aac13..5c718f1 100644
--- a/core/java/android/util/MathUtils.java
+++ b/core/java/android/util/MathUtils.java
@@ -24,7 +24,6 @@
  * @hide Pending API council approval
  */
 public final class MathUtils {
-    private static final Random sRandom = new Random();
     private static final float DEG_TO_RAD = 3.1415926f / 180.0f;
     private static final float RAD_TO_DEG = 180.0f / 3.1415926f;
 
@@ -185,28 +184,6 @@
         return maxStart + (maxStart - maxStop) * ((value - minStart) / (minStop - minStart));
     }
 
-    public static int random(int howbig) {
-        return (int) (sRandom.nextFloat() * howbig);
-    }
-
-    public static int random(int howsmall, int howbig) {
-        if (howsmall >= howbig) return howsmall;
-        return (int) (sRandom.nextFloat() * (howbig - howsmall) + howsmall);
-    }
-
-    public static float random(float howbig) {
-        return sRandom.nextFloat() * howbig;
-    }
-
-    public static float random(float howsmall, float howbig) {
-        if (howsmall >= howbig) return howsmall;
-        return sRandom.nextFloat() * (howbig - howsmall) + howsmall;
-    }
-
-    public static void randomSeed(long seed) {
-        sRandom.setSeed(seed);
-    }
-
     /**
      * Returns the sum of the two parameters, or throws an exception if the resulting sum would
      * cause an overflow or underflow.
diff --git a/core/java/android/util/Patterns.java b/core/java/android/util/Patterns.java
index 910a6b1..ca39854 100644
--- a/core/java/android/util/Patterns.java
+++ b/core/java/android/util/Patterns.java
@@ -243,12 +243,12 @@
     public static final String GOOD_IRI_CHAR =
         "a-zA-Z0-9\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF";
 
-    public static final Pattern IP_ADDRESS
-        = Pattern.compile(
+    private static final String IP_ADDRESS_STRING =
             "((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(25[0-5]|2[0-4]"
             + "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]"
             + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
-            + "|[1-9][0-9]|[0-9]))");
+            + "|[1-9][0-9]|[0-9]))";
+    public static final Pattern IP_ADDRESS = Pattern.compile(IP_ADDRESS_STRING);
 
     /**
      * Valid UCS characters defined in RFC 3987. Excludes space characters.
@@ -298,8 +298,8 @@
 
     private static final String HOST_NAME = "(" + IRI_LABEL + "\\.)+" + TLD;
 
-    public static final Pattern DOMAIN_NAME
-        = Pattern.compile("(" + HOST_NAME + "|" + IP_ADDRESS + ")");
+    private static final String DOMAIN_NAME_STR = "(" + HOST_NAME + "|" + IP_ADDRESS_STRING + ")";
+    public static final Pattern DOMAIN_NAME = Pattern.compile(DOMAIN_NAME_STR);
 
     private static final String PROTOCOL = "(?i:http|https|rtsp)://";
 
@@ -323,7 +323,7 @@
     public static final Pattern WEB_URL = Pattern.compile("("
             + "("
             + "(?:" + PROTOCOL + "(?:" + USER_INFO + ")?" + ")?"
-            + "(?:" + DOMAIN_NAME + ")"
+            + "(?:" + DOMAIN_NAME_STR + ")"
             + "(?:" + PORT_NUMBER + ")?"
             + ")"
             + "(" + PATH_AND_QUERY + ")?"
@@ -346,14 +346,14 @@
      * Regular expression that matches domain names using either {@link #STRICT_HOST_NAME} or
      * {@link #IP_ADDRESS}
      */
-    private static final Pattern STRICT_DOMAIN_NAME
-            = Pattern.compile("(?:" + STRICT_HOST_NAME + "|" + IP_ADDRESS + ")");
+    private static final String STRICT_DOMAIN_NAME = "(?:" + STRICT_HOST_NAME + "|"
+            + IP_ADDRESS_STRING + ")";
 
     /**
      * Regular expression that matches domain names without a TLD
      */
     private static final String RELAXED_DOMAIN_NAME =
-            "(?:" + "(?:" + IRI_LABEL + "(?:\\.(?=\\S))" +"?)+" + "|" + IP_ADDRESS + ")";
+            "(?:" + "(?:" + IRI_LABEL + "(?:\\.(?=\\S))" +"?)+" + "|" + IP_ADDRESS_STRING + ")";
 
     /**
      * Regular expression to match strings that do not start with a supported protocol. The TLDs
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 83b6a52..5494377 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -21,6 +21,7 @@
 import android.annotation.IntDef;
 import android.annotation.RequiresPermission;
 import android.content.res.CompatibilityInfo;
+import android.content.res.Resources;
 import android.graphics.PixelFormat;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -71,7 +72,8 @@
     private final String mAddress;
     private final int mOwnerUid;
     private final String mOwnerPackageName;
-    private final DisplayAdjustments mDisplayAdjustments;
+    private final Resources mResources;
+    private DisplayAdjustments mDisplayAdjustments;
 
     private DisplayInfo mDisplayInfo; // never null
     private boolean mIsValid;
@@ -300,7 +302,6 @@
      *
      * @see #getState
      * @see android.os.PowerManager#isInteractive
-     * @hide
      */
     public static final int STATE_VR = 5;
 
@@ -355,19 +356,39 @@
 
     /**
      * Internal method to create a display.
+     * The display created with this method will have a static {@link DisplayAdjustments} applied.
      * Applications should use {@link android.view.WindowManager#getDefaultDisplay()}
      * or {@link android.hardware.display.DisplayManager#getDisplay}
      * to get a display object.
      *
      * @hide
      */
-    public Display(DisplayManagerGlobal global,
-            int displayId, DisplayInfo displayInfo /*not null*/,
+    public Display(DisplayManagerGlobal global, int displayId, /*@NotNull*/ DisplayInfo displayInfo,
             DisplayAdjustments daj) {
+        this(global, displayId, displayInfo, daj, null /*res*/);
+    }
+
+    /**
+     * Internal method to create a display.
+     * The display created with this method will be adjusted based on the adjustments in the
+     * supplied {@link Resources}.
+     *
+     * @hide
+     */
+    public Display(DisplayManagerGlobal global, int displayId, /*@NotNull*/ DisplayInfo displayInfo,
+            Resources res) {
+        this(global, displayId, displayInfo, null /*daj*/, res);
+    }
+
+    private Display(DisplayManagerGlobal global, int displayId,
+            /*@NotNull*/ DisplayInfo displayInfo, DisplayAdjustments daj, Resources res) {
         mGlobal = global;
         mDisplayId = displayId;
         mDisplayInfo = displayInfo;
-        mDisplayAdjustments = new DisplayAdjustments(daj);
+        mResources = res;
+        mDisplayAdjustments = mResources != null
+            ? new DisplayAdjustments(mResources.getConfiguration())
+            : daj != null ? new DisplayAdjustments(daj) : null;
         mIsValid = true;
 
         // Cache properties that cannot change as long as the display is valid.
@@ -512,6 +533,13 @@
      * @hide
      */
     public DisplayAdjustments getDisplayAdjustments() {
+        if (mResources != null) {
+            final DisplayAdjustments currentAdjustements = mResources.getDisplayAdjustments();
+            if (!mDisplayAdjustments.equals(currentAdjustements)) {
+                mDisplayAdjustments = new DisplayAdjustments(currentAdjustements);
+            }
+        }
+
         return mDisplayAdjustments;
     }
 
@@ -562,7 +590,7 @@
     public void getSize(Point outSize) {
         synchronized (this) {
             updateDisplayInfoLocked();
-            mDisplayInfo.getAppMetrics(mTempMetrics, mDisplayAdjustments);
+            mDisplayInfo.getAppMetrics(mTempMetrics, getDisplayAdjustments());
             outSize.x = mTempMetrics.widthPixels;
             outSize.y = mTempMetrics.heightPixels;
         }
@@ -577,7 +605,7 @@
     public void getRectSize(Rect outSize) {
         synchronized (this) {
             updateDisplayInfoLocked();
-            mDisplayInfo.getAppMetrics(mTempMetrics, mDisplayAdjustments);
+            mDisplayInfo.getAppMetrics(mTempMetrics, getDisplayAdjustments());
             outSize.set(0, 0, mTempMetrics.widthPixels, mTempMetrics.heightPixels);
         }
     }
@@ -908,7 +936,7 @@
     public void getMetrics(DisplayMetrics outMetrics) {
         synchronized (this) {
             updateDisplayInfoLocked();
-            mDisplayInfo.getAppMetrics(outMetrics, mDisplayAdjustments);
+            mDisplayInfo.getAppMetrics(outMetrics, getDisplayAdjustments());
         }
     }
 
@@ -1017,7 +1045,7 @@
         long now = SystemClock.uptimeMillis();
         if (now > mLastCachedAppSizeUpdate + CACHED_APP_SIZE_DURATION_MILLIS) {
             updateDisplayInfoLocked();
-            mDisplayInfo.getAppMetrics(mTempMetrics, mDisplayAdjustments);
+            mDisplayInfo.getAppMetrics(mTempMetrics, getDisplayAdjustments());
             mCachedAppWidthCompat = mTempMetrics.widthPixels;
             mCachedAppHeightCompat = mTempMetrics.heightPixels;
             mLastCachedAppSizeUpdate = now;
@@ -1029,7 +1057,7 @@
     public String toString() {
         synchronized (this) {
             updateDisplayInfoLocked();
-            mDisplayInfo.getAppMetrics(mTempMetrics, mDisplayAdjustments);
+            mDisplayInfo.getAppMetrics(mTempMetrics, getDisplayAdjustments());
             return "Display id " + mDisplayId + ": " + mDisplayInfo
                     + ", " + mTempMetrics + ", isValid=" + mIsValid;
         }
diff --git a/core/java/android/view/FocusFinder.java b/core/java/android/view/FocusFinder.java
index 7fde8a6..61c9201 100644
--- a/core/java/android/view/FocusFinder.java
+++ b/core/java/android/view/FocusFinder.java
@@ -117,7 +117,7 @@
     public View findNextKeyboardNavigationCluster(
             @NonNull View root,
             @Nullable View currentCluster,
-            int direction) {
+            @View.FocusDirection int direction) {
         View next = null;
 
         final ArrayList<View> clusters = mTempList;
@@ -206,7 +206,7 @@
             View root,
             View currentCluster,
             List<View> clusters,
-            int direction) {
+            @View.FocusDirection int direction) {
         final int count = clusters.size();
 
         switch (direction) {
diff --git a/core/java/android/view/FrameMetrics.java b/core/java/android/view/FrameMetrics.java
index 92f0e8f..358a2d1 100644
--- a/core/java/android/view/FrameMetrics.java
+++ b/core/java/android/view/FrameMetrics.java
@@ -132,6 +132,26 @@
      */
     public static final int FIRST_DRAW_FRAME = 9;
 
+    /**
+     * Metric identifier for the timestamp of the intended vsync for this frame.
+     * <p>
+     * The intended start point for the frame. If this value is different from
+     * {@link #VSYNC_TIMESTAMP}, there was work occurring on the UI thread that
+     * prevented it from responding to the vsync signal in a timely fashion.
+     * </p>
+     */
+    public static final int INTENDED_VSYNC_TIMESTAMP = 10;
+
+    /**
+     * Metric identifier for the timestamp of the actual vsync for this frame.
+     * <p>
+     * The time value that was used in all the vsync listeners and drawing for
+     * the frame (Choreographer frame callbacks, animations,
+     * {@link View#getDrawingTime()}, etc…)
+     * </p>
+     */
+    public static final int VSYNC_TIMESTAMP = 11;
+
     private static final int FRAME_INFO_FLAG_FIRST_DRAW = 1 << 0;
 
     /**
@@ -151,6 +171,8 @@
             SWAP_BUFFERS_DURATION,
             TOTAL_DURATION,
             FIRST_DRAW_FRAME,
+            INTENDED_VSYNC_TIMESTAMP,
+            VSYNC_TIMESTAMP,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface Metric {}
@@ -261,7 +283,7 @@
      * @return the value of the metric or -1 if it is not available.
      */
     public long getMetric(@Metric int id) {
-        if (id < UNKNOWN_DELAY_DURATION || id > FIRST_DRAW_FRAME) {
+        if (id < UNKNOWN_DELAY_DURATION || id > VSYNC_TIMESTAMP) {
             return -1;
         }
 
@@ -271,6 +293,10 @@
 
         if (id == FIRST_DRAW_FRAME) {
             return (mTimingData[Index.FLAGS] & FRAME_INFO_FLAG_FIRST_DRAW) != 0 ? 1 : 0;
+        } else if (id == INTENDED_VSYNC_TIMESTAMP) {
+            return mTimingData[Index.INTENDED_VSYNC];
+        } else if (id == VSYNC_TIMESTAMP) {
+            return mTimingData[Index.VSYNC];
         }
 
         int durationsIdx = 2 * id;
diff --git a/core/java/android/view/IGraphicsStats.aidl b/core/java/android/view/IGraphicsStats.aidl
index c235eb2..e6b750b 100644
--- a/core/java/android/view/IGraphicsStats.aidl
+++ b/core/java/android/view/IGraphicsStats.aidl
@@ -17,10 +17,11 @@
 package android.view;
 
 import android.os.ParcelFileDescriptor;
+import android.view.IGraphicsStatsCallback;
 
 /**
  * @hide
  */
 interface IGraphicsStats {
-    ParcelFileDescriptor requestBufferForProcess(String packageName, IBinder token);
+    ParcelFileDescriptor requestBufferForProcess(String packageName, IGraphicsStatsCallback callback);
 }
diff --git a/core/java/android/net/NetworkScorerAppManager.aidl b/core/java/android/view/IGraphicsStatsCallback.aidl
similarity index 82%
copy from core/java/android/net/NetworkScorerAppManager.aidl
copy to core/java/android/view/IGraphicsStatsCallback.aidl
index d968343..f70e141 100644
--- a/core/java/android/net/NetworkScorerAppManager.aidl
+++ b/core/java/android/view/IGraphicsStatsCallback.aidl
@@ -14,6 +14,11 @@
  * limitations under the License.
  */
 
-package android.net;
+package android.view;
 
-parcelable NetworkScorerAppManager.NetworkScorerAppData;
+/**
+ * @hide
+ */
+oneway interface IGraphicsStatsCallback {
+    void onRotateGraphicsStatsBuffer();
+}
diff --git a/core/java/android/view/IPinnedStackListener.aidl b/core/java/android/view/IPinnedStackListener.aidl
index c7340bf..782f349 100644
--- a/core/java/android/view/IPinnedStackListener.aidl
+++ b/core/java/android/view/IPinnedStackListener.aidl
@@ -38,9 +38,11 @@
      * to be changed (ie. after configuration change, aspect ratio change, etc). It then provides
      * the components that allow the listener to calculate the movement bounds itself. The
      * {@param normalBounds} are also the default bounds that the PiP would be entered in its
-     * current state with the aspect ratio applied.
+     * current state with the aspect ratio applied.  The {@param animatingBounds} are provided
+     * to indicate the current target bounds of the pinned stack (the final bounds if animating,
+     * the current bounds if not), which may be helpful in calculating dependent animation bounds.
      */
-    void onMovementBoundsChanged(in Rect insetBounds, in Rect normalBounds,
+    void onMovementBoundsChanged(in Rect insetBounds, in Rect normalBounds, in Rect animatingBounds,
             boolean fromImeAdjustement);
 
     /**
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index c3d3f39..fe91978 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -23,9 +23,7 @@
 import android.graphics.Outline;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
-import android.os.Bundle;
 import android.util.AttributeSet;
-import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.ImageView;
 import android.widget.RemoteViews;
 
@@ -67,33 +65,7 @@
             }
         }
     };
-    final AccessibilityDelegate mExpandDelegate = new AccessibilityDelegate() {
-
-        @Override
-        public boolean performAccessibilityAction(View host, int action, Bundle args) {
-            if (super.performAccessibilityAction(host, action, args)) {
-                return true;
-            }
-            if (action == AccessibilityNodeInfo.ACTION_COLLAPSE
-                    || action == AccessibilityNodeInfo.ACTION_EXPAND) {
-                mExpandClickListener.onClick(mExpandButton);
-                return true;
-            }
-            return false;
-        }
-
-        @Override
-        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
-            super.onInitializeAccessibilityNodeInfo(host, info);
-            // Avoid that the button description is also spoken
-            info.setClassName(getClass().getName());
-            if (mExpanded) {
-                info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_COLLAPSE);
-            } else {
-                info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_EXPAND);
-            }
-        }
-    };
+    private boolean mAcceptAllTouches;
 
     public NotificationHeaderView(Context context) {
         this(context, null);
@@ -123,9 +95,6 @@
         mAppName = findViewById(com.android.internal.R.id.app_name_text);
         mHeaderText = findViewById(com.android.internal.R.id.header_text);
         mExpandButton = (ImageView) findViewById(com.android.internal.R.id.expand_button);
-        if (mExpandButton != null) {
-            mExpandButton.setAccessibilityDelegate(mExpandDelegate);
-        }
         mIcon = (CachingIconView) findViewById(com.android.internal.R.id.icon);
         mProfileBadge = findViewById(com.android.internal.R.id.profile_badge);
     }
@@ -294,13 +263,19 @@
 
     private void updateExpandButton() {
         int drawableId;
+        int contentDescriptionId;
         if (mExpanded) {
             drawableId = com.android.internal.R.drawable.ic_collapse_notification;
+            contentDescriptionId
+                    = com.android.internal.R.string.expand_button_content_description_expanded;
         } else {
             drawableId = com.android.internal.R.drawable.ic_expand_notification;
+            contentDescriptionId
+                    = com.android.internal.R.string.expand_button_content_description_collapsed;
         }
         mExpandButton.setImageDrawable(getContext().getDrawable(drawableId));
         mExpandButton.setColorFilter(mOriginalNotificationColor);
+        mExpandButton.setContentDescription(mContext.getText(contentDescriptionId));
     }
 
     public void setShowWorkBadgeAtEnd(boolean showWorkBadgeAtEnd) {
@@ -374,6 +349,8 @@
                 case MotionEvent.ACTION_DOWN:
                     mTrackGesture = false;
                     if (isInside(x, y)) {
+                        mDownX = x;
+                        mDownY = y;
                         mTrackGesture = true;
                         return true;
                     }
@@ -388,7 +365,7 @@
                     break;
                 case MotionEvent.ACTION_UP:
                     if (mTrackGesture) {
-                        mExpandClickListener.onClick(NotificationHeaderView.this);
+                        mExpandButton.performClick();
                     }
                     break;
             }
@@ -396,11 +373,12 @@
         }
 
         private boolean isInside(float x, float y) {
+            if (mAcceptAllTouches) {
+                return true;
+            }
             for (int i = 0; i < mTouchRects.size(); i++) {
                 Rect r = mTouchRects.get(i);
                 if (r.contains((int) x, (int) y)) {
-                    mDownX = x;
-                    mDownY = y;
                     return true;
                 }
             }
@@ -433,4 +411,9 @@
         }
         return mTouchListener.isInside(x, y);
     }
+
+    @RemotableViewMethod
+    public void setAcceptAllTouches(boolean acceptAllTouches) {
+        mAcceptAllTouches = acceptAllTouches;
+    }
 }
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index cf8da17..b718696 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -508,9 +508,9 @@
         nativeSetAlpha(mNativeObject, alpha);
     }
 
-    public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
+    public void setMatrix(float dsdx, float dtdx, float dtdy, float dsdy) {
         checkNotReleased();
-        nativeSetMatrix(mNativeObject, dsdx, dtdx, dsdy, dtdy);
+        nativeSetMatrix(mNativeObject, dsdx, dtdx, dtdy, dsdy);
     }
 
     public void setWindowCrop(Rect crop) {
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 4ceb236..c66bf874 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -25,9 +25,9 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.drawable.AnimatedVectorDrawable;
-import android.os.Binder;
 import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.Trace;
 import android.util.Log;
@@ -164,6 +164,18 @@
     public static final String OVERDRAW_PROPERTY_SHOW = "show";
 
     /**
+     * Defines the rendering pipeline to be used by the ThreadedRenderer.
+     *
+     * Possible values:
+     * "opengl", will use the existing OpenGL renderer
+     * "skiagl", will use Skia's OpenGL renderer
+     * "skiavk", will use Skia's Vulkan renderer
+     *
+     * @hide
+     */
+    public static final String DEBUG_RENDERER_PROPERTY = "debug.hwui.renderer";
+
+    /**
      * Turn on to debug non-rectangular clip operations.
      *
      * Possible values:
@@ -248,10 +260,10 @@
      *
      * @return A threaded renderer backed by OpenGL.
      */
-    public static ThreadedRenderer create(Context context, boolean translucent) {
+    public static ThreadedRenderer create(Context context, boolean translucent, String name) {
         ThreadedRenderer renderer = null;
         if (isAvailable()) {
-            renderer = new ThreadedRenderer(context, translucent);
+            renderer = new ThreadedRenderer(context, translucent, name);
         }
         return renderer;
     }
@@ -275,10 +287,6 @@
         nOverrideProperty(name, value);
     }
 
-    public static void dumpProfileData(byte[] data, FileDescriptor fd) {
-        nDumpProfileData(data, fd);
-    }
-
     // Keep in sync with DrawFrameTask.h SYNC_* flags
     // Nothing interesting to report
     private static final int SYNC_OK = 0;
@@ -334,7 +342,7 @@
     private boolean mEnabled;
     private boolean mRequested = true;
 
-    ThreadedRenderer(Context context, boolean translucent) {
+    ThreadedRenderer(Context context, boolean translucent, String name) {
         final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
         mLightY = a.getDimension(R.styleable.Lighting_lightY, 0);
         mLightZ = a.getDimension(R.styleable.Lighting_lightZ, 0);
@@ -348,6 +356,7 @@
         mRootNode = RenderNode.adopt(rootNodePtr);
         mRootNode.setClipToBounds(false);
         mNativeProxy = nCreateProxy(translucent, rootNodePtr);
+        nSetName(mNativeProxy, name);
 
         ProcessInitializer.sInstance.init(context, mNativeProxy);
 
@@ -815,15 +824,6 @@
     }
 
     /**
-     * Optional, sets the name of the renderer. Useful for debugging purposes.
-     *
-     * @param name The name of this renderer, can be null
-     */
-    void setName(String name) {
-        nSetName(mNativeProxy, name);
-    }
-
-    /**
      * Blocks until all previously queued work has completed.
      */
     void fence() {
@@ -884,20 +884,29 @@
 
     private static class ProcessInitializer {
         static ProcessInitializer sInstance = new ProcessInitializer();
-        private static IBinder sProcToken;
 
         private boolean mInitialized = false;
 
+        private Context mAppContext;
+        private IGraphicsStats mGraphicsStatsService;
+        private IGraphicsStatsCallback mGraphicsStatsCallback = new IGraphicsStatsCallback.Stub() {
+            @Override
+            public void onRotateGraphicsStatsBuffer() throws RemoteException {
+                rotateBuffer();
+            }
+        };
+
         private ProcessInitializer() {}
 
         synchronized void init(Context context, long renderProxy) {
             if (mInitialized) return;
             mInitialized = true;
+            mAppContext = context.getApplicationContext();
             initSched(context, renderProxy);
-            initGraphicsStats(context, renderProxy);
+            initGraphicsStats();
         }
 
-        private static void initSched(Context context, long renderProxy) {
+        private void initSched(Context context, long renderProxy) {
             try {
                 int tid = nGetRenderThreadTid(renderProxy);
                 ActivityManager.getService().setRenderThread(tid);
@@ -906,17 +915,28 @@
             }
         }
 
-        private static void initGraphicsStats(Context context, long renderProxy) {
+        private void initGraphicsStats() {
             try {
                 IBinder binder = ServiceManager.getService("graphicsstats");
                 if (binder == null) return;
-                IGraphicsStats graphicsStatsService = IGraphicsStats.Stub
-                        .asInterface(binder);
-                sProcToken = new Binder();
-                final String pkg = context.getApplicationInfo().packageName;
-                ParcelFileDescriptor pfd = graphicsStatsService.
-                        requestBufferForProcess(pkg, sProcToken);
-                nSetProcessStatsBuffer(renderProxy, pfd.getFd());
+                mGraphicsStatsService = IGraphicsStats.Stub.asInterface(binder);
+                requestBuffer();
+            } catch (Throwable t) {
+                Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
+            }
+        }
+
+        private void rotateBuffer() {
+            nRotateProcessStatsBuffer();
+            requestBuffer();
+        }
+
+        private void requestBuffer() {
+            try {
+                final String pkg = mAppContext.getApplicationInfo().packageName;
+                ParcelFileDescriptor pfd = mGraphicsStatsService
+                        .requestBufferForProcess(pkg, mGraphicsStatsCallback);
+                nSetProcessStatsBuffer(pfd.getFd());
                 pfd.close();
             } catch (Throwable t) {
                 Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
@@ -936,7 +956,8 @@
 
     static native void setupShadersDiskCache(String cacheFile);
 
-    private static native void nSetProcessStatsBuffer(long nativeProxy, int fd);
+    private static native void nRotateProcessStatsBuffer();
+    private static native void nSetProcessStatsBuffer(int fd);
     private static native int nGetRenderThreadTid(long nativeProxy);
 
     private static native long nCreateRootRenderNode();
@@ -981,7 +1002,6 @@
 
     private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd,
             @DumpFlags int dumpFlags);
-    private static native void nDumpProfileData(byte[] data, FileDescriptor fd);
 
     private static native void nAddRenderNode(long nativeProxy, long rootRenderNode,
              boolean placeFront);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index df0a161..8cfd6a7 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -953,7 +953,7 @@
     public @interface AutoFillMode {}
 
     /**
-     * This view inherits the autofill state from it's parent. If there is no parent it is
+     * This view inherits the auto-fill state from it's parent. If there is no parent it is
      * {@link #AUTO_FILL_MODE_AUTO}.
      * Use with {@link #setAutoFillMode(int)} and <a href="#attr_android:autoFillMode">
      * {@code android:autoFillMode}.
@@ -968,12 +968,236 @@
     public static final int AUTO_FILL_MODE_AUTO = 1;
 
     /**
-     * Require the user to manually force an auto-fill request.
+     * Do not trigger an auto-fill request if this view is focused. The user can still force
+     * an auto-fill request.
+     * <p>This does not prevent this field from being auto-filled if an auto-fill operation is
+     * triggered from a different view.</p>
+     *
      * Use with {@link #setAutoFillMode(int)} and <a href="#attr_android:autoFillMode">{@code
      * android:autoFillMode}.
      */
     public static final int AUTO_FILL_MODE_MANUAL = 2;
 
+    /** @hide */
+    @IntDef({
+            AUTO_FILL_HINT_NONE,
+            AUTO_FILL_HINT_EMAIL_ADDRESS,
+            AUTO_FILL_HINT_NAME,
+            AUTO_FILL_HINT_POSTAL_ADDRESS,
+            AUTO_FILL_HINT_PASSWORD,
+            AUTO_FILL_HINT_PHONE,
+            AUTO_FILL_HINT_USERNAME,
+            AUTO_FILL_HINT_POSTAL_CODE,
+            AUTO_FILL_HINT_CREDIT_CARD_NUMBER,
+            AUTO_FILL_HINT_CREDIT_CARD_SECURITY_CODE,
+            AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_DATE,
+            AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_MONTH,
+            AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_YEAR,
+            AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_DAY,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface AutoFillHint {}
+
+    /**
+     * No auto-fill hint is set.
+     *
+     * Use with {@link #setAutoFillHint(int)} and <a href="#attr_android:autoFillHint">
+     * {@code android:autoFillHint}.
+     */
+    public static final int AUTO_FILL_HINT_NONE = 0;
+
+    /**
+     * This view contains an email address.
+     *
+     * Use with {@link #setAutoFillHint(int)} and <a href="#attr_android:autoFillHint">
+     * {@code android:autoFillHint}.
+     */
+    public static final int AUTO_FILL_HINT_EMAIL_ADDRESS = 0x1;
+
+    /**
+     * The view contains a real name.
+     *
+     * Use with {@link #setAutoFillHint(int)} and <a href="#attr_android:autoFillHint">
+     * {@code android:autoFillHint}.
+     */
+    public static final int AUTO_FILL_HINT_NAME = 0x2;
+
+    /**
+     * The view contains a user name.
+     *
+     * Use with {@link #setAutoFillHint(int)} and <a href="#attr_android:autoFillHint">
+     * {@code android:autoFillHint}.
+     */
+    public static final int AUTO_FILL_HINT_USERNAME = 0x4;
+
+    /**
+     * The view contains a password.
+     *
+     * Use with {@link #setAutoFillHint(int)} and <a href="#attr_android:autoFillHint">
+     * {@code android:autoFillHint}.
+     */
+    public static final int AUTO_FILL_HINT_PASSWORD = 0x8;
+
+    /**
+     * The view contains a phone number.
+     *
+     * Use with {@link #setAutoFillHint(int)} and <a href="#attr_android:autoFillHint">
+     * {@code android:autoFillHint}.
+     */
+    public static final int AUTO_FILL_HINT_PHONE = 0x10;
+
+    /**
+     * The view contains a postal address.
+     *
+     * Use with {@link #setAutoFillHint(int)} and <a href="#attr_android:autoFillHint">
+     * {@code android:autoFillHint}.
+     */
+    public static final int AUTO_FILL_HINT_POSTAL_ADDRESS = 0x20;
+
+    /**
+     * The view contains a postal code.
+     *
+     * Use with {@link #setAutoFillHint(int)} and <a href="#attr_android:autoFillHint">
+     * {@code android:autoFillHint}.
+     */
+    public static final int AUTO_FILL_HINT_POSTAL_CODE = 0x40;
+
+    /**
+     * The view contains a credit card number.
+     *
+     * Use with {@link #setAutoFillHint(int)} and <a href="#attr_android:autoFillHint">
+     * {@code android:autoFillHint}.
+     */
+    public static final int AUTO_FILL_HINT_CREDIT_CARD_NUMBER = 0x80;
+
+    /**
+     * The view contains a credit card security code.
+     *
+     * Use with {@link #setAutoFillHint(int)} and <a href="#attr_android:autoFillHint">
+     * {@code android:autoFillHint}.
+     */
+    public static final int AUTO_FILL_HINT_CREDIT_CARD_SECURITY_CODE = 0x100;
+
+    /**
+     * The view contains a credit card expiration date.
+     *
+     * Use with {@link #setAutoFillHint(int)} and <a href="#attr_android:autoFillHint">
+     * {@code android:autoFillHint}.
+     */
+    public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_DATE = 0x200;
+
+    /**
+     * The view contains the month a credit card expires.
+     *
+     * Use with {@link #setAutoFillHint(int)} and <a href="#attr_android:autoFillHint">
+     * {@code android:autoFillHint}.
+     */
+    public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_MONTH = 0x400;
+
+    /**
+     * The view contains the year a credit card expires.
+     *
+     * Use with {@link #setAutoFillHint(int)} and <a href="#attr_android:autoFillHint">
+     * {@code android:autoFillHint}.
+     */
+    public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_YEAR = 0x800;
+
+    /**
+     * The view contains the day a credit card expires.
+     *
+     * Use with {@link #setAutoFillHint(int)} and <a href="#attr_android:autoFillHint">
+     * {@code android:autoFillHint}.
+     */
+    public static final int AUTO_FILL_HINT_CREDIT_CARD_EXPIRATION_DAY = 0x1000;
+
+    /**
+     * Hint for the auto-fill services that describes the content of the view.
+     */
+    @AutoFillHint private int mAutoFillHint;
+
+    /** @hide */
+    @IntDef({
+            AUTOFILL_TYPE_NONE,
+            AUTOFILL_TYPE_TEXT,
+            AUTOFILL_TYPE_TOGGLE,
+            AUTOFILL_TYPE_LIST,
+            AUTOFILL_TYPE_DATE
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface AutofillType {}
+
+    /**
+     * Autofill type for views that cannot be autofilled.
+     */
+    public static final int AUTOFILL_TYPE_NONE = 0;
+
+    /**
+     * Autofill type for a text field, which is filled by a {@link CharSequence}.
+     *
+     * <p>{@link AutoFillValue} instances for autofilling a {@link View} can be obtained through
+     * {@link AutoFillValue#forText(CharSequence)}, and the value passed to auto-fill a
+     * {@link View} can be fetched through {@link AutoFillValue#getTextValue()}.
+     */
+    public static final int AUTOFILL_TYPE_TEXT = 1;
+
+    /**
+     * Autofill type for a togglable field, which is filled by a {@code boolean}.
+     *
+     * <p>{@link AutoFillValue} instances for auto-filling a {@link View} can be obtained through
+     * {@link AutoFillValue#forToggle(boolean)}, and the value passed to auto-fill a
+     * {@link View} can be fetched through {@link AutoFillValue#getToggleValue()}.
+     */
+    public static final int AUTOFILL_TYPE_TOGGLE = 2;
+
+    /**
+     * Autofill type for a selection list field, which is filled by an {@code int}
+     * representing the element index inside the list (starting at {@code 0}).
+     *
+     * <p>{@link AutoFillValue} instances for autofilling a {@link View} can be obtained through
+     * {@link AutoFillValue#forList(int)}, and the value passed to auto-fill a
+     * {@link View} can be fetched through {@link AutoFillValue#getListValue()}.
+     *
+     * <p>The available options in the selection list are typically provided by
+     * {@link android.app.assist.AssistStructure.ViewNode#getAutoFillOptions()}.
+     */
+    public static final int AUTOFILL_TYPE_LIST = 3;
+
+
+    /**
+     * Autofill type for a field that contains a date, which is represented by a long representing
+     * the number of milliseconds since the standard base time known as "the epoch", namely
+     * January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}.
+     *
+     * <p>{@link AutoFillValue} instances for autofilling a {@link View} can be obtained through
+     * {@link AutoFillValue#forDate(long)}, and the values passed to
+     * auto-fill a {@link View} can be fetched through {@link AutoFillValue#getDateValue()}.
+     */
+    public static final int AUTOFILL_TYPE_DATE = 4;
+
+    /** @hide */
+    @IntDef({
+            IMPORTANT_FOR_AUTOFILL_AUTO,
+            IMPORTANT_FOR_AUTOFILL_YES,
+            IMPORTANT_FOR_AUTOFILL_NO
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface AutofillImportance {}
+
+    /**
+     * Automatically determine whether a view is important for auto-fill.
+     */
+    public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0x0;
+
+    /**
+     * The view is important for important for auto-fill.
+     */
+    public static final int IMPORTANT_FOR_AUTOFILL_YES = 0x1;
+
+    /**
+     * The view is not important for auto-fill.
+     */
+    public static final int IMPORTANT_FOR_AUTOFILL_NO = 0x2;
+
     /**
      * This view is enabled. Interpretation varies by subclass.
      * Use with ENABLED_MASK when calling setFlags.
@@ -2545,7 +2769,7 @@
      *                1                  PFLAG3_FINGER_DOWN
      *               1                   PFLAG3_FOCUSED_BY_DEFAULT
      *             11                    PFLAG3_AUTO_FILL_MODE_MASK
-     *           xx                      * NO LONGER NEEDED, SHOULD BE REUSED *
+     *           11                      PFLAG3_IMPORTANT_FOR_AUTOFILL
      *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
      *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
      *        1                          PFLAG3_TEMPORARY_DETACH
@@ -2783,6 +3007,20 @@
             | AUTO_FILL_MODE_AUTO | AUTO_FILL_MODE_MANUAL) << PFLAG3_AUTO_FILL_MODE_SHIFT;
 
     /**
+     * Shift for the bits in {@link #mPrivateFlags3} related to the
+     * "importantForAutofill" attribute.
+     */
+    static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT = 21;
+
+    /**
+     * Mask for obtaining the bits which specify how to determine
+     * whether a view is important for autofill.
+     */
+    static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK = (IMPORTANT_FOR_AUTOFILL_AUTO
+            | IMPORTANT_FOR_AUTOFILL_YES | IMPORTANT_FOR_AUTOFILL_NO)
+            << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
+
+    /**
      * Whether this view has rendered elements that overlap (see {@link
      * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
      * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
@@ -4500,6 +4738,8 @@
                     break;
                 case com.android.internal.R.styleable.View_focusableInTouchMode:
                     if (a.getBoolean(attr, false)) {
+                        // unset auto focus since focusableInTouchMode implies explicit focusable
+                        viewFlagValues &= ~FOCUSABLE_AUTO;
                         viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
                         viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
                     }
@@ -4797,11 +5037,21 @@
                         setFocusedByDefault(a.getBoolean(attr, true));
                     }
                     break;
-                case com.android.internal.R.styleable.View_autoFillMode:
+                case R.styleable.View_autoFillMode:
                     if (a.peekValue(attr) != null) {
                         setAutoFillMode(a.getInt(attr, AUTO_FILL_MODE_INHERIT));
                     }
                     break;
+                case R.styleable.View_autoFillHint:
+                    if (a.peekValue(attr) != null) {
+                        setAutoFillHint(a.getInt(attr, AUTO_FILL_HINT_NONE));
+                    }
+                    break;
+                case R.styleable.View_importantForAutofill:
+                    if (a.peekValue(attr) != null) {
+                        setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
+                    }
+                    break;
             }
         }
 
@@ -6471,12 +6721,18 @@
                 }
             }
         }
+
+        // Invisible and gone views are never focusable.
         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
             return false;
         }
-        return (allowAutoFocus
-                ? getFocusable() != NOT_FOCUSABLE
-                : getFocusable() == FOCUSABLE) && isFocusable();
+
+        // Only use effective focusable value when allowed.
+        if ((allowAutoFocus || getFocusable() != FOCUSABLE_AUTO) && isFocusable()) {
+            return true;
+        }
+
+        return false;
     }
 
     /**
@@ -6520,13 +6776,6 @@
             imm.focusIn(this);
         }
 
-        if (isAutoFillable()) {
-            AutoFillManager afm = getAutoFillManager();
-            if (afm != null) {
-                afm.focusChanged(this, gainFocus);
-            }
-        }
-
         invalidate(true);
         ListenerInfo li = mListenerInfo;
         if (li != null && li.mOnFocusChangeListener != null) {
@@ -6536,6 +6785,18 @@
         if (mAttachInfo != null) {
             mAttachInfo.mKeyDispatchState.reset(this);
         }
+
+        if (isAutoFillable() && isAttachedToWindow()
+                && getResolvedAutoFillMode() == AUTO_FILL_MODE_AUTO) {
+            AutoFillManager afm = getAutoFillManager();
+            if (afm != null) {
+                if (gainFocus) {
+                    afm.startAutoFillRequest(this);
+                } else {
+                    afm.stopAutoFillRequest(this);
+                }
+            }
+        }
     }
 
     /**
@@ -6983,19 +7244,19 @@
     /**
      * Called when assist structure is being retrieved from a view as part of an auto-fill request.
      *
-     * <p>When implementing this method, subclasses must also:
-     *
+     * <p>This method already provides most of what's needed for auto-fill, but should be overridden
      * <ol>
-     * <li>Implement {@link #autoFill(AutoFillValue)}, {@link #getAutoFillType()}
-     * and {@link #getAutoFillValue()}.
-     * <li>Call {@link android.view.autofill.AutoFillManager#virtualValueChanged(View, int,
-     * AutoFillValue)} when its value changed.
+     * <li>The view contents does not include PII (Personally Identifiable Information), so it
+     * can call {@link ViewStructure#setSanitized(boolean)} passing {@code true}.
+     * <li>It must set fields such {@link ViewStructure#setText(CharSequence)},
+     * {@link ViewStructure#setAutoFillOptions(String[])}, or {@link ViewStructure#setUrl(String)}.
      * </ol>
      *
      * @param structure Fill in with structured view data. The default implementation
      * fills in all data that can be inferred from the view itself.
      * @param flags optional flags (currently {@code 0}).
      */
+    @CallSuper
     public void onProvideAutoFillStructure(ViewStructure structure, int flags) {
         onProvideStructureForAssistOrAutoFill(structure, true);
     }
@@ -7019,14 +7280,15 @@
         }
 
         if (forAutoFill) {
-            final AutoFillType autoFillType = getAutoFillType();
+            final @AutofillType int autofillType = getAutofillType();
             // Don't need to fill auto-fill info if view does not support it.
             // For example, only TextViews that are editable support auto-fill
-            if (autoFillType != null) {
+            if (autofillType != AUTOFILL_TYPE_NONE) {
                 // The auto-fill id needs to be unique, but its value doesn't matter, so it's better
                 // to reuse the accessibility id to save space.
                 structure.setAutoFillId(getAccessibilityViewId());
-                structure.setAutoFillType(autoFillType);
+                structure.setAutofillType(autofillType);
+                structure.setAutoFillHint(getAutoFillHint());
                 structure.setAutoFillValue(getAutoFillValue());
             }
         }
@@ -7097,8 +7359,10 @@
      * <ol>
      * <li>Also implement {@link #autoFillVirtual(int, AutoFillValue)} to auto-fill the virtual
      * children.
-     * <li>Call {@link android.view.autofill.AutoFillManager#virtualFocusChanged(View, int, Rect,
-     * boolean)} when the focus inside the view changed.
+     * <li>Call
+     * {@link android.view.autofill.AutoFillManager#startAutoFillRequestOnVirtualView} and
+     * {@link android.view.autofill.AutoFillManager#stopAutoFillRequestOnVirtualView(View, int)}
+     * when the focus inside the view changed.
      * <li>Call {@link android.view.autofill.AutoFillManager#virtualValueChanged(View, int,
      * AutoFillValue)} when the value of a child changed.
      * <li>Call {@link android.view.autofill.AutoFillManager#reset()} when the auto-fill context
@@ -7129,7 +7393,7 @@
     /**
      * Automatically fills the content of this view with the {@code value}.
      *
-     * <p>By default does nothing, but views should override it (and {@link #getAutoFillType()},
+     * <p>By default does nothing, but views should override it (and {@link #getAutofillType()},
      * {@link #getAutoFillValue()}, and {@link #onProvideAutoFillStructure(ViewStructure, int)}
      * to support the AutoFill Framework.
      *
@@ -7168,22 +7432,53 @@
     }
 
     /**
+     * @deprecated TODO(b/35956626): remove once clients use getAutoFilltype
+     */
+    @Deprecated
+    @Nullable
+    public final AutoFillType getAutoFillType() {
+        switch (getAutofillType()) {
+            case AUTOFILL_TYPE_TEXT:
+                return AutoFillType.forText();
+            case AUTOFILL_TYPE_TOGGLE:
+                return AutoFillType.forToggle();
+            case AUTOFILL_TYPE_LIST:
+                return AutoFillType.forList();
+            case AUTOFILL_TYPE_DATE:
+                return AutoFillType.forDate();
+            default:
+                return null;
+        }
+    }
+
+    /**
      * Describes the auto-fill type that should be used on calls to
      * {@link #autoFill(AutoFillValue)} and {@link #autoFillVirtual(int, AutoFillValue)}.
-
-     * <p>By default returns {@code null}, but views should override it (and
+     *
+     * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it (and
      * {@link #autoFill(AutoFillValue)} to support the AutoFill Framework.
      */
-    @Nullable
-    public AutoFillType getAutoFillType() {
-        return null;
+    public @AutofillType int getAutofillType() {
+        return AUTOFILL_TYPE_NONE;
+    }
+
+    /**
+     * Describes the content of a view so that a auto-fill service can fill in the appropriate data.
+     *
+     * @return The hint set via the attribute
+     *
+     * @attr ref android.R.styleable#View_autoFillHint
+     */
+    @ViewDebug.ExportedProperty()
+    @AutoFillHint public int getAutoFillHint() {
+        return mAutoFillHint;
     }
 
     /**
      * Gets the {@link View}'s current auto-fill value.
      *
-     * <p>By default returns {@code null}, but views should override it,
-     * {@link #autoFill(AutoFillValue)}, and {@link #getAutoFillType()} to support the AutoFill
+     * <p>By default returns {@code null}, but views should override it (and
+     * {@link #autoFill(AutoFillValue)}, and {@link #getAutofillType()} to support the AutoFill
      * Framework.
      */
     @Nullable
@@ -7191,13 +7486,125 @@
         return null;
     }
 
+    /**
+     * Gets the mode for determining whether this View is important for autofill.
+     *
+     * <p>See {@link #setImportantForAutofill(int)} for more info about this mode.
+     *
+     * @return {@link #IMPORTANT_FOR_AUTOFILL_AUTO} by default, or value passed to
+     * {@link #setImportantForAutofill(int)}.
+     *
+     * @attr ref android.R.styleable#View_importantForAutofill
+     */
+    @ViewDebug.ExportedProperty(mapping = {
+            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_AUTO, to = "auto"),
+            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES, to = "yes"),
+            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO, to = "no")})
+    public @AutofillImportance int getImportantForAutofill() {
+        return (mPrivateFlags3
+                & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK) >> PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
+    }
+
+    /**
+     * Sets the mode for determining whether this View is important for autofill.
+     *
+     * <p>See {@link #setImportantForAutofill(int)} for more info about this mode.
+     *
+     * @param mode {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, {@link #IMPORTANT_FOR_AUTOFILL_YES},
+     * or {@link #IMPORTANT_FOR_AUTOFILL_NO}.
+     *
+     * @attr ref android.R.styleable#View_importantForAutofill
+     */
+    public void setImportantForAutofill(@AutofillImportance int mode) {
+        mPrivateFlags3 &= ~PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
+        mPrivateFlags3 |= (mode << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT)
+                & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
+    }
+
+    /**
+     * Hints the Android System whether the {@link android.app.assist.AssistStructure.ViewNode}
+     * associated with this View should be included in a {@link ViewStructure} used for
+     * autofill purposes.
+     *
+     * <p>Generally speaking, a view is important for autofill if:
+     * <ol>
+     * <li>The view can-be autofilled by an {@link android.service.autofill.AutoFillService}.
+     * <li>The view contents can help an {@link android.service.autofill.AutoFillService} to
+     * autofill other views.
+     * <ol>
+     *
+     * <p>For example, view containers should typically return {@code false} for performance reasons
+     * (since the important info is provided by their children), but if the container is actually
+     * whose children are part of a compound view, it should return {@code true} (and then override
+     * {@link #dispatchProvideAutoFillStructure(ViewStructure, int)} to simply call
+     * {@link #onProvideAutoFillStructure(ViewStructure, int)} so its children are not included in
+     * the structure). On the other hand, views representing labels or editable fields should
+     * typically return {@code true}, but in some cases they could return {@code false} (for
+     * example, if they're part of a "Captcha" mechanism).
+     *
+     * <p>By default, this method returns {@code true} if {@link #getImportantForAutofill()} returns
+     * {@link #IMPORTANT_FOR_AUTOFILL_YES}, {@code false } if it returns
+     * {@link #IMPORTANT_FOR_AUTOFILL_NO}, and use some heuristics to define the importance when it
+     * returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}. Hence, it should rarely be overridden - Views
+     * should use {@link #setImportantForAutofill(int)} instead.
+     *
+     * <p><strong>Note:</strong> returning {@code false} does not guarantee the view will be
+     * excluded from the structure; for example, if the user explicitly requested auto-fill, the
+     * View might be always included.
+     *
+     * <p>This decision applies just for the view, not its children - if the view children are not
+     * important for autofill, the view should override
+     * {@link #dispatchProvideAutoFillStructure(ViewStructure, int)} to simply call
+     * {@link #onProvideAutoFillStructure(ViewStructure, int)} (instead of calling
+     * {@link #dispatchProvideAutoFillStructure(ViewStructure, int)} for each child).
+     *
+     * @return whether the view is considered important for autofill.
+     *
+     * @see #IMPORTANT_FOR_AUTOFILL_AUTO
+     * @see #IMPORTANT_FOR_AUTOFILL_YES
+     * @see #IMPORTANT_FOR_AUTOFILL_NO
+     */
+    public final boolean isImportantForAutofill() {
+        final int flag = getImportantForAutofill();
+
+        // First, check if view explicity set it to YES or NO
+        if ((flag & IMPORTANT_FOR_AUTOFILL_YES) != 0) {
+            return true;
+        }
+        if ((flag & IMPORTANT_FOR_AUTOFILL_NO) != 0) {
+            return false;
+        }
+
+        // Then use some heuristics to handle AUTO.
+
+        // Always include views that have a explicity resource id.
+        final int id = mID;
+        if (id != NO_ID && !isViewIdGenerated(id)) {
+            final Resources res = getResources();
+            String entry = null;
+            String pkg = null;
+            try {
+                entry = res.getResourceEntryName(id);
+                pkg = res.getResourcePackageName(id);
+            } catch (Resources.NotFoundException e) {
+                // ignore
+            }
+            if (entry != null && pkg != null && pkg.equals(mContext.getPackageName())) {
+                return true;
+            }
+        }
+
+        // Otherwise, assume it's not important...
+        return false;
+    }
+
     @Nullable
     private AutoFillManager getAutoFillManager() {
         return mContext.getSystemService(AutoFillManager.class);
     }
 
     private boolean isAutoFillable() {
-        return getAutoFillType() != null && !isAutoFillBlocked();
+        return getAutofillType() != AUTOFILL_TYPE_NONE && !isAutoFillBlocked();
     }
 
     private void populateVirtualStructure(ViewStructure structure,
@@ -8666,7 +9073,10 @@
         // which, in touch mode, will not successfully request focus on this view
         // because the focusable in touch mode flag is not set
         setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
+
+        // Clear FOCUSABLE_AUTO if set.
         if (focusableInTouchMode) {
+            // Clears FOCUSABLE_AUTO if set.
             setFlags(FOCUSABLE, FOCUSABLE_MASK);
         }
     }
@@ -8687,6 +9097,17 @@
     }
 
     /**
+     * Sets the a hint that helps the auto-fill service to select the appropriate data to fill the
+     * view.
+     *
+     * @param autoFillHint The auto-fill hint to set
+     * @attr ref android.R.styleable#View_autoFillHint
+     */
+    public void setAutoFillHint(@AutoFillHint int autoFillHint) {
+        mAutoFillHint = autoFillHint;
+    }
+
+    /**
      * Set whether this view should have sound effects enabled for events such as
      * clicking and touching.
      *
@@ -9307,6 +9728,31 @@
     }
 
     /**
+     * Returns the resolved auto-fill mode for this view.
+     *
+     * This is the same as {@link #getAutoFillMode()} but if the mode is
+     * {@link #AUTO_FILL_MODE_INHERIT} the parents auto-fill mode will be returned.
+     *
+     * @return One of {@link #AUTO_FILL_MODE_AUTO}, or {@link #AUTO_FILL_MODE_MANUAL}. If the auto-
+     *         fill mode can not be resolved e.g. {@link #getAutoFillMode()} is
+     *         {@link #AUTO_FILL_MODE_INHERIT} and the {@link View} is detached
+     *         {@link #AUTO_FILL_MODE_AUTO} is returned.
+     */
+    public @AutoFillMode int getResolvedAutoFillMode() {
+        @AutoFillMode int autoFillMode = getAutoFillMode();
+
+        if (autoFillMode == AUTO_FILL_MODE_INHERIT) {
+            if (mParent == null) {
+                return AUTO_FILL_MODE_AUTO;
+            } else {
+                return mParent.getResolvedAutoFillMode();
+            }
+        } else {
+            return autoFillMode;
+        }
+    }
+
+    /**
      * Find the nearest view in the specified direction that can take focus.
      * This does not actually give focus to that view.
      *
@@ -9433,7 +9879,8 @@
      * @return The nearest keyboard navigation cluster in the specified direction, or null if none
      *         can be found
      */
-    public View keyboardNavigationClusterSearch(View currentCluster, int direction) {
+    public View keyboardNavigationClusterSearch(View currentCluster,
+            @FocusDirection int direction) {
         if (isKeyboardNavigationCluster()) {
             currentCluster = this;
         }
@@ -11729,7 +12176,10 @@
                 && isOnScrollbar(event.getX(), event.getY())) {
             awakenScrollBars();
         }
-        if (isHoverable()) {
+
+        // If we consider ourself hoverable, or if we we're already hovered,
+        // handle changing state in response to ENTER and EXIT events.
+        if (isHoverable() || isHovered()) {
             switch (action) {
                 case MotionEvent.ACTION_HOVER_ENTER:
                     setHovered(true);
@@ -12260,12 +12710,13 @@
         // If focusable is auto, update the FOCUSABLE bit.
         int focusableChangedByAuto = 0;
         if (((mViewFlags & FOCUSABLE_AUTO) != 0)
-                && (changed & (FOCUSABLE_MASK | CLICKABLE | FOCUSABLE_IN_TOUCH_MODE)) != 0) {
-            int newFocus = NOT_FOCUSABLE;
-            if ((mViewFlags & (CLICKABLE | FOCUSABLE_IN_TOUCH_MODE)) != 0) {
+                && (changed & (FOCUSABLE_MASK | CLICKABLE)) != 0) {
+            // Heuristic only takes into account whether view is clickable.
+            final int newFocus;
+            if ((mViewFlags & CLICKABLE) != 0) {
                 newFocus = FOCUSABLE;
             } else {
-                mViewFlags = (mViewFlags & ~FOCUSABLE_IN_TOUCH_MODE);
+                newFocus = NOT_FOCUSABLE;
             }
             mViewFlags = (mViewFlags & ~FOCUSABLE) | newFocus;
             focusableChangedByAuto = (old & FOCUSABLE) ^ (newFocus & FOCUSABLE);
@@ -16437,6 +16888,13 @@
             refreshDrawableState();
         }
         needGlobalAttributesUpdate(false);
+
+        if (isAutoFillable() && isFocused() && getResolvedAutoFillMode() == AUTO_FILL_MODE_AUTO) {
+            AutoFillManager afm = getAutoFillManager();
+            if (afm != null) {
+                afm.startAutoFillRequest(this);
+            }
+        }
     }
 
     void dispatchDetachedFromWindow() {
@@ -16483,6 +16941,13 @@
         if (mOverlay != null) {
             mOverlay.getOverlayView().dispatchDetachedFromWindow();
         }
+
+        if (isAutoFillable() && isFocused() && getResolvedAutoFillMode() == AUTO_FILL_MODE_AUTO) {
+            AutoFillManager afm = getAutoFillManager();
+            if (afm != null) {
+                afm.stopAutoFillRequest(this);
+            }
+        }
     }
 
     /**
@@ -20259,9 +20724,9 @@
      * @return the view of the specified id, null if cannot be found
      * @hide
      */
-    protected View findViewTraversal(@IdRes int id) {
+    protected <T extends View> T findViewTraversal(@IdRes int id) {
         if (id == mID) {
-            return this;
+            return (T) this;
         }
         return null;
     }
@@ -20271,9 +20736,9 @@
      * @return the view of specified tag, null if cannot be found
      * @hide
      */
-    protected View findViewWithTagTraversal(Object tag) {
+    protected <T extends View> T findViewWithTagTraversal(Object tag) {
         if (tag != null && tag.equals(mTag)) {
-            return this;
+            return (T) this;
         }
         return null;
     }
@@ -20284,9 +20749,10 @@
      * @return The first view that matches the predicate or null.
      * @hide
      */
-    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
+    protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
+            View childToSkip) {
         if (predicate.test(this)) {
-            return this;
+            return (T) this;
         }
         return null;
     }
@@ -20299,7 +20765,7 @@
      * @return The view that has the given id in the hierarchy or null
      */
     @Nullable
-    public final View findViewById(@IdRes int id) {
+    public final <T extends View> T findViewById(@IdRes int id) {
         if (id < 0) {
             return null;
         }
@@ -20312,11 +20778,11 @@
      * @param accessibilityId The searched accessibility id.
      * @return The found view.
      */
-    final View findViewByAccessibilityId(int accessibilityId) {
+    final <T extends View> T  findViewByAccessibilityId(int accessibilityId) {
         if (accessibilityId < 0) {
             return null;
         }
-        View view = findViewByAccessibilityIdTraversal(accessibilityId);
+        T view = findViewByAccessibilityIdTraversal(accessibilityId);
         if (view != null) {
             return view.includeForAccessibility() ? view : null;
         }
@@ -20335,12 +20801,11 @@
      *
      * @param accessibilityId The accessibility id.
      * @return The found view.
-     *
      * @hide
      */
-    public View findViewByAccessibilityIdTraversal(int accessibilityId) {
+    public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) {
         if (getAccessibilityViewId() == accessibilityId) {
-            return this;
+            return (T) this;
         }
         return null;
     }
@@ -20352,7 +20817,7 @@
      * @param tag The tag to search for, using "tag.equals(getTag())".
      * @return The View that has the given tag in the hierarchy or null
      */
-    public final View findViewWithTag(Object tag) {
+    public final <T extends View> T findViewWithTag(Object tag) {
         if (tag == null) {
             return null;
         }
@@ -20367,7 +20832,7 @@
      * @return The first view that matches the predicate or null.
      * @hide
      */
-    public final View findViewByPredicate(Predicate<View> predicate) {
+    public final <T extends View> T findViewByPredicate(Predicate<View> predicate) {
         return findViewByPredicateTraversal(predicate, null);
     }
 
@@ -20387,10 +20852,11 @@
      * @return The first view that matches the predicate or null.
      * @hide
      */
-    public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
+    public final <T extends View> T findViewByPredicateInsideOut(
+            View start, Predicate<View> predicate) {
         View childToSkip = null;
         for (;;) {
-            View view = start.findViewByPredicateTraversal(predicate, childToSkip);
+            T view = start.findViewByPredicateTraversal(predicate, childToSkip);
             if (view != null || start == this) {
                 return view;
             }
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 5d01b416..f16fcc9 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -35,7 +35,7 @@
      * Defines the width of the horizontal scrollbar and the height of the vertical scrollbar in
      * dips
      */
-    private static final int SCROLL_BAR_SIZE = 10;
+    private static final int SCROLL_BAR_SIZE = 4;
 
     /**
      * Duration of the fade when scrollbars fade away in milliseconds
@@ -346,7 +346,8 @@
 
         mEdgeSlop = (int) (sizeAndDensity * EDGE_SLOP + 0.5f);
         mFadingEdgeLength = (int) (sizeAndDensity * FADING_EDGE_LENGTH + 0.5f);
-        mScrollbarSize = (int) (density * SCROLL_BAR_SIZE + 0.5f);
+        mScrollbarSize = res.getDimensionPixelSize(
+                com.android.internal.R.dimen.config_scrollbarSize);
         mDoubleTapSlop = (int) (sizeAndDensity * DOUBLE_TAP_SLOP + 0.5f);
         mWindowTouchSlop = (int) (sizeAndDensity * WINDOW_TOUCH_SLOP + 0.5f);
 
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 047a515..66c0578 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -107,10 +107,10 @@
          * these human readable values:
          *
          * <pre>
-         * @ViewDebug.ExportedProperty(mapping = {
-         *     @ViewDebug.IntToString(from = 0, to = "VISIBLE"),
-         *     @ViewDebug.IntToString(from = 4, to = "INVISIBLE"),
-         *     @ViewDebug.IntToString(from = 8, to = "GONE")
+         * {@literal @}ViewDebug.ExportedProperty(mapping = {
+         *     {@literal @}ViewDebug.IntToString(from = 0, to = "VISIBLE"),
+         *     {@literal @}ViewDebug.IntToString(from = 4, to = "INVISIBLE"),
+         *     {@literal @}ViewDebug.IntToString(from = 8, to = "GONE")
          * })
          * public int getVisibility() { ...
          * <pre>
@@ -127,10 +127,10 @@
          * of an array:
          *
          * <pre>
-         * @ViewDebug.ExportedProperty(indexMapping = {
-         *     @ViewDebug.IntToString(from = 0, to = "INVALID"),
-         *     @ViewDebug.IntToString(from = 1, to = "FIRST"),
-         *     @ViewDebug.IntToString(from = 2, to = "SECOND")
+         * {@literal @}ViewDebug.ExportedProperty(indexMapping = {
+         *     {@literal @}ViewDebug.IntToString(from = 0, to = "INVALID"),
+         *     {@literal @}ViewDebug.IntToString(from = 1, to = "FIRST"),
+         *     {@literal @}ViewDebug.IntToString(from = 2, to = "SECOND")
          * })
          * private int[] mElements;
          * <pre>
@@ -148,9 +148,11 @@
          * for the flags of an integer:
          *
          * <pre>
-         * @ViewDebug.ExportedProperty(flagMapping = {
-         *     @ViewDebug.FlagToString(mask = ENABLED_MASK, equals = ENABLED, name = "ENABLED"),
-         *     @ViewDebug.FlagToString(mask = ENABLED_MASK, equals = DISABLED, name = "DISABLED"),
+         * {@literal @}ViewDebug.ExportedProperty(flagMapping = {
+         *     {@literal @}ViewDebug.FlagToString(mask = ENABLED_MASK, equals = ENABLED,
+         *             name = "ENABLED"),
+         *     {@literal @}ViewDebug.FlagToString(mask = ENABLED_MASK, equals = DISABLED,
+         *             name = "DISABLED"),
          * })
          * private int mFlags;
          * <pre>
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 7aa2168..214249f 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -595,6 +595,7 @@
 
     public ViewGroup(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
+
         initViewGroup();
         initFromAttributes(context, attrs, defStyleAttr, defStyleRes);
     }
@@ -1148,18 +1149,21 @@
 
     @Override
     boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) {
+        // This should probably be super.hasFocusable, but that would change
+        // behavior. Historically, we have not checked the ancestor views for
+        // shouldBlockFocusForTouchscreen() in ViewGroup.hasFocusable.
+
+        // Invisible and gone views are never focusable.
         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
             return false;
         }
 
-        // TODO This should probably be super.hasFocusable, but that would change behavior.
-        // The below is a much simpler check than we do in the superclass implementation,
-        // but it's been this way for a long time and other code likely relies on it.
-        if ((allowAutoFocus ? getFocusable() != NOT_FOCUSABLE : getFocusable() == FOCUSABLE)
-                && isFocusable()) {
+        // Only use effective focusable value when allowed.
+        if ((allowAutoFocus || getFocusable() != FOCUSABLE_AUTO) && isFocusable()) {
             return true;
         }
 
+        // Determine whether we have a focused descendant.
         final int descendantFocusability = getDescendantFocusability();
         if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) {
             final int count = mChildrenCount;
@@ -3338,82 +3342,122 @@
         dispatchProvideStructureForAssistOrAutoFill(structure, true);
     }
 
+    /** @hide */
+    private ArrayList<View> getChildrenForAutofill() {
+        final ArrayList<View> list = new ArrayList<>();
+        populateChildrenForAutofill(list);
+        return list;
+    }
+
+    /** @hide */
+    private void populateChildrenForAutofill(ArrayList<View> list) {
+        final int count = mChildrenCount;
+        for (int i = 0; i < count; i++) {
+            final View child = mChildren[i];
+            if (child.isImportantForAutofill()) {
+                list.add(child);
+            } else if (child instanceof ViewGroup) {
+                ((ViewGroup) child).populateChildrenForAutofill(list);
+            }
+        }
+    }
+
     private void dispatchProvideStructureForAssistOrAutoFill(ViewStructure structure,
             boolean forAutoFill) {
         boolean blocked = forAutoFill ? isAutoFillBlocked() : isAssistBlocked();
+        if (blocked || structure.getChildCount() != 0) {
+            return;
+        }
+        final View[] childrenArray;
+        final ArrayList<View> childrenList;
+        final int childrenCount;
 
-        if (!blocked) {
-            if (structure.getChildCount() == 0) {
-                final int childrenCount = getChildCount();
-                if (childrenCount > 0) {
-                    structure.setChildCount(childrenCount);
-                    ArrayList<View> preorderedList = buildOrderedChildList();
-                    boolean customOrder = preorderedList == null
-                            && isChildrenDrawingOrderEnabled();
-                    final View[] children = mChildren;
-                    for (int i=0; i<childrenCount; i++) {
-                        int childIndex;
-                        try {
-                            childIndex = getAndVerifyPreorderedIndex(childrenCount, i, customOrder);
-                        } catch (IndexOutOfBoundsException e) {
-                            childIndex = i;
-                            if (mContext.getApplicationInfo().targetSdkVersion
-                                    < Build.VERSION_CODES.M) {
-                                Log.w(TAG, "Bad getChildDrawingOrder while collecting assist @ "
-                                        + i + " of " + childrenCount, e);
-                                // At least one app is failing when we call getChildDrawingOrder
-                                // at this point, so deal semi-gracefully with it by falling back
-                                // on the basic order.
-                                customOrder = false;
-                                if (i > 0) {
-                                    // If we failed at the first index, there really isn't
-                                    // anything to do -- we will just proceed with the simple
-                                    // sequence order.
-                                    // Otherwise, we failed in the middle, so need to come up
-                                    // with an order for the remaining indices and use that.
-                                    // Failed at the first one, easy peasy.
-                                    int[] permutation = new int[childrenCount];
-                                    SparseBooleanArray usedIndices = new SparseBooleanArray();
-                                    // Go back and collected the indices we have done so far.
-                                    for (int j=0; j<i; j++) {
-                                        permutation[j] = getChildDrawingOrder(childrenCount, j);
-                                        usedIndices.put(permutation[j], true);
-                                    }
-                                    // Fill in the remaining indices with indices that have not
-                                    // yet been used.
-                                    int nextIndex = 0;
-                                    for (int j=i; j<childrenCount; j++) {
-                                        while (usedIndices.get(nextIndex, false)) {
-                                            nextIndex++;
-                                        }
-                                        permutation[j] = nextIndex;
-                                        nextIndex++;
-                                    }
-                                    // Build the final view list.
-                                    preorderedList = new ArrayList<>(childrenCount);
-                                    for (int j=0; j<childrenCount; j++) {
-                                        preorderedList.add(children[permutation[j]]);
-                                    }
+        if (forAutoFill) {
+            childrenArray = null;
+            // TODO(b/33197203): the current algorithm allocates a new list for each children that
+            // is a view group; ideally, we should use mAttachInfo.mTempArrayList instead, but that
+            // would complicated the algorithm a lot...
+            childrenList = getChildrenForAutofill();
+
+            childrenCount = childrenList.size();
+        } else {
+            childrenArray = mChildren;
+            childrenList = null;
+            childrenCount = getChildCount();
+        }
+
+        if (childrenCount > 0) {
+            structure.setChildCount(childrenCount);
+            ArrayList<View> preorderedList = buildOrderedChildList();
+            boolean customOrder = preorderedList == null
+                    && isChildrenDrawingOrderEnabled();
+            for (int i = 0; i < childrenCount; i++) {
+                int childIndex;
+                try {
+                    childIndex = getAndVerifyPreorderedIndex(childrenCount, i, customOrder);
+                } catch (IndexOutOfBoundsException e) {
+                    childIndex = i;
+                    if (mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.M) {
+                        Log.w(TAG, "Bad getChildDrawingOrder while collecting assist @ "
+                                + i + " of " + childrenCount, e);
+                        // At least one app is failing when we call getChildDrawingOrder
+                        // at this point, so deal semi-gracefully with it by falling back
+                        // on the basic order.
+                        customOrder = false;
+                        if (i > 0) {
+                            // If we failed at the first index, there really isn't
+                            // anything to do -- we will just proceed with the simple
+                            // sequence order.
+                            // Otherwise, we failed in the middle, so need to come up
+                            // with an order for the remaining indices and use that.
+                            // Failed at the first one, easy peasy.
+                            int[] permutation = new int[childrenCount];
+                            SparseBooleanArray usedIndices = new SparseBooleanArray();
+                            // Go back and collected the indices we have done so far.
+                            for (int j = 0; j < i; j++) {
+                                permutation[j] = getChildDrawingOrder(childrenCount, j);
+                                usedIndices.put(permutation[j], true);
+                            }
+                            // Fill in the remaining indices with indices that have not
+                            // yet been used.
+                            int nextIndex = 0;
+                            for (int j = i; j < childrenCount; j++) {
+                                while (usedIndices.get(nextIndex, false)) {
+                                    nextIndex++;
                                 }
-                            } else {
-                                throw e;
+                                permutation[j] = nextIndex;
+                                nextIndex++;
+                            }
+                            // Build the final view list.
+                            preorderedList = new ArrayList<>(childrenCount);
+                            for (int j = 0; j < childrenCount; j++) {
+                                final int index = permutation[j];
+                                final View child = forAutoFill
+                                        ? childrenList.get(index)
+                                        : childrenArray[index];
+                                preorderedList.add(child);
                             }
                         }
-
-                        final View child = getAndVerifyPreorderedView(
-                                preorderedList, children, childIndex);
-                        final ViewStructure cstructure = structure.newChild(i);
-
-                        // Must explicitly check which recursive method to call.
-                        if (forAutoFill) {
-                            // NOTE: flags are not currently supported, hence 0
-                            child.dispatchProvideAutoFillStructure(cstructure, 0);
-                        } else {
-                            child.dispatchProvideStructure(cstructure);
-                        }
+                    } else {
+                        throw e;
                     }
-                    if (preorderedList != null) preorderedList.clear();
                 }
+
+                final View child = forAutoFill
+                        ? getAndVerifyPreorderedView(preorderedList, childrenList, childIndex)
+                        : getAndVerifyPreorderedView(preorderedList, childrenArray, childIndex);
+                final ViewStructure cstructure = structure.newChild(i);
+
+                // Must explicitly check which recursive method to call.
+                if (forAutoFill) {
+                    // NOTE: flags are not currently supported, hence 0
+                    child.dispatchProvideAutoFillStructure(cstructure, 0);
+                } else {
+                    child.dispatchProvideStructure(cstructure);
+                }
+            }
+            if (preorderedList != null) {
+                preorderedList.clear();
             }
         }
     }
@@ -3433,6 +3477,21 @@
         return child;
     }
 
+    private static View getAndVerifyPreorderedView(ArrayList<View> preorderedList,
+            ArrayList<View> children, int childIndex) {
+        final View child;
+        if (preorderedList != null) {
+            child = preorderedList.get(childIndex);
+            if (child == null) {
+                throw new RuntimeException("Invalid preorderedList contained null child at index "
+                        + childIndex);
+            }
+        } else {
+            child = children.get(childIndex);
+        }
+        return child;
+    }
+
     /** @hide */
     @Override
     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
@@ -4324,9 +4383,9 @@
      * {@hide}
      */
     @Override
-    protected View findViewTraversal(@IdRes int id) {
+    protected <T extends View> T findViewTraversal(@IdRes int id) {
         if (id == mID) {
-            return this;
+            return (T) this;
         }
 
         final View[] where = mChildren;
@@ -4339,7 +4398,7 @@
                 v = v.findViewById(id);
 
                 if (v != null) {
-                    return v;
+                    return (T) v;
                 }
             }
         }
@@ -4351,9 +4410,9 @@
      * {@hide}
      */
     @Override
-    protected View findViewWithTagTraversal(Object tag) {
+    protected <T extends View> T findViewWithTagTraversal(Object tag) {
         if (tag != null && tag.equals(mTag)) {
-            return this;
+            return (T) this;
         }
 
         final View[] where = mChildren;
@@ -4366,7 +4425,7 @@
                 v = v.findViewWithTag(tag);
 
                 if (v != null) {
-                    return v;
+                    return (T) v;
                 }
             }
         }
@@ -4378,9 +4437,10 @@
      * {@hide}
      */
     @Override
-    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
+    protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
+            View childToSkip) {
         if (predicate.test(this)) {
-            return this;
+            return (T) this;
         }
 
         final View[] where = mChildren;
@@ -4393,7 +4453,7 @@
                 v = v.findViewByPredicate(predicate);
 
                 if (v != null) {
-                    return v;
+                    return (T) v;
                 }
             }
         }
diff --git a/core/java/android/view/ViewParent.java b/core/java/android/view/ViewParent.java
index cc11cb8..1467b69 100644
--- a/core/java/android/view/ViewParent.java
+++ b/core/java/android/view/ViewParent.java
@@ -659,4 +659,17 @@
      * @return true if the action was consumed by this ViewParent
      */
     public boolean onNestedPrePerformAccessibilityAction(View target, int action, Bundle arguments);
+
+    /**
+     * Return the resolved auto-fill mode.
+     *
+     * @return One of {@link View#AUTO_FILL_MODE_AUTO}, {@link View#AUTO_FILL_MODE_MANUAL} if the
+     *         auto-fill mode can be resolved. If the auto-fill mode cannot be resolved
+     *         {@link View#AUTO_FILL_MODE_AUTO}.
+     *
+     * @see View#getResolvedAutoFillMode()
+     */
+    default @View.AutoFillMode int getResolvedAutoFillMode() {
+        return View.AUTO_FILL_MODE_AUTO;
+    }
 }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 6cdd483..20d960f 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -72,6 +72,7 @@
 import android.util.TypedValue;
 import android.view.Surface.OutOfResourcesException;
 import android.view.View.AttachInfo;
+import android.view.View.FocusDirection;
 import android.view.View.MeasureSpec;
 import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
 import android.view.accessibility.AccessibilityEvent;
@@ -887,9 +888,9 @@
                 final boolean hasSurfaceInsets = insets.left != 0 || insets.right != 0
                         || insets.top != 0 || insets.bottom != 0;
                 final boolean translucent = attrs.format != PixelFormat.OPAQUE || hasSurfaceInsets;
-                mAttachInfo.mThreadedRenderer = ThreadedRenderer.create(mContext, translucent);
+                mAttachInfo.mThreadedRenderer = ThreadedRenderer.create(mContext, translucent,
+                        attrs.getTitle().toString());
                 if (mAttachInfo.mThreadedRenderer != null) {
-                    mAttachInfo.mThreadedRenderer.setName(attrs.getTitle().toString());
                     mAttachInfo.mHardwareAccelerated =
                             mAttachInfo.mHardwareAccelerationRequested = true;
                 }
@@ -1047,8 +1048,8 @@
 
         // Get new instance of display based on current display adjustments. It may be updated later
         // if moving between the displays also involved a configuration change.
-        final DisplayAdjustments displayAdjustments = mView.getResources().getDisplayAdjustments();
-        mDisplay = ResourcesManager.getInstance().getAdjustedDisplay(displayId, displayAdjustments);
+        mDisplay = ResourcesManager.getInstance().getAdjustedDisplay(displayId,
+            mView.getResources());
         mAttachInfo.mDisplayState = mDisplay.getState();
         // Internal state updated, now notify the view hierarchy.
         mView.dispatchMovedToDisplay(mDisplay);
@@ -3384,7 +3385,7 @@
             if (force || mLastConfiguration.diff(config) != 0) {
                 // Update the display with new DisplayAdjustments.
                 mDisplay = ResourcesManager.getInstance().getAdjustedDisplay(
-                        mDisplay.getDisplayId(), localResources.getDisplayAdjustments());
+                        mDisplay.getDisplayId(), localResources);
 
                 final int lastLayoutDirection = mLastConfiguration.getLayoutDirection();
                 final int currentLayoutDirection = config.getLayoutDirection();
@@ -4304,11 +4305,11 @@
                 mTranslator.translateEventInScreenToAppWindow(event);
             }
 
-            // Enter touch mode on down or scroll.
+            // Enter touch mode on down or scroll, if it is coming from a touch screen device,
+            // exit otherwise.
             final int action = event.getAction();
-            if (event.isFromSource(InputDevice.SOURCE_TOUCHSCREEN)
-                    && (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_SCROLL)) {
-                ensureTouchMode(true);
+            if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_SCROLL) {
+                ensureTouchMode(event.isFromSource(InputDevice.SOURCE_TOUCHSCREEN));
             }
 
             if (action == MotionEvent.ACTION_DOWN && mAttachInfo.mTooltipHost != null) {
@@ -5975,7 +5976,8 @@
      * {@inheritDoc}
      */
     @Override
-    public View keyboardNavigationClusterSearch(View currentCluster, int direction) {
+    public View keyboardNavigationClusterSearch(View currentCluster,
+            @FocusDirection int direction) {
         checkThread();
         return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
                 mView, currentCluster, direction);
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index 9ce23e6..c7c2bb8 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -31,16 +31,6 @@
 public abstract class ViewStructure {
 
     /**
-     * Flag used when adding virtual views for auto-fill, it indicates the contents of the view
-     * (such as * {@link android.app.assist.AssistStructure.ViewNode#getText()} and
-     * {@link android.app.assist.AssistStructure.ViewNode#getAutoFillValue()})
-     * can be passed to the {@link
-     * android.service.autofill.AutoFillService#onFillRequest(android.app.assist.AssistStructure,
-     * Bundle, android.os.CancellationSignal, android.service.autofill.FillCallback)} call.
-     */
-    public static final int AUTO_FILL_FLAG_SANITIZED = 0x1;
-
-    /**
      * Set the identifier for this view.
      *
      * @param id The view's identifier, as per {@link View#getId View.getId()}.
@@ -268,20 +258,25 @@
     /**
      * Create a new child {@link ViewStructure} in this view, putting into the list of
      * children at <var>index</var>.
+     *
      * @return Returns an fresh {@link ViewStructure} ready to be filled in.
      */
     public abstract ViewStructure newChild(int index);
 
     /**
-     * Like {@link #newChild(int)}, but providing a {@code virtualId} to the child so it can be
-     * auto-filled by {@link View#autoFillVirtual(int, AutoFillValue)}.
+     * Create a new child {@link ViewStructure} in this view for auto-fill purposes.
      *
-     * @param index child index
-     * @param virtualId id identifying the virtual child inside the custom view.
-     * @param flags currently {@code 0} or {@link #AUTO_FILL_FLAG_SANITIZED}.
+     * @param index the index (in the list of children) to put the new child at (see
+     *            {@link #addChildCount(int)} and {@link #setChildCount(int)}.
+     * @param virtualId an opaque ID to the Android System (although it could be meaningful to the
+     *            {@link View} creating the {@link ViewStructure}), but it's the same id used on
+     *            {@link View#autoFillVirtual(int, AutoFillValue)}.
+     * @param flags currently {@code 0}.
+     *
+     * @return Returns an fresh {@link ViewStructure} ready to be filled in.
      */
     // TODO(b/33197203, b/33802548): add CTS/unit test
-    public abstract ViewStructure newChild(int index, int virtualId, int flags);
+    public abstract ViewStructure newChildForAutoFill(int index, int virtualId, int flags);
 
     /**
      * Like {@link #newChild}, but allows the caller to asynchronously populate the returned
@@ -294,35 +289,81 @@
     public abstract ViewStructure asyncNewChild(int index);
 
     /**
-     * Like {@link #asyncNewChild(int)}, but providing a {@code virtualId} to the child so it can be
-     * auto-filled by {@link View#autoFillVirtual(int, AutoFillValue)}.
+     * Like {@link #newChildForAutoFill(int, int, int)}, but allows the caller to asynchronously
+     * populate the returned child.
      *
-     * @param index child index
-     * @param virtualId id identifying the virtual child inside the custom view.
-     * @param flags currently {@code 0} or {@link #AUTO_FILL_FLAG_SANITIZED}.
+     * <p>It can transfer the returned {@link ViewStructure} to another thread for it to build its
+     * content (and children etc).
+     *
+     * <p>Once done, some thread must call {@link #asyncCommit()} to tell the containing
+     * {@link ViewStructure} that the async population is done.
+     *
+     * @param index the index (in the list of children) to put the new child at (see
+     *            {@link #addChildCount(int)} and {@link #setChildCount(int)}.
+     * @param virtualId an opaque ID to the Android System (although it could be meaningful to the
+     *            {@link View} creating the {@link ViewStructure}), but it's the same id used on
+     *            {@link View#autoFillVirtual(int, AutoFillValue)}.
+     * @param flags currently {@code 0}.
+     *
+     * @return Returns an fresh {@link ViewStructure} ready to be filled in.
      */
     // TODO(b/33197203, b/33802548): add CTS/unit test
-    public abstract ViewStructure asyncNewChild(int index, int virtualId, int flags);
+    public abstract ViewStructure asyncNewChildForAutoFill(int index, int virtualId, int flags);
 
     /**
-     * Sets the {@link AutoFillType} that can be used to auto-fill this node.
+     * @deprecated TODO(b/35956626): remove once clients use setAutoFilltype()
      */
-    // TODO(b/33197203, b/33802548): add CTS/unit test
+    @Deprecated
     public abstract void setAutoFillType(AutoFillType info);
 
     /**
+     * Sets the {@link View#getAutofillType()} that can be used to autofill this node.
+     */
+    public abstract void setAutofillType(@View.AutofillType int type);
+
+    /**
+     * Sets the a hint that helps the auto-fill service to select the appropriate data to fill the
+     * view.
+     */
+    // TODO(b/35364993): add CTS/unit test
+    public abstract void setAutoFillHint(@View.AutoFillHint int hint);
+
+    /**
      * Sets the {@link AutoFillValue} representing the current value of this node.
      */
     // TODO(b/33197203, b/33802548): add CTS/unit test
     public abstract void setAutoFillValue(AutoFillValue value);
 
     /**
-     * @hide
+     * Sets the options that can be used to auto-fill this node.
      *
-     * TODO(b/33197203, b/33269702): temporary set it as not sanitized until
-     * AssistStructure automaticaly sets sanitization based on text coming from resources
+     * <p>Typically used by nodes whose {@link AutoFillType} is a list to indicate the meaning of
+     * each possible value in the list.
      */
-    public abstract void setSanitized(boolean sensitive);
+    // TODO(b/33197203, b/33802548): add CTS/unit test
+    public abstract void setAutoFillOptions(String[] options);
+
+    /**
+     * Sets the {@link android.text.InputType} bits of this node.
+     *
+     * @param inputType inputType bits as defined by {@link android.text.InputType}.
+     */
+    public abstract void setInputType(int inputType);
+
+    /**
+     * Marks this node as sanitized so its content are sent on {@link
+     * android.service.autofill.AutoFillService#onFillRequest(android.app.assist.AssistStructure,
+     * Bundle, android.os.CancellationSignal, android.service.autofill.FillCallback)}.
+     *
+     * <p>Only nodes that does not have PII (Personally Identifiable Information - sensitive data
+     * such as email addresses, credit card numbers, passwords, etc...) should be marked
+     * as sanitized; a good rule of thumb is to mark as sanitized nodes whose value were statically
+     * set from resources.
+     *
+     * <p>Should only be set when the node is used for AutoFill purposes - it will be ignored
+     * when used for Assist.
+     */
+    public abstract void setSanitized(boolean sanitized);
 
     /**
      * Call when done populating a {@link ViewStructure} returned by
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 67d7ff8..8094fa6 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -28,6 +28,7 @@
 import android.os.Parcelable;
 import android.text.InputType;
 import android.text.Spannable;
+import android.text.SpannableStringBuilder;
 import android.text.Spanned;
 import android.text.TextUtils;
 import android.text.style.AccessibilityClickableSpan;
@@ -2421,7 +2422,7 @@
             ClickableSpan[] spans =
                     ((Spanned) text).getSpans(0, text.length(), ClickableSpan.class);
             if (spans.length > 0) {
-                Spannable spannable = Spannable.Factory.getInstance().newSpannable(text);
+                Spannable spannable = new SpannableStringBuilder(text);
                 for (int i = 0; i < spans.length; i++) {
                     ClickableSpan span = spans[i];
                     if ((span instanceof AccessibilityClickableSpan)
@@ -3590,6 +3591,7 @@
      * <li><strong>Standard actions</strong> - These are actions that are reported and
      * handled by the standard UI widgets in the platform. For each standard action
      * there is a static constant defined in this class, e.g. {@link #ACTION_FOCUS}.
+     * These actions will have {@code null} labels.
      * </li>
      * <li><strong>Custom actions action</strong> - These are actions that are reported
      * and handled by custom widgets. i.e. ones that are not part of the UI toolkit. For
diff --git a/core/java/android/view/autofill/AutoFillManager.java b/core/java/android/view/autofill/AutoFillManager.java
index f7a1b61..8beaf4e 100644
--- a/core/java/android/view/autofill/AutoFillManager.java
+++ b/core/java/android/view/autofill/AutoFillManager.java
@@ -16,6 +16,12 @@
 
 package android.view.autofill;
 
+import static android.view.autofill.Helper.DEBUG;
+import static android.view.autofill.Helper.VERBOSE;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
@@ -24,10 +30,12 @@
 import android.os.IBinder;
 import android.os.Parcelable;
 import android.os.RemoteException;
-import android.util.ArrayMap;
 import android.util.Log;
 import android.view.View;
+import android.view.WindowManagerGlobal;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.lang.ref.WeakReference;
 import java.util.List;
 
@@ -37,7 +45,6 @@
 // TODO(b/33197203): improve this javadoc
 //TODO(b/33197203): restrict manager calls to activity
 public final class AutoFillManager {
-    private static final boolean DEBUG = false;
 
     private static final String TAG = "AutoFillManager";
 
@@ -69,21 +76,14 @@
     /** @hide */ public static final int FLAG_FOCUS_LOST = 0x4;
     /** @hide */ public static final int FLAG_VALUE_CHANGED = 0x8;
 
-    // These are activities that may have auto-fill UI which are keyed off their tokens.
-    // This is done instead of the activity setting the client in the auto-fill manager
-    // to avoid unnecessary instantiation of the manager and do this only if there is an
-    // auto-fillable focused. This has only the cost of loading the class vs creating an
-    // auto-fill manager for every activity even one that cannot be filled.
-    private static final ArrayMap<IBinder, AutoFillClient> sPendingClients = new ArrayMap<>();
-
     private final Rect mTempRect = new Rect();
 
     private final IAutoFillManager mService;
     private IAutoFillManagerClient mServiceClient;
 
-    private Context mContext;
+    private AutofillCallback mCallback;
 
-    private AutoFillClient mClient;
+    private Context mContext;
 
     private boolean mHasSession;
     private boolean mEnabled;
@@ -105,6 +105,11 @@
          * @param fillInIntent The authentication fill-in intent.
          */
         void authenticate(IntentSender intent, Intent fillInIntent);
+
+        /**
+         * Tells the client this manager has state to be reset.
+         */
+        void resetableStateAvailable();
     }
 
     /**
@@ -116,12 +121,11 @@
     }
 
     /**
-     * Called to indicate the focus on an auto-fillable {@link View} changed.
+     * Called when an auto-fill operation on a {@link View} should start.
      *
-     * @param view view whose focus changed.
-     * @param gainFocus whether focus was gained or lost.
+     * @param view {@link View} that triggered the auto-fill request.
      */
-    public void focusChanged(View view, boolean gainFocus) {
+    public void startAutoFillRequest(@NonNull View view) {
         ensureServiceClientAddedIfNeeded();
 
         if (!mEnabled) {
@@ -134,25 +138,40 @@
         final AutoFillValue value = view.getAutoFillValue();
 
         if (!mHasSession) {
-            if (gainFocus) {
-                // Starts new session.
-                startSession(id, bounds, value);
-            }
+            // Starts new session.
+            startSession(id, view.getWindowToken(), bounds, value);
         } else {
             // Update focus on existing session.
-            updateSession(id, bounds, value, gainFocus ? FLAG_FOCUS_GAINED : FLAG_FOCUS_LOST);
+            updateSession(id, bounds, value, FLAG_FOCUS_GAINED);
         }
     }
 
     /**
-     * Called to indicate the focus on an auto-fillable virtual {@link View} changed.
+     * Called when an auto-fill operation on a {@link View} should stop.
      *
-     * @param parent parent view whose focus changed.
+     * @param view {@link View} that triggered the auto-fill request in
+     *             {@link #startAutoFillRequest(View)}.
+     */
+    public void stopAutoFillRequest(@NonNull View view) {
+        ensureServiceClientAddedIfNeeded();
+
+        if (mEnabled && mHasSession) {
+            final AutoFillId id = getAutoFillId(view);
+
+            // Update focus on existing session.
+            updateSession(id, null, null, FLAG_FOCUS_LOST);
+        }
+    }
+
+    /**
+     * Called when an auto-fill operation on a virtual {@link View} should start.
+     *
+     * @param parent parent of the {@link View} that triggered the auto-fill request.
      * @param childId id identifying the virtual child inside the parent view.
      * @param bounds child boundaries, relative to the top window.
-     * @param gainFocus whether focus was gained or lost.
      */
-    public void virtualFocusChanged(View parent, int childId, Rect bounds, boolean gainFocus) {
+    public void startAutoFillRequestOnVirtualView(@NonNull View parent, int childId,
+            @NonNull Rect bounds) {
         ensureServiceClientAddedIfNeeded();
 
         if (!mEnabled) {
@@ -162,24 +181,38 @@
         final AutoFillId id = getAutoFillId(parent, childId);
 
         if (!mHasSession) {
-            if (gainFocus) {
-                // Starts new session.
-                startSession(id, bounds, null);
-            }
+            // Starts new session.
+            startSession(id, parent.getWindowToken(), bounds, null);
         } else {
             // Update focus on existing session.
-            updateSession(id, bounds, null, gainFocus ? FLAG_FOCUS_GAINED : FLAG_FOCUS_LOST);
+            updateSession(id, bounds, null, FLAG_FOCUS_GAINED);
+        }
+    }
+
+    /**
+     * Called when an auto-fill operation on a virtual {@link View} should stop.
+     *
+     * @param parent parent of the {@link View} that triggered the auto-fill request in
+     *               {@link #startAutoFillRequestOnVirtualView(View, int, Rect)}.
+     * @param childId id identifying the virtual child inside the parent view.
+     */
+    public void stopAutoFillRequestOnVirtualView(@NonNull View parent, int childId) {
+        ensureServiceClientAddedIfNeeded();
+
+        if (mEnabled && mHasSession) {
+            final AutoFillId id = getAutoFillId(parent, childId);
+
+            // Update focus on existing session.
+            updateSession(id, null, null, FLAG_FOCUS_LOST);
         }
     }
 
     /**
      * Called to indicate the value of an auto-fillable {@link View} changed.
      *
-     * @param view view whose focus changed.
+     * @param view view whose value changed.
      */
     public void valueChanged(View view) {
-        ensureServiceClientAddedIfNeeded();
-
         if (!mEnabled || !mHasSession) {
             return;
         }
@@ -198,8 +231,6 @@
      * @param value new value of the child.
      */
     public void virtualValueChanged(View parent, int childId, AutoFillValue value) {
-        ensureServiceClientAddedIfNeeded();
-
         if (!mEnabled || !mHasSession) {
             return;
         }
@@ -215,8 +246,6 @@
      * call this method after the form is submitted and another page is rendered.
      */
     public void reset() {
-        ensureServiceClientAddedIfNeeded();
-
         if (!mEnabled && !mHasSession) {
             return;
         }
@@ -224,35 +253,27 @@
         finishSession();
     }
 
-    /** @hide */
-    public static void addClient(IBinder token, AutoFillClient client) {
-        sPendingClients.put(token, client);
-    }
-
-    /** @hide */
-    public static boolean isClientActive(IBinder token) {
-        return !sPendingClients.containsKey(token);
-    }
-
-    private void activateClient() {
-        mClient = sPendingClients.remove(mContext.getActivityToken());
-    }
-
     private AutoFillClient getClient() {
-        if (mClient == null) {
-            return sPendingClients.get(mContext.getActivityToken());
+        if (mContext instanceof AutoFillClient) {
+            return (AutoFillClient) mContext;
         }
-        return mClient;
+        return null;
     }
 
     /** @hide */
     public void onAuthenticationResult(Intent data) {
+        // TODO(b/33197203): the result code is being ignored, so this method is not reliably
+        // handling the cases where it's not RESULT_OK: it works fine if the service does not
+        // set the EXTRA_AUTHENTICATION_RESULT extra, but it could cause weird results if the
+        // service set the extra and returned RESULT_CANCELED...
+
+        if (DEBUG) Log.d(TAG, "onAuthenticationResult(): d=" + data);
+
         if (data == null) {
             return;
         }
-        Parcelable result = data.getParcelableExtra(
-                EXTRA_AUTHENTICATION_RESULT);
-        Bundle responseData = new Bundle();
+        final Parcelable result = data.getParcelableExtra(EXTRA_AUTHENTICATION_RESULT);
+        final Bundle responseData = new Bundle();
         responseData.putParcelable(EXTRA_AUTHENTICATION_RESULT, result);
         try {
             mService.setAuthenticationResult(responseData,
@@ -262,23 +283,29 @@
         }
     }
 
-    private AutoFillId getAutoFillId(View view) {
+    private static AutoFillId getAutoFillId(View view) {
         return new AutoFillId(view.getAccessibilityViewId());
     }
 
-    private AutoFillId getAutoFillId(View parent, int childId) {
+    private static AutoFillId getAutoFillId(View parent, int childId) {
         return new AutoFillId(parent.getAccessibilityViewId(), childId);
     }
 
-    private void startSession(AutoFillId id, Rect bounds, AutoFillValue value) {
+    private void startSession(AutoFillId id, IBinder windowToken,
+            Rect bounds, AutoFillValue value) {
         if (DEBUG) {
-            Log.v(TAG, "startSession(): id=" + id + ", bounds=" + bounds + ", value=" + value);
+            Log.d(TAG, "startSession(): id=" + id + ", bounds=" + bounds + ", value=" + value);
         }
+
         try {
-            mService.startSession(mContext.getActivityToken(), mServiceClient.asBinder(),
-                    id, bounds, value, mContext.getUserId());
+            mService.startSession(mContext.getActivityToken(), windowToken,
+                    mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(),
+                    mCallback != null);
+            final AutoFillClient client = getClient();
+            if (client != null) {
+                client.resetableStateAvailable();
+            }
             mHasSession = true;
-            activateClient();
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -286,7 +313,7 @@
 
     private void finishSession() {
         if (DEBUG) {
-            Log.v(TAG, "finishSession()");
+            Log.d(TAG, "finishSession()");
         }
         mHasSession = false;
         try {
@@ -298,9 +325,12 @@
 
     private void updateSession(AutoFillId id, Rect bounds, AutoFillValue value, int flags) {
         if (DEBUG) {
-            Log.v(TAG, "updateSession(): id=" + id + ", bounds=" + bounds + ", value=" + value
+            if (VERBOSE || (flags & FLAG_FOCUS_LOST) != 0) {
+                Log.d(TAG, "updateSession(): id=" + id + ", bounds=" + bounds + ", value=" + value
                     + ", flags=" + flags);
+            }
         }
+
         try {
             mService.updateSession(mContext.getActivityToken(), id, bounds, value, flags,
                     mContext.getUserId());
@@ -323,6 +353,119 @@
         }
     }
 
+    /**
+     * Registers a {@link AutofillCallback} to receive autofill events.
+     *
+     * @param callback callback to receive events.
+     */
+    public void registerCallback(@Nullable AutofillCallback callback) {
+        if (callback == null) return;
+
+        final boolean hadCallback = mCallback != null;
+        mCallback = callback;
+
+        if (mHasSession && !hadCallback) {
+            try {
+                mService.setHasCallback(mContext.getActivityToken(), mContext.getUserId(), true);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    /**
+     * Unregisters a {@link AutofillCallback} to receive autofill events.
+     *
+     * @param callback callback to stop receiving events.
+     */
+    public void unregisterCallback(@Nullable AutofillCallback callback) {
+        if (callback == null || mCallback == null || callback != mCallback) return;
+
+        mCallback = null;
+
+        if (mHasSession) {
+            try {
+                mService.setHasCallback(mContext.getActivityToken(), mContext.getUserId(), false);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    private void onAutofillEvent(IBinder windowToken, AutoFillId id, int event) {
+        if (mCallback == null) return;
+        if (id == null) {
+            Log.w(TAG, "onAutofillEvent(): no id for event " + event);
+            return;
+        }
+
+        final View root = WindowManagerGlobal.getInstance().getWindowView(windowToken);
+        if (root == null) {
+            Log.w(TAG, "onAutofillEvent() for " + id + ": root view gone");
+            return;
+        }
+        final View view = root.findViewByAccessibilityIdTraversal(id.getViewId());
+        if (view == null) {
+            Log.w(TAG, "onAutofillEvent() for " + id + ": view gone");
+            return;
+        }
+        if (id.isVirtual()) {
+            mCallback.onAutofillEventVirtual(view, id.getVirtualChildId(), event);
+        } else {
+            mCallback.onAutofillEvent(view, event);
+        }
+    }
+
+    /**
+     * Callback for auto-fill related events.
+     *
+     * <p>Typically used for applications that display their own "auto-complete" views, so they can
+     * enable / disable such views when the auto-fill UI affordance is shown / hidden.
+     */
+    public abstract static class AutofillCallback {
+
+        /** @hide */
+        @IntDef({EVENT_INPUT_SHOWN, EVENT_INPUT_HIDDEN})
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface AutofillEventType {}
+
+        /**
+         * The auto-fill input UI affordance associated with the view was shown.
+         *
+         * <p>If the view provides its own auto-complete UI affordance and its currently shown, it
+         * should be hidden upon receiving this event.
+         */
+        public static final int EVENT_INPUT_SHOWN = 1;
+
+        /**
+         * The auto-fill input UI affordance associated with the view was hidden.
+         *
+         * <p>If the view provides its own auto-complete UI affordance that was hidden upon a
+         * {@link #EVENT_INPUT_SHOWN} event, it could be shown again now.
+         */
+        public static final int EVENT_INPUT_HIDDEN = 2;
+
+        /**
+         * Called after a change in the autofill state associated with a view.
+         *
+         * @param view view associated with the change.
+         *
+         * @param event currently either {@link #EVENT_INPUT_SHOWN} or {@link #EVENT_INPUT_HIDDEN}.
+         */
+        public void onAutofillEvent(@NonNull View view, @AutofillEventType int event) {}
+
+        /**
+         * Called after a change in the autofill state associated with a virtual view.
+         *
+         * @param view parent view associated with the change.
+         * @param childId id identifying the virtual child inside the parent view.
+         *
+         * @param event currently either {@link #EVENT_INPUT_SHOWN} or {@link #EVENT_INPUT_HIDDEN}.
+         */
+        public void onAutofillEventVirtual(@NonNull View view, int childId,
+                @AutofillEventType int event) {}
+    }
+
     private static final class AutoFillManagerClient extends IAutoFillManagerClient.Stub {
         private final WeakReference<AutoFillManager> mAutoFillManager;
 
@@ -364,5 +507,17 @@
                 });
             }
         }
+
+        @Override
+        public void onAutofillEvent(IBinder windowToken, AutoFillId id, int event) {
+            final AutoFillManager autoFillManager = mAutoFillManager.get();
+            if (autoFillManager != null) {
+                autoFillManager.mContext.getMainThreadHandler().post(() -> {
+                    if (autoFillManager.getClient() != null) {
+                        autoFillManager.onAutofillEvent(windowToken, id, event);
+                    }
+                });
+            }
+        }
     }
 }
diff --git a/core/java/android/view/autofill/AutoFillType.aidl b/core/java/android/view/autofill/AutoFillType.aidl
index a63d7c5..4606b48 100644
--- a/core/java/android/view/autofill/AutoFillType.aidl
+++ b/core/java/android/view/autofill/AutoFillType.aidl
@@ -16,4 +16,7 @@
 
 package android.view.autofill;
 
+/*
+ * TODO(b/35956626): remove once clients use getAutoFilltype()
+ */
 parcelable AutoFillType;
\ No newline at end of file
diff --git a/core/java/android/view/autofill/AutoFillType.java b/core/java/android/view/autofill/AutoFillType.java
index 017f7f8..37966b2 100644
--- a/core/java/android/view/autofill/AutoFillType.java
+++ b/core/java/android/view/autofill/AutoFillType.java
@@ -21,16 +21,13 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.view.View;
-import android.widget.TextView;
 
 /**
  * Defines the type of a object that can be used to auto-fill a {@link View} so the
  * {@link android.service.autofill.AutoFillService} can use the proper {@link AutoFillValue} to
  * fill it.
  *
- * <p>Some {@link AutoFillType}s can have an optional {@code sub-type}: the
- * main {@code type} defines the view's UI control category (like a text field), while the optional
- * {@code sub-type} define its semantics (like a postal address).
+ * TODO(b/35956626): remove once clients use getAutoFilltype
  */
 public final class AutoFillType implements Parcelable {
 
@@ -38,39 +35,29 @@
     // class idiom" (Effective Java, Item 71) to avoid memory utilization when auto-fill is not
     // enabled.
     private static class DefaultTypesHolder {
-        static final AutoFillType TOGGLE = new AutoFillType(TYPE_TOGGLE, 0);
-        static final AutoFillType LIST = new AutoFillType(TYPE_LIST, 0);
+        static final AutoFillType TEXT = new AutoFillType(TYPE_TEXT);
+        static final AutoFillType TOGGLE = new AutoFillType(TYPE_TOGGLE);
+        static final AutoFillType LIST = new AutoFillType(TYPE_LIST);
+        static final AutoFillType DATE = new AutoFillType(TYPE_DATE);
     }
 
     private static final int TYPE_TEXT = 1;
     private static final int TYPE_TOGGLE = 2;
-    // TODO(b/33197203): make sure it works with Spinners and/or add a new type for them
-    // (since they're often used for credit card selection)
     private static final int TYPE_LIST = 3;
-
-    // TODO(b/33197203): add others, like date picker? That would be trick, because they're set as:
-    // updateDate(int year, int month, int dayOfMonth)
-    // So, we would have to either use a long representing the Date.time(), or a custom long
-    // representing:
-    // year * 10000 + month * 100 + day
-    // Then a custom getDatePickerValue(Bundle) that returns an immutable object with these 3 fields
+    private static final int TYPE_DATE = 4;
 
     private final int mType;
-    private final int mSubType;
 
-    private AutoFillType(int type, int subType) {
+    private AutoFillType(int type) {
         mType = type;
-        mSubType = subType;
     }
 
     /**
      * Checks if this is a type for a text field, which is filled by a {@link CharSequence}.
      *
      * <p>{@link AutoFillValue} instances for auto-filling a {@link View} can be obtained through
-     * {@link AutoFillValue#forText(CharSequence)}, and the value of a bundle passed to auto-fill a
+     * {@link AutoFillValue#forText(CharSequence)}, and the value passed to auto-fill a
      * {@link View} can be fetched through {@link AutoFillValue#getTextValue()}.
-     *
-     * <p>Sub-type for this type is the value defined by {@link TextView#getInputType()}.
      */
     public boolean isText() {
         return mType == TYPE_TEXT;
@@ -80,10 +67,8 @@
      * Checks if this is a a type for a togglable field, which is filled by a {@code boolean}.
      *
      * <p>{@link AutoFillValue} instances for auto-filling a {@link View} can be obtained through
-     * {@link AutoFillValue#forToggle(boolean)}, and the value of a bundle passed to auto-fill a
+     * {@link AutoFillValue#forToggle(boolean)}, and the value passed to auto-fill a
      * {@link View} can be fetched through {@link AutoFillValue#getToggleValue()}.
-     *
-     * <p>This type has no sub-types.
      */
     public boolean isToggle() {
         return mType == TYPE_TOGGLE;
@@ -94,23 +79,27 @@
      * representing the element index inside the list (starting at {@code 0}.
      *
      * <p>{@link AutoFillValue} instances for auto-filling a {@link View} can be obtained through
-     * {@link AutoFillValue#forList(int)}, and the value of a bundle passed to auto-fill a
+     * {@link AutoFillValue#forList(int)}, and the value passed to auto-fill a
      * {@link View} can be fetched through {@link AutoFillValue#getListValue()}.
      *
-     * <p>This type has no sub-types.
+     * <p>The available options in the selection list are typically provided by
+     * {@link android.app.assist.AssistStructure.ViewNode#getAutoFillOptions()}.
      */
     public boolean isList() {
         return mType == TYPE_LIST;
     }
 
-
     /**
-     * Gets the optional sub-type, representing the {@link View}'s semantic.
+     * Checks if this is a type for a date and time, which is represented by a long representing
+     * the number of milliseconds since the standard base time known as "the epoch", namely
+     * January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}.
      *
-     * @return {@code 0} if type does not support sub-types.
+     * <p>{@link AutoFillValue} instances for auto-filling a {@link View} can be obtained through
+     * {@link AutoFillValue#forDate(long)}, and the values passed to
+     * auto-fill a {@link View} can be fetched through {@link AutoFillValue#getDateValue()}.
      */
-    public int getSubType() {
-        return mSubType;
+    public boolean isDate() {
+        return mType == TYPE_DATE;
     }
 
     /////////////////////////////////////
@@ -121,14 +110,13 @@
     public String toString() {
         if (!DEBUG) return super.toString();
 
-        return "AutoFillType [type=" + mType + ", subType=" + mSubType + "]";
+        return "AutoFillType [type=" + mType + "]";
     }
 
     @Override
     public int hashCode() {
         final int prime = 31;
         int result = 1;
-        result = prime * result + mSubType;
         result = prime * result + mType;
         return result;
     }
@@ -139,7 +127,6 @@
         if (obj == null) return false;
         if (getClass() != obj.getClass()) return false;
         final AutoFillType other = (AutoFillType) obj;
-        if (mSubType != other.mSubType) return false;
         if (mType != other.mType) return false;
         return true;
     }
@@ -156,12 +143,10 @@
     @Override
     public void writeToParcel(Parcel parcel, int flags) {
         parcel.writeInt(mType);
-        parcel.writeInt(mSubType);
     }
 
     private AutoFillType(Parcel parcel) {
         mType = parcel.readInt();
-        mSubType = parcel.readInt();
     }
 
     public static final Parcelable.Creator<AutoFillType> CREATOR =
@@ -186,8 +171,8 @@
      *
      * <p>See {@link #isText()} for more info.
      */
-    public static AutoFillType forText(int inputType) {
-        return new AutoFillType(TYPE_TEXT, inputType);
+    public static AutoFillType forText() {
+        return DefaultTypesHolder.TEXT;
     }
 
     /**
@@ -208,4 +193,13 @@
     public static AutoFillType forList() {
         return DefaultTypesHolder.LIST;
     }
+
+    /**
+     * Creates a type that represents a date.
+     *
+     * <p>See {@link #isDate()} for more info.
+     */
+    public static AutoFillType forDate() {
+        return DefaultTypesHolder.DATE;
+    }
 }
diff --git a/core/java/android/view/autofill/AutoFillValue.java b/core/java/android/view/autofill/AutoFillValue.java
index af70361..11fab68 100644
--- a/core/java/android/view/autofill/AutoFillValue.java
+++ b/core/java/android/view/autofill/AutoFillValue.java
@@ -32,44 +32,54 @@
  * {@code sub-type} define its semantics (like a postal address).
  */
 public final class AutoFillValue implements Parcelable {
-
     private final String mText;
     private final int mListIndex;
     private final boolean mToggle;
+    private final long mDate;
 
-    private AutoFillValue(CharSequence text, int listIndex, boolean toggle) {
+    private AutoFillValue(CharSequence text, int listIndex, boolean toggle, long date) {
         mText = (text == null) ? null : text.toString();
         mListIndex = listIndex;
         mToggle = toggle;
+        mDate = date;
     }
 
     /**
-     * Gets the value to auto-fill a text field.
+     * Gets the value to autofill a text field.
      *
-     * <p>See {@link AutoFillType#isText()} for more info.
+     * <p>See {@link View#AUTOFILL_TYPE_TEXT} for more info.
      */
     public CharSequence getTextValue() {
         return mText;
     }
 
     /**
-     * Gets the value to auto-fill a toggable field.
+     * Gets the value to autofill a toggable field.
      *
-     * <p>See {@link AutoFillType#isToggle()} for more info.
+     * <p>See {@link View#AUTOFILL_TYPE_TOGGLE} for more info.
      */
     public boolean getToggleValue() {
         return mToggle;
     }
 
     /**
-     * Gets the value to auto-fill a selection list field.
+     * Gets the value to autofill a selection list field.
      *
-     * <p>See {@link AutoFillType#isList()} for more info.
+     * <p>See {@link View#AUTOFILL_TYPE_LIST} for more info.
      */
     public int getListValue() {
         return mListIndex;
     }
 
+    /**
+     * Gets the value to autofill a date field.
+     *
+     * <p>See {@link View#AUTOFILL_TYPE_DATE} for more info.
+     */
+    public long getDateValue() {
+        return mDate;
+    }
+
     /////////////////////////////////////
     //  Object "contract" methods. //
     /////////////////////////////////////
@@ -78,9 +88,10 @@
     public int hashCode() {
         final int prime = 31;
         int result = 1;
-        result = prime * result + mListIndex;
         result = prime * result + ((mText == null) ? 0 : mText.hashCode());
+        result = prime * result + mListIndex;
         result = prime * result + (mToggle ? 1231 : 1237);
+        result = prime * result + (int) (mDate ^ (mDate >>> 32));
         return result;
     }
 
@@ -90,16 +101,23 @@
         if (obj == null) return false;
         if (getClass() != obj.getClass()) return false;
         final AutoFillValue other = (AutoFillValue) obj;
-        if (mListIndex != other.mListIndex) return false;
         if (mText == null) {
             if (other.mText != null) return false;
         } else {
             if (!mText.equals(other.mText)) return false;
         }
+        if (mListIndex != other.mListIndex) return false;
         if (mToggle != other.mToggle) return false;
+        if (mDate != other.mDate) return false;
         return true;
     }
 
+    /** @hide */
+    public String coerceToString() {
+        // TODO(b/33197203): How can we filter on toggles or list values?
+        return mText;
+    }
+
     @Override
     public String toString() {
         if (!DEBUG) return super.toString();
@@ -108,7 +126,7 @@
             return mText.length() + "_chars";
         }
 
-        return "[listIndex=" + mListIndex + ", toggle=" + mToggle + "]";
+        return "[l=" + mListIndex + ", t=" + mToggle + ", d=" + mDate + "]";
     }
 
     /////////////////////////////////////
@@ -125,12 +143,14 @@
         parcel.writeString(mText);
         parcel.writeInt(mListIndex);
         parcel.writeInt(mToggle ? 1 : 0);
+        parcel.writeLong(mDate);
     }
 
     private AutoFillValue(Parcel parcel) {
         mText = parcel.readString();
         mListIndex = parcel.readInt();
         mToggle = parcel.readInt() == 1;
+        mDate = parcel.readLong();
     }
 
     public static final Parcelable.Creator<AutoFillValue> CREATOR =
@@ -152,31 +172,42 @@
 
     // TODO(b/33197203): add unit tests for each supported type (new / get should return same value)
     /**
-     * Creates a new {@link AutoFillValue} to auto-fill a text field.
+     * Creates a new {@link AutoFillValue} to autofill a {@link View} representing a text field.
      *
-     * <p>See {@link AutoFillType#isText()} for more info.
+     * <p>See {@link View#AUTOFILL_TYPE_TEXT} for more info.
      */
     // TODO(b/33197203): use cache
     @Nullable
     public static AutoFillValue forText(@Nullable CharSequence value) {
-        return value == null ? null : new AutoFillValue(value, 0, false);
+        return value == null ? null : new AutoFillValue(value, 0, false, 0);
     }
 
     /**
-     * Creates a new {@link AutoFillValue} to auto-fill a toggable field.
+     * Creates a new {@link AutoFillValue} to autofill a {@link View} representing a toggable
+     * field.
      *
-     * <p>See {@link AutoFillType#isToggle()} for more info.
+     * <p>See {@link View#AUTOFILL_TYPE_TOGGLE} for more info.
      */
     public static AutoFillValue forToggle(boolean value) {
-        return new AutoFillValue(null, 0, value);
+        return new AutoFillValue(null, 0, value, 0);
     }
 
     /**
-     * Creates a new {@link AutoFillValue} to auto-fill a selection list field.
+     * Creates a new {@link AutoFillValue} to autofill a {@link View} representing a selection
+     * list.
      *
-     * <p>See {@link AutoFillType#isList()} for more info.
+     * <p>See {@link View#AUTOFILL_TYPE_LIST} for more info.
      */
     public static AutoFillValue forList(int value) {
-        return new AutoFillValue(null, value, false);
+        return new AutoFillValue(null, value, false, 0);
+    }
+
+    /**
+     * Creates a new {@link AutoFillValue} to autofill a {@link View} representing a date.
+     *
+     * <p>See {@link View#AUTOFILL_TYPE_DATE} for more info.
+     */
+    public static AutoFillValue forDate(long date) {
+        return new AutoFillValue(null, 0, false, date);
     }
 }
diff --git a/core/java/android/view/autofill/Helper.java b/core/java/android/view/autofill/Helper.java
index b1c9efa..aa94de0 100644
--- a/core/java/android/view/autofill/Helper.java
+++ b/core/java/android/view/autofill/Helper.java
@@ -25,9 +25,9 @@
 /** @hide */
 public final class Helper {
 
-    static final boolean DEBUG = true; // TODO(b/33197203): set to false when stable
-    static final boolean VERBOSE = false;
-    static final String REDACTED = "[REDACTED]";
+    public static final boolean DEBUG = true; // TODO(b/33197203): set to false when stable
+    public static final boolean VERBOSE = false;
+    public static final String REDACTED = "[REDACTED]";
 
     static StringBuilder append(StringBuilder builder, Bundle bundle) {
         if (bundle == null) {
diff --git a/core/java/android/view/autofill/IAutoFillManager.aidl b/core/java/android/view/autofill/IAutoFillManager.aidl
index 0433a8f..b36c0f1 100644
--- a/core/java/android/view/autofill/IAutoFillManager.aidl
+++ b/core/java/android/view/autofill/IAutoFillManager.aidl
@@ -30,11 +30,13 @@
  */
 interface IAutoFillManager {
     boolean addClient(in IAutoFillManagerClient client, int userId);
-    oneway void startSession(in IBinder activityToken, in IBinder appCallback,
-            in AutoFillId autoFillId, in Rect bounds, in AutoFillValue value, int userId);
+    oneway void startSession(in IBinder activityToken, IBinder windowToken, in IBinder appCallback,
+            in AutoFillId autoFillId, in Rect bounds, in AutoFillValue value, int userId,
+            boolean hasCallback);
     oneway void updateSession(in IBinder activityToken, in AutoFillId id, in Rect bounds,
             in AutoFillValue value, int flags, int userId);
     oneway void finishSession(in IBinder activityToken, int userId);
     oneway void setAuthenticationResult(in Bundle data,
             in IBinder activityToken, int userId);
+    oneway void setHasCallback(in IBinder activityToken, int userId, boolean hasIt);
 }
diff --git a/core/java/android/view/autofill/IAutoFillManagerClient.aidl b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
index 45f363d..9eef7d0 100644
--- a/core/java/android/view/autofill/IAutoFillManagerClient.aidl
+++ b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
@@ -20,6 +20,7 @@
 
 import android.content.Intent;
 import android.content.IntentSender;
+import android.os.IBinder;
 import android.view.autofill.AutoFillId;
 import android.view.autofill.AutoFillValue;
 
@@ -43,4 +44,9 @@
       * Authenticates a fill response or a data set.
       */
     void authenticate(in IntentSender intent, in Intent fillInIntent);
+
+    /**
+     * Notifies the client when the auto-fill UI changed.
+     */
+    void onAutofillEvent(in IBinder windowToken, in AutoFillId id, int event);
 }
diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java
index 791543e..46f7a81 100644
--- a/core/java/android/view/textclassifier/TextClassifier.java
+++ b/core/java/android/view/textclassifier/TextClassifier.java
@@ -18,7 +18,9 @@
 
 import android.annotation.IntRange;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.StringDef;
+import android.os.LocaleList;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -51,20 +53,43 @@
 
         @Override
         public TextSelection suggestSelection(
-                CharSequence text, int selectionStartIndex, int selectionEndIndex) {
+                CharSequence text,
+                int selectionStartIndex,
+                int selectionEndIndex,
+                LocaleList defaultLocales) {
             return new TextSelection.Builder(selectionStartIndex, selectionEndIndex).build();
         }
 
         @Override
         public TextClassificationResult getTextClassificationResult(
-                CharSequence text, int startIndex, int endIndex) {
+                CharSequence text, int startIndex, int endIndex, LocaleList defaultLocales) {
             return TextClassificationResult.EMPTY;
         }
 
         @Override
-        public LinksInfo getLinks(CharSequence text, int linkMask) {
+        public LinksInfo getLinks(CharSequence text, int linkMask, LocaleList defaultLocales) {
             return LinksInfo.NO_OP;
         }
+
+        // TODO: Remove
+        @Override
+        public TextSelection suggestSelection(
+                CharSequence text, int selectionStartIndex, int selectionEndIndex) {
+            throw new UnsupportedOperationException("Removed");
+        }
+
+        // TODO: Remove
+        @Override
+        public TextClassificationResult getTextClassificationResult(
+                CharSequence text, int startIndex, int endIndex) {
+            throw new UnsupportedOperationException("Removed");
+        }
+
+        // TODO: Remove
+        @Override
+        public LinksInfo getLinks(CharSequence text, int linkMask) {
+            throw new UnsupportedOperationException("Removed");
+        }
     };
 
     /**
@@ -75,15 +100,20 @@
      *      by the sub sequence starting at selectionStartIndex and ending at selectionEndIndex)
      * @param selectionStartIndex start index of the selected part of text
      * @param selectionEndIndex end index of the selected part of text
+     * @param defaultLocales ordered list of locale preferences that can be used to disambiguate
+     *      the provided text. If no locale preferences exist, set this to null or an empty locale
+     *      list in which case the classifier will decide whether to use no locale information, use
+     *      a default locale, or use the system default.
      *
      * @throws IllegalArgumentException if text is null; selectionStartIndex is negative;
-     *      selectionEndIndex is greater than text.length() or less than selectionStartIndex
+     *      selectionEndIndex is greater than text.length() or not greater than selectionStartIndex
      */
     @NonNull
     TextSelection suggestSelection(
             @NonNull CharSequence text,
             @IntRange(from = 0) int selectionStartIndex,
-            @IntRange(from = 0) int selectionEndIndex);
+            @IntRange(from = 0) int selectionEndIndex,
+            @Nullable LocaleList defaultLocales);
 
     /**
      * Returns a {@link TextClassificationResult} object that can be used to generate a widget for
@@ -93,13 +123,20 @@
      *      by the sub sequence starting at startIndex and ending at endIndex)
      * @param startIndex start index of the text to classify
      * @param endIndex end index of the text to classify
+     * @param defaultLocales ordered list of locale preferences that can be used to disambiguate
+     *      the provided text. If no locale preferences exist, set this to null or an empty locale
+     *      list in which case the classifier will decide whether to use no locale information, use
+     *      a default locale, or use the system default.
      *
      * @throws IllegalArgumentException if text is null; startIndex is negative;
-     *      endIndex is greater than text.length() or less than startIndex
+     *      endIndex is greater than text.length() or not greater than startIndex
      */
     @NonNull
     TextClassificationResult getTextClassificationResult(
-            @NonNull CharSequence text, int startIndex, int endIndex);
+            @NonNull CharSequence text,
+            @IntRange(from = 0) int startIndex,
+            @IntRange(from = 0) int endIndex,
+            @Nullable LocaleList defaultLocales);
 
     /**
      * Returns a {@link LinksInfo} that may be applied to the text to annotate it with links
@@ -108,8 +145,25 @@
      * @param text the text to generate annotations for
      * @param linkMask See {@link android.text.util.Linkify} for a list of linkMasks that may be
      *      specified. Subclasses of this interface may specify additional linkMasks
+     * @param defaultLocales  ordered list of locale preferences that can be used to disambiguate
+     *      the provided text. If no locale preferences exist, set this to null or an empty locale
+     *      list in which case the classifier will decide whether to use no locale information, use
+     *      a default locale, or use the system default.
      *
      * @throws IllegalArgumentException if text is null
      */
-    LinksInfo getLinks(@NonNull CharSequence text, int linkMask);
+    LinksInfo getLinks(
+            @NonNull CharSequence text, int linkMask, @Nullable LocaleList defaultLocales);
+
+    // TODO: Remove
+    /** @removed */
+    TextSelection suggestSelection(
+            CharSequence text, int selectionStartIndex, int selectionEndIndex);
+    // TODO: Remove
+    /** @removed */
+    TextClassificationResult getTextClassificationResult(
+            CharSequence text, int startIndex, int endIndex);
+    // TODO: Remove
+    /** @removed */
+    LinksInfo getLinks(CharSequence text, int linkMask);
 }
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 97a36fd..0486f9f 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -26,6 +26,7 @@
 import android.graphics.drawable.Drawable;
 import android.icu.text.BreakIterator;
 import android.net.Uri;
+import android.os.LocaleList;
 import android.os.ParcelFileDescriptor;
 import android.provider.Browser;
 import android.text.Spannable;
@@ -74,7 +75,8 @@
 
     @Override
     public TextSelection suggestSelection(
-            @NonNull CharSequence text, int selectionStartIndex, int selectionEndIndex) {
+            @NonNull CharSequence text, int selectionStartIndex, int selectionEndIndex,
+            LocaleList defaultLocales) {
         validateInput(text, selectionStartIndex, selectionEndIndex);
         try {
             if (text.length() > 0) {
@@ -101,12 +103,12 @@
         }
         // Getting here means something went wrong, return a NO_OP result.
         return TextClassifier.NO_OP.suggestSelection(
-                text, selectionStartIndex, selectionEndIndex);
+                text, selectionStartIndex, selectionEndIndex, defaultLocales);
     }
 
     @Override
     public TextClassificationResult getTextClassificationResult(
-            @NonNull CharSequence text, int startIndex, int endIndex) {
+            @NonNull CharSequence text, int startIndex, int endIndex, LocaleList defaultLocales) {
         validateInput(text, startIndex, endIndex);
         try {
             if (text.length() > 0) {
@@ -125,11 +127,12 @@
             Log.e(LOG_TAG, "Error getting assist info.", t);
         }
         // Getting here means something went wrong, return a NO_OP result.
-        return TextClassifier.NO_OP.getTextClassificationResult(text, startIndex, endIndex);
+        return TextClassifier.NO_OP.getTextClassificationResult(
+                text, startIndex, endIndex, defaultLocales);
     }
 
     @Override
-    public LinksInfo getLinks(CharSequence text, int linkMask) {
+    public LinksInfo getLinks(CharSequence text, int linkMask, LocaleList defaultLocales) {
         Preconditions.checkArgument(text != null);
         try {
             return LinksInfoFactory.create(
@@ -139,7 +142,27 @@
             Log.e(LOG_TAG, "Error getting links info.", t);
         }
         // Getting here means something went wrong, return a NO_OP result.
-        return TextClassifier.NO_OP.getLinks(text, linkMask);
+        return TextClassifier.NO_OP.getLinks(text, linkMask, defaultLocales);
+    }
+
+    // TODO: Remove
+    @Override
+    public TextSelection suggestSelection(
+            CharSequence text, int selectionStartIndex, int selectionEndIndex) {
+        throw new UnsupportedOperationException("Removed");
+    }
+
+    // TODO: Remove
+    @Override
+    public TextClassificationResult getTextClassificationResult(
+            CharSequence text, int startIndex, int endIndex) {
+        throw new UnsupportedOperationException("Removed");
+    }
+
+    // TODO: Remove
+    @Override
+    public LinksInfo getLinks(CharSequence text, int linkMask) {
+        throw new UnsupportedOperationException("Removed");
     }
 
     private SmartSelection getSmartSelection() throws FileNotFoundException {
@@ -195,13 +218,13 @@
 
     /**
      * @throws IllegalArgumentException if text is null; startIndex is negative;
-     *      endIndex is greater than text.length() or less than startIndex
+     *      endIndex is greater than text.length() or is not greater than startIndex
      */
     private static void validateInput(@NonNull CharSequence text, int startIndex, int endIndex) {
         Preconditions.checkArgument(text != null);
         Preconditions.checkArgument(startIndex >= 0);
         Preconditions.checkArgument(endIndex <= text.length());
-        Preconditions.checkArgument(endIndex >= startIndex);
+        Preconditions.checkArgument(endIndex > startIndex);
     }
 
     /**
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 1e7cddf..3fbeb03 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -630,6 +630,12 @@
     protected WebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes,
             Map<String, Object> javaScriptInterfaces, boolean privateBrowsing) {
         super(context, attrs, defStyleAttr, defStyleRes);
+
+        // WebView is important by default, unless app developer overrode attribute.
+        if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
+            setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
+        }
+
         if (context == null) {
             throw new IllegalArgumentException("Invalid context argument");
         }
@@ -2784,6 +2790,10 @@
      * package that was used to load it. Otherwise, the package that would be used if the WebView
      * was loaded right now will be returned; this does not cause WebView to be loaded, so this
      * information may become outdated at any time.
+     * The WebView package changes either when the current WebView package is updated, disabled, or
+     * uninstalled. It can also be changed through a Developer Setting.
+     * If the WebView package changes, any app process that has loaded WebView will be killed. The
+     * next time the app starts and loads WebView it will use the new WebView package instead.
      * @return the current WebView package, or null if there is none.
      */
     public static PackageInfo getCurrentWebViewPackage() {
diff --git a/core/java/android/webkit/WebViewZygote.java b/core/java/android/webkit/WebViewZygote.java
index 2d6f443..f9d7332 100644
--- a/core/java/android/webkit/WebViewZygote.java
+++ b/core/java/android/webkit/WebViewZygote.java
@@ -176,7 +176,7 @@
             // paths and pass them to the zygote as strings.
             final List<String> zipPaths = new ArrayList<>(10);
             final List<String> libPaths = new ArrayList<>(10);
-            LoadedApk.makePaths(null, sPackage.applicationInfo, zipPaths, libPaths);
+            LoadedApk.makePaths(null, false, sPackage.applicationInfo, zipPaths, libPaths);
             final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths);
             final String zip = (zipPaths.size() == 1) ? zipPaths.get(0) :
                     TextUtils.join(File.pathSeparator, zipPaths);
diff --git a/core/java/android/widget/AbsSpinner.java b/core/java/android/widget/AbsSpinner.java
index bc3dfff..e6cd566 100644
--- a/core/java/android/widget/AbsSpinner.java
+++ b/core/java/android/widget/AbsSpinner.java
@@ -26,6 +26,8 @@
 import android.util.SparseArray;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewStructure;
+import android.view.autofill.AutoFillValue;
 
 import com.android.internal.R;
 
@@ -68,6 +70,12 @@
 
     public AbsSpinner(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
+
+        // Spinner is important by default, unless app developer overrode attribute.
+        if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
+            setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
+        }
+
         initAbsSpinner();
 
         final TypedArray a = context.obtainStyledAttributes(
@@ -480,4 +488,43 @@
     public CharSequence getAccessibilityClassName() {
         return AbsSpinner.class.getName();
     }
+
+    // TODO(b/33197203): add unit/CTS tests for auto-fill methods (and make sure they handle enable)
+
+    @Override
+    public void onProvideAutoFillStructure(ViewStructure structure, int flags) {
+        super.onProvideAutoFillStructure(structure, flags);
+
+        if (getAdapter() == null) return;
+
+        // TODO(b/33197203): implement sanitization so initial value is only sanitized when coming
+        // from resources.
+
+        final int count = getAdapter().getCount();
+        if (count > 0) {
+            final String[] options = new String[count];
+            for (int i = 0; i < count; i++) {
+                options[i] = getAdapter().getItem(i).toString();
+            }
+            structure.setAutoFillOptions(options);
+        }
+    }
+
+    @Override
+    public void autoFill(AutoFillValue value) {
+        if (!isEnabled()) return;
+
+        final int position = value.getListValue();
+        setSelection(position);
+    }
+
+    @Override
+    public @AutofillType int getAutofillType() {
+        return isEnabled() ? AUTOFILL_TYPE_LIST : AUTOFILL_TYPE_NONE;
+    }
+
+    @Override
+    public AutoFillValue getAutoFillValue() {
+        return isEnabled() ? AutoFillValue.forList(getSelectedItemPosition()) : null;
+    }
 }
diff --git a/core/java/android/widget/ActivityChooserView.java b/core/java/android/widget/ActivityChooserView.java
index 51587a7..9a39a17 100644
--- a/core/java/android/widget/ActivityChooserView.java
+++ b/core/java/android/widget/ActivityChooserView.java
@@ -250,7 +250,7 @@
         mDefaultActivityButton = (FrameLayout) findViewById(R.id.default_activity_button);
         mDefaultActivityButton.setOnClickListener(mCallbacks);
         mDefaultActivityButton.setOnLongClickListener(mCallbacks);
-        mDefaultActivityButtonImage = (ImageView) mDefaultActivityButton.findViewById(R.id.image);
+        mDefaultActivityButtonImage = mDefaultActivityButton.findViewById(R.id.image);
 
         final FrameLayout expandButton = (FrameLayout) findViewById(R.id.expand_activities_button);
         expandButton.setOnClickListener(mCallbacks);
@@ -282,7 +282,7 @@
         mExpandActivityOverflowButton = expandButton;
 
         mExpandActivityOverflowButtonImage =
-            (ImageView) expandButton.findViewById(R.id.image);
+            expandButton.findViewById(R.id.image);
         mExpandActivityOverflowButtonImage.setImageDrawable(expandActivityOverflowButtonDrawable);
 
         mAdapter = new ActivityChooserViewAdapter();
@@ -760,7 +760,7 @@
                         convertView = LayoutInflater.from(getContext()).inflate(
                                 R.layout.activity_chooser_view_list_item, parent, false);
                         convertView.setId(ITEM_VIEW_TYPE_FOOTER);
-                        TextView titleView = (TextView) convertView.findViewById(R.id.title);
+                        TextView titleView = convertView.findViewById(R.id.title);
                         titleView.setText(mContext.getString(
                                 R.string.activity_chooser_view_see_all));
                     }
@@ -772,11 +772,11 @@
                     }
                     PackageManager packageManager = mContext.getPackageManager();
                     // Set the icon
-                    ImageView iconView = (ImageView) convertView.findViewById(R.id.icon);
+                    ImageView iconView = convertView.findViewById(R.id.icon);
                     ResolveInfo activity = (ResolveInfo) getItem(position);
                     iconView.setImageDrawable(activity.loadIcon(packageManager));
                     // Set the title.
-                    TextView titleView = (TextView) convertView.findViewById(R.id.title);
+                    TextView titleView = convertView.findViewById(R.id.title);
                     titleView.setText(activity.loadLabel(packageManager));
                     // Highlight the default.
                     if (mShowDefaultActivity && position == 0 && mHighlightDefaultActivity) {
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index 2cfefba..0b3cff1 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -34,6 +34,7 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.autofill.AutoFillManager;
 
 /**
  * An AdapterView is a view whose children are determined by an {@link Adapter}.
@@ -914,6 +915,11 @@
                 dispatchOnItemSelected();
             }
         }
+        // Always notify AutoFillManager - it will return right away if auto-fill is disabled.
+        final AutoFillManager afm = mContext.getSystemService(AutoFillManager.class);
+        if (afm != null) {
+            afm.valueChanged(this);
+        }
     }
 
     private void dispatchOnItemSelected() {
diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java
index 68e6809..06d4868 100644
--- a/core/java/android/widget/AppSecurityPermissions.java
+++ b/core/java/android/widget/AppSecurityPermissions.java
@@ -451,7 +451,7 @@
 
     private View getPermissionsView(int which, boolean showRevokeUI) {
         LinearLayout permsView = (LinearLayout) mInflater.inflate(R.layout.app_perms_summary, null);
-        LinearLayout displayList = (LinearLayout) permsView.findViewById(R.id.perms_list);
+        LinearLayout displayList = permsView.findViewById(R.id.perms_list);
         View noPermsView = permsView.findViewById(R.id.no_permissions);
 
         displayPermissions(mPermGroupsList, displayList, which, showRevokeUI);
@@ -517,8 +517,8 @@
             CharSequence grpName, CharSequence permList, boolean dangerous, Drawable icon) {
         View permView = inflater.inflate(R.layout.app_permission_item_old, null);
 
-        TextView permGrpView = (TextView) permView.findViewById(R.id.permission_group);
-        TextView permDescView = (TextView) permView.findViewById(R.id.permission_list);
+        TextView permGrpView = permView.findViewById(R.id.permission_group);
+        TextView permDescView = permView.findViewById(R.id.permission_list);
 
         ImageView imgView = (ImageView)permView.findViewById(R.id.perm_icon);
         imgView.setImageDrawable(icon);
diff --git a/core/java/android/widget/ArrayAdapter.java b/core/java/android/widget/ArrayAdapter.java
index bbc50da..81f0d3d 100644
--- a/core/java/android/widget/ArrayAdapter.java
+++ b/core/java/android/widget/ArrayAdapter.java
@@ -388,7 +388,7 @@
                 text = (TextView) view;
             } else {
                 //  Otherwise, find the TextView field within the layout
-                text = (TextView) view.findViewById(mFieldId);
+                text = view.findViewById(mFieldId);
 
                 if (text == null) {
                     throw new RuntimeException("Failed to find view with ID "
diff --git a/core/java/android/widget/CalendarViewLegacyDelegate.java b/core/java/android/widget/CalendarViewLegacyDelegate.java
index 557d411..1b899db 100644
--- a/core/java/android/widget/CalendarViewLegacyDelegate.java
+++ b/core/java/android/widget/CalendarViewLegacyDelegate.java
@@ -316,9 +316,9 @@
         View content = layoutInflater.inflate(R.layout.calendar_view, null, false);
         mDelegator.addView(content);
 
-        mListView = (ListView) mDelegator.findViewById(R.id.list);
-        mDayNamesHeader = (ViewGroup) content.findViewById(R.id.day_names);
-        mMonthName = (TextView) content.findViewById(R.id.month_name);
+        mListView = mDelegator.findViewById(R.id.list);
+        mDayNamesHeader = content.findViewById(R.id.day_names);
+        mMonthName = content.findViewById(R.id.month_name);
 
         setUpHeader();
         setUpListView();
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index 6f687fe..dce33a0 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -32,9 +32,10 @@
 import android.view.SoundEffectConstants;
 import android.view.ViewDebug;
 import android.view.ViewHierarchyEncoder;
+import android.view.ViewStructure;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.autofill.AutoFillType;
+import android.view.autofill.AutoFillManager;
 import android.view.autofill.AutoFillValue;
 
 import com.android.internal.R;
@@ -67,6 +68,10 @@
     private OnCheckedChangeListener mOnCheckedChangeListener;
     private OnCheckedChangeListener mOnCheckedChangeWidgetListener;
 
+    // Indicates whether the toggle state was set from resources or dynamically, so it can be used
+    // to sanitize auto-fill requests.
+    private boolean mCheckedFromResource = false;
+
     private static final int[] CHECKED_STATE_SET = {
         R.attr.state_checked
     };
@@ -108,6 +113,7 @@
         final boolean checked = a.getBoolean(
                 com.android.internal.R.styleable.CompoundButton_checked, false);
         setChecked(checked);
+        mCheckedFromResource = true;
 
         a.recycle();
 
@@ -147,6 +153,7 @@
     @Override
     public void setChecked(boolean checked) {
         if (mChecked != checked) {
+            mCheckedFromResource = false;
             mChecked = checked;
             refreshDrawableState();
             notifyViewAccessibilityStateChangedIfNeeded(
@@ -164,6 +171,10 @@
             if (mOnCheckedChangeWidgetListener != null) {
                 mOnCheckedChangeWidgetListener.onCheckedChanged(this, mChecked);
             }
+            final AutoFillManager afm = mContext.getSystemService(AutoFillManager.class);
+            if (afm != null) {
+                afm.valueChanged(this);
+            }
 
             mBroadcasting = false;
         }
@@ -563,7 +574,12 @@
 
     // TODO(b/33197203): add unit/CTS tests for auto-fill methods (and make sure they handle enable)
 
-    // TODO(b/33197203): override onProvideAutoFillStructure and add a change listener
+    @Override
+    public void onProvideAutoFillStructure(ViewStructure structure, int flags) {
+        super.onProvideAutoFillStructure(structure, flags);
+
+        structure.setSanitized(mCheckedFromResource);
+    }
 
     @Override
     public void autoFill(AutoFillValue value) {
@@ -573,12 +589,12 @@
     }
 
     @Override
-    public AutoFillType getAutoFillType() {
-        return AutoFillType.forToggle();
+    public @AutofillType int getAutofillType() {
+        return isEnabled() ? AUTOFILL_TYPE_TOGGLE : AUTOFILL_TYPE_NONE;
     }
 
     @Override
     public AutoFillValue getAutoFillValue() {
-        return isEnabled() ? null : AutoFillValue.forToggle(isChecked());
+        return isEnabled() ? AutoFillValue.forToggle(isChecked()) : null;
     }
 }
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 517e20cd..c905172 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -31,7 +31,10 @@
 import android.util.AttributeSet;
 import android.util.SparseArray;
 import android.view.View;
+import android.view.ViewStructure;
 import android.view.accessibility.AccessibilityEvent;
+import android.view.autofill.AutoFillManager;
+import android.view.autofill.AutoFillValue;
 
 import com.android.internal.R;
 
@@ -142,6 +145,11 @@
     public DatePicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
 
+        // DatePicker is important by default, unless app developer overrode attribute.
+        if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
+            setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
+        }
+
         final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DatePicker,
                 defStyleAttr, defStyleRes);
         final boolean isDialogMode = a.getBoolean(R.styleable.DatePicker_dialogMode, false);
@@ -170,6 +178,13 @@
         if (firstDayOfWeek != 0) {
             setFirstDayOfWeek(firstDayOfWeek);
         }
+
+        mDelegate.setAutoFillChangeListener((v, y, m, d) -> {
+            final AutoFillManager afm = context.getSystemService(AutoFillManager.class);
+            if (afm != null) {
+                afm.valueChanged(this);
+            }
+        });
     }
 
     private DatePickerDelegate createSpinnerUIDelegate(Context context, AttributeSet attrs,
@@ -503,12 +518,15 @@
                   OnDateChangedListener onDateChangedListener);
 
         void setOnDateChangedListener(OnDateChangedListener onDateChangedListener);
+        void setAutoFillChangeListener(OnDateChangedListener onDateChangedListener);
 
         void updateDate(int year, int month, int dayOfMonth);
+        void updateDate(long date);
 
         int getYear();
         int getMonth();
         int getDayOfMonth();
+        long getDate();
 
         void setFirstDayOfWeek(int firstDayOfWeek);
         int getFirstDayOfWeek();
@@ -558,6 +576,7 @@
 
         // Callbacks
         protected OnDateChangedListener mOnDateChangedListener;
+        protected OnDateChangedListener mAutoFillChangeListener;
         protected ValidationCallback mValidationCallback;
 
         public AbstractDatePickerDelegate(DatePicker delegator, Context context) {
@@ -580,10 +599,28 @@
         }
 
         @Override
+        public void setAutoFillChangeListener(OnDateChangedListener callback) {
+            mAutoFillChangeListener = callback;
+        }
+
+        @Override
         public void setValidationCallback(ValidationCallback callback) {
             mValidationCallback = callback;
         }
 
+        @Override
+        public void updateDate(long date) {
+            Calendar cal = Calendar.getInstance(mCurrentLocale);
+            cal.setTimeInMillis(date);
+            updateDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH),
+                    cal.get(Calendar.DAY_OF_MONTH));
+        }
+
+        @Override
+        public long getDate() {
+            return mCurrentDate.getTimeInMillis();
+        }
+
         protected void onValidationChanged(boolean valid) {
             if (mValidationCallback != null) {
                 mValidationCallback.onValidationChanged(valid);
@@ -723,4 +760,31 @@
     public interface ValidationCallback {
         void onValidationChanged(boolean valid);
     }
+
+    // TODO(b/33197203): add unit/CTS tests for auto-fill methods (and make sure they handle enable)
+
+    @Override
+    public void dispatchProvideAutoFillStructure(ViewStructure structure, int flags) {
+        // This view is self-sufficient for auto-fill, so it needs to call
+        // onProvideAutoFillStructure() to fill itself, but it does not need to call
+        // dispatchProvideAutoFillStructure() to fill its children.
+        onProvideAutoFillStructure(structure, flags);
+    }
+
+    @Override
+    public void autoFill(AutoFillValue value) {
+        if (!isEnabled()) return;
+
+        mDelegate.updateDate(value.getDateValue());
+    }
+
+    @Override
+    public @AutofillType int getAutofillType() {
+        return isEnabled() ? AUTOFILL_TYPE_DATE : AUTOFILL_TYPE_NONE;
+    }
+
+    @Override
+    public AutoFillValue getAutoFillValue() {
+        return isEnabled() ? AutoFillValue.forDate(mDelegate.getDate()) : null;
+    }
 }
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index f712685..ca1bf58 100755
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -115,10 +115,10 @@
         mDelegator.addView(mContainer);
 
         // Set up header views.
-        final ViewGroup header = (ViewGroup) mContainer.findViewById(R.id.date_picker_header);
-        mHeaderYear = (TextView) header.findViewById(R.id.date_picker_header_year);
+        final ViewGroup header = mContainer.findViewById(R.id.date_picker_header);
+        mHeaderYear = header.findViewById(R.id.date_picker_header_year);
         mHeaderYear.setOnClickListener(mOnHeaderClickListener);
-        mHeaderMonthDay = (TextView) header.findViewById(R.id.date_picker_header_date);
+        mHeaderMonthDay = header.findViewById(R.id.date_picker_header_date);
         mHeaderMonthDay.setOnClickListener(mOnHeaderClickListener);
 
         // For the sake of backwards compatibility, attempt to extract the text
@@ -154,10 +154,10 @@
         a.recycle();
 
         // Set up picker container.
-        mAnimator = (ViewAnimator) mContainer.findViewById(R.id.animator);
+        mAnimator = mContainer.findViewById(R.id.animator);
 
         // Set up day picker view.
-        mDayPickerView = (DayPickerView) mAnimator.findViewById(R.id.date_picker_day_picker);
+        mDayPickerView = mAnimator.findViewById(R.id.date_picker_day_picker);
         mDayPickerView.setFirstDayOfWeek(mFirstDayOfWeek);
         mDayPickerView.setMinDate(mMinDate.getTimeInMillis());
         mDayPickerView.setMaxDate(mMaxDate.getTimeInMillis());
@@ -165,7 +165,7 @@
         mDayPickerView.setOnDaySelectedListener(mOnDaySelectedListener);
 
         // Set up year picker view.
-        mYearPickerView = (YearPickerView) mAnimator.findViewById(R.id.date_picker_year_picker);
+        mYearPickerView = mAnimator.findViewById(R.id.date_picker_year_picker);
         mYearPickerView.setRange(mMinDate, mMaxDate);
         mYearPickerView.setYear(mCurrentDate.get(Calendar.YEAR));
         mYearPickerView.setOnYearSelectedListener(mOnYearSelectedListener);
@@ -390,10 +390,16 @@
     private void onDateChanged(boolean fromUser, boolean callbackToClient) {
         final int year = mCurrentDate.get(Calendar.YEAR);
 
-        if (callbackToClient && mOnDateChangedListener != null) {
+        if (callbackToClient
+                && (mOnDateChangedListener != null || mAutoFillChangeListener != null)) {
             final int monthOfYear = mCurrentDate.get(Calendar.MONTH);
             final int dayOfMonth = mCurrentDate.get(Calendar.DAY_OF_MONTH);
-            mOnDateChangedListener.onDateChanged(mDelegator, year, monthOfYear, dayOfMonth);
+            if (mOnDateChangedListener != null) {
+                mOnDateChangedListener.onDateChanged(mDelegator, year, monthOfYear, dayOfMonth);
+            }
+            if (mAutoFillChangeListener != null) {
+                mAutoFillChangeListener.onDateChanged(mDelegator, year, monthOfYear, dayOfMonth);
+            }
         }
 
         mDayPickerView.setDate(mCurrentDate.getTimeInMillis());
diff --git a/core/java/android/widget/DatePickerSpinnerDelegate.java b/core/java/android/widget/DatePickerSpinnerDelegate.java
index 702b2a5..fc2d1fa 100644
--- a/core/java/android/widget/DatePickerSpinnerDelegate.java
+++ b/core/java/android/widget/DatePickerSpinnerDelegate.java
@@ -576,6 +576,10 @@
             mOnDateChangedListener.onDateChanged(mDelegator, getYear(), getMonth(),
                     getDayOfMonth());
         }
+        if (mAutoFillChangeListener != null) {
+            mAutoFillChangeListener.onDateChanged(mDelegator, getYear(), getMonth(),
+                    getDayOfMonth());
+        }
     }
 
     /**
diff --git a/core/java/android/widget/DayPickerPagerAdapter.java b/core/java/android/widget/DayPickerPagerAdapter.java
index 8d5bf8f..63621e1 100644
--- a/core/java/android/widget/DayPickerPagerAdapter.java
+++ b/core/java/android/widget/DayPickerPagerAdapter.java
@@ -225,7 +225,7 @@
     public Object instantiateItem(ViewGroup container, int position) {
         final View itemView = mInflater.inflate(mLayoutResId, container, false);
 
-        final SimpleMonthView v = (SimpleMonthView) itemView.findViewById(mCalendarViewId);
+        final SimpleMonthView v = itemView.findViewById(mCalendarViewId);
         v.setOnDayClickListener(mOnDayClickListener);
         v.setMonthTextAppearance(mMonthTextAppearance);
         v.setDayOfWeekTextAppearance(mDayOfWeekTextAppearance);
diff --git a/core/java/android/widget/DayPickerView.java b/core/java/android/widget/DayPickerView.java
index 919c1e2..0f0e6c3 100644
--- a/core/java/android/widget/DayPickerView.java
+++ b/core/java/android/widget/DayPickerView.java
@@ -294,14 +294,15 @@
      * @param animate whether to smooth scroll to the new position
      * @param setSelected whether to set the specified day as selected
      *
-     * @throws IllegalArgumentException as of {@link android.os.Build.VERSION_CODES#N_MR1} if the
-     *         provided timeInMillis is before the range start or after the range end.
+     * @throws IllegalArgumentException if the build version is greater than
+     *         {@link android.os.Build.VERSION_CODES#N_MR1} and the provided timeInMillis is before
+     *         the range start or after the range end.
      */
     private void setDate(long timeInMillis, boolean animate, boolean setSelected) {
         getTempCalendarForTime(timeInMillis);
 
         final int targetSdkVersion = mContext.getApplicationInfo().targetSdkVersion;
-        if (targetSdkVersion >= N_MR1) {
+        if (targetSdkVersion > N_MR1) {
             if (mTempCalendar.before(mMinDate) || mTempCalendar.after(mMaxDate)) {
                 throw new IllegalArgumentException("timeInMillis must be between the values of "
                         + "getMinDate() and getMaxDate()");
diff --git a/core/java/android/widget/DayPickerViewPager.java b/core/java/android/widget/DayPickerViewPager.java
index a27e022..1704ed7 100644
--- a/core/java/android/widget/DayPickerViewPager.java
+++ b/core/java/android/widget/DayPickerViewPager.java
@@ -137,9 +137,10 @@
     }
 
     @Override
-    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
+    protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
+            View childToSkip) {
         if (predicate.test(this)) {
-            return this;
+            return (T) this;
         }
 
         // Always try the selected view first.
@@ -148,7 +149,7 @@
         if (current != childToSkip && current != null) {
             final View v = current.findViewByPredicate(predicate);
             if (v != null) {
-                return v;
+                return (T) v;
             }
         }
 
@@ -160,7 +161,7 @@
                 final View v = child.findViewByPredicate(predicate);
 
                 if (v != null) {
-                    return v;
+                    return (T) v;
                 }
             }
         }
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index dd3b054..ade03e1 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -2183,6 +2183,11 @@
     }
 
     void onTouchUpEvent(MotionEvent event) {
+        if (getSelectionActionModeHelper().resetOriginalSelection(
+                getTextView().getOffsetForPosition(event.getX(), event.getY()))) {
+            return;
+        }
+
         boolean selectAllGotFocus = mSelectAllOnFocus && mTextView.didTouchFocusSelect();
         hideCursorAndSpanControllers();
         stopTextActionMode();
@@ -3916,7 +3921,7 @@
         @Override
         public void onDestroyActionMode(ActionMode mode) {
             // Clear mTextActionMode not to recursively destroy action mode by clearing selection.
-            getSelectionActionModeHelper().cancelAsyncTask();
+            getSelectionActionModeHelper().onDestroyActionMode();
             mTextActionMode = null;
             Callback customCallback = getCustomCallback();
             if (customCallback != null) {
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index cd80651..7e6f2e4 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -156,6 +156,11 @@
 
         initImageView();
 
+        // ImageView is not important by default, unless app developer overrode attribute.
+        if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
+            setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_NO);
+        }
+
         final TypedArray a = context.obtainStyledAttributes(
                 attrs, R.styleable.ImageView, defStyleAttr, defStyleRes);
 
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 46e998a..1c0c4ef 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -3740,20 +3740,21 @@
      * @removed For internal use only. This should have been hidden.
      */
     @Override
-    protected View findViewTraversal(@IdRes int id) {
-        View v;
-        v = super.findViewTraversal(id);
+    protected <T extends View> T findViewTraversal(@IdRes int id) {
+        // First look in our children, then in any header and footer views that
+        // may be scrolled off.
+        View v = super.findViewTraversal(id);
         if (v == null) {
             v = findViewInHeadersOrFooters(mHeaderViewInfos, id);
             if (v != null) {
-                return v;
+                return (T) v;
             }
             v = findViewInHeadersOrFooters(mFooterViewInfos, id);
             if (v != null) {
-                return v;
+                return (T) v;
             }
         }
-        return v;
+        return (T) v;
     }
 
     View findViewInHeadersOrFooters(ArrayList<FixedViewInfo> where, int id) {
@@ -3782,21 +3783,22 @@
      * @removed For internal use only. This should have been hidden.
      */
     @Override
-    protected View findViewWithTagTraversal(Object tag) {
-        View v;
-        v = super.findViewWithTagTraversal(tag);
+    protected <T extends View> T findViewWithTagTraversal(Object tag) {
+        // First look in our children, then in any header and footer views that
+        // may be scrolled off.
+        View v = super.findViewWithTagTraversal(tag);
         if (v == null) {
             v = findViewWithTagInHeadersOrFooters(mHeaderViewInfos, tag);
             if (v != null) {
-                return v;
+                return (T) v;
             }
 
             v = findViewWithTagInHeadersOrFooters(mFooterViewInfos, tag);
             if (v != null) {
-                return v;
+                return (T) v;
             }
         }
-        return v;
+        return (T) v;
     }
 
     View findViewWithTagInHeadersOrFooters(ArrayList<FixedViewInfo> where, Object tag) {
@@ -3829,21 +3831,21 @@
      * @hide
      */
     @Override
-    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
-        View v;
-        v = super.findViewByPredicateTraversal(predicate, childToSkip);
+    protected <T extends View> T findViewByPredicateTraversal(
+            Predicate<View> predicate, View childToSkip) {
+        View v = super.findViewByPredicateTraversal(predicate, childToSkip);
         if (v == null) {
             v = findViewByPredicateInHeadersOrFooters(mHeaderViewInfos, predicate, childToSkip);
             if (v != null) {
-                return v;
+                return (T) v;
             }
 
             v = findViewByPredicateInHeadersOrFooters(mFooterViewInfos, predicate, childToSkip);
             if (v != null) {
-                return v;
+                return (T) v;
             }
         }
-        return v;
+        return (T) v;
     }
 
     /**
diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java
index 8008637..8e04f1c 100644
--- a/core/java/android/widget/MediaController.java
+++ b/core/java/android/widget/MediaController.java
@@ -257,13 +257,13 @@
                 .getText(com.android.internal.R.string.lockscreen_transport_play_description);
         mPauseDescription = res
                 .getText(com.android.internal.R.string.lockscreen_transport_pause_description);
-        mPauseButton = (ImageButton) v.findViewById(com.android.internal.R.id.pause);
+        mPauseButton = v.findViewById(com.android.internal.R.id.pause);
         if (mPauseButton != null) {
             mPauseButton.requestFocus();
             mPauseButton.setOnClickListener(mPauseListener);
         }
 
-        mFfwdButton = (ImageButton) v.findViewById(com.android.internal.R.id.ffwd);
+        mFfwdButton = v.findViewById(com.android.internal.R.id.ffwd);
         if (mFfwdButton != null) {
             mFfwdButton.setOnClickListener(mFfwdListener);
             if (!mFromXml) {
@@ -271,7 +271,7 @@
             }
         }
 
-        mRewButton = (ImageButton) v.findViewById(com.android.internal.R.id.rew);
+        mRewButton = v.findViewById(com.android.internal.R.id.rew);
         if (mRewButton != null) {
             mRewButton.setOnClickListener(mRewListener);
             if (!mFromXml) {
@@ -280,16 +280,16 @@
         }
 
         // By default these are hidden. They will be enabled when setPrevNextListeners() is called
-        mNextButton = (ImageButton) v.findViewById(com.android.internal.R.id.next);
+        mNextButton = v.findViewById(com.android.internal.R.id.next);
         if (mNextButton != null && !mFromXml && !mListenersSet) {
             mNextButton.setVisibility(View.GONE);
         }
-        mPrevButton = (ImageButton) v.findViewById(com.android.internal.R.id.prev);
+        mPrevButton = v.findViewById(com.android.internal.R.id.prev);
         if (mPrevButton != null && !mFromXml && !mListenersSet) {
             mPrevButton.setVisibility(View.GONE);
         }
 
-        mProgress = (ProgressBar) v.findViewById(com.android.internal.R.id.mediacontroller_progress);
+        mProgress = v.findViewById(com.android.internal.R.id.mediacontroller_progress);
         if (mProgress != null) {
             if (mProgress instanceof SeekBar) {
                 SeekBar seeker = (SeekBar) mProgress;
@@ -298,8 +298,8 @@
             mProgress.setMax(1000);
         }
 
-        mEndTime = (TextView) v.findViewById(com.android.internal.R.id.time);
-        mCurrentTime = (TextView) v.findViewById(com.android.internal.R.id.time_current);
+        mEndTime = v.findViewById(com.android.internal.R.id.time);
+        mCurrentTime = v.findViewById(com.android.internal.R.id.time_current);
         mFormatBuilder = new StringBuilder();
         mFormatter = new Formatter(mFormatBuilder, Locale.getDefault());
 
diff --git a/core/java/android/widget/RadioGroup.java b/core/java/android/widget/RadioGroup.java
index 8ba4694..bb8cd28 100644
--- a/core/java/android/widget/RadioGroup.java
+++ b/core/java/android/widget/RadioGroup.java
@@ -24,7 +24,8 @@
 import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.autofill.AutoFillType;
+import android.view.ViewStructure;
+import android.view.autofill.AutoFillManager;
 import android.view.autofill.AutoFillValue;
 
 import com.android.internal.R;
@@ -65,6 +66,10 @@
     private OnCheckedChangeListener mOnCheckedChangeListener;
     private PassThroughHierarchyChangeListener mPassThroughListener;
 
+    // Indicates whether the child was set from resources or dynamically, so it can be used
+    // to sanitize auto-fill requests.
+    private int mInitialCheckedId = View.NO_ID;
+
     /**
      * {@inheritDoc}
      */
@@ -80,6 +85,11 @@
     public RadioGroup(Context context, AttributeSet attrs) {
         super(context, attrs);
 
+        // RadioGroup is important by default, unless app developer overrode attribute.
+        if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
+            setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
+        }
+
         // retrieve selected radio button as requested by the user in the
         // XML layout file
         TypedArray attributes = context.obtainStyledAttributes(
@@ -88,8 +98,8 @@
         int value = attributes.getResourceId(R.styleable.RadioGroup_checkedButton, View.NO_ID);
         if (value != View.NO_ID) {
             mCheckedId = value;
+            mInitialCheckedId = value;
         }
-
         final int index = attributes.getInt(com.android.internal.R.styleable.RadioGroup_orientation, VERTICAL);
         setOrientation(index);
 
@@ -177,6 +187,10 @@
         if (mOnCheckedChangeListener != null) {
             mOnCheckedChangeListener.onCheckedChanged(this, mCheckedId);
         }
+        final AutoFillManager afm = mContext.getSystemService(AutoFillManager.class);
+        if (afm != null) {
+            afm.valueChanged(this);
+        }
     }
 
     private void setCheckedStateForView(int viewId, boolean checked) {
@@ -405,7 +419,11 @@
 
     // TODO(b/33197203): add unit/CTS tests for auto-fill methods (and make sure they handle enable)
 
-    // TODO(b/33197203): override onProvideAutoFillStructure and add a change listener
+    @Override
+    public void onProvideAutoFillStructure(ViewStructure structure, int flags) {
+        super.onProvideAutoFillStructure(structure, flags);
+        structure.setSanitized(mCheckedId == mInitialCheckedId);
+    }
 
     @Override
     public void autoFill(AutoFillValue value) {
@@ -421,12 +439,21 @@
     }
 
     @Override
-    public AutoFillType getAutoFillType() {
-        return AutoFillType.forList();
+    public @AutofillType int getAutofillType() {
+        return isEnabled() ? AUTOFILL_TYPE_LIST : AUTOFILL_TYPE_NONE;
     }
 
     @Override
     public AutoFillValue getAutoFillValue() {
-        return isEnabled() ? AutoFillValue.forList(getCheckedRadioButtonId()) : null;
+        if (!isEnabled()) return null;
+
+        final int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+            if (child.getId() == mCheckedId) {
+                return AutoFillValue.forList(i);
+            }
+        }
+        return null;
     }
 }
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 359d04e..5505f2f 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -1578,7 +1578,7 @@
         @Override
         public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
             final Context context = root.getContext();
-            final ViewGroup target = (ViewGroup) root.findViewById(viewId);
+            final ViewGroup target = root.findViewById(viewId);
             if (target == null) return;
             if (nestedViews != null) {
                 // Inflate nested views and add as children
@@ -1757,7 +1757,7 @@
 
         @Override
         public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
-            final TextView target = (TextView) root.findViewById(viewId);
+            final TextView target = root.findViewById(viewId);
             if (target == null) return;
             if (drawablesLoaded) {
                 if (isRelative) {
@@ -1857,7 +1857,7 @@
 
         @Override
         public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
-            final TextView target = (TextView) root.findViewById(viewId);
+            final TextView target = root.findViewById(viewId);
             if (target == null) return;
             target.setTextSize(units, size);
         }
@@ -2045,7 +2045,7 @@
 
         @Override
         public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
-            final TextView target = (TextView) root.findViewById(viewId);
+            final TextView target = root.findViewById(viewId);
             if (target == null) return;
             Drawable[] drawables = isRelative
                     ? target.getCompoundDrawablesRelative()
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index 770d9ee..a032383 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -21,6 +21,7 @@
 import android.annotation.UiThread;
 import android.annotation.WorkerThread;
 import android.os.AsyncTask;
+import android.os.LocaleList;
 import android.text.Selection;
 import android.text.Spannable;
 import android.text.TextUtils;
@@ -54,18 +55,20 @@
     private TextClassificationResult mTextClassificationResult;
     private AsyncTask mTextClassificationAsyncTask;
 
+    private final SelectionInfo mSelectionInfo = new SelectionInfo();
+
     SelectionActionModeHelper(@NonNull Editor editor) {
         mEditor = Preconditions.checkNotNull(editor);
         final TextView textView = mEditor.getTextView();
         mTextClassificationHelper = new TextClassificationHelper(
-                textView.getTextClassifier(), textView.getText(),
-                textView.getSelectionStart(), textView.getSelectionEnd());
+                textView.getTextClassifier(), textView.getText(), 0, 1, textView.getTextLocales());
     }
 
     public void startActionModeAsync() {
         cancelAsyncTask();
-        if (isNoOpTextClassifier()) {
+        if (isNoOpTextClassifier() || !hasSelection()) {
             // No need to make an async call for a no-op TextClassifier.
+            // Do not call the TextClassifier if there is no selection.
             startActionMode(null);
         } else {
             resetTextClassificationHelper();
@@ -82,8 +85,9 @@
 
     public void invalidateActionModeAsync() {
         cancelAsyncTask();
-        if (isNoOpTextClassifier()) {
+        if (isNoOpTextClassifier() || !hasSelection()) {
             // No need to make an async call for a no-op TextClassifier.
+            // Do not call the TextClassifier if there is no selection.
             invalidateActionMode(null);
         } else {
             resetTextClassificationHelper();
@@ -94,12 +98,12 @@
         }
     }
 
-    public void cancelAsyncTask() {
-        if (mTextClassificationAsyncTask != null) {
-            mTextClassificationAsyncTask.cancel(true);
-            mTextClassificationAsyncTask = null;
+    public boolean resetOriginalSelection(int textIndex) {
+        if (mSelectionInfo.resetOriginalSelection(textIndex, mEditor.getTextView().getText())) {
+            invalidateActionModeAsync();
+            return true;
         }
-        mTextClassificationResult = null;
+        return false;
     }
 
     @Nullable
@@ -107,12 +111,33 @@
         return mTextClassificationResult;
     }
 
+    public void onDestroyActionMode() {
+        mSelectionInfo.onSelectionDestroyed();
+        cancelAsyncTask();
+    }
+
+    private void cancelAsyncTask() {
+        if (mTextClassificationAsyncTask != null) {
+            mTextClassificationAsyncTask.cancel(true);
+            mTextClassificationAsyncTask = null;
+        }
+        mTextClassificationResult = null;
+    }
+
     private boolean isNoOpTextClassifier() {
         return mEditor.getTextView().getTextClassifier() == TextClassifier.NO_OP;
     }
 
+    private boolean hasSelection() {
+        final TextView textView = mEditor.getTextView();
+        return textView.getSelectionEnd() > textView.getSelectionStart();
+    }
+
     private void startActionMode(@Nullable SelectionResult result) {
-        final CharSequence text = mEditor.getTextView().getText();
+        final TextView textView = mEditor.getTextView();
+        final CharSequence text = textView.getText();
+        mSelectionInfo.setOriginalSelection(
+                textView.getSelectionStart(), textView.getSelectionEnd());
         if (result != null && text instanceof Spannable) {
             Selection.setSelection((Spannable) text, result.mStart, result.mEnd);
             mTextClassificationResult = result.mResult;
@@ -124,6 +149,9 @@
             if (controller != null) {
                 controller.show();
             }
+            if (result != null) {
+                mSelectionInfo.onSelectionStarted(result.mStart, result.mEnd);
+            }
         }
         mEditor.setRestartActionModeOnNextRefresh(false);
         mTextClassificationAsyncTask = null;
@@ -135,13 +163,66 @@
         if (actionMode != null) {
             actionMode.invalidate();
         }
+        final TextView textView = mEditor.getTextView();
+        mSelectionInfo.onSelectionUpdated(textView.getSelectionStart(), textView.getSelectionEnd());
         mTextClassificationAsyncTask = null;
     }
 
     private void resetTextClassificationHelper() {
         final TextView textView = mEditor.getTextView();
         mTextClassificationHelper.reset(textView.getTextClassifier(), textView.getText(),
-                textView.getSelectionStart(), textView.getSelectionEnd());
+                textView.getSelectionStart(), textView.getSelectionEnd(),
+                textView.getTextLocales());
+    }
+
+    /**
+     * Holds information about the selection and uses it to decide on whether or not to update
+     * the selection when resetOriginalSelection is called.
+     * The expected UX here is to allow the user to re-snap the selection back to the original word
+     * that was selected with one tap on that word.
+     */
+    private static final class SelectionInfo {
+
+        private int mOriginalStart;
+        private int mOriginalEnd;
+        private int mSelectionStart;
+        private int mSelectionEnd;
+
+        private boolean mResetOriginal;
+
+        public void setOriginalSelection(int selectionStart, int selectionEnd) {
+            mOriginalStart = selectionStart;
+            mOriginalEnd = selectionEnd;
+            mResetOriginal = false;
+        }
+
+        public void onSelectionStarted(int selectionStart, int selectionEnd) {
+            // Set the reset flag to true if the selection changed.
+            mSelectionStart = selectionStart;
+            mSelectionEnd = selectionEnd;
+            mResetOriginal = mSelectionStart != mOriginalStart || mSelectionEnd != mOriginalEnd;
+        }
+
+        public void onSelectionUpdated(int selectionStart, int selectionEnd) {
+            // If the selection did not change, maintain the reset state. Otherwise, disable reset.
+            mResetOriginal &= selectionStart == mSelectionStart && selectionEnd == mSelectionEnd;
+        }
+
+        public void onSelectionDestroyed() {
+            mResetOriginal = false;
+        }
+
+        public boolean resetOriginalSelection(int textIndex, CharSequence text) {
+            if (mResetOriginal
+                    && textIndex >= mOriginalStart && textIndex <= mOriginalEnd
+                    && text instanceof Spannable) {
+                Selection.setSelection((Spannable) text, mOriginalStart, mOriginalEnd);
+                // Only allow a reset once.
+                mResetOriginal = false;
+                return true;
+            }
+            return false;
+        }
     }
 
     /**
@@ -218,6 +299,7 @@
         private int mSelectionStart;
         /** End index relative to mText. */
         private int mSelectionEnd;
+        private LocaleList mLocales;
 
         /** Trimmed text starting from mTrimStart in mText. */
         private CharSequence mTrimmedText;
@@ -229,17 +311,19 @@
         private int mRelativeEnd;
 
         TextClassificationHelper(TextClassifier textClassifier,
-                CharSequence text, int selectionStart, int selectionEnd) {
-            reset(textClassifier, text, selectionStart, selectionEnd);
+                CharSequence text, int selectionStart, int selectionEnd, LocaleList locales) {
+            reset(textClassifier, text, selectionStart, selectionEnd, locales);
         }
 
         @UiThread
         public void reset(TextClassifier textClassifier,
-                CharSequence text, int selectionStart, int selectionEnd) {
+                CharSequence text, int selectionStart, int selectionEnd, LocaleList locales) {
             mTextClassifier = Preconditions.checkNotNull(textClassifier);
             mText = Preconditions.checkNotNull(text).toString();
+            Preconditions.checkArgument(selectionEnd > selectionStart);
             mSelectionStart = selectionStart;
             mSelectionEnd = selectionEnd;
+            mLocales = locales;
         }
 
         @WorkerThread
@@ -249,14 +333,14 @@
                     mSelectionStart,
                     mSelectionEnd,
                     mTextClassifier.getTextClassificationResult(
-                            mTrimmedText, mRelativeStart, mRelativeEnd));
+                            mTrimmedText, mRelativeStart, mRelativeEnd, mLocales));
         }
 
         @WorkerThread
         public SelectionResult suggestSelection() {
             trimText();
             final TextSelection sel = mTextClassifier.suggestSelection(
-                    mTrimmedText, mRelativeStart, mRelativeEnd);
+                    mTrimmedText, mRelativeStart, mRelativeEnd, mLocales);
             mSelectionStart = Math.max(0, sel.getSelectionStartIndex() + mTrimStart);
             mSelectionEnd = Math.min(mText.length(), sel.getSelectionEndIndex() + mTrimStart);
             return classifyText();
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index 28cc693..3811e1a 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -41,6 +41,7 @@
 import android.view.PointerIcon;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewStructure;
 import android.view.ViewTreeObserver;
 import android.view.ViewTreeObserver.OnGlobalLayoutListener;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -784,6 +785,7 @@
         return handled;
     }
 
+    @Override
     public void onClick(DialogInterface dialog, int which) {
         setSelection(which);
         dialog.dismiss();
@@ -912,6 +914,27 @@
         return super.onResolvePointerIcon(event, pointerIndex);
     }
 
+    // TODO(b/33197203): add unit/CTS tests for auto-fill methods (and make sure they handle enable)
+
+    @Override
+    public void onProvideAutoFillStructure(ViewStructure structure, int flags) {
+        super.onProvideAutoFillStructure(structure, flags);
+
+        if (getAdapter() == null) return;
+
+        // TODO(b/33197203): implement sanitization so initial value is only sanitized when coming
+        // from resources.
+
+        final int count = getAdapter().getCount();
+        if (count > 0) {
+            final String[] options = new String[count];
+            for (int i = 0; i < count; i++) {
+                options[i] = getAdapter().getItem(i).toString();
+            }
+            structure.setAutoFillOptions(options);
+        }
+    }
+
     static class SavedState extends AbsSpinner.SavedState {
         boolean showDropdown;
 
diff --git a/core/java/android/widget/SuggestionsAdapter.java b/core/java/android/widget/SuggestionsAdapter.java
index f833d1b..fbb8993 100644
--- a/core/java/android/widget/SuggestionsAdapter.java
+++ b/core/java/android/widget/SuggestionsAdapter.java
@@ -286,7 +286,7 @@
         v.setTag(new ChildViewCache(v));
 
         // Set up icon.
-        final ImageView iconRefine = (ImageView) v.findViewById(R.id.edit_query);
+        final ImageView iconRefine = v.findViewById(R.id.edit_query);
         iconRefine.setImageResource(mCommitIconResId);
 
         return v;
@@ -304,11 +304,11 @@
         public final ImageView mIconRefine;
 
         public ChildViewCache(View v) {
-            mText1 = (TextView) v.findViewById(com.android.internal.R.id.text1);
-            mText2 = (TextView) v.findViewById(com.android.internal.R.id.text2);
-            mIcon1 = (ImageView) v.findViewById(com.android.internal.R.id.icon1);
-            mIcon2 = (ImageView) v.findViewById(com.android.internal.R.id.icon2);
-            mIconRefine = (ImageView) v.findViewById(com.android.internal.R.id.edit_query);
+            mText1 = v.findViewById(com.android.internal.R.id.text1);
+            mText2 = v.findViewById(com.android.internal.R.id.text2);
+            mIcon1 = v.findViewById(com.android.internal.R.id.icon1);
+            mIcon2 = v.findViewById(com.android.internal.R.id.icon2);
+            mIconRefine = v.findViewById(com.android.internal.R.id.edit_query);
         }
     }
 
diff --git a/core/java/android/widget/TabHost.java b/core/java/android/widget/TabHost.java
index 32418cd..7e2cadf 100644
--- a/core/java/android/widget/TabHost.java
+++ b/core/java/android/widget/TabHost.java
@@ -619,7 +619,7 @@
                     mTabWidget, // tab widget is the parent
                     false); // no inflate params
 
-            final TextView tv = (TextView) tabIndicator.findViewById(R.id.title);
+            final TextView tv = tabIndicator.findViewById(R.id.title);
             tv.setText(mLabel);
 
             if (context.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.DONUT) {
@@ -653,8 +653,8 @@
                     mTabWidget, // tab widget is the parent
                     false); // no inflate params
 
-            final TextView tv = (TextView) tabIndicator.findViewById(R.id.title);
-            final ImageView iconView = (ImageView) tabIndicator.findViewById(R.id.icon);
+            final TextView tv = tabIndicator.findViewById(R.id.title);
+            final ImageView iconView = tabIndicator.findViewById(R.id.icon);
 
             // when icon is gone by default, we're in exclusive mode
             final boolean exclusive = iconView.getVisibility() == View.GONE;
diff --git a/core/java/android/widget/TextInputTimePickerView.java b/core/java/android/widget/TextInputTimePickerView.java
index ef91576..0183343 100644
--- a/core/java/android/widget/TextInputTimePickerView.java
+++ b/core/java/android/widget/TextInputTimePickerView.java
@@ -177,15 +177,15 @@
 
         mAmPmSpinner.setVisibility(is24Hour ? View.INVISIBLE : View.VISIBLE);
 
-        mHourEditText.setText(String.format(format, localizedHour));
-        mMinuteEditText.setText(String.format(format, minute));
-
         if (amOrPm == AM) {
             mAmPmSpinner.setSelection(0);
         } else {
             mAmPmSpinner.setSelection(1);
         }
 
+        mHourEditText.setText(String.format(format, localizedHour));
+        mMinuteEditText.setText(String.format(format, minute));
+
         if (mErrorShowing) {
             validateInput();
         }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 6fa8428..b901ab4 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -63,7 +63,6 @@
 import android.os.Parcelable;
 import android.os.ParcelableParcel;
 import android.os.SystemClock;
-import android.os.UserHandle;
 import android.provider.Settings;
 import android.text.BoringLayout;
 import android.text.DynamicLayout;
@@ -113,6 +112,7 @@
 import android.text.style.UpdateAppearance;
 import android.text.util.Linkify;
 import android.util.AttributeSet;
+import android.util.DisplayMetrics;
 import android.util.IntArray;
 import android.util.Log;
 import android.util.TypedValue;
@@ -141,7 +141,6 @@
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.animation.AnimationUtils;
 import android.view.autofill.AutoFillManager;
-import android.view.autofill.AutoFillType;
 import android.view.autofill.AutoFillValue;
 import android.view.inputmethod.BaseInputConnection;
 import android.view.inputmethod.CompletionInfo;
@@ -266,7 +265,7 @@
  * @attr ref android.R.styleable#TextView_fontFeatureSettings
  * @attr ref android.R.styleable#TextView_breakStrategy
  * @attr ref android.R.styleable#TextView_hyphenationFrequency
- * @attr ref android.R.styleable#TextView_autoSizeText
+ * @attr ref android.R.styleable#TextView_autoSizeTextType
  * @attr ref android.R.styleable#TextView_autoSizeMinTextSize
  * @attr ref android.R.styleable#TextView_autoSizeMaxTextSize
  * @attr ref android.R.styleable#TextView_autoSizeStepGranularity
@@ -691,31 +690,39 @@
      */
     private int mDeviceProvisionedState = DEVICE_PROVISIONED_UNKNOWN;
 
-    // The TextView does not auto-size text (default).
+    /**
+     * The TextView does not auto-size text (default).
+     */
     public static final int AUTO_SIZE_TEXT_TYPE_NONE = 0;
-    // The TextView performs uniform horizontal and vertical text size scaling to fit within the
-    // container.
+
+    /**
+     * The TextView scales text size both horizontally and vertically to fit within the
+     * container.
+     */
     public static final int AUTO_SIZE_TEXT_TYPE_UNIFORM = 1;
+
     /** @hide */
     @IntDef({AUTO_SIZE_TEXT_TYPE_NONE, AUTO_SIZE_TEXT_TYPE_UNIFORM})
     @Retention(RetentionPolicy.SOURCE)
     public @interface AutoSizeTextType {}
-    // Default minimum size for auto-sizing text in scaled pixels. {@see #setAutoSizeMinTextSize}.
+    // Default minimum size for auto-sizing text in scaled pixels.
     private static final int DEFAULT_AUTO_SIZE_MIN_TEXT_SIZE_IN_SP = 12;
-    // Default maximum size for auto-sizing text in scaled pixels. {@see #setAutoSizeMaxTextSize}.
+    // Default maximum size for auto-sizing text in scaled pixels.
     private static final int DEFAULT_AUTO_SIZE_MAX_TEXT_SIZE_IN_SP = 112;
     // Default value for the step size in pixels.
     private static final int DEFAULT_AUTO_SIZE_GRANULARITY_IN_PX = 1;
+    // Use this to specify that any of the auto-size configuration int values have not been set.
+    private static final int UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE = -1;
     // Auto-size text type.
     private int mAutoSizeTextType = AUTO_SIZE_TEXT_TYPE_NONE;
     // Specify if auto-size text is needed.
     private boolean mNeedsAutoSizeText = false;
     // Step size for auto-sizing in pixels.
-    private int mAutoSizeStepGranularityInPx = 0;
+    private int mAutoSizeStepGranularityInPx = UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE;
     // Minimum text size for auto-sizing in pixels.
-    private int mAutoSizeMinTextSizeInPx = 0;
+    private int mAutoSizeMinTextSizeInPx = UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE;
     // Maximum text size for auto-sizing in pixels.
-    private int mAutoSizeMaxTextSizeInPx = 0;
+    private int mAutoSizeMaxTextSizeInPx = UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE;
     // Contains a (specified or computed) distinct sorted set of text sizes in pixels to pick from
     // when auto-sizing text.
     private int[] mAutoSizeTextSizesInPx = EmptyArray.INT;
@@ -724,8 +731,9 @@
     // mAutoSizeStepGranularityInPx.
     private boolean mHasPresetAutoSizeValues = false;
 
-    // Watcher used to notify changes to auto-fill manager.
-    private AutoFillChangeWatcher mAutoFillChangeWatcher;
+    // Indicates whether the text was set from resources or dynamically, so it can be used to
+    // sanitize auto-fill requests.
+    private boolean mTextFromResource = false;
 
     /**
      * Kick-start the font cache for the zygote process (to pay the cost of
@@ -781,6 +789,11 @@
             Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
 
+        // TextView is important by default, unless app developer overrode attribute.
+        if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
+            setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
+        }
+
         mText = "";
 
         final Resources res = getResources();
@@ -868,7 +881,7 @@
                     case com.android.internal.R.styleable.TextAppearance_fontFamily:
                         try {
                             fontTypeface = appearance.getFont(attr);
-                        } catch (UnsupportedOperationException e) {
+                        } catch (UnsupportedOperationException | Resources.NotFoundException e) {
                             // Expected if it is not a font resource.
                         }
                         if (fontTypeface == null) {
@@ -937,11 +950,16 @@
         CharSequence text = "";
         CharSequence hint = null;
         boolean password = false;
+        int autoSizeMinTextSizeInPx = UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE;
+        int autoSizeMaxTextSizeInPx = UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE;
+        int autoSizeStepGranularityInPx = UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE;
         int inputType = EditorInfo.TYPE_NULL;
         a = theme.obtainStyledAttributes(
                     attrs, com.android.internal.R.styleable.TextView, defStyleAttr, defStyleRes);
 
         int n = a.getIndexCount();
+
+        boolean fromResourceId = false;
         for (int i = 0; i < n; i++) {
             int attr = a.getIndex(i);
 
@@ -1083,6 +1101,7 @@
                     break;
 
                 case com.android.internal.R.styleable.TextView_text:
+                    fromResourceId = true;
                     text = a.getText(attr);
                     break;
 
@@ -1179,8 +1198,9 @@
                 case com.android.internal.R.styleable.TextView_fontFamily:
                     try {
                         fontTypeface = a.getFont(attr);
-                    } catch (UnsupportedOperationException e) {
-                        // Expected if it is not a font resource.
+                    } catch (UnsupportedOperationException | Resources.NotFoundException e) {
+                        // Expected if it is not a resource reference or if it is a reference to
+                        // another resource type.
                     }
                     if (fontTypeface == null) {
                         fontFamily = a.getString(attr);
@@ -1299,20 +1319,23 @@
                     mHyphenationFrequency = a.getInt(attr, Layout.HYPHENATION_FREQUENCY_NONE);
                     break;
 
-                case com.android.internal.R.styleable.TextView_autoSizeText:
+                case com.android.internal.R.styleable.TextView_autoSizeTextType:
                     mAutoSizeTextType = a.getInt(attr, AUTO_SIZE_TEXT_TYPE_NONE);
                     break;
 
                 case com.android.internal.R.styleable.TextView_autoSizeStepGranularity:
-                    mAutoSizeStepGranularityInPx = a.getDimensionPixelSize(attr, 0);
+                    autoSizeStepGranularityInPx = a.getDimensionPixelSize(attr,
+                        UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE);
                     break;
 
                 case com.android.internal.R.styleable.TextView_autoSizeMinTextSize:
-                    mAutoSizeMinTextSizeInPx = a.getDimensionPixelSize(attr, 0);
+                    autoSizeMinTextSizeInPx = a.getDimensionPixelSize(attr,
+                        UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE);
                     break;
 
                 case com.android.internal.R.styleable.TextView_autoSizeMaxTextSize:
-                    mAutoSizeMaxTextSizeInPx = a.getDimensionPixelSize(attr, 0);
+                    autoSizeMaxTextSizeInPx = a.getDimensionPixelSize(attr,
+                        UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE);
                     break;
 
                 case com.android.internal.R.styleable.TextView_autoSizePresetSizes:
@@ -1320,7 +1343,7 @@
                     if (autoSizeStepSizeArrayResId > 0) {
                         final TypedArray autoSizePreDefTextSizes = a.getResources()
                                 .obtainTypedArray(autoSizeStepSizeArrayResId);
-                        setupAutoSizePresetSizes(autoSizePreDefTextSizes);
+                        setupAutoSizeUniformPresetSizes(autoSizePreDefTextSizes);
                         autoSizePreDefTextSizes.recycle();
                     }
                     break;
@@ -1558,6 +1581,10 @@
         }
 
         setText(text, bufferType);
+        if (fromResourceId) {
+            mTextFromResource = true;
+        }
+
         if (hint != null) setHint(hint);
 
         /*
@@ -1598,40 +1625,78 @@
             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
         }
 
-        setupAutoSizeText();
+        if (supportsAutoSizeText()) {
+            if (mAutoSizeTextType == AUTO_SIZE_TEXT_TYPE_UNIFORM) {
+                // If uniform auto-size has been specified but preset values have not been set then
+                // replace the auto-size configuration values that have not been specified with the
+                // defaults.
+                if (!mHasPresetAutoSizeValues) {
+                    final DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
+
+                    if (autoSizeMinTextSizeInPx == UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE) {
+                        autoSizeMinTextSizeInPx = (int) TypedValue.applyDimension(
+                                TypedValue.COMPLEX_UNIT_SP,
+                                DEFAULT_AUTO_SIZE_MIN_TEXT_SIZE_IN_SP,
+                                displayMetrics);
+                    }
+
+                    if (autoSizeMaxTextSizeInPx == UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE) {
+                        autoSizeMaxTextSizeInPx = (int) TypedValue.applyDimension(
+                                TypedValue.COMPLEX_UNIT_SP,
+                                DEFAULT_AUTO_SIZE_MAX_TEXT_SIZE_IN_SP,
+                                displayMetrics);
+                    }
+
+                    if (autoSizeMinTextSizeInPx == UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE) {
+                        autoSizeStepGranularityInPx = DEFAULT_AUTO_SIZE_GRANULARITY_IN_PX;
+                    }
+
+                    validateAndSetAutoSizeTextTypeUniformConfiguration(autoSizeMinTextSizeInPx,
+                            autoSizeMaxTextSizeInPx,
+                            autoSizeStepGranularityInPx);
+                }
+
+                setupAutoSizeText();
+            }
+        } else {
+            mAutoSizeTextType = AUTO_SIZE_TEXT_TYPE_NONE;
+        }
     }
 
     /**
      * Specify whether this widget should automatically scale the text to try to perfectly fit
-     * within the layout bounds by taking into account the auto-size configuration.
+     * within the layout bounds by using the default auto-size configuration.
      *
      * @param autoSizeTextType the type of auto-size. Must be one of
      *        {@link TextView#AUTO_SIZE_TEXT_TYPE_NONE} or
      *        {@link TextView#AUTO_SIZE_TEXT_TYPE_UNIFORM}
      *
-     * @attr ref android.R.styleable#TextView_autoSizeText
+     * @attr ref android.R.styleable#TextView_autoSizeTextType
      *
      * @see #getAutoSizeTextType()
      */
-    public void setAutoSizeTextType(@AutoSizeTextType int autoSizeTextType) {
+    public void setAutoSizeTextTypeWithDefaults(@AutoSizeTextType int autoSizeTextType) {
         if (supportsAutoSizeText()) {
             switch (autoSizeTextType) {
                 case AUTO_SIZE_TEXT_TYPE_NONE:
-                    if (mAutoSizeTextType != AUTO_SIZE_TEXT_TYPE_NONE) {
-                        // Clear all auto-size configuration
-                        mAutoSizeTextType = AUTO_SIZE_TEXT_TYPE_NONE;
-                        mAutoSizeMinTextSizeInPx = 0;
-                        mAutoSizeMaxTextSizeInPx = 0;
-                        mAutoSizeStepGranularityInPx = 0;
-                        mAutoSizeTextSizesInPx = EmptyArray.INT;
-                        mNeedsAutoSizeText = false;
-                    }
+                    clearAutoSizeConfiguration();
                     break;
                 case AUTO_SIZE_TEXT_TYPE_UNIFORM:
-                    if (mAutoSizeTextType != AUTO_SIZE_TEXT_TYPE_UNIFORM) {
-                        mAutoSizeTextType = AUTO_SIZE_TEXT_TYPE_UNIFORM;
-                        setupAutoSizeText();
-                    }
+                    final DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
+                    final int autoSizeMinTextSizeInPx = (int) TypedValue.applyDimension(
+                            TypedValue.COMPLEX_UNIT_SP,
+                            DEFAULT_AUTO_SIZE_MIN_TEXT_SIZE_IN_SP,
+                            displayMetrics);
+                    final int autoSizeMaxTextSizeInPx = (int) TypedValue.applyDimension(
+                            TypedValue.COMPLEX_UNIT_SP,
+                            DEFAULT_AUTO_SIZE_MAX_TEXT_SIZE_IN_SP,
+                            displayMetrics);
+
+                    validateAndSetAutoSizeTextTypeUniformConfiguration(
+                            autoSizeMinTextSizeInPx,
+                            autoSizeMaxTextSizeInPx,
+                            DEFAULT_AUTO_SIZE_GRANULARITY_IN_PX);
+                    setupAutoSizeText();
                     break;
                 default:
                     throw new IllegalArgumentException(
@@ -1641,15 +1706,122 @@
     }
 
     /**
+     * Specify whether this widget should automatically scale the text to try to perfectly fit
+     * within the layout bounds. If all the configuration params are valid the type of auto-size is
+     * set to {@link #AUTO_SIZE_TEXT_TYPE_UNIFORM}.
+     *
+     * @param autoSizeMinTextSize the minimum text size available for auto-size
+     * @param autoSizeMaxTextSize the maximum text size available for auto-size
+     * @param autoSizeStepGranularity the auto-size step granularity. It is used in conjunction with
+     *                                the minimum and maximum text size in order to build the set of
+     *                                text sizes the system uses to choose from when auto-sizing
+     * @param unit the desired dimension unit for all sizes above. See {@link TypedValue} for the
+     *             possible dimension units
+     *
+     * @throws IllegalArgumentException if any of the configuration params are invalid.
+     *
+     * @attr ref android.R.styleable#TextView_autoSizeTextType
+     * @attr ref android.R.styleable#TextView_autoSizeMinTextSize
+     * @attr ref android.R.styleable#TextView_autoSizeMaxTextSize
+     * @attr ref android.R.styleable#TextView_autoSizeStepGranularity
+     *
+     * @see #setAutoSizeTextTypeWithDefaults(int)
+     * @see #setAutoSizeTextTypeUniformWithPresetSizes(int[], int)
+     * @see #getAutoSizeMinTextSize()
+     * @see #getAutoSizeMaxTextSize()
+     * @see #getAutoSizeStepGranularity()
+     * @see #getAutoSizeTextAvailableSizes()
+     */
+    public void setAutoSizeTextTypeUniformWithConfiguration(
+            int autoSizeMinTextSize,
+            int autoSizeMaxTextSize,
+            int autoSizeStepGranularity,
+            int unit) throws IllegalArgumentException {
+        if (supportsAutoSizeText()) {
+            final DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
+            final int autoSizeMinTextSizeInPx = (int) TypedValue.applyDimension(
+                    unit, autoSizeMinTextSize, displayMetrics);
+            final int autoSizeMaxTextSizeInPx = (int) TypedValue.applyDimension(
+                    unit, autoSizeMaxTextSize, displayMetrics);
+            final int autoSizeStepGranularityInPx = (int) TypedValue.applyDimension(
+                    unit, autoSizeStepGranularity, displayMetrics);
+
+            validateAndSetAutoSizeTextTypeUniformConfiguration(autoSizeMinTextSizeInPx,
+                    autoSizeMaxTextSizeInPx,
+                    autoSizeStepGranularityInPx);
+            setupAutoSizeText();
+        }
+    }
+
+    /**
+     * Specify whether this widget should automatically scale the text to try to perfectly fit
+     * within the layout bounds. If at least one value from the <code>presetSizes</code> is valid
+     * then the type of auto-size is set to {@link #AUTO_SIZE_TEXT_TYPE_UNIFORM}.
+     *
+     * @param presetSizes an {@code int} array of sizes in pixels
+     * @param unit the desired dimension unit for the preset sizes above. See {@link TypedValue} for
+     *             the possible dimension units
+     *
+     * @throws IllegalArgumentException if all of the <code>presetSizes</code> are invalid.
+     *
+     * @attr ref android.R.styleable#TextView_autoSizeTextType
+     * @attr ref android.R.styleable#TextView_autoSizePresetSizes
+     *
+     * @see #setAutoSizeTextTypeWithDefaults(int)
+     * @see #setAutoSizeTextTypeUniformWithConfiguration(int, int, int, int)
+     * @see #getAutoSizeMinTextSize()
+     * @see #getAutoSizeMaxTextSize()
+     * @see #getAutoSizeTextAvailableSizes()
+     */
+    public void setAutoSizeTextTypeUniformWithPresetSizes(@NonNull int[] presetSizes, int unit)
+            throws IllegalArgumentException {
+        if (supportsAutoSizeText()) {
+            final int presetSizesLength = presetSizes.length;
+            if (presetSizesLength > 0) {
+                int[] presetSizesInPx = new int[presetSizesLength];
+
+                if (unit == TypedValue.COMPLEX_UNIT_PX) {
+                    presetSizesInPx = Arrays.copyOf(presetSizes, presetSizesLength);
+                } else {
+                    final DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
+                    // Convert all to sizes to pixels.
+                    for (int i = 0; i < presetSizesLength; i++) {
+                        presetSizesInPx[i] = (int) TypedValue.applyDimension(unit, presetSizes[i],
+                            displayMetrics);
+                    }
+                }
+
+                mAutoSizeTextSizesInPx = cleanupAutoSizePresetSizes(presetSizesInPx);
+                final int sizesLength = mAutoSizeTextSizesInPx.length;
+                mHasPresetAutoSizeValues = sizesLength > 0;
+                if (mHasPresetAutoSizeValues) {
+                    mAutoSizeTextType = AUTO_SIZE_TEXT_TYPE_UNIFORM;
+                    mAutoSizeMinTextSizeInPx = mAutoSizeTextSizesInPx[0];
+                    mAutoSizeMaxTextSizeInPx = mAutoSizeTextSizesInPx[sizesLength - 1];
+                    mAutoSizeStepGranularityInPx = UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE;
+                } else {
+                    throw new IllegalArgumentException("None of the preset sizes is valid: "
+                        + Arrays.toString(presetSizes));
+                }
+            } else {
+                mHasPresetAutoSizeValues = false;
+            }
+            setupAutoSizeText();
+        }
+    }
+
+    /**
      * Returns the type of auto-size set for this widget.
      *
      * @return an {@code int} corresponding to one of the auto-size types:
      *         {@link TextView#AUTO_SIZE_TEXT_TYPE_NONE} or
      *         {@link TextView#AUTO_SIZE_TEXT_TYPE_UNIFORM}
      *
-     * @attr ref android.R.styleable#TextView_autoSizeText
+     * @attr ref android.R.styleable#TextView_autoSizeTextType
      *
-     * @see #setAutoSizeTextType(int)
+     * @see #setAutoSizeTextTypeWithDefaults(int)
+     * @see #setAutoSizeTextTypeUniformWithConfiguration(int, int, int, int)
+     * @see #setAutoSizeTextTypeUniformWithPresetSizes(int[], int)
      */
     @AutoSizeTextType
     public int getAutoSizeTextType() {
@@ -1657,155 +1829,53 @@
     }
 
     /**
-     * Sets the auto-size step granularity. It is used in conjunction with auto-size minimum
-     * and maximum text size in order to build the set of text sizes the system uses to choose
-     * from when auto-sizing.
-     *
-     * @param unit the desired dimension unit. See {@link TypedValue} for the possible
-     *             dimension units
-     * @param size the desired size in the given units
+     * @return the current auto-size step granularity in pixels.
      *
      * @attr ref android.R.styleable#TextView_autoSizeStepGranularity
      *
-     * @see #getAutoSizeStepGranularity()
-     * @see #setAutoSizeMinTextSize(int, float)
-     * @see #setAutoSizeMaxTextSize(int, float)
-     */
-    public void setAutoSizeStepGranularity(int unit, float size) {
-        if (supportsAutoSizeText()) {
-            mAutoSizeStepGranularityInPx = (int) TypedValue.applyDimension(
-                    unit, size, getResources().getDisplayMetrics());
-            mHasPresetAutoSizeValues = false;
-            setupAutoSizeText();
-        }
-    }
-
-    /**
-     * @return the current auto-size step granularity in pixels.
-     *
-     * @see #setAutoSizeStepGranularity(int, float)
+     * @see #setAutoSizeTextTypeUniformWithConfiguration(int, int, int, int)
      */
     public int getAutoSizeStepGranularity() {
         return mAutoSizeStepGranularityInPx;
     }
 
     /**
-     * Sets the minimum text size to be used in conjunction with auto-size maximum text size and
-     * auto-size step granularity in order to build the set of text sizes the system uses to choose
-     * from when auto-sizing.
-     *
-     * @param unit the desired dimension unit. See {@link TypedValue} for the possible
-     *             dimension units
-     * @param size the desired size in the given units
+     * @return the current auto-size minimum text size in pixels (the default is 12sp). Note that
+     *         if auto-size has not been configured this function returns {@code -1}.
      *
      * @attr ref android.R.styleable#TextView_autoSizeMinTextSize
      *
-     * @see #getAutoSizeMinTextSize()
-     * @see #setAutoSizeMaxTextSize(int, float)
-     * @see #setAutoSizeStepGranularity(int, float)
-     */
-    public void setAutoSizeMinTextSize(int unit, float size) {
-        if (supportsAutoSizeText()) {
-            mAutoSizeMinTextSizeInPx = (int) TypedValue.applyDimension(
-                    unit, size, getResources().getDisplayMetrics());
-            mHasPresetAutoSizeValues = false;
-            setupAutoSizeText();
-        }
-    }
-
-    /**
-     * @return the current auto-size minimum text size in pixels (the default is 12sp). Note that
-     *         if auto-size has not been configured this function returns {@code 0}.
-     *
-     * @see #setAutoSizeMinTextSize(int, float)
+     * @see #setAutoSizeTextTypeUniformWithConfiguration(int, int, int, int)
+     * @see #setAutoSizeTextTypeUniformWithPresetSizes(int[], int)
      */
     public int getAutoSizeMinTextSize() {
         return mAutoSizeMinTextSizeInPx;
     }
 
     /**
-     * Sets the maximum text size to be used in conjunction with auto-size minimum text size and
-     * auto-size step granularity in order to build the set of text sizes the system uses to choose
-     * from when auto-sizing.
-     *
-     * @param unit the desired dimension unit. See {@link TypedValue} for the possible
-     *             dimension units
-     * @param size the desired size in the given units
+     * @return the current auto-size maximum text size in pixels (the default is 112sp). Note that
+     *         if auto-size has not been configured this function returns {@code -1}.
      *
      * @attr ref android.R.styleable#TextView_autoSizeMaxTextSize
      *
-     * @see #getAutoSizeMaxTextSize()
-     * @see #setAutoSizeMinTextSize(int, float)
-     * @see #setAutoSizeStepGranularity(int, float)
-     */
-    public void setAutoSizeMaxTextSize(int unit, float size) {
-        if (supportsAutoSizeText()) {
-            mAutoSizeMaxTextSizeInPx = (int) TypedValue.applyDimension(
-                    unit, size, getResources().getDisplayMetrics());
-            mHasPresetAutoSizeValues = false;
-            setupAutoSizeText();
-        }
-    }
-
-    /**
-     * @return the current auto-size maximum text size in pixels (the default is 112sp). Note that
-     *         if auto-size has not been configured this function returns {@code 0}.
-     *
-     * @see #setAutoSizeMaxTextSize(int, float)
+     * @see #setAutoSizeTextTypeUniformWithConfiguration(int, int, int, int)
+     * @see #setAutoSizeTextTypeUniformWithPresetSizes(int[], int)
      */
     public int getAutoSizeMaxTextSize() {
         return mAutoSizeMaxTextSizeInPx;
     }
 
     /**
-     * Sets a predefined array of sizes to be used when auto-sizing.
-     *
-     * <ul>Note:
-     * <li>when <code>presetSizes</code> is not empty then the auto-size algorithm will use the
-     * values provided here instead of calculating the values based on min, max and step size. Also
-     * the values will be de-duplicated, sorted and negative or zero values will be removed.
-     * <li>when <code>presetSizes</code> is empty then the auto-size algorithm will use the min, max
-     * and step size to build the set of available sizes to choose from. Note that if no values have
-     * been provided for any of min, max or step size then defaults will be used.
-     * </ul>
-     *
-     * @param presetSizes an {@code int} array of sizes in pixels
-     *
-     * @attr ref android.R.styleable#TextView_autoSizePresetSizes
-     *
-     * @see #getAutoSizeTextAvailableSizes()
-     */
-    public void setAutoSizeTextPresetSizes(@NonNull int[] presetSizes) {
-        if (supportsAutoSizeText()) {
-            if (presetSizes.length > 0) {
-                mAutoSizeTextSizesInPx = cleanupAutoSizePresetSizes(presetSizes);
-                final int sizesLength = mAutoSizeTextSizesInPx.length;
-                mHasPresetAutoSizeValues = sizesLength > 0;
-                if (mHasPresetAutoSizeValues) {
-                    mAutoSizeMinTextSizeInPx = mAutoSizeTextSizesInPx[0];
-                    mAutoSizeMaxTextSizeInPx = mAutoSizeTextSizesInPx[sizesLength - 1];
-                    mAutoSizeStepGranularityInPx = 0;
-                }
-            } else {
-                mHasPresetAutoSizeValues = false;
-            }
-            setupAutoSizeText();
-        }
-    }
-
-    /**
      * @return the current auto-size {@code int} sizes array (in pixels).
      *
-     * @see #setAutoSizeTextPresetSizes(int[])
-     * @see #setAutoSizeMinTextSize(int, float)
-     * @see #setAutoSizeMaxTextSize(int, float)
-     * @see #setAutoSizeStepGranularity(int, float)
+     * @see #setAutoSizeTextTypeUniformWithConfiguration(int, int, int, int)
+     * @see #setAutoSizeTextTypeUniformWithPresetSizes(int[], int)
      */
     public int[] getAutoSizeTextAvailableSizes() {
         return mAutoSizeTextSizesInPx;
     }
 
-    private void setupAutoSizePresetSizes(TypedArray textSizes) {
+    private void setupAutoSizeUniformPresetSizes(TypedArray textSizes) {
         final int textSizesLength = textSizes.length();
         final int[] parsedSizes = new int[textSizesLength];
 
@@ -1818,6 +1888,49 @@
         }
     }
 
+    /**
+     * If all params are valid then save the auto-size configuration.
+     *
+     * @throws IllegalArgumentException if any of the params are invalid
+     */
+    private void validateAndSetAutoSizeTextTypeUniformConfiguration(
+            int autoSizeMinTextSizeInPx,
+            int autoSizeMaxTextSizeInPx,
+            int autoSizeStepGranularityInPx) throws IllegalArgumentException {
+        // First validate.
+        if (autoSizeMinTextSizeInPx <= 0) {
+            throw new IllegalArgumentException("Minimum auto-size text size ("
+                + autoSizeMinTextSizeInPx  + "px) is less or equal to 0px)");
+        }
+
+        if (autoSizeMaxTextSizeInPx <= autoSizeMinTextSizeInPx) {
+            throw new IllegalArgumentException("Maximum auto-size text size ("
+                + autoSizeMaxTextSizeInPx + "px) is less or equal to minimum auto-size "
+                + "text size (" + autoSizeMinTextSizeInPx + "px)");
+        }
+
+        if (autoSizeStepGranularityInPx <= 0) {
+            throw new IllegalArgumentException("Minimum auto-size text size ("
+                + autoSizeStepGranularityInPx + "px) is less or equal to 0px)");
+        }
+
+        // All good, persist the configuration.
+        mAutoSizeTextType = AUTO_SIZE_TEXT_TYPE_UNIFORM;
+        mAutoSizeMinTextSizeInPx = autoSizeMinTextSizeInPx;
+        mAutoSizeMaxTextSizeInPx = autoSizeMaxTextSizeInPx;
+        mAutoSizeStepGranularityInPx = autoSizeStepGranularityInPx;
+        mHasPresetAutoSizeValues = false;
+    }
+
+    private void clearAutoSizeConfiguration() {
+        mAutoSizeTextType = AUTO_SIZE_TEXT_TYPE_NONE;
+        mAutoSizeMinTextSizeInPx = UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE;
+        mAutoSizeMaxTextSizeInPx = UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE;
+        mAutoSizeStepGranularityInPx = UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE;
+        mAutoSizeTextSizesInPx = EmptyArray.INT;
+        mNeedsAutoSizeText = false;
+    }
+
     // Returns distinct sorted positive values.
     private int[] cleanupAutoSizePresetSizes(int[] presetValues) {
         final int presetValuesLength = presetValues.length;
@@ -1846,33 +1959,6 @@
             // Calculate the sizes set based on minimum size, maximum size and step size if we do
             // not have a predefined set of sizes or if the current sizes array is empty.
             if (!mHasPresetAutoSizeValues || mAutoSizeTextSizesInPx.length == 0) {
-                // Set valid defaults.
-                if (mAutoSizeMinTextSizeInPx <= 0) {
-                    mAutoSizeMinTextSizeInPx = (int) TypedValue.applyDimension(
-                            TypedValue.COMPLEX_UNIT_SP,
-                            DEFAULT_AUTO_SIZE_MIN_TEXT_SIZE_IN_SP,
-                            getResources().getDisplayMetrics());
-                }
-
-                if (mAutoSizeMaxTextSizeInPx <= 0) {
-                    mAutoSizeMaxTextSizeInPx = (int) TypedValue.applyDimension(
-                            TypedValue.COMPLEX_UNIT_SP,
-                            DEFAULT_AUTO_SIZE_MAX_TEXT_SIZE_IN_SP,
-                            getResources().getDisplayMetrics());
-                }
-
-                if (mAutoSizeStepGranularityInPx <= 0) {
-                    mAutoSizeStepGranularityInPx = DEFAULT_AUTO_SIZE_GRANULARITY_IN_PX;
-                }
-
-                // Validate.
-                if (mAutoSizeMaxTextSizeInPx <= mAutoSizeMinTextSizeInPx) {
-                    throw new IllegalStateException("Maximum auto-size text size ("
-                            + mAutoSizeMaxTextSizeInPx
-                            + "px) is less or equal to minimum auto-size "
-                            + "text size (" + mAutoSizeMinTextSizeInPx + "px)");
-                }
-
                 // Calculate sizes to choose from based on the current auto-size configuration.
                 int autoSizeValuesLength = (int) Math.ceil(
                         (mAutoSizeMaxTextSizeInPx - mAutoSizeMinTextSizeInPx)
@@ -3244,7 +3330,7 @@
         String fontFamily = null;
         try {
             fontTypeface = ta.getFont(R.styleable.TextAppearance_fontFamily);
-        } catch (UnsupportedOperationException e) {
+        } catch (UnsupportedOperationException | Resources.NotFoundException e) {
             // Expected if it is not a font resource.
         }
         if (fontTypeface == null) {
@@ -4999,6 +5085,7 @@
 
     private void setText(CharSequence text, BufferType type,
                          boolean notifyBefore, int oldlen) {
+        mTextFromResource = false;
         if (text == null) {
             text = "";
         }
@@ -5143,6 +5230,9 @@
 
         if (needEditableForNotification) {
             sendAfterTextChanged((Editable) text);
+        } else {
+            // Always notify AutoFillManager - it will return right away if auto-fill is disabled.
+            notifyAutoFillManagerAfterTextChanged();
         }
 
         // SelectionModifierCursorController depends on textCanBeSelected, which depends on text
@@ -5233,6 +5323,7 @@
     @android.view.RemotableViewMethod
     public final void setText(@StringRes int resid) {
         setText(getContext().getResources().getText(resid));
+        mTextFromResource = true;
     }
 
     /**
@@ -5259,6 +5350,7 @@
      */
     public final void setText(@StringRes int resid, BufferType type) {
         setText(getContext().getResources().getText(resid), type);
+        mTextFromResource = true;
     }
 
     /**
@@ -7953,9 +8045,9 @@
             TEMP_RECTF.setEmpty();
             TEMP_RECTF.right = maxWidth;
             TEMP_RECTF.bottom = maxHeight;
-            final float textSize = findLargestTextSizeWhichFits(TEMP_RECTF);
-            if (textSize != getTextSize()) {
-                setTextSizeInternal(TypedValue.COMPLEX_UNIT_PX, textSize);
+            final float optimalTextSize = findLargestTextSizeWhichFits(TEMP_RECTF);
+            if (optimalTextSize != getTextSize()) {
+                setTextSizeInternal(TypedValue.COMPLEX_UNIT_PX, optimalTextSize);
             }
         }
     }
@@ -8127,7 +8219,7 @@
         // If we have a fixed width, we can just swap in a new text layout
         // if the text height stays the same or if the view height is fixed.
 
-        if (((mLayoutParams.width != LayoutParams.WRAP_CONTENT && mLayoutParams.width != 0)
+        if ((mLayoutParams.width != LayoutParams.WRAP_CONTENT
                 || (mMaxWidthMode == mMinWidthMode && mMaxWidth == mMinWidth))
                 && (mHint == null || mHintLayout != null)
                 && (mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight() > 0)) {
@@ -9031,9 +9123,23 @@
                 list.get(i).afterTextChanged(text);
             }
         }
+
+        // Always notify AutoFillManager - it will return right away if auto-fill is disabled.
+        notifyAutoFillManagerAfterTextChanged();
+
         hideErrorIfUnchanged();
     }
 
+    private void notifyAutoFillManagerAfterTextChanged() {
+        final AutoFillManager afm = mContext.getSystemService(AutoFillManager.class);
+        if (afm != null) {
+            if (DEBUG_AUTOFILL) {
+                Log.v(LOG_TAG, "sendAfterTextChanged(): notify AFM for text=" + mText);
+            }
+            afm.valueChanged(TextView.this);
+        }
+    }
+
     void updateAfterEdit() {
         invalidate();
         int curs = getSelectionStart();
@@ -9772,16 +9878,6 @@
         }
     }
 
-    /**
-     * @return true if the user has explicitly allowed accessibility services
-     * to speak passwords.
-     */
-    private boolean shouldSpeakPasswordsForAccessibility() {
-        return (Settings.Secure.getIntForUser(mContext.getContentResolver(),
-                Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD, 0,
-                UserHandle.USER_CURRENT_OR_SELF) == 1);
-    }
-
     @Override
     public CharSequence getAccessibilityClassName() {
         return TextView.class.getName();
@@ -9804,14 +9900,7 @@
         final boolean isPassword = hasPasswordTransformationMethod()
                 || isPasswordInputType(getInputType());
         if (forAutoFill) {
-            // TODO(b/33197203, b/33269702): temporary set it as not sanitized until
-            // AssistStructure automaticaly sets sanitization based on text coming from resources
-            structure.setSanitized(!isPassword);
-            if (mAutoFillChangeWatcher == null && isTextEditable()) {
-                mAutoFillChangeWatcher = new AutoFillChangeWatcher();
-                addTextChangedListener(mAutoFillChangeWatcher);
-                // TODO(b/33197203): remove mAutoFillValueListener auto-fill session is finished
-            }
+            structure.setSanitized(mTextFromResource);
         }
 
         if (!isPassword || forAutoFill) {
@@ -9918,6 +10007,7 @@
                     AssistStructure.ViewNode.TEXT_COLOR_UNDEFINED /* bgColor */, style);
         }
         structure.setHint(getHint());
+        structure.setInputType(getInputType());
     }
 
     // TODO(b/33197203): add unit/CTS tests for auto-fill methods
@@ -9932,9 +10022,8 @@
     }
 
     @Override
-    @Nullable
-    public AutoFillType getAutoFillType() {
-        return isTextEditable() ? AutoFillType.forText(getInputType()) : null;
+    public @AutofillType int getAutofillType() {
+        return isTextEditable() ? AUTOFILL_TYPE_TEXT : AUTOFILL_TYPE_NONE;
     }
 
     @Override
@@ -10251,7 +10340,7 @@
                         Selection.setSelection((Spannable) text, start, end);
                         // Make sure selection mode is engaged.
                         if (mEditor != null) {
-                            mEditor.startSelectionActionModeAsync();
+                            mEditor.startSelectionActionMode();
                         }
                         return true;
                     }
@@ -10356,13 +10445,7 @@
             return mHint;
         }
 
-        // Check whether we need to bypass the transformation
-        // method and expose unobscured text.
-        if (hasPasswordTransformationMethod() && shouldSpeakPasswordsForAccessibility()) {
-            return mText;
-        }
-
-        // Otherwise, speak whatever text is being displayed.
+        // Otherwise, return whatever text is being displayed.
         return mTransformed;
     }
 
@@ -11444,30 +11527,6 @@
         }
     }
 
-    // TODO(b/33197203): implements SpanWatcher too?
-    private final class AutoFillChangeWatcher implements TextWatcher {
-
-        private final AutoFillManager mAfm = mContext.getSystemService(AutoFillManager.class);
-
-        @Override
-        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
-        }
-
-        @Override
-        public void onTextChanged(CharSequence s, int start, int before, int count) {
-        }
-
-        @Override
-        public void afterTextChanged(Editable s) {
-            if (mAfm != null) {
-                if (DEBUG_AUTOFILL) {
-                    Log.v(LOG_TAG, "AutoFillChangeWatcher.afterTextChanged(): s=" + s);
-                }
-                mAfm.valueChanged(TextView.this);
-            }
-        }
-    }
-
     private class ChangeWatcher implements TextWatcher, SpanWatcher {
 
         private CharSequence mBeforeText;
@@ -11479,9 +11538,7 @@
                         + " before=" + before + " after=" + after + ": " + buffer);
             }
 
-            if (AccessibilityManager.getInstance(mContext).isEnabled()
-                    && ((!isPasswordInputType(getInputType()) && !hasPasswordTransformationMethod())
-                            || shouldSpeakPasswordsForAccessibility())) {
+            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
                 mBeforeText = buffer.toString();
             }
 
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index 9f38b04..3a19f21 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -23,12 +23,16 @@
 import android.annotation.Widget;
 import android.content.Context;
 import android.content.res.TypedArray;
+import android.icu.util.Calendar;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.AttributeSet;
 import android.util.MathUtils;
 import android.view.View;
+import android.view.ViewStructure;
 import android.view.accessibility.AccessibilityEvent;
+import android.view.autofill.AutoFillManager;
+import android.view.autofill.AutoFillValue;
 
 import com.android.internal.R;
 
@@ -107,6 +111,11 @@
     public TimePicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
 
+        // DatePicker is important by default, unless app developer overrode attribute.
+        if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
+            setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
+        }
+
         final TypedArray a = context.obtainStyledAttributes(
                 attrs, R.styleable.TimePicker, defStyleAttr, defStyleRes);
         final boolean isDialogMode = a.getBoolean(R.styleable.TimePicker_dialogMode, false);
@@ -132,6 +141,12 @@
                         this, context, attrs, defStyleAttr, defStyleRes);
                 break;
         }
+        mDelegate.setAutoFillChangeListener((v, h, m) -> {
+            final AutoFillManager afm = context.getSystemService(AutoFillManager.class);
+            if (afm != null) {
+                afm.valueChanged(this);
+            }
+        });
     }
 
     /**
@@ -348,12 +363,16 @@
         void setMinute(@IntRange(from = 0, to = 59) int minute);
         int getMinute();
 
+        void setDate(long date);
+        long getDate();
+
         void setIs24Hour(boolean is24Hour);
         boolean is24Hour();
 
         boolean validateInput();
 
         void setOnTimeChangedListener(OnTimeChangedListener onTimeChangedListener);
+        void setAutoFillChangeListener(OnTimeChangedListener autoFillChangeListener);
 
         void setEnabled(boolean enabled);
         boolean isEnabled();
@@ -398,6 +417,7 @@
         protected final Locale mLocale;
 
         protected OnTimeChangedListener mOnTimeChangedListener;
+        protected OnTimeChangedListener mAutoFillChangeListener;
 
         public AbstractTimePickerDelegate(@NonNull TimePicker delegator, @NonNull Context context) {
             mDelegator = delegator;
@@ -410,6 +430,27 @@
             mOnTimeChangedListener = callback;
         }
 
+        @Override
+        public void setAutoFillChangeListener(OnTimeChangedListener callback) {
+            mAutoFillChangeListener = callback;
+        }
+
+        @Override
+        public void setDate(long date) {
+            Calendar cal = Calendar.getInstance(mLocale);
+            cal.setTimeInMillis(date);
+            setHour(cal.get(Calendar.HOUR_OF_DAY));
+            setMinute(cal.get(Calendar.MINUTE));
+        }
+
+        @Override
+        public long getDate() {
+            Calendar cal = Calendar.getInstance(mLocale);
+            cal.set(Calendar.HOUR_OF_DAY, getHour());
+            cal.set(Calendar.MINUTE, getMinute());
+            return cal.getTimeInMillis();
+        }
+
         protected static class SavedState extends View.BaseSavedState {
             private final int mHour;
             private final int mMinute;
@@ -474,4 +515,31 @@
             };
         }
     }
+
+    // TODO(b/33197203): add unit/CTS tests for auto-fill methods (and make sure they handle enable)
+
+    @Override
+    public void dispatchProvideAutoFillStructure(ViewStructure structure, int flags) {
+        // This view is self-sufficient for auto-fill, so it needs to call
+        // onProvideAutoFillStructure() to fill itself, but it does not need to call
+        // dispatchProvideAutoFillStructure() to fill its children.
+        onProvideAutoFillStructure(structure, flags);
+    }
+
+    @Override
+    public void autoFill(AutoFillValue value) {
+        if (!isEnabled()) return;
+
+        mDelegate.setDate(value.getDateValue());
+    }
+
+    @Override
+    public @AutofillType int getAutofillType() {
+        return isEnabled() ? AUTOFILL_TYPE_DATE : AUTOFILL_TYPE_NONE;
+    }
+
+    @Override
+    public AutoFillValue getAutoFillValue() {
+        return isEnabled() ? AutoFillValue.forDate(mDelegate.getDate()) : null;
+    }
 }
diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java
index 3a09063..3605585 100644
--- a/core/java/android/widget/TimePickerClockDelegate.java
+++ b/core/java/android/widget/TimePickerClockDelegate.java
@@ -671,6 +671,9 @@
         if (mOnTimeChangedListener != null) {
             mOnTimeChangedListener.onTimeChanged(mDelegator, getHour(), getMinute());
         }
+        if (mAutoFillChangeListener != null) {
+            mAutoFillChangeListener.onTimeChanged(mDelegator, getHour(), getMinute());
+        }
     }
 
     private void tryVibrate() {
@@ -813,8 +816,12 @@
     private final OnValueSelectedListener mOnValueSelectedListener = new OnValueSelectedListener() {
         @Override
         public void onValueSelected(int pickerType, int newValue, boolean autoAdvance) {
+            boolean valueChanged = false;
             switch (pickerType) {
                 case RadialTimePickerView.HOURS:
+                    if (getHour() != newValue) {
+                        valueChanged = true;
+                    }
                     final boolean isTransition = mAllowAutoAdvance && autoAdvance;
                     setHourInternal(newValue, FROM_RADIAL_PICKER, !isTransition);
                     if (isTransition) {
@@ -825,11 +832,14 @@
                     }
                     break;
                 case RadialTimePickerView.MINUTES:
+                    if (getMinute() != newValue) {
+                        valueChanged = true;
+                    }
                     setMinuteInternal(newValue, FROM_RADIAL_PICKER);
                     break;
             }
 
-            if (mOnTimeChangedListener != null) {
+            if (mOnTimeChangedListener != null && valueChanged) {
                 mOnTimeChangedListener.onTimeChanged(mDelegator, getHour(), getMinute());
             }
         }
diff --git a/core/java/android/widget/TimePickerSpinnerDelegate.java b/core/java/android/widget/TimePickerSpinnerDelegate.java
index 7ef54a5..813c30e3 100644
--- a/core/java/android/widget/TimePickerSpinnerDelegate.java
+++ b/core/java/android/widget/TimePickerSpinnerDelegate.java
@@ -86,7 +86,7 @@
         inflater.inflate(layoutResourceId, mDelegator, true);
 
         // hour
-        mHourSpinner = (NumberPicker) delegator.findViewById(R.id.hour);
+        mHourSpinner = delegator.findViewById(R.id.hour);
         mHourSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
             public void onValueChange(NumberPicker spinner, int oldVal, int newVal) {
                 updateInputState();
@@ -100,17 +100,17 @@
                 onTimeChanged();
             }
         });
-        mHourSpinnerInput = (EditText) mHourSpinner.findViewById(R.id.numberpicker_input);
+        mHourSpinnerInput = mHourSpinner.findViewById(R.id.numberpicker_input);
         mHourSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT);
 
         // divider (only for the new widget style)
-        mDivider = (TextView) mDelegator.findViewById(R.id.divider);
+        mDivider = mDelegator.findViewById(R.id.divider);
         if (mDivider != null) {
             setDividerText();
         }
 
         // minute
-        mMinuteSpinner = (NumberPicker) mDelegator.findViewById(R.id.minute);
+        mMinuteSpinner = mDelegator.findViewById(R.id.minute);
         mMinuteSpinner.setMinValue(0);
         mMinuteSpinner.setMaxValue(59);
         mMinuteSpinner.setOnLongPressUpdateInterval(100);
@@ -138,7 +138,7 @@
                 onTimeChanged();
             }
         });
-        mMinuteSpinnerInput = (EditText) mMinuteSpinner.findViewById(R.id.numberpicker_input);
+        mMinuteSpinnerInput = mMinuteSpinner.findViewById(R.id.numberpicker_input);
         mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT);
 
         // Get the localized am/pm strings and use them in the spinner.
@@ -173,13 +173,13 @@
                     onTimeChanged();
                 }
             });
-            mAmPmSpinnerInput = (EditText) mAmPmSpinner.findViewById(R.id.numberpicker_input);
+            mAmPmSpinnerInput = mAmPmSpinner.findViewById(R.id.numberpicker_input);
             mAmPmSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_DONE);
         }
 
         if (isAmPmAtStart()) {
             // Move the am/pm view to the beginning
-            ViewGroup amPmParent = (ViewGroup) delegator.findViewById(R.id.timePickerLayout);
+            ViewGroup amPmParent = delegator.findViewById(R.id.timePickerLayout);
             amPmParent.removeView(amPmView);
             amPmParent.addView(amPmView, 0);
             // Swap layout margins if needed. They may be not symmetrical (Old Standard Theme
@@ -495,6 +495,9 @@
             mOnTimeChangedListener.onTimeChanged(mDelegator, getHour(),
                     getMinute());
         }
+        if (mAutoFillChangeListener != null) {
+            mAutoFillChangeListener.onTimeChanged(mDelegator, getHour(), getMinute());
+        }
     }
 
     private void updateHourControl() {
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index 789e60b..bf0601d 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -299,7 +299,7 @@
         if (mNextView == null) {
             throw new RuntimeException("This Toast was not created with Toast.makeText()");
         }
-        TextView tv = (TextView) mNextView.findViewById(com.android.internal.R.id.message);
+        TextView tv = mNextView.findViewById(com.android.internal.R.id.message);
         if (tv == null) {
             throw new RuntimeException("This Toast was not created with Toast.makeText()");
         }
diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java
index b973324..7b2efea 100644
--- a/core/java/android/widget/VideoView.java
+++ b/core/java/android/widget/VideoView.java
@@ -16,11 +16,13 @@
 
 package android.widget;
 
+import android.annotation.NonNull;
 import android.app.AlertDialog;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.res.Resources;
 import android.graphics.Canvas;
+import android.media.AudioAttributes;
 import android.media.AudioManager;
 import android.media.Cea708CaptionRenderer;
 import android.media.ClosedCaptionRenderer;
@@ -67,6 +69,14 @@
  * {@link android.app.Activity#onRestoreInstanceState}.<p>
  * Also note that the audio session id (from {@link #getAudioSessionId}) may
  * change from its previously returned value when the VideoView is restored.
+ * <p>
+ * By default, VideoView requests audio focus with {@link AudioManager#AUDIOFOCUS_GAIN}. Use
+ * {@link #setAudioFocusRequest(int)} to change this behavior.
+ * <p>
+ * The default {@link AudioAttributes} used during playback have a usage of
+ * {@link AudioAttributes#USAGE_MEDIA} and a content type of
+ * {@link AudioAttributes#CONTENT_TYPE_MOVIE}, use {@link #setAudioAttributes(AudioAttributes)} to
+ * modify them.
  */
 public class VideoView extends SurfaceView
         implements MediaPlayerControl, SubtitleController.Anchor {
@@ -113,6 +123,9 @@
     private boolean mCanPause;
     private boolean mCanSeekBack;
     private boolean mCanSeekForward;
+    private AudioManager mAudioManager;
+    private int mAudioFocusType = AudioManager.AUDIOFOCUS_GAIN; // legacy focus gain
+    private AudioAttributes mAudioAttributes;
 
     /** Subtitle rendering widget overlaid on top of the video. */
     private RenderingWidget mSubtitleWidget;
@@ -138,6 +151,10 @@
         mVideoWidth = 0;
         mVideoHeight = 0;
 
+        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+        mAudioAttributes = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA)
+                .setContentType(AudioAttributes.CONTENT_TYPE_MOVIE).build();
+
         getHolder().addCallback(mSHCallback);
         getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
 
@@ -260,6 +277,41 @@
     }
 
     /**
+     * Sets which type of audio focus will be requested during the playback, or configures playback
+     * to not request audio focus. Valid values for focus requests are
+     * {@link AudioManager#AUDIOFOCUS_GAIN}, {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT},
+     * {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK}, and
+     * {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE}. Or use
+     * {@link AudioManager#AUDIOFOCUS_NONE} to express that audio focus should not be
+     * requested when playback starts. You can for instance use this when playing a silent animation
+     * through this class, and you don't want to affect other audio applications playing in the
+     * background.
+     * @param focusGain the type of audio focus gain that will be requested, or
+     *    {@link AudioManager#AUDIOFOCUS_NONE} to disable the use audio focus during playback.
+     */
+    public void setAudioFocusRequest(int focusGain) {
+        if (focusGain != AudioManager.AUDIOFOCUS_NONE
+                && focusGain != AudioManager.AUDIOFOCUS_GAIN
+                && focusGain != AudioManager.AUDIOFOCUS_GAIN_TRANSIENT
+                && focusGain != AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
+                && focusGain != AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE) {
+            throw new IllegalArgumentException("Illegal audio focus type " + focusGain);
+        }
+        mAudioFocusType = focusGain;
+    }
+
+    /**
+     * Sets the {@link AudioAttributes} to be used during the playback of the video.
+     * @param attributes non-null <code>AudioAttributes</code>.
+     */
+    public void setAudioAttributes(@NonNull AudioAttributes attributes) {
+        if (attributes == null) {
+            throw new IllegalArgumentException("Illegal null AudioAttributes");
+        }
+        mAudioAttributes = attributes;
+    }
+
+    /**
      * Adds an external subtitle source file (from the provided input stream.)
      *
      * Note that a single external subtitle source may contain multiple or no
@@ -301,8 +353,7 @@
             mMediaPlayer = null;
             mCurrentState = STATE_IDLE;
             mTargetState  = STATE_IDLE;
-            AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
-            am.abandonAudioFocus(null);
+            mAudioManager.abandonAudioFocus(null);
         }
     }
 
@@ -315,8 +366,10 @@
         // called start() previously
         release(false);
 
-        AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
-        am.requestAudioFocus(null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
+        if (mAudioFocusType != AudioManager.AUDIOFOCUS_NONE) {
+            // TODO this should have a focus listener
+            mAudioManager.requestAudioFocus(null, mAudioAttributes, mAudioFocusType, 0 /*flags*/);
+        }
 
         try {
             mMediaPlayer = new MediaPlayer();
@@ -345,7 +398,7 @@
             mCurrentBufferPercentage = 0;
             mMediaPlayer.setDataSource(mContext, mUri, mHeaders);
             mMediaPlayer.setDisplay(mSurfaceHolder);
-            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
+            mMediaPlayer.setAudioAttributes(mAudioAttributes);
             mMediaPlayer.setScreenOnWhilePlaying(true);
             mMediaPlayer.prepareAsync();
 
@@ -482,6 +535,9 @@
             if (mOnCompletionListener != null) {
                 mOnCompletionListener.onCompletion(mMediaPlayer);
             }
+            if (mAudioFocusType != AudioManager.AUDIOFOCUS_NONE) {
+                mAudioManager.abandonAudioFocus(null);
+            }
         }
     };
 
@@ -644,8 +700,9 @@
             if (cleartargetstate) {
                 mTargetState  = STATE_IDLE;
             }
-            AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
-            am.abandonAudioFocus(null);
+            if (mAudioFocusType != AudioManager.AUDIOFOCUS_NONE) {
+                mAudioManager.abandonAudioFocus(null);
+            }
         }
     }
 
diff --git a/core/java/android/widget/ZoomButtonsController.java b/core/java/android/widget/ZoomButtonsController.java
index 69b79971..1a3ca86 100644
--- a/core/java/android/widget/ZoomButtonsController.java
+++ b/core/java/android/widget/ZoomButtonsController.java
@@ -264,7 +264,7 @@
                 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         inflater.inflate(com.android.internal.R.layout.zoom_container, container);
 
-        mControls = (ZoomControls) container.findViewById(com.android.internal.R.id.zoomControls);
+        mControls = container.findViewById(com.android.internal.R.id.zoomControls);
         mControls.setOnZoomInClickListener(new OnClickListener() {
             public void onClick(View v) {
                 dismissControlsDelayed(ZOOM_CONTROLS_TIMEOUT);
diff --git a/core/java/com/android/internal/alsa/AlsaDevicesParser.java b/core/java/com/android/internal/alsa/AlsaDevicesParser.java
index 81b7943..5203723 100644
--- a/core/java/com/android/internal/alsa/AlsaDevicesParser.java
+++ b/core/java/com/android/internal/alsa/AlsaDevicesParser.java
@@ -184,7 +184,7 @@
         }
     }
 
-    private ArrayList<AlsaDeviceRecord> mDeviceRecords = new ArrayList<AlsaDeviceRecord>();
+    private final ArrayList<AlsaDeviceRecord> mDeviceRecords = new ArrayList<AlsaDeviceRecord>();
 
     public AlsaDevicesParser() {}
 
@@ -199,9 +199,11 @@
     //
     // Predicates
     //
+/*
    public boolean hasPlaybackDevices() {
         return mHasPlaybackDevices;
     }
+*/
 
     public boolean hasPlaybackDevices(int card) {
         for (AlsaDeviceRecord deviceRecord : mDeviceRecords) {
@@ -214,9 +216,11 @@
         return false;
     }
 
+/*
     public boolean hasCaptureDevices() {
         return mHasCaptureDevices;
     }
+*/
 
     public boolean hasCaptureDevices(int card) {
         for (AlsaDeviceRecord deviceRecord : mDeviceRecords) {
@@ -229,9 +233,11 @@
         return false;
     }
 
+/*
     public boolean hasMIDIDevices() {
         return mHasMIDIDevices;
     }
+*/
 
     public boolean hasMIDIDevices(int card) {
         for (AlsaDeviceRecord deviceRecord : mDeviceRecords) {
diff --git a/core/java/com/android/internal/alsa/LineTokenizer.java b/core/java/com/android/internal/alsa/LineTokenizer.java
index 43047a9..b395da9 100644
--- a/core/java/com/android/internal/alsa/LineTokenizer.java
+++ b/core/java/com/android/internal/alsa/LineTokenizer.java
@@ -23,7 +23,7 @@
 public class LineTokenizer {
     public static final int kTokenNotFound = -1;
 
-    private String mDelimiters = "";
+    private final String mDelimiters;
 
     public LineTokenizer(String delimiters) {
         mDelimiters = delimiters;
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 84c8f7a..c235ebd 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -23,15 +23,21 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.IntentSender;
 import android.content.IntentSender.SendIntentException;
 import android.content.ServiceConnection;
 import android.content.SharedPreferences;
 import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.LabeledIntent;
+import android.content.pm.LauncherApps;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ParceledListSlice;
 import android.content.pm.ResolveInfo;
+import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutManager;
 import android.database.DataSetObserver;
 import android.graphics.Color;
 import android.graphics.drawable.Drawable;
@@ -84,6 +90,14 @@
 public class ChooserActivity extends ResolverActivity {
     private static final String TAG = "ChooserActivity";
 
+    /**
+     * Boolean extra to change the following behavior: Normally, ChooserActivity finishes itself
+     * in onStop when launched in a new task. If this extra is set to true, we do not finish
+     * ourselves when onStop gets called.
+     */
+    public static final String EXTRA_PRIVATE_RETAIN_IN_ON_STOP
+            = "com.android.internal.app.ChooserActivity.EXTRA_PRIVATE_RETAIN_IN_ON_STOP";
+
     private static final boolean DEBUG = false;
 
     private static final int QUERY_TARGET_SERVICE_LIMIT = 5;
@@ -260,6 +274,7 @@
         }
 
         mPinnedSharedPrefs = getPinnedSharedPrefs(this);
+        setRetainInOnStop(intent.getBooleanExtra(EXTRA_PRIVATE_RETAIN_IN_ON_STOP, false));
         super.onCreate(savedInstanceState, target, title, defaultTitleRes, initialIntents,
                 null, false);
 
@@ -347,6 +362,7 @@
             mChooserListAdapter.addServiceResults(null, Lists.newArrayList(mCallerChooserTargets));
         }
         mChooserRowAdapter = new ChooserRowAdapter(mChooserListAdapter);
+        mChooserRowAdapter.updateRowScales();
         mChooserRowAdapter.registerDataSetObserver(new OffsetDataSetObserver(adapterView));
         adapterView.setAdapter(mChooserRowAdapter);
         if (listView != null) {
@@ -833,7 +849,9 @@
                 return false;
             }
             intent.setComponent(mChooserTarget.getComponentName());
-            intent.putExtras(mChooserTarget.getIntentExtras());
+            if (mChooserTarget.getIntentExtras() != null) {
+                intent.putExtras(mChooserTarget.getIntentExtras());
+            }
 
             // Important: we will ignore the target security checks in ActivityManager
             // if and only if the ChooserTarget's target package is the same package
@@ -916,6 +934,8 @@
         private static final int MAX_SERVICE_TARGETS = 8;
         private static final int MAX_TARGETS_PER_SERVICE = 4;
 
+        private boolean mAreChooserShortcutsRetrieved;
+
         private final List<ChooserTargetInfo> mServiceTargets = new ArrayList<>();
         private final List<TargetInfo> mCallerTargets = new ArrayList<>();
         private boolean mShowServiceTargets;
@@ -1007,6 +1027,21 @@
             if (mServiceTargets != null) {
                 pruneServiceTargets();
             }
+
+            if (DEBUG) Log.d(TAG, "Adding pushed chooser targets");
+
+            if (!mAreChooserShortcutsRetrieved) {
+                LauncherApps launcherApps = getLauncherApps();
+                LauncherApps.ShortcutQuery query = new LauncherApps.ShortcutQuery();
+                query.setIntent(getTargetIntent());
+                query.setQueryFlags(LauncherApps.ShortcutQuery.FLAG_MATCH_CHOOSER);
+                List<ShortcutInfo> shortcuts = launcherApps.getShortcuts(query,
+                        android.os.Process.myUserHandle());
+                if (DEBUG) Log.d(TAG, "Adding " + shortcuts.size() + " chooser shortcuts");
+                addShortcuts(shortcuts);
+                mAreChooserShortcutsRetrieved = true;
+            }
+
             if (DEBUG) Log.d(TAG, "List built querying services");
             queryTargetServices(this);
         }
@@ -1032,6 +1067,7 @@
 
         public int getServiceTargetCount() {
             if (!mShowServiceTargets) {
+                if (DEBUG) Log.d("TAG", "Hiding service targets");
                 return 0;
             }
             return Math.min(mServiceTargets.size(), MAX_SERVICE_TARGETS);
@@ -1123,6 +1159,71 @@
             notifyDataSetChanged();
         }
 
+        // TODO: Pushed targets need to be scored correctly
+        public void addShortcuts(List<ShortcutInfo> infos) {
+            for (ShortcutInfo info : infos) {
+                List<ChooserTarget> newTargets = new ArrayList<>();
+                final ComponentName cn = info.getActivity();
+                ActivityInfo ai;
+                ResolveInfo ri = new ResolveInfo();
+                if (cn != null) {
+                    try {
+                        ai = getPackageManager().getActivityInfo(cn, 0);
+                        ri.activityInfo = ai;
+                        UserManager userManager =
+                                (UserManager) getSystemService(Context.USER_SERVICE);
+                        ri.iconResourceId = ai.icon;
+                        ri.labelRes = ai.labelRes;
+                        ri.resolvePackageName = ai.packageName;
+                        ri.activityInfo.applicationInfo = new ApplicationInfo(
+                                ri.activityInfo.applicationInfo);
+                        ri.activityInfo.applicationInfo = ai.applicationInfo;
+                        ri.activityInfo.applicationInfo.uid = getUserId();
+                    } catch (PackageManager.NameNotFoundException ignored) {
+                        if (DEBUG) Log.d(TAG, "Package not found, skipping this shortcut");
+                        continue;
+                    }
+                }
+
+                DisplayResolveInfo resolveInfo = new DisplayResolveInfo(getTargetIntent(),
+                        ri,
+                        info.getShortLabel(),
+                        info.getLongLabel(),
+                        getTargetIntent());
+
+                int bestMatch = 0;
+                ComponentName bestComponent = null;
+                for (int i = 0; i < info.getChooserIntentFilters().length; i++) {
+                    int newMatch = info.getChooserIntentFilters()[i]
+                            .match(getContentResolver(), getTargetIntent(), false, TAG);
+                    if (DEBUG) Log.d(TAG, "A match was found with value: " + newMatch);
+                    if (newMatch > bestMatch) {
+                        bestMatch = newMatch;
+                        bestComponent = info.getChooserComponentNames()[i];
+                    }
+                }
+                if (bestMatch == 0) {
+                    Log.e(TAG, "Unexpectedly, no match was found for the provided chooser intent");
+                    return;
+                }
+
+                Bundle extrasToAdd =
+                        info.getChooserExtras() == null ? null: new Bundle(info.getChooserExtras());
+                if (DEBUG) Log.d(TAG, "Adding service target " + info.getShortLabel());
+                newTargets.add(new ChooserTarget(
+                        info.getShortLabel(),
+                        info.getIcon(),
+                        1,
+                        bestComponent,
+                        extrasToAdd));
+                addServiceResults(resolveInfo, newTargets);
+            }
+            if (mChooserRowAdapter != null) {
+                mChooserRowAdapter.updateRowScales();
+            }
+            setShowServiceTargets(true);
+        }
+
         /**
          * Set to true to reveal all service targets at once.
          */
@@ -1237,37 +1338,7 @@
                 @Override
                 public void onChanged() {
                     super.onChanged();
-                    final int rcount = getServiceTargetRowCount();
-                    if (mServiceTargetScale == null
-                            || mServiceTargetScale.length != rcount) {
-                        RowScale[] old = mServiceTargetScale;
-                        int oldRCount = old != null ? old.length : 0;
-                        mServiceTargetScale = new RowScale[rcount];
-                        if (old != null && rcount > 0) {
-                            System.arraycopy(old, 0, mServiceTargetScale, 0,
-                                    Math.min(old.length, rcount));
-                        }
-
-                        for (int i = rcount; i < oldRCount; i++) {
-                            old[i].cancelAnimation();
-                        }
-
-                        for (int i = oldRCount; i < rcount; i++) {
-                            final RowScale rs = new RowScale(ChooserRowAdapter.this, 0.f, 1.f)
-                                    .setInterpolator(mInterpolator);
-                            mServiceTargetScale[i] = rs;
-                        }
-
-                        // Start the animations in a separate loop.
-                        // The process of starting animations will result in
-                        // binding views to set up initial values, and we must
-                        // have ALL of the new RowScale objects created above before
-                        // we get started.
-                        for (int i = oldRCount; i < rcount; i++) {
-                            mServiceTargetScale[i].startAnimation();
-                        }
-                    }
-
+                    updateRowScales();
                     notifyDataSetChanged();
                 }
 
@@ -1284,6 +1355,40 @@
             });
         }
 
+         void updateRowScales() {
+            final int rcount = getServiceTargetRowCount();
+            if (mServiceTargetScale == null
+                    || mServiceTargetScale.length != rcount) {
+                if (DEBUG) Log.d(TAG, "Row scales need adjusting to " + rcount + " rows.");
+                RowScale[] old = mServiceTargetScale;
+                int oldRCount = old != null ? old.length : 0;
+                mServiceTargetScale = new RowScale[rcount];
+                if (old != null && rcount > 0) {
+                    System.arraycopy(old, 0, mServiceTargetScale, 0,
+                            Math.min(old.length, rcount));
+                }
+
+                for (int i = rcount; i < oldRCount; i++) {
+                    old[i].cancelAnimation();
+                }
+
+                for (int i = oldRCount; i < rcount; i++) {
+                    final RowScale rs = new RowScale(ChooserRowAdapter.this, 0.f, 1.f)
+                            .setInterpolator(mInterpolator);
+                    mServiceTargetScale[i] = rs;
+                }
+
+                // Start the animations in a separate loop.
+                // The process of starting animations will result in
+                // binding views to set up initial values, and we must
+                // have ALL of the new RowScale objects created above before
+                // we get started.
+                for (int i = oldRCount; i < rcount; i++) {
+                    mServiceTargetScale[i].startAnimation();
+                }
+            }
+        }
+
         private float getRowScale(int rowPosition) {
             final int start = getCallerTargetRowCount();
             final int end = start + getServiceTargetRowCount();
@@ -1554,6 +1659,10 @@
         }
     }
 
+    public LauncherApps getLauncherApps() {
+        return (LauncherApps) getSystemService(Context.LAUNCHER_APPS_SERVICE);
+    }
+
     static class ServiceResultInfo {
         public final DisplayResolveInfo originalTarget;
         public final List<ChooserTarget> resultTargets;
diff --git a/core/java/com/android/internal/app/NightDisplayController.java b/core/java/com/android/internal/app/NightDisplayController.java
index 03cd729..68afe02 100644
--- a/core/java/com/android/internal/app/NightDisplayController.java
+++ b/core/java/com/android/internal/app/NightDisplayController.java
@@ -18,13 +18,13 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.app.ActivityManager;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.database.ContentObserver;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.Looper;
-import android.os.UserHandle;
 import android.provider.Settings.Secure;
 import android.util.Slog;
 
@@ -81,7 +81,7 @@
     private Callback mCallback;
 
     public NightDisplayController(@NonNull Context context) {
-        this(context, UserHandle.myUserId());
+        this(context, ActivityManager.getCurrentUser());
     }
 
     public NightDisplayController(@NonNull Context context, int userId) {
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 2d0ddef..3f1c9ad 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -116,6 +116,10 @@
     private Runnable mPostListReadyRunnable;
 
     private boolean mRegistered;
+
+    /** See {@link #setRetainInOnStop}. */
+    private boolean mRetainInOnStop;
+
     private final PackageMonitor mPackageMonitor = new PackageMonitor() {
         @Override public void onSomePackagesChanged() {
             mAdapter.handlePackagesChanged();
@@ -502,7 +506,7 @@
         }
         final Intent intent = getIntent();
         if ((intent.getFlags() & FLAG_ACTIVITY_NEW_TASK) != 0 && !isVoiceInteraction()
-                && !mResolvingHome) {
+                && !mResolvingHome && !mRetainInOnStop) {
             // This resolver is in the unusual situation where it has been
             // launched at the top of a new task.  We don't let it be added
             // to the recent tasks shown to the user, and we need to make sure
@@ -531,16 +535,7 @@
     @Override
     protected void onRestoreInstanceState(Bundle savedInstanceState) {
         super.onRestoreInstanceState(savedInstanceState);
-        if (mSupportsAlwaysUseOption) {
-            final int checkedPos = mAdapterView.getCheckedItemPosition();
-            final boolean hasValidSelection = checkedPos != ListView.INVALID_POSITION;
-            mLastSelected = checkedPos;
-            setAlwaysButtonEnabled(hasValidSelection, checkedPos, true);
-            mOnceButton.setEnabled(hasValidSelection);
-            if (hasValidSelection) {
-                mAdapterView.setSelection(checkedPos);
-            }
-        }
+        resetAlwaysOrOnceButtonBar();
     }
 
     private boolean hasManagedProfile() {
@@ -577,7 +572,13 @@
         boolean enabled = false;
         if (hasValidSelection) {
             ResolveInfo ri = mAdapter.resolveInfoForPosition(checkedPos, filtered);
-            if (ri.targetUserId == UserHandle.USER_CURRENT) {
+            if (ri == null) {
+                Log.e(TAG, "Invalid position supplied to setAlwaysButtonEnabled");
+                return;
+            } else if (ri.targetUserId != UserHandle.USER_CURRENT) {
+                Log.e(TAG, "Attempted to set selection to resolve info for another user");
+                return;
+            } else {
                 enabled = true;
             }
         }
@@ -1029,6 +1030,14 @@
     }
 
     /**
+     * If {@code retainInOnStop} is set to true, we will not finish ourselves when onStop gets
+     * called and we are launched in a new task.
+     */
+    protected void setRetainInOnStop(boolean retainInOnStop) {
+        mRetainInOnStop = retainInOnStop;
+    }
+
+    /**
      * Check a simple match for the component of two ResolveInfos.
      */
     static boolean resolveInfoMatch(ResolveInfo lhs, ResolveInfo rhs) {
@@ -1434,7 +1443,7 @@
                     mUnfilteredResolveList = originalList;
                 }
 
-                if (N > 1) {
+                if (currentResolveList.size() > 1) {
                     setPlaceholderCount(currentResolveList.size());
                     AsyncTask<List<ResolvedComponentInfo>,
                             Void,
diff --git a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
index 81db93d..f987a9f 100644
--- a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
+++ b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
@@ -68,7 +68,7 @@
     int[] getAppWidgetIds(in ComponentName providerComponent);
     boolean isBoundWidgetPackage(String packageName, int userId);
     boolean requestPinAppWidget(String packageName, in ComponentName providerComponent,
-            in IntentSender resultIntent);
+            in Bundle extras, in IntentSender resultIntent);
     boolean isRequestPinAppWidgetSupported();
 }
 
diff --git a/core/java/com/android/internal/content/FileSystemProvider.java b/core/java/com/android/internal/content/FileSystemProvider.java
new file mode 100644
index 0000000..3ac5a72
--- /dev/null
+++ b/core/java/com/android/internal/content/FileSystemProvider.java
@@ -0,0 +1,487 @@
+/*
+ * 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.internal.content;
+
+import android.annotation.CallSuper;
+import android.content.ContentResolver;
+import android.content.Intent;
+import android.content.res.AssetFileDescriptor;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.database.MatrixCursor.RowBuilder;
+import android.graphics.Point;
+import android.net.Uri;
+import android.os.CancellationSignal;
+import android.os.FileObserver;
+import android.os.FileUtils;
+import android.os.Handler;
+import android.os.ParcelFileDescriptor;
+import android.provider.DocumentsContract;
+import android.provider.DocumentsContract.Document;
+import android.provider.DocumentsProvider;
+import android.provider.MediaStore;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.webkit.MimeTypeMap;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A helper class for {@link android.provider.DocumentsProvider} to perform file operations on local
+ * files.
+ */
+public abstract class FileSystemProvider extends DocumentsProvider {
+
+    private static final String TAG = "FileSystemProvider";
+
+    private static final boolean LOG_INOTIFY = false;
+
+    private String[] mDefaultProjection;
+
+    @GuardedBy("mObservers")
+    private final ArrayMap<File, DirectoryObserver> mObservers = new ArrayMap<>();
+
+    private Handler mHandler;
+
+    protected abstract File getFileForDocId(String docId, boolean visible)
+            throws FileNotFoundException;
+
+    protected abstract String getDocIdForFile(File file) throws FileNotFoundException;
+
+    protected abstract Uri buildNotificationUri(String docId);
+
+    @Override
+    public boolean onCreate() {
+        throw new UnsupportedOperationException(
+                "Subclass should override this and call onCreate(defaultDocumentProjection)");
+    }
+
+    @CallSuper
+    protected void onCreate(String[] defaultProjection) {
+        mHandler = new Handler();
+        mDefaultProjection = defaultProjection;
+    }
+
+    @Override
+    public boolean isChildDocument(String parentDocId, String docId) {
+        try {
+            final File parent = getFileForDocId(parentDocId).getCanonicalFile();
+            final File doc = getFileForDocId(docId).getCanonicalFile();
+            return FileUtils.contains(parent, doc);
+        } catch (IOException e) {
+            throw new IllegalArgumentException(
+                    "Failed to determine if " + docId + " is child of " + parentDocId + ": " + e);
+        }
+    }
+
+    protected final List<String> findDocumentPath(File parent, File doc)
+            throws FileNotFoundException {
+
+        if (!doc.exists()) {
+            throw new FileNotFoundException(doc + " is not found.");
+        }
+
+        if (!FileUtils.contains(parent, doc)) {
+            throw new FileNotFoundException(doc + " is not found under " + parent);
+        }
+
+        LinkedList<String> path = new LinkedList<>();
+        while (doc != null && FileUtils.contains(parent, doc)) {
+            path.addFirst(getDocIdForFile(doc));
+
+            doc = doc.getParentFile();
+        }
+
+        return path;
+    }
+
+    @Override
+    public String createDocument(String docId, String mimeType, String displayName)
+            throws FileNotFoundException {
+        displayName = FileUtils.buildValidFatFilename(displayName);
+
+        final File parent = getFileForDocId(docId);
+        if (!parent.isDirectory()) {
+            throw new IllegalArgumentException("Parent document isn't a directory");
+        }
+
+        final File file = FileUtils.buildUniqueFile(parent, mimeType, displayName);
+        if (Document.MIME_TYPE_DIR.equals(mimeType)) {
+            if (!file.mkdir()) {
+                throw new IllegalStateException("Failed to mkdir " + file);
+            }
+        } else {
+            try {
+                if (!file.createNewFile()) {
+                    throw new IllegalStateException("Failed to touch " + file);
+                }
+            } catch (IOException e) {
+                throw new IllegalStateException("Failed to touch " + file + ": " + e);
+            }
+        }
+
+        return getDocIdForFile(file);
+    }
+
+    @Override
+    public String renameDocument(String docId, String displayName) throws FileNotFoundException {
+        // Since this provider treats renames as generating a completely new
+        // docId, we're okay with letting the MIME type change.
+        displayName = FileUtils.buildValidFatFilename(displayName);
+
+        final File before = getFileForDocId(docId);
+        final File after = FileUtils.buildUniqueFile(before.getParentFile(), displayName);
+        final File visibleFileBefore = getFileForDocId(docId, true);
+        if (!before.renameTo(after)) {
+            throw new IllegalStateException("Failed to rename to " + after);
+        }
+        removeFromMediaStore(visibleFileBefore);
+
+        final String afterDocId = getDocIdForFile(after);
+        scanFile(getFileForDocId(afterDocId, true));
+
+        if (!TextUtils.equals(docId, afterDocId)) {
+            return afterDocId;
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public void deleteDocument(String docId) throws FileNotFoundException {
+        final File file = getFileForDocId(docId);
+        final File visibleFile = getFileForDocId(docId, true);
+
+        final boolean isDirectory = file.isDirectory();
+        if (isDirectory) {
+            FileUtils.deleteContents(file);
+        }
+        if (!file.delete()) {
+            throw new IllegalStateException("Failed to delete " + file);
+        }
+
+        removeFromMediaStore(visibleFile);
+    }
+
+    @Override
+    public String moveDocument(String sourceDocumentId, String sourceParentDocumentId,
+            String targetParentDocumentId)
+            throws FileNotFoundException {
+        final File before = getFileForDocId(sourceDocumentId);
+        final File after = new File(getFileForDocId(targetParentDocumentId), before.getName());
+        final File visibleFileBefore = getFileForDocId(sourceDocumentId, true);
+
+        if (after.exists()) {
+            throw new IllegalStateException("Already exists " + after);
+        }
+        if (!before.renameTo(after)) {
+            throw new IllegalStateException("Failed to move to " + after);
+        }
+
+        // Notify media store to update its content
+        removeFromMediaStore(visibleFileBefore);
+        final String docId = getDocIdForFile(after);
+        scanFile(getFileForDocId(docId, true));
+
+        return docId;
+    }
+
+    private void removeFromMediaStore(File visibleFile) throws FileNotFoundException {
+        if (visibleFile != null) {
+            final ContentResolver resolver = getContext().getContentResolver();
+            final Uri externalUri = MediaStore.Files.getContentUri("external");
+
+            // Remove media store entries for any files inside this directory, using
+            // path prefix match. Logic borrowed from MtpDatabase.
+            if (visibleFile.isDirectory()) {
+                final String path = visibleFile.getAbsolutePath() + "/";
+                resolver.delete(externalUri,
+                        "_data LIKE ?1 AND lower(substr(_data,1,?2))=lower(?3)",
+                        new String[] { path + "%", Integer.toString(path.length()), path });
+            }
+
+            // Remove media store entry for this exact file.
+            final String path = visibleFile.getAbsolutePath();
+            resolver.delete(externalUri,
+                    "_data LIKE ?1 AND lower(_data)=lower(?2)",
+                    new String[] { path, path });
+        }
+    }
+
+    @Override
+    public Cursor queryDocument(String documentId, String[] projection)
+            throws FileNotFoundException {
+        final MatrixCursor result = new MatrixCursor(resolveProjection(projection));
+        includeFile(result, documentId, null);
+        return result;
+    }
+
+    @Override
+    public Cursor queryChildDocuments(
+            String parentDocumentId, String[] projection, String sortOrder)
+            throws FileNotFoundException {
+
+        final File parent = getFileForDocId(parentDocumentId);
+        final MatrixCursor result = new DirectoryCursor(
+                resolveProjection(projection), parentDocumentId, parent);
+        for (File file : parent.listFiles()) {
+            includeFile(result, null, file);
+        }
+        return result;
+    }
+
+    /**
+     * Searches documents under the given folder.
+     *
+     * To avoid runtime explosion only returns the at most 23 items.
+     *
+     * @param folder the root folder where recursive search begins
+     * @param query the search condition used to match file names
+     * @param projection projection of the returned cursor
+     * @param exclusion absolute file paths to exclude from result
+     * @return cursor containing search result
+     * @throws FileNotFoundException when root folder doesn't exist or search fails
+     */
+    protected final Cursor querySearchDocuments(
+            File folder, String query, String[] projection, Set<String> exclusion)
+            throws FileNotFoundException {
+
+        query = query.toLowerCase();
+        final MatrixCursor result = new MatrixCursor(resolveProjection(projection));
+        final LinkedList<File> pending = new LinkedList<>();
+        pending.add(folder);
+        while (!pending.isEmpty() && result.getCount() < 24) {
+            final File file = pending.removeFirst();
+            if (file.isDirectory()) {
+                for (File child : file.listFiles()) {
+                    pending.add(child);
+                }
+            }
+            if (file.getName().toLowerCase().contains(query)
+                    && !exclusion.contains(file.getAbsolutePath())) {
+                includeFile(result, null, file);
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public String getDocumentType(String documentId) throws FileNotFoundException {
+        final File file = getFileForDocId(documentId);
+        return getTypeForFile(file);
+    }
+
+    @Override
+    public ParcelFileDescriptor openDocument(
+            String documentId, String mode, CancellationSignal signal)
+            throws FileNotFoundException {
+        final File file = getFileForDocId(documentId);
+        final File visibleFile = getFileForDocId(documentId, true);
+
+        final int pfdMode = ParcelFileDescriptor.parseMode(mode);
+        if (pfdMode == ParcelFileDescriptor.MODE_READ_ONLY || visibleFile == null) {
+            return ParcelFileDescriptor.open(file, pfdMode);
+        } else {
+            try {
+                // When finished writing, kick off media scanner
+                return ParcelFileDescriptor.open(
+                        file, pfdMode, mHandler, (IOException e) -> scanFile(visibleFile));
+            } catch (IOException e) {
+                throw new FileNotFoundException("Failed to open for writing: " + e);
+            }
+        }
+    }
+
+    private void scanFile(File visibleFile) {
+        final Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
+        intent.setData(Uri.fromFile(visibleFile));
+        getContext().sendBroadcast(intent);
+    }
+
+    @Override
+    public AssetFileDescriptor openDocumentThumbnail(
+            String documentId, Point sizeHint, CancellationSignal signal)
+            throws FileNotFoundException {
+        final File file = getFileForDocId(documentId);
+        return DocumentsContract.openImageThumbnail(file);
+    }
+
+    protected RowBuilder includeFile(MatrixCursor result, String docId, File file)
+            throws FileNotFoundException {
+        if (docId == null) {
+            docId = getDocIdForFile(file);
+        } else {
+            file = getFileForDocId(docId);
+        }
+
+        int flags = 0;
+
+        if (file.canWrite()) {
+            if (file.isDirectory()) {
+                flags |= Document.FLAG_DIR_SUPPORTS_CREATE;
+                flags |= Document.FLAG_SUPPORTS_DELETE;
+                flags |= Document.FLAG_SUPPORTS_RENAME;
+                flags |= Document.FLAG_SUPPORTS_MOVE;
+            } else {
+                flags |= Document.FLAG_SUPPORTS_WRITE;
+                flags |= Document.FLAG_SUPPORTS_DELETE;
+                flags |= Document.FLAG_SUPPORTS_RENAME;
+                flags |= Document.FLAG_SUPPORTS_MOVE;
+            }
+        }
+
+        final String mimeType = getTypeForFile(file);
+        final String displayName = file.getName();
+        if (mimeType.startsWith("image/")) {
+            flags |= Document.FLAG_SUPPORTS_THUMBNAIL;
+        }
+
+        final RowBuilder row = result.newRow();
+        row.add(Document.COLUMN_DOCUMENT_ID, docId);
+        row.add(Document.COLUMN_DISPLAY_NAME, displayName);
+        row.add(Document.COLUMN_SIZE, file.length());
+        row.add(Document.COLUMN_MIME_TYPE, mimeType);
+        row.add(Document.COLUMN_FLAGS, flags);
+
+        // Only publish dates reasonably after epoch
+        long lastModified = file.lastModified();
+        if (lastModified > 31536000000L) {
+            row.add(Document.COLUMN_LAST_MODIFIED, lastModified);
+        }
+
+        // Return the row builder just in case any subclass want to add more stuff to it.
+        return row;
+    }
+
+    private static String getTypeForFile(File file) {
+        if (file.isDirectory()) {
+            return Document.MIME_TYPE_DIR;
+        } else {
+            return getTypeForName(file.getName());
+        }
+    }
+
+    private static String getTypeForName(String name) {
+        final int lastDot = name.lastIndexOf('.');
+        if (lastDot >= 0) {
+            final String extension = name.substring(lastDot + 1).toLowerCase();
+            final String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
+            if (mime != null) {
+                return mime;
+            }
+        }
+
+        return "application/octet-stream";
+    }
+
+    protected final File getFileForDocId(String docId) throws FileNotFoundException {
+        return getFileForDocId(docId, false);
+    }
+
+    private String[] resolveProjection(String[] projection) {
+        return projection == null ? mDefaultProjection : projection;
+    }
+
+    private void startObserving(File file, Uri notifyUri) {
+        synchronized (mObservers) {
+            DirectoryObserver observer = mObservers.get(file);
+            if (observer == null) {
+                observer = new DirectoryObserver(
+                        file, getContext().getContentResolver(), notifyUri);
+                observer.startWatching();
+                mObservers.put(file, observer);
+            }
+            observer.mRefCount++;
+
+            if (LOG_INOTIFY) Log.d(TAG, "after start: " + observer);
+        }
+    }
+
+    private void stopObserving(File file) {
+        synchronized (mObservers) {
+            DirectoryObserver observer = mObservers.get(file);
+            if (observer == null) return;
+
+            observer.mRefCount--;
+            if (observer.mRefCount == 0) {
+                mObservers.remove(file);
+                observer.stopWatching();
+            }
+
+            if (LOG_INOTIFY) Log.d(TAG, "after stop: " + observer);
+        }
+    }
+
+    private static class DirectoryObserver extends FileObserver {
+        private static final int NOTIFY_EVENTS = ATTRIB | CLOSE_WRITE | MOVED_FROM | MOVED_TO
+                | CREATE | DELETE | DELETE_SELF | MOVE_SELF;
+
+        private final File mFile;
+        private final ContentResolver mResolver;
+        private final Uri mNotifyUri;
+
+        private int mRefCount = 0;
+
+        public DirectoryObserver(File file, ContentResolver resolver, Uri notifyUri) {
+            super(file.getAbsolutePath(), NOTIFY_EVENTS);
+            mFile = file;
+            mResolver = resolver;
+            mNotifyUri = notifyUri;
+        }
+
+        @Override
+        public void onEvent(int event, String path) {
+            if ((event & NOTIFY_EVENTS) != 0) {
+                if (LOG_INOTIFY) Log.d(TAG, "onEvent() " + event + " at " + path);
+                mResolver.notifyChange(mNotifyUri, null, false);
+            }
+        }
+
+        @Override
+        public String toString() {
+            return "DirectoryObserver{file=" + mFile.getAbsolutePath() + ", ref=" + mRefCount + "}";
+        }
+    }
+
+    private class DirectoryCursor extends MatrixCursor {
+        private final File mFile;
+
+        public DirectoryCursor(String[] columnNames, String docId, File file) {
+            super(columnNames);
+
+            final Uri notifyUri = buildNotificationUri(docId);
+            setNotificationUri(getContext().getContentResolver(), notifyUri);
+
+            mFile = file;
+            startObserving(mFile, notifyUri);
+        }
+
+        @Override
+        public void close() {
+            super.close();
+            stopObserving(mFile);
+        }
+    }
+}
diff --git a/core/java/com/android/internal/logging/MetricsLogger.java b/core/java/com/android/internal/logging/MetricsLogger.java
index c8bf302..949e7ac 100644
--- a/core/java/com/android/internal/logging/MetricsLogger.java
+++ b/core/java/com/android/internal/logging/MetricsLogger.java
@@ -29,8 +29,10 @@
  */
 public class MetricsLogger {
     // define metric categories in frameworks/base/proto/src/metrics_constants.proto.
+    // mirror changes in native version at system/core/libmetricslogger/metrics_logger.cpp
 
     public static final int VIEW_UNKNOWN = MetricsEvent.VIEW_UNKNOWN;
+    public static final int LOGTAG = EventLogTags.SYSUI_MULTI_ACTION;
 
     public static void visible(Context context, int category) throws IllegalArgumentException {
         if (Build.IS_DEBUGGABLE && category == VIEW_UNKNOWN) {
@@ -125,6 +127,7 @@
 
     /** Increment the bucket with the integer label on the histogram with the given name. */
     public static void histogram(Context context, String name, int bucket) {
+        // see LogHistogram in system/core/libmetricslogger/metrics_logger.cpp
         EventLogTags.writeSysuiHistogram(name, bucket);
         EventLogTags.writeSysuiMultiAction(
                 new LogMaker(MetricsEvent.RESERVED_FOR_LOGBUILDER_HISTOGRAM)
diff --git a/core/java/com/android/internal/logging/legacy/EventLogCollector.java b/core/java/com/android/internal/logging/legacy/EventLogCollector.java
deleted file mode 100644
index 598f0d5..0000000
--- a/core/java/com/android/internal/logging/legacy/EventLogCollector.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * 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.internal.logging.legacy;
-
-import android.util.ArrayMap;
-import android.util.EventLog;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-
-/**
- * Scan the event log for interaction metrics events.
- * @hide
- */
-public class EventLogCollector {
-    private static final String TAG = "EventLogCollector";
-
-    // TODO replace this with GoogleLogTags.TRON_HEARTBEAT
-    @VisibleForTesting
-    static final int TRON_HEARTBEAT = 208000;
-
-    private static EventLogCollector sInstance;
-
-    private final ArrayMap<Integer, TagParser> mTagParsers;
-    private int[] mInterestingTags;
-
-    private LogReader mLogReader;
-
-    private EventLogCollector() {
-        mTagParsers = new ArrayMap<>();
-        addParser(new PowerScreenStateParser());
-        addParser(new SysuiMultiActionParser());
-
-        mLogReader = new LogReader();
-    }
-
-    public static EventLogCollector getInstance() {
-        if (sInstance == null) {
-            sInstance = new EventLogCollector();
-        }
-        return sInstance;
-    }
-
-    @VisibleForTesting
-    public void setLogReader(LogReader logReader) {
-        mLogReader = logReader;
-    }
-
-    private int[] getInterestingTags() {
-        if (mInterestingTags == null) {
-            mInterestingTags = new int[mTagParsers.size()];
-            for (int i = 0; i < mTagParsers.size(); i++) {
-                mInterestingTags[i] = mTagParsers.valueAt(i).getTag();
-            }
-        }
-        return mInterestingTags;
-    }
-
-    // I would customize ArrayMap to add put(TagParser), but ArrayMap is final.
-    @VisibleForTesting
-    void addParser(TagParser parser) {
-        mTagParsers.put(parser.getTag(), parser);
-        mInterestingTags = null;
-    }
-
-    public void collect(LegacyConversionLogger logger) {
-        collect(logger, 0L);
-    }
-
-    public long collect(TronLogger logger, long lastSeenEventMs) {
-        long lastEventMs = 0L;
-        final boolean debug = Util.debug();
-
-        if (debug) {
-            Log.d(TAG, "Eventlog Collection");
-        }
-        ArrayList<Event> events = new ArrayList<>();
-        try {
-            mLogReader.readEvents(getInterestingTags(), events);
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-        if (debug) {
-            Log.d(TAG, "read this many events: " + events.size());
-        }
-
-        for (Event event : events) {
-            final long millis = event.getTimeNanos() / 1000000;
-            if (millis > lastSeenEventMs) {
-                final int tag = event.getTag();
-                TagParser parser = mTagParsers.get(tag);
-                if (parser == null) {
-                    if (debug) {
-                        Log.d(TAG, "unknown tag: " + tag);
-                    }
-                    continue;
-                }
-                if (debug) {
-                    Log.d(TAG, "parsing tag: " + tag);
-                }
-                parser.parseEvent(logger, event);
-                lastEventMs = Math.max(lastEventMs, millis);
-            } else {
-                if (debug) {
-                    Log.d(TAG, "old event: " + millis + " < " + lastSeenEventMs);
-                }
-            }
-        }
-        return lastEventMs;
-    }
-
-    @VisibleForTesting
-    static class Event {
-        long mTimeNanos;
-        int mTag;
-        Object mData;
-
-        Event(long timeNanos, int tag, Object data) {
-            super();
-            mTimeNanos = timeNanos;
-            mTag = tag;
-            mData = data;
-        }
-
-        Event(EventLog.Event event) {
-            mTimeNanos = event.getTimeNanos();
-            mTag = event.getTag();
-            mData = event.getData();
-        }
-
-        public long getTimeNanos() {
-            return mTimeNanos;
-        }
-
-        public int getTag() {
-            return mTag;
-        }
-
-        public Object getData() {
-            return mData;
-        }
-    }
-
-    @VisibleForTesting
-    static class LogReader {
-        public void readEvents(int[] tags, Collection<Event> events) throws IOException {
-            // Testing in Android: the Static Final Class Strikes Back!
-            ArrayList<EventLog.Event> nativeEvents = new ArrayList<>();
-            EventLog.readEventsOnWrapping(tags, 0L, nativeEvents);
-            for (EventLog.Event nativeEvent : nativeEvents) {
-                Event event = new Event(nativeEvent);
-                events.add(event);
-            }
-        }
-    }
-}
diff --git a/core/java/com/android/internal/logging/legacy/LegacyConversionLogger.java b/core/java/com/android/internal/logging/legacy/LegacyConversionLogger.java
deleted file mode 100644
index 1209e4d..0000000
--- a/core/java/com/android/internal/logging/legacy/LegacyConversionLogger.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * 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.internal.logging.legacy;
-
-import android.metrics.LogMaker;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.Queue;
-
-/** @hide */
-public class LegacyConversionLogger implements TronLogger {
-    private final Queue<LogMaker> mQueue;
-    private HashMap<String, Boolean> mConfig;
-
-    public LegacyConversionLogger() {
-        mQueue = new LinkedList<>();
-    }
-
-    public Queue<LogMaker> getEvents() {
-        return mQueue;
-    }
-
-    @Override
-    public void increment(String counterName) {
-        LogMaker b = new LogMaker(MetricsEvent.RESERVED_FOR_LOGBUILDER_COUNTER)
-                .setCounterName(counterName)
-                .setCounterValue(1);
-        mQueue.add(b);
-    }
-
-    @Override
-    public void incrementBy(String counterName, int value) {
-        LogMaker b = new LogMaker(MetricsEvent.RESERVED_FOR_LOGBUILDER_COUNTER)
-                .setCounterName(counterName)
-                .setCounterValue(value);
-        mQueue.add(b);
-    }
-
-    @Override
-    public void incrementIntHistogram(String counterName, int bucket) {
-        LogMaker b = new LogMaker(MetricsEvent.RESERVED_FOR_LOGBUILDER_HISTOGRAM)
-                .setCounterName(counterName)
-                .setCounterBucket(bucket)
-                .setCounterValue(1);
-        mQueue.add(b);
-    }
-
-    @Override
-    public void incrementLongHistogram(String counterName, long bucket) {
-        LogMaker b = new LogMaker(MetricsEvent.RESERVED_FOR_LOGBUILDER_HISTOGRAM)
-                .setCounterName(counterName)
-                .setCounterBucket(bucket)
-                .setCounterValue(1);
-        mQueue.add(b);
-    }
-
-    @Override
-    public LogMaker obtain() {
-        return new LogMaker(MetricsEvent.VIEW_UNKNOWN);
-    }
-
-    @Override
-    public void dispose(LogMaker proto) {
-    }
-
-    @Override
-    public void addEvent(LogMaker proto) {
-        mQueue.add(proto);
-    }
-
-    @Override
-    public boolean getConfig(String configName) {
-        if (mConfig != null && mConfig.containsKey(configName)) {
-            return mConfig.get(configName);
-        }
-        return false;
-    }
-
-    @Override
-    public void setConfig(String configName, boolean newValue) {
-        if (mConfig == null) {
-            mConfig = new HashMap<>();
-        }
-        mConfig.put(configName, newValue);
-    }
-}
diff --git a/core/java/com/android/internal/logging/legacy/PowerScreenStateParser.java b/core/java/com/android/internal/logging/legacy/PowerScreenStateParser.java
deleted file mode 100644
index e9baf9b..0000000
--- a/core/java/com/android/internal/logging/legacy/PowerScreenStateParser.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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.internal.logging.legacy;
-
-import android.util.Log;
-
-import android.metrics.LogMaker;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
-/**
- * Parse the Android lockscreen gesture logs.
- * @hide
- */
-public class PowerScreenStateParser extends TagParser {
-    private static final String TAG = "PowerScreenStateParser";
-    private static final int EVENTLOG_TAG = 2728;
-
-    // source of truth is android.view.WindowManagerPolicy, why:
-    // 0: on
-    // 1: OFF_BECAUSE_OF_ADMIN
-    // 2: OFF_BECAUSE_OF_USER
-    // 3: OFF_BECAUSE_OF_TIMEOUT
-
-    @Override
-    public int getTag() {
-        return EVENTLOG_TAG;
-    }
-
-    @Override
-    public void parseEvent(TronLogger logger, long eventTimeMs, Object[] operands) {
-        final boolean debug = Util.debug();
-        if (operands.length >= 2) {
-            try {
-                // (offOrOn|1|5),(becauseOfUser|1|5),(totalTouchDownTime|2|3),(touchCycles|1|1)
-                boolean state = (((Integer) operands[0]).intValue()) == 1;
-                int why = ((Integer) operands[1]).intValue();
-
-                LogMaker proto = logger.obtain();
-                proto.setCategory(MetricsEvent.SCREEN);
-                proto.setType(state ? MetricsEvent.TYPE_OPEN : MetricsEvent.TYPE_CLOSE);
-                proto.setTimestamp(eventTimeMs);
-                proto.setSubtype(why);
-                logger.addEvent(proto);
-            } catch (ClassCastException e) {
-                if (debug) {
-                    Log.e(TAG, "unexpected operand type: ", e);
-                }
-            }
-        } else if (debug) {
-            Log.w(TAG, "wrong number of operands: " + operands.length);
-        }
-    }
-}
diff --git a/core/java/com/android/internal/logging/legacy/SysuiMultiActionParser.java b/core/java/com/android/internal/logging/legacy/SysuiMultiActionParser.java
deleted file mode 100644
index 0c77b7a..0000000
--- a/core/java/com/android/internal/logging/legacy/SysuiMultiActionParser.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.internal.logging.legacy;
-
-import android.util.Log;
-
-import android.metrics.LogMaker;
-
-/**
- * ...and one parser to rule them all.
- *
- * This should, at some point in the future, be the only parser.
- * @hide
- */
-public class SysuiMultiActionParser extends TagParser {
-    private static final String TAG = "SysuiMultiActionParser";
-    private static final int EVENTLOG_TAG = 524292;
-
-    @Override
-    public int getTag() {
-        return EVENTLOG_TAG;
-    }
-
-    @Override
-    public void parseEvent(TronLogger logger, long eventTimeMs, Object[] operands) {
-        final boolean debug = Util.debug();
-        try {
-            logger.addEvent(new LogMaker(operands).setTimestamp(eventTimeMs));
-        } catch (ClassCastException e) {
-            if (debug) {
-                Log.e(TAG, "unexpected operand type: ", e);
-            }
-        }
-    }
-}
diff --git a/core/java/com/android/internal/logging/legacy/TagParser.java b/core/java/com/android/internal/logging/legacy/TagParser.java
deleted file mode 100755
index 3bffdd5..0000000
--- a/core/java/com/android/internal/logging/legacy/TagParser.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * 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.internal.logging.legacy;
-
-import android.util.Log;
-
-import android.metrics.LogMaker;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
-/**
- * Abstraction layer between EventLog static classes and the actual TagParsers.
- * @hide
- */
-public abstract class TagParser {
-    private static final String TAG = "TagParser";
-
-    protected int mSinceCreationMillis;
-    protected int mSinceUpdateMillis;
-    protected int mSinceVisibleMillis;
-
-    abstract int getTag();
-
-    @VisibleForTesting
-    abstract public void parseEvent(TronLogger logger, long eventTimeMs, Object[] objects);
-
-    /**
-     * Parse the event into the proto: return true if proto was modified.
-     */
-    public void  parseEvent(TronLogger logger, EventLogCollector.Event event) {
-        final boolean debug = Util.debug();
-        Object data = event.getData();
-        Object[] objects;
-        if (data instanceof Object[]) {
-            objects = (Object[]) data;
-            for (int i = 0; i < objects.length; i++) {
-                if (objects[i] == null) {
-                    if (debug) {
-                        Log.d(TAG, "unexpected null value:" + event.getTag());
-                    }
-                    return;
-                }
-            }
-        } else {
-            // wrap scalar objects
-            objects = new Object[1];
-            objects[0] = data;
-        }
-
-        parseEvent(logger, event.getTimeNanos() / 1000000, objects);
-    }
-
-    protected void resetTimes() {
-        mSinceCreationMillis = 0;
-        mSinceUpdateMillis = 0;
-        mSinceVisibleMillis = 0;
-    }
-
-    public void parseTimes(Object[] operands, int index) {
-        resetTimes();
-
-        if (operands.length > index && operands[index] instanceof Integer) {
-            mSinceCreationMillis = (Integer) operands[index];
-        }
-
-        index++;
-        if (operands.length > index && operands[index] instanceof Integer) {
-            mSinceUpdateMillis = (Integer) operands[index];
-        }
-
-        index++;
-        if (operands.length > index && operands[index] instanceof Integer) {
-            mSinceVisibleMillis = (Integer) operands[index];
-        }
-    }
-
-   public void filltimes(LogMaker proto) {
-        if (mSinceCreationMillis != 0) {
-            proto.addTaggedData(MetricsEvent.NOTIFICATION_SINCE_CREATE_MILLIS,
-                    mSinceCreationMillis);
-        }
-        if (mSinceUpdateMillis != 0) {
-            proto.addTaggedData(MetricsEvent.NOTIFICATION_SINCE_UPDATE_MILLIS,
-                    mSinceUpdateMillis);
-        }
-        if (mSinceVisibleMillis != 0) {
-            proto.addTaggedData(MetricsEvent.NOTIFICATION_SINCE_VISIBLE_MILLIS,
-                    mSinceVisibleMillis);
-        }
-    }
-}
diff --git a/core/java/com/android/internal/logging/legacy/TronCounters.java b/core/java/com/android/internal/logging/legacy/TronCounters.java
deleted file mode 100644
index e0828a2..0000000
--- a/core/java/com/android/internal/logging/legacy/TronCounters.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.internal.logging.legacy;
-
-/**
- * Names of the counters that the Tron package defines.
- *
- * Other counter names may be generated by AOSP code.
- * @hide
- */
-public class TronCounters {
-
-    static final String TRON_COLLECTIONS = "tron_collections";
-
-    static final String TRON_COLLECTION_PERIOD = "tron_collection_period_minutes";
-
-    static final String TRON_EVENTLOG_LENGTH = "tron_eventlog_horizon";
-
-    static final String TRON_NOTE_DISMISS = "tron_note_dismiss";
-
-    static final String TRON_NOTE_DISMISS_BY_USER = "tron_note_dismiss_user";
-
-    static final String TRON_NOTE_DISMISS_BY_CLICK = "tron_note_dismiss_click";
-
-    static final String TRON_NOTE_DISMISS_BY_LISTENER = "tron_note_dismiss_listener";
-
-    static final String TRON_NOTE_DISMISS_BY_BAN = "tron_note_dismiss_ban";
-
-    static final String TRON_NOTE_REVEALED = "tron_note_revealed";
-
-    static final String TRON_NOTIFICATION_LOAD = "tron_notification_load";
-
-    static final String TRON_VIEW = "tron_view";
-
-    static final String TRON_ACTION = "tron_action";
-
-    static final String TRON_DETAIL = "tron_detail";
-
-    static final String TRON_NOTE_LIFETIME = "tron_note_lifetime";
-
-    /** Append the AOSP-generated name */
-    static final String TRON_AOSP_PREFIX = "tron_varz_";
-
-    static final String TRON_ACTION_BAD_INT = "tron_action_bad_int";
-
-    static final String TRON_NOTE_FRESHNESS = "tron_note_freshness";
-
-    static final String TRON_NOTE_BUZZ = "tron_note_buzz";
-
-    static final String TRON_NOTE_BEEP = "tron_note_beep";
-
-    static final String TRON_NOTE_BLINK = "tron_note_blink";
-
-    static final String TRON_DISABLE = "tron_disable";
-
-    static final String TRON_LAST_HEART_AGE = "tron_last_heart_minutes";
-
-    static final String TRON_HEARTS_SEEN = "tron_hearts_seen";
-}
diff --git a/core/java/com/android/internal/logging/legacy/TronLogger.java b/core/java/com/android/internal/logging/legacy/TronLogger.java
deleted file mode 100644
index ee9341a..0000000
--- a/core/java/com/android/internal/logging/legacy/TronLogger.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.internal.logging.legacy;
-
-import android.metrics.LogMaker;
-
-/**
- * An entity that knows how to log events and counters.
- */
-public interface TronLogger {
-    /** Add one to the named counter. */
-    void increment(String counterName);
-
-    /** Add an arbitrary value to the named counter. */
-    void incrementBy(String counterName, int value);
-
-    /** Increment a specified bucket on the named histogram by one. */
-    void incrementIntHistogram(String counterName, int bucket);
-
-    /** Increment the specified bucket on the named histogram by one. */
-    void incrementLongHistogram(String counterName, long bucket);
-
-    /** Obtain a SystemUiEvent proto, must release this with dispose() or addEvent(). */
-    LogMaker obtain();
-
-    void dispose(LogMaker proto);
-
-    /** Submit an event to be logged. Logger will dispose of proto. */
-    void addEvent(LogMaker proto);
-
-    /** Get a config flag. */
-    boolean getConfig(String configName);
-
-    /** Set a config flag. */
-    void setConfig(String configName, boolean newValue);
-}
diff --git a/core/java/com/android/internal/notification/SystemNotificationChannels.java b/core/java/com/android/internal/notification/SystemNotificationChannels.java
new file mode 100644
index 0000000..ec3aac2
--- /dev/null
+++ b/core/java/com/android/internal/notification/SystemNotificationChannels.java
@@ -0,0 +1,136 @@
+/*
+ * 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.internal.notification;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.provider.Settings;
+
+import com.android.internal.R;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+// Manages the NotificationChannels used by the frameworks itself.
+public class SystemNotificationChannels {
+    public static String VIRTUAL_KEYBOARD  = "VIRTUAL_KEYBOARD";
+    public static String PHYSICAL_KEYBOARD = "PHYSICAL_KEYBOARD";
+    public static String SECURITY = "SECURITY";
+    public static String CAR_MODE = "CAR_MODE";
+    public static String ACCOUNT = "ACCOUNT";
+    public static String DEVELOPER = "DEVELOPER";
+    public static String UPDATES = "UPDATES";
+    public static String NETWORK_STATUS = "NETWORK_STATUS";
+    public static String NETWORK_ALERTS = "NETWORK_ALERTS";
+    public static String VPN = "VPN";
+    public static String DEVICE_ADMIN = "DEVICE_ADMIN";
+    public static String ALERTS = "ALERTS";
+    public static String RETAIL_MODE = "RETAIL_MODE";
+    public static String USB = "USB";
+
+    public static void createAll(Context context) {
+        final NotificationManager nm = context.getSystemService(NotificationManager.class);
+        List<NotificationChannel> channelsList = new ArrayList<NotificationChannel>();
+        channelsList.add(new NotificationChannel(
+                VIRTUAL_KEYBOARD,
+                R.string.notification_channel_virtual_keyboard,
+                NotificationManager.IMPORTANCE_LOW));
+
+        final NotificationChannel physicalKeyboardChannel = new NotificationChannel(
+                PHYSICAL_KEYBOARD,
+                R.string.notification_channel_physical_keyboard,
+                NotificationManager.IMPORTANCE_DEFAULT);
+        physicalKeyboardChannel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI,
+                Notification.AUDIO_ATTRIBUTES_DEFAULT);
+        channelsList.add(physicalKeyboardChannel);
+
+        channelsList.add(new NotificationChannel(
+                SECURITY,
+                R.string.notification_channel_security,
+                NotificationManager.IMPORTANCE_LOW));
+
+        channelsList.add(new NotificationChannel(
+                CAR_MODE,
+                R.string.notification_channel_car_mode,
+                NotificationManager.IMPORTANCE_LOW));
+
+        channelsList.add(new NotificationChannel(
+                DEVELOPER,
+                R.string.notification_channel_developer,
+                NotificationManager.IMPORTANCE_LOW));
+
+        channelsList.add(new NotificationChannel(
+                UPDATES,
+                R.string.notification_channel_updates,
+                NotificationManager.IMPORTANCE_LOW));
+
+        channelsList.add(new NotificationChannel(
+                NETWORK_STATUS,
+                R.string.notification_channel_network_status,
+                NotificationManager.IMPORTANCE_LOW));
+
+        final NotificationChannel networkAlertsChannel = new NotificationChannel(
+                NETWORK_ALERTS,
+                R.string.notification_channel_network_alerts,
+                NotificationManager.IMPORTANCE_HIGH);
+        networkAlertsChannel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI,
+                Notification.AUDIO_ATTRIBUTES_DEFAULT);
+        channelsList.add(networkAlertsChannel);
+
+        channelsList.add(new NotificationChannel(
+                VPN,
+                R.string.notification_channel_vpn,
+                NotificationManager.IMPORTANCE_LOW));
+
+        channelsList.add(new NotificationChannel(
+                DEVICE_ADMIN,
+                R.string.notification_channel_device_admin,
+                NotificationManager.IMPORTANCE_LOW));
+
+        final NotificationChannel alertsChannel = new NotificationChannel(
+                ALERTS,
+                R.string.notification_channel_alerts,
+                NotificationManager.IMPORTANCE_DEFAULT);
+        alertsChannel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI,
+                Notification.AUDIO_ATTRIBUTES_DEFAULT);
+        channelsList.add(alertsChannel);
+
+        channelsList.add(new NotificationChannel(
+                RETAIL_MODE,
+                R.string.notification_channel_retail_mode,
+                NotificationManager.IMPORTANCE_LOW));
+
+        channelsList.add(new NotificationChannel(
+                USB,
+                R.string.notification_channel_usb,
+                NotificationManager.IMPORTANCE_MIN));
+
+        nm.createNotificationChannels(channelsList);
+        createAccountChannelForPackage(context.getPackageName(), context);
+    }
+
+    public static void createAccountChannelForPackage(String pkg, Context context) {
+        final NotificationManager nm = context.getSystemService(NotificationManager.class);
+        nm.createNotificationChannelsForPackage(pkg, Arrays.asList(new NotificationChannel(
+                ACCOUNT,
+                R.string.notification_channel_account,
+                NotificationManager.IMPORTANCE_LOW)));
+    }
+
+    private SystemNotificationChannels() {}
+}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 9dca5ea..2aeddb3 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -3706,6 +3706,20 @@
 
     public void noteScreenStateLocked(int state) {
         state = mPretendScreenOff ? Display.STATE_OFF : state;
+
+        // Battery stats relies on there being 4 states. To accommodate this, new states beyond the
+        // original 4 are mapped to one of the originals.
+        if (state > MAX_TRACKED_SCREEN_STATE) {
+            switch (state) {
+                case Display.STATE_VR:
+                    state = Display.STATE_ON;
+                    break;
+                default:
+                    Slog.wtf(TAG, "Unknown screen state (not mapped): " + state);
+                    break;
+            }
+        }
+
         if (mScreenState != state) {
             recordDailyStatsIfNeededLocked(true);
             final int oldState = mScreenState;
@@ -3715,9 +3729,9 @@
 
             if (state != Display.STATE_UNKNOWN) {
                 int stepState = state-1;
-                if (stepState < 4) {
-                    mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_SCREEN_STATE) ^ stepState;
-                    mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_SCREEN_STATE) | stepState;
+                if ((stepState & STEP_LEVEL_MODE_SCREEN_STATE) == stepState) {
+                    mModStepMode |= (mCurStepMode & STEP_LEVEL_MODE_SCREEN_STATE) ^ stepState;
+                    mCurStepMode = (mCurStepMode & ~STEP_LEVEL_MODE_SCREEN_STATE) | stepState;
                 } else {
                     Slog.wtf(TAG, "Unexpected screen state: " + state);
                 }
@@ -7914,12 +7928,11 @@
         }
 
         public void noteStartSensor(int sensor, long elapsedRealtimeMs) {
-            StopwatchTimer t = getSensorTimerLocked(sensor, true);
-            if (t != null) {
-                t.startRunningLocked(elapsedRealtimeMs);
-            }
-            Counter c = getSensorBgCounterLocked(sensor, true);
-            if (c != null && mProcessState >= PROCESS_STATE_BACKGROUND) {
+            StopwatchTimer t = getSensorTimerLocked(sensor, /* create= */ true);
+            t.startRunningLocked(elapsedRealtimeMs);
+
+            Counter c = getSensorBgCounterLocked(sensor, /* create= */ true);
+            if (mProcessState >= PROCESS_STATE_BACKGROUND && t.mNesting == 1) {
                 c.stepAtomic();
             }
         }
@@ -7933,17 +7946,17 @@
         }
 
         public void noteStartGps(long elapsedRealtimeMs) {
-            StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, true);
-            if (t != null) {
-                t.startRunningLocked(elapsedRealtimeMs);
-            }
-            Counter c = getSensorBgCounterLocked(Sensor.GPS, true);
-            if (c != null && mProcessState >= PROCESS_STATE_BACKGROUND) {
+            StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, /* create= */ true);
+            t.startRunningLocked(elapsedRealtimeMs);
+
+            Counter c = getSensorBgCounterLocked(Sensor.GPS, /* create= */ true);
+            if (mProcessState >= PROCESS_STATE_BACKGROUND && t.mNesting == 1) {
                 c.stepAtomic();
             }
         }
 
         public void noteStopGps(long elapsedRealtimeMs) {
+            // Don't create a timer if one doesn't already exist
             StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, false);
             if (t != null) {
                 t.stopRunningLocked(elapsedRealtimeMs);
@@ -8871,6 +8884,10 @@
                 if (entry.rxBytes != 0) {
                     u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes,
                             entry.rxPackets);
+                    if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
+                        u.noteNetworkActivityLocked(NETWORK_WIFI_BG_RX_DATA, entry.rxBytes,
+                                entry.rxPackets);
+                    }
                     mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
                             entry.rxBytes);
                     mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
@@ -8886,6 +8903,10 @@
                 if (entry.txBytes != 0) {
                     u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes,
                             entry.txPackets);
+                    if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
+                        u.noteNetworkActivityLocked(NETWORK_WIFI_BG_TX_DATA, entry.txBytes,
+                                entry.txPackets);
+                    }
                     mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
                             entry.txBytes);
                     mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
@@ -9105,6 +9126,12 @@
                 final Uid u = getUidStatsLocked(mapUid(entry.uid));
                 u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes, entry.rxPackets);
                 u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes, entry.txPackets);
+                if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
+                    u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_RX_DATA,
+                            entry.rxBytes, entry.rxPackets);
+                    u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_TX_DATA,
+                            entry.txBytes, entry.txPackets);
+                }
 
                 mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
                         entry.rxBytes);
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index fa71a62..e065843 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -100,6 +100,8 @@
           int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
           int[] fdsToIgnore, String instructionSet, String appDataDir) {
         VM_HOOKS.preFork();
+        // Resets nice priority for zygote process.
+        resetNicePriority();
         int pid = nativeForkAndSpecialize(
                   uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
                   fdsToIgnore, instructionSet, appDataDir);
@@ -144,6 +146,8 @@
     public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
             int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
         VM_HOOKS.preFork();
+        // Resets nice priority for zygote process.
+        resetNicePriority();
         int pid = nativeForkSystemServer(
                 uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
         // Enable tracing as soon as we enter the system_server.
@@ -174,9 +178,13 @@
     }
 
     /**
-     * Resets this process' priority to the default value (0).
+     * Resets the calling thread priority to the default value (Thread.NORM_PRIORITY
+     * or nice value 0). This updates both the priority value in java.lang.Thread and
+     * the nice value (setpriority).
      */
-    native static void nativeResetNicePriority();
+    static void resetNicePriority() {
+        Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
+    }
 
     /**
      * Executes "/system/bin/sh -c &lt;command&gt;" using the exec() system call.
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 310cbc7..a7e900a 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -715,7 +715,7 @@
                     SystemClock.uptimeMillis());
                 bootTimingsTraceLog.traceEnd(); // ZygotePreload
             } else {
-                Zygote.nativeResetNicePriority();
+                Zygote.resetNicePriority();
             }
 
             // Finish profiling the zygote initialization.
diff --git a/core/java/com/android/internal/policy/PipSnapAlgorithm.java b/core/java/com/android/internal/policy/PipSnapAlgorithm.java
index 040f150..f88ac49 100644
--- a/core/java/com/android/internal/policy/PipSnapAlgorithm.java
+++ b/core/java/com/android/internal/policy/PipSnapAlgorithm.java
@@ -18,9 +18,11 @@
 
 import android.content.Context;
 import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.graphics.Point;
 import android.graphics.PointF;
 import android.graphics.Rect;
+import android.util.Size;
 import android.view.Gravity;
 import android.view.ViewConfiguration;
 import android.widget.Scroller;
@@ -56,6 +58,10 @@
     private final int mDefaultSnapMode = SNAP_MODE_CORNERS_AND_EDGES;
     private int mSnapMode = mDefaultSnapMode;
 
+    private final float mDefaultSizePercent;
+    private final float mMinAspectRatioForMinSize;
+    private final float mMaxAspectRatioForMinSize;
+
     private Scroller mScroller;
     private int mOrientation = Configuration.ORIENTATION_UNDEFINED;
 
@@ -63,9 +69,15 @@
     private boolean mIsMinimized;
 
     public PipSnapAlgorithm(Context context) {
+        Resources res = context.getResources();
         mContext = context;
-        mMinimizedVisibleSize = context.getResources().getDimensionPixelSize(
+        mMinimizedVisibleSize = res.getDimensionPixelSize(
                 com.android.internal.R.dimen.pip_minimized_visible_size);
+        mDefaultSizePercent = res.getFloat(
+                com.android.internal.R.dimen.config_pictureInPictureDefaultSizePercent);
+        mMaxAspectRatioForMinSize = res.getFloat(
+                com.android.internal.R.dimen.config_pictureInPictureAspectRatioLimitForMinSize);
+        mMinAspectRatioForMinSize = 1f / mMaxAspectRatioForMinSize;
         onConfigurationChanged();
     }
 
@@ -242,6 +254,40 @@
     }
 
     /**
+     * @return the size of the PiP at the given {@param aspectRatio}, ensuring that the minimum edge
+     * is at least {@param minEdgeSize}.
+     */
+    public Size getSizeForAspectRatio(float aspectRatio, float minEdgeSize, int displayWidth,
+            int displayHeight) {
+        final int smallestDisplaySize = Math.min(displayWidth, displayHeight);
+        final int minSize = (int) Math.max(minEdgeSize, smallestDisplaySize * mDefaultSizePercent);
+
+        final int width;
+        final int height;
+        if (aspectRatio <= mMinAspectRatioForMinSize || aspectRatio > mMaxAspectRatioForMinSize) {
+            // Beyond these points, we can just use the min size as the shorter edge
+            if (aspectRatio <= 1) {
+                // Portrait, width is the minimum size
+                width = minSize;
+                height = Math.round(width / aspectRatio);
+            } else {
+                // Landscape, height is the minimum size
+                height = minSize;
+                width = Math.round(height * aspectRatio);
+            }
+        } else {
+            // Within these points, we ensure that the bounds fit within the radius of the limits
+            // at the points
+            final float widthAtMaxAspectRatioForMinSize = mMaxAspectRatioForMinSize * minSize;
+            final float radius = PointF.length(widthAtMaxAspectRatioForMinSize, minSize);
+            height = (int) Math.round(Math.sqrt((radius * radius) /
+                    (aspectRatio * aspectRatio + 1)));
+            width = Math.round(height * aspectRatio);
+        }
+        return new Size(width, height);
+    }
+
+    /**
      * @return the closest point in {@param points} to the given {@param x} and {@param y}.
      */
     private Point findClosestPoint(int x, int y, Point[] points) {
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index cb3a250..be69d9f8 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -31,6 +31,7 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
+import java.util.function.Function;
 
 /**
  * ArrayUtils contains some methods that you can call to find out
@@ -260,10 +261,19 @@
      */
     @SuppressWarnings("unchecked")
     public static @NonNull <T> T[] appendElement(Class<T> kind, @Nullable T[] array, T element) {
+        return appendElement(kind, array, element, false);
+    }
+
+    /**
+     * Adds value to given array.
+     */
+    @SuppressWarnings("unchecked")
+    public static @NonNull <T> T[] appendElement(Class<T> kind, @Nullable T[] array, T element,
+            boolean allowDuplicates) {
         final T[] result;
         final int end;
         if (array != null) {
-            if (contains(array, element)) return array;
+            if (!allowDuplicates && contains(array, element)) return array;
             end = array.length;
             result = (T[])Array.newInstance(kind, end + 1);
             System.arraycopy(array, 0, result, 0, end);
@@ -299,17 +309,19 @@
     }
 
     /**
-     * Adds value to given array if not already present, providing set-like
-     * behavior.
+     * Adds value to given array.
      */
-    public static @NonNull int[] appendInt(@Nullable int[] cur, int val) {
+    public static @NonNull int[] appendInt(@Nullable int[] cur, int val,
+            boolean allowDuplicates) {
         if (cur == null) {
             return new int[] { val };
         }
         final int N = cur.length;
-        for (int i = 0; i < N; i++) {
-            if (cur[i] == val) {
-                return cur;
+        if (!allowDuplicates) {
+            for (int i = 0; i < N; i++) {
+                if (cur[i] == val) {
+                    return cur;
+                }
             }
         }
         int[] ret = new int[N + 1];
@@ -319,6 +331,14 @@
     }
 
     /**
+     * Adds value to given array if not already present, providing set-like
+     * behavior.
+     */
+    public static @NonNull int[] appendInt(@Nullable int[] cur, int val) {
+        return appendInt(cur, val, false);
+    }
+
+    /**
      * Removes value from given array if present, providing set-like behavior.
      */
     public static @Nullable int[] removeInt(@Nullable int[] cur, int val) {
@@ -455,12 +475,25 @@
         }
     }
 
+    public static int size(@Nullable Collection<?> cur) {
+        return cur != null ? cur.size() : 0;
+    }
+
+    public static @NonNull <I, O> List<O> map(@Nullable List<I> cur,
+            Function<? super I, ? extends O> f) {
+        if (cur == null || cur.isEmpty()) return Collections.emptyList();
+        final ArrayList<O> result = new ArrayList<>();
+        for (int i = 0; i < cur.size(); i++) {
+            result.add(f.apply(cur.get(i)));
+        }
+        return result;
+    }
+
     /**
      * Returns the given list, or an immutable empty list if the provided list is null
      *
      * @see Collections#emptyList
      */
-
     public static @NonNull <T> List<T> emptyIfNull(@Nullable List<T> cur) {
         return cur == null ? Collections.emptyList() : cur;
     }
diff --git a/core/java/com/android/internal/util/ExponentiallyBucketedHistogram.java b/core/java/com/android/internal/util/ExponentiallyBucketedHistogram.java
new file mode 100644
index 0000000..dc9f3f4
--- /dev/null
+++ b/core/java/com/android/internal/util/ExponentiallyBucketedHistogram.java
@@ -0,0 +1,97 @@
+/*
+ * 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.internal.util;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.util.Log;
+
+import java.util.Arrays;
+
+/**
+ * A histogram for positive integers where each bucket is twice the size of the previous one.
+ */
+public class ExponentiallyBucketedHistogram {
+    @NonNull
+    private final int[] mData;
+
+    /**
+     * Create a new histogram.
+     *
+     * @param numBuckets The number of buckets. The highest bucket is for all value >=
+     *                   2<sup>numBuckets - 1</sup>
+     */
+    public ExponentiallyBucketedHistogram(@IntRange(from = 1, to = 31) int numBuckets) {
+        numBuckets = Preconditions.checkArgumentInRange(numBuckets, 1, 31, "numBuckets");
+
+        mData = new int[numBuckets];
+    }
+
+    /**
+     * Add a new value to the histogram.
+     *
+     * All values <= 0 are in the first bucket. The last bucket contains all values >=
+     * 2<sup>numBuckets - 1</sup>
+     *
+     * @param value The value to add
+     */
+    public void add(int value) {
+        if (value <= 0) {
+            mData[0]++;
+        } else {
+            mData[Math.min(mData.length - 1, 32 - Integer.numberOfLeadingZeros(value))]++;
+        }
+    }
+
+    /**
+     * Clear all data from the histogram
+     */
+    public void reset() {
+        Arrays.fill(mData, 0);
+    }
+
+    /**
+     * Write the histogram to the log.
+     *
+     * @param tag    The tag to use when logging
+     * @param prefix A custom prefix that is printed in front of the histogram
+     */
+    public void log(@NonNull String tag, @Nullable CharSequence prefix) {
+        StringBuilder builder = new StringBuilder(prefix);
+        builder.append('[');
+
+        for (int i = 0; i < mData.length; i++) {
+            if (i != 0) {
+                builder.append(", ");
+            }
+
+            if (i < mData.length - 1) {
+                builder.append("<");
+                builder.append(1 << i);
+            } else {
+                builder.append(">=");
+                builder.append(1 << (i - 1));
+            }
+
+            builder.append(": ");
+            builder.append(mData[i]);
+        }
+        builder.append("]");
+
+        Log.d(tag, builder.toString());
+    }
+}
diff --git a/core/java/com/android/internal/util/ParcelableString.java b/core/java/com/android/internal/util/ParcelableString.java
deleted file mode 100644
index 6bd856f..0000000
--- a/core/java/com/android/internal/util/ParcelableString.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2014, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.util;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Helper class to adapt a simple String to cases where a Parcelable is expected.
- * @hide
- */
-public class ParcelableString implements Parcelable {
-    public String string;
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeString(string);
-    }
-
-    public static final Parcelable.Creator<ParcelableString> CREATOR =
-            new Parcelable.Creator<ParcelableString>() {
-                @Override
-                public ParcelableString createFromParcel(Parcel in) {
-                    ParcelableString ret = new ParcelableString();
-                    ret.string = in.readString();
-                    return ret;
-                }
-                @Override
-                public ParcelableString[] newArray(int size) {
-                    return new ParcelableString[size];
-                }
-    };
-}
\ No newline at end of file
diff --git a/core/java/com/android/internal/util/Predicate.java b/core/java/com/android/internal/util/Predicate.java
index bc6d6b3..1b5eaff 100644
--- a/core/java/com/android/internal/util/Predicate.java
+++ b/core/java/com/android/internal/util/Predicate.java
@@ -25,7 +25,10 @@
  * <p/>
  * Implementors of Predicate which may cause side effects upon evaluation are
  * strongly encouraged to state this fact clearly in their API documentation.
+ *
+ * @deprecated Use {@code java.util.function.Predicate} instead.
  */
+@Deprecated
 public interface Predicate<T> {
 
     boolean apply(T t);
diff --git a/core/java/com/android/internal/util/StateMachine.java b/core/java/com/android/internal/util/StateMachine.java
index be10608df..d67cef3 100644
--- a/core/java/com/android/internal/util/StateMachine.java
+++ b/core/java/com/android/internal/util/StateMachine.java
@@ -23,6 +23,8 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.io.StringWriter;
@@ -1495,7 +1497,7 @@
     }
 
     /**
-     * @return number of log records
+     * @return the number of log records currently readable
      */
     public final int getLogRecSize() {
         // mSmHandler can be null if the state machine has quit.
@@ -1505,6 +1507,17 @@
     }
 
     /**
+     * @return the number of log records we can store
+     */
+    @VisibleForTesting
+    public final int getLogRecMaxSize() {
+        // mSmHandler can be null if the state machine has quit.
+        SmHandler smh = mSmHandler;
+        if (smh == null) return 0;
+        return smh.mLogRecords.mMaxSize;
+    }
+
+    /**
      * @return the total number of records processed
      */
     public final int getLogRecCount() {
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java
index 555263d..28291ae 100644
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java
@@ -496,6 +496,7 @@
                 } finally {
                     args.recycle();
                 }
+                return;
             }
             case DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO: {
                 SomeArgs args = (SomeArgs)msg.obj;
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItem.java b/core/java/com/android/internal/view/menu/ActionMenuItem.java
index ace0cce..ac226dd 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItem.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItem.java
@@ -145,12 +145,12 @@
     }
 
     public MenuItem setAlphabeticShortcut(char alphaChar) {
-        mShortcutAlphabeticChar = alphaChar;
+        mShortcutAlphabeticChar = Character.toLowerCase(alphaChar);
         return this;
     }
 
     public MenuItem setAlphabeticShortcut(char alphachar, int alphaModifiers) {
-        mShortcutAlphabeticChar = alphachar;
+        mShortcutAlphabeticChar = Character.toLowerCase(alphachar);
         mShortcutAlphabeticModifiers = KeyEvent.normalizeMetaState(alphaModifiers);
         return this;
     }
@@ -210,7 +210,7 @@
 
     public MenuItem setShortcut(char numericChar, char alphaChar) {
         mShortcutNumericChar = numericChar;
-        mShortcutAlphabeticChar = alphaChar;
+        mShortcutAlphabeticChar = Character.toLowerCase(alphaChar);
         return this;
     }
 
@@ -218,7 +218,7 @@
             int alphaModifiers) {
         mShortcutNumericChar = numericChar;
         mShortcutNumericModifiers = KeyEvent.normalizeMetaState(numericModifiers);
-        mShortcutAlphabeticChar = alphaChar;
+        mShortcutAlphabeticChar = Character.toLowerCase(alphaChar);
         mShortcutAlphabeticModifiers = KeyEvent.normalizeMetaState(alphaModifiers);
         return this;
     }
diff --git a/core/java/com/android/internal/view/menu/CascadingMenuPopup.java b/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
index 69e974c..1de0af6 100644
--- a/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
+++ b/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
@@ -388,14 +388,22 @@
             final boolean showOnRight = nextMenuPosition == HORIZ_POSITION_RIGHT;
             mLastPosition = nextMenuPosition;
 
-            final int[] tempLocation = new int[2];
+            // A popup anchored to mAnchorView with (0,0) offset would be shown at this position.
+            final int[] offsetOrigin = new int[2];
+            mAnchorView.getLocationOnScreen(offsetOrigin);
+            offsetOrigin[1] += mAnchorView.getHeight();
 
-            // This popup menu will be positioned relative to the top-left edge
-            // of the view representing its parent menu.
-            parentView.getLocationInWindow(tempLocation);
-            final int parentOffsetLeft = parentInfo.window.getHorizontalOffset() + tempLocation[0];
-            final int parentOffsetTop = parentInfo.window.getVerticalOffset() + tempLocation[1];
+            final int[] parentViewScreenLocation = new int[2];
+            parentView.getLocationOnScreen(parentViewScreenLocation);
 
+            // Translate the parent view location into the offset coordinate space.
+            // If used as horizontal/vertical offsets, these values would position the submenu
+            // at the exact same position as the parent item.
+            final int parentOffsetLeft = parentViewScreenLocation[0] - offsetOrigin[0];
+            final int parentOffsetTop = parentViewScreenLocation[1] - offsetOrigin[1];
+
+            // Adjust the horizontal offset to display the submenu to the right or to the left
+            // of the parent item.
             // By now, mDropDownGravity is the resolved absolute gravity, so
             // this should work in both LTR and RTL.
             final int x;
@@ -412,11 +420,10 @@
                     x = parentOffsetLeft - menuWidth;
                 }
             }
-
             popupWindow.setHorizontalOffset(x);
 
-            final int y = parentOffsetTop;
-            popupWindow.setVerticalOffset(y);
+            // Use the same vertical offset as the parent item.
+            popupWindow.setVerticalOffset(parentOffsetTop);
         } else {
             if (mHasXOffset) {
                 popupWindow.setHorizontalOffset(mXOffset);
diff --git a/core/java/com/android/internal/view/menu/ListMenuItemView.java b/core/java/com/android/internal/view/menu/ListMenuItemView.java
index 43005e6..919cf99 100644
--- a/core/java/com/android/internal/view/menu/ListMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ListMenuItemView.java
@@ -115,7 +115,6 @@
         setEnabled(itemData.isEnabled());
         setSubMenuArrowVisible(itemData.hasSubMenu());
         setContentDescription(itemData.getContentDescription());
-        setTooltipText(itemData.getTooltipText());
     }
 
     public void setForceShowIcon(boolean forceShow) {
diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java
index 4c3118d..9310d14 100644
--- a/core/java/com/android/internal/view/menu/MenuItemImpl.java
+++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java
@@ -255,7 +255,7 @@
             return this;
         }
 
-        mShortcutAlphabeticChar = alphaChar;
+        mShortcutAlphabeticChar = Character.toLowerCase(alphaChar);
         mShortcutAlphabeticModifiers = KeyEvent.normalizeMetaState(alphaModifiers);
 
         mMenu.onItemsChanged(false);
@@ -307,7 +307,7 @@
             int alphaModifiers) {
         mShortcutNumericChar = numericChar;
         mShortcutNumericModifiers = KeyEvent.normalizeMetaState(numericModifiers);
-        mShortcutAlphabeticChar = alphaChar;
+        mShortcutAlphabeticChar = Character.toLowerCase(alphaChar);
         mShortcutAlphabeticModifiers = KeyEvent.normalizeMetaState(alphaModifiers);
 
         mMenu.onItemsChanged(false);
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
index 854d013..79b0cd1 100644
--- a/core/java/com/android/internal/widget/FloatingToolbar.java
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -54,7 +54,6 @@
 import android.view.animation.Interpolator;
 import android.widget.AdapterView;
 import android.widget.ArrayAdapter;
-import android.widget.Button;
 import android.widget.ImageButton;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
@@ -278,10 +277,14 @@
     private List<Object> getShowingMenuItemsReferences(List<MenuItem> menuItems) {
         List<Object> references = new ArrayList<Object>();
         for (MenuItem menuItem : menuItems) {
-            if (isIconOnlyMenuItem(menuItem)) {
+            if (menuItem.getItemId() != Menu.NONE) {
+                references.add(menuItem.getItemId());
+            } else if (!TextUtils.isEmpty(menuItem.getTitle())) {
+                references.add(menuItem.getTitle());
+            } else if (menuItem.getIcon() != null){
                 references.add(menuItem.getIcon());
             } else {
-                references.add(menuItem.getTitle());
+                references.add(menuItem);
             }
         }
         return references;
@@ -364,6 +367,9 @@
                     }
                 };
 
+        private final int mLineHeight;
+        private final int mIconTextSpacing;
+
         /**
          * @see OverflowPanelViewHelper#preparePopupContent().
          */
@@ -418,6 +424,10 @@
                     .getDimensionPixelSize(R.dimen.floating_toolbar_horizontal_margin);
             mMarginVertical = parent.getResources()
                     .getDimensionPixelSize(R.dimen.floating_toolbar_vertical_margin);
+            mLineHeight = context.getResources()
+                    .getDimensionPixelSize(R.dimen.floating_toolbar_height);
+            mIconTextSpacing = context.getResources()
+                    .getDimensionPixelSize(R.dimen.floating_toolbar_menu_button_side_padding);
 
             // Interpolators
             mLogAccelerateInterpolator = new LogAccelerateInterpolator();
@@ -607,7 +617,7 @@
                     mViewPortOnScreen.bottom - contentRectOnScreen.bottom;
 
             final int margin = 2 * mMarginVertical;
-            final int toolbarHeightWithVerticalMargin = getLineHeight(mContext) + margin;
+            final int toolbarHeightWithVerticalMargin = mLineHeight + margin;
 
             if (!hasOverflow()) {
                 if (availableHeightAboveContent >= toolbarHeightWithVerticalMargin) {
@@ -616,7 +626,7 @@
                 } else if (availableHeightBelowContent >= toolbarHeightWithVerticalMargin) {
                     // There is enough space at the bottom of the content.
                     y = contentRectOnScreen.bottom;
-                } else if (availableHeightBelowContent >= getLineHeight(mContext)) {
+                } else if (availableHeightBelowContent >= mLineHeight) {
                     // Just enough space to fit the toolbar with no vertical margins.
                     y = contentRectOnScreen.bottom - mMarginVertical;
                 } else {
@@ -993,7 +1003,7 @@
         private void updateOverflowHeight(int suggestedHeight) {
             if (hasOverflow()) {
                 final int maxItemSize = (suggestedHeight - mOverflowButtonSize.getHeight()) /
-                        getLineHeight(mContext);
+                        mLineHeight;
                 final int newHeight = calculateOverflowHeight(maxItemSize);
                 if (mOverflowPanelSize.getHeight() != newHeight) {
                     mOverflowPanelSize = new Size(mOverflowPanelSize.getWidth(), newHeight);
@@ -1118,7 +1128,7 @@
             boolean isFirstItem = true;
             while (!remainingMenuItems.isEmpty()) {
                 final MenuItem menuItem = remainingMenuItems.peek();
-                View menuItemButton = createMenuItemButton(mContext, menuItem);
+                View menuItemButton = createMenuItemButton(mContext, menuItem, mIconTextSpacing);
 
                 // Adding additional start padding for the first button to even out button spacing.
                 if (isFirstItem) {
@@ -1185,6 +1195,8 @@
                     }
 
                     setButtonTagAndClickListener(menuItemButton, menuItem);
+                    // Set tooltips for main panel items, but not overflow items (b/35726766).
+                    menuItemButton.setTooltipText(menuItem.getTooltipText());
                     mMainPanel.addView(menuItemButton);
                     final ViewGroup.LayoutParams params = menuItemButton.getLayoutParams();
                     params.width = menuItemButtonWidth + extraPadding / 2;
@@ -1296,20 +1308,16 @@
             if (actualSize < mOverflowPanel.getCount()) {
                 // The overflow will require scrolling to get to all the items.
                 // Extend the height so that part of the hidden items is displayed.
-                extension = (int) (getLineHeight(mContext) * 0.5f);
+                extension = (int) (mLineHeight * 0.5f);
             }
-            return actualSize * getLineHeight(mContext)
+            return actualSize * mLineHeight
                     + mOverflowButtonSize.getHeight()
                     + extension;
         }
 
         private void setButtonTagAndClickListener(View menuItemButton, MenuItem menuItem) {
-            View button = menuItemButton;
-            if (isIconOnlyMenuItem(menuItem)) {
-                button = menuItemButton.findViewById(R.id.floating_toolbar_menu_item_image_button);
-            }
-            button.setTag(menuItem);
-            button.setOnClickListener(mMenuItemButtonOnClickListener);
+            menuItemButton.setTag(menuItem);
+            menuItemButton.setOnClickListener(mMenuItemButtonOnClickListener);
         }
 
         /**
@@ -1395,16 +1403,6 @@
             final ArrayAdapter adapter =
                     new ArrayAdapter<MenuItem>(mContext, 0) {
                         @Override
-                        public int getViewTypeCount() {
-                            return mOverflowPanelViewHelper.getViewTypeCount();
-                        }
-
-                        @Override
-                        public int getItemViewType(int position) {
-                            return mOverflowPanelViewHelper.getItemViewType(getItem(position));
-                        }
-
-                        @Override
                         public View getView(int position, View convertView, ViewGroup parent) {
                             return mOverflowPanelViewHelper.getView(
                                     getItem(position), mOverflowPanelSize.getWidth(), convertView);
@@ -1496,10 +1494,6 @@
             setSize(view, params.width, height);
         }
 
-        private static int getLineHeight(Context context) {
-            return context.getResources().getDimensionPixelSize(R.dimen.floating_toolbar_height);
-        }
-
         /**
          * A custom ListView for the overflow panel.
          */
@@ -1562,138 +1556,86 @@
          */
         private static final class OverflowPanelViewHelper {
 
-            private static final int NUM_OF_VIEW_TYPES = 2;
-            private static final int VIEW_TYPE_STRING_TITLE = 0;
-            private static final int VIEW_TYPE_ICON_ONLY = 1;
-
-            private final TextView mStringTitleViewCalculator;
-            private final View mIconOnlyViewCalculator;
+            private final View mCalculator;
+            private final int mIconTextSpacing;
+            private final int mSidePadding;
 
             private final Context mContext;
 
             public OverflowPanelViewHelper(Context context) {
                 mContext = Preconditions.checkNotNull(context);
-                mStringTitleViewCalculator = getStringTitleView(null, 0, null);
-                mIconOnlyViewCalculator = getIconOnlyView(null, 0, null);
-            }
-
-            public int getViewTypeCount() {
-                return NUM_OF_VIEW_TYPES;
+                mIconTextSpacing = context.getResources()
+                        .getDimensionPixelSize(R.dimen.floating_toolbar_menu_button_side_padding);
+                mSidePadding = context.getResources()
+                        .getDimensionPixelSize(R.dimen.floating_toolbar_overflow_side_padding);
+                mCalculator = createMenuButton(null);
             }
 
             public View getView(MenuItem menuItem, int minimumWidth, View convertView) {
                 Preconditions.checkNotNull(menuItem);
-                if (getItemViewType(menuItem) == VIEW_TYPE_ICON_ONLY) {
-                    return getIconOnlyView(menuItem, minimumWidth, convertView);
+                if (convertView != null) {
+                    updateMenuItemButton(convertView, menuItem, mIconTextSpacing);
+                } else {
+                    convertView = createMenuButton(menuItem);
                 }
-                return getStringTitleView(menuItem, minimumWidth, convertView);
-            }
-
-            public int getItemViewType(MenuItem menuItem) {
-                Preconditions.checkNotNull(menuItem);
-                if (isIconOnlyMenuItem(menuItem)) {
-                    return VIEW_TYPE_ICON_ONLY;
-                }
-                return VIEW_TYPE_STRING_TITLE;
+                convertView.setMinimumWidth(minimumWidth);
+                return convertView;
             }
 
             public int calculateWidth(MenuItem menuItem) {
-                final View calculator;
-                if (isIconOnlyMenuItem(menuItem)) {
-                    ((ImageView) mIconOnlyViewCalculator
-                            .findViewById(R.id.floating_toolbar_menu_item_image_button))
-                            .setImageDrawable(menuItem.getIcon());
-                    calculator = mIconOnlyViewCalculator;
-                } else {
-                    mStringTitleViewCalculator.setText(menuItem.getTitle());
-                    calculator = mStringTitleViewCalculator;
-                }
-                calculator.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
-                return calculator.getMeasuredWidth();
+                updateMenuItemButton(mCalculator, menuItem, mIconTextSpacing);
+                mCalculator.measure(
+                        View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
+                return mCalculator.getMeasuredWidth();
             }
 
-            private TextView getStringTitleView(
-                    MenuItem menuItem, int minimumWidth, View convertView) {
-                TextView menuButton;
-                if (convertView != null) {
-                    menuButton = (TextView) convertView;
-                } else {
-                    menuButton = (TextView) LayoutInflater.from(mContext)
-                            .inflate(R.layout.floating_popup_overflow_list_item, null);
-                    menuButton.setLayoutParams(new ViewGroup.LayoutParams(
-                            ViewGroup.LayoutParams.MATCH_PARENT,
-                            ViewGroup.LayoutParams.WRAP_CONTENT));
-                }
-                if (menuItem != null) {
-                    menuButton.setText(menuItem.getTitle());
-                    final CharSequence contentDescription = menuItem.getContentDescription();
-                    if (TextUtils.isEmpty(contentDescription)) {
-                        menuButton.setContentDescription(menuItem.getTitle());
-                    } else {
-                        menuButton.setContentDescription(contentDescription);
-                    }
-                    menuButton.setTooltipText(menuItem.getTooltipText());
-                    menuButton.setMinimumWidth(minimumWidth);
-                }
-                return menuButton;
-            }
-
-            private View getIconOnlyView(
-                    MenuItem menuItem, int minimumWidth, View convertView) {
-                View menuButton;
-                if (convertView != null) {
-                    menuButton = convertView;
-                } else {
-                    menuButton = LayoutInflater.from(mContext).inflate(
-                            R.layout.floating_popup_overflow_image_list_item, null);
-                    menuButton.setLayoutParams(new ViewGroup.LayoutParams(
-                            ViewGroup.LayoutParams.WRAP_CONTENT,
-                            ViewGroup.LayoutParams.WRAP_CONTENT));
-                }
-                if (menuItem != null) {
-                    ((ImageView) menuButton
-                            .findViewById(R.id.floating_toolbar_menu_item_image_button))
-                            .setImageDrawable(menuItem.getIcon());
-                    menuButton.setMinimumWidth(minimumWidth);
-                }
-                return menuButton;
+            private View createMenuButton(MenuItem menuItem) {
+                View button = createMenuItemButton(mContext, menuItem, mIconTextSpacing);
+                button.setPadding(mSidePadding, 0, mSidePadding, 0);
+                return button;
             }
         }
     }
 
     /**
-     * @return {@code true} if the menu item does not not have a string title but has an icon.
-     *   {@code false} otherwise.
-     */
-    private static boolean isIconOnlyMenuItem(MenuItem menuItem) {
-        if (TextUtils.isEmpty(menuItem.getTitle()) && menuItem.getIcon() != null) {
-            return true;
-        }
-        return false;
-    }
-
-    /**
      * Creates and returns a menu button for the specified menu item.
      */
-    private static View createMenuItemButton(Context context, MenuItem menuItem) {
-        final View menuItemButton;
-        if (isIconOnlyMenuItem(menuItem)) {
-            menuItemButton = LayoutInflater.from(context)
-                    .inflate(R.layout.floating_popup_menu_image_button, null);
-            ((ImageButton) menuItemButton
-                    .findViewById(R.id.floating_toolbar_menu_item_image_button))
-                    .setImageDrawable(menuItem.getIcon());
-            final CharSequence tooltipText = menuItem.getTooltipText();
-            if (TextUtils.isEmpty(tooltipText)) {
-                menuItemButton.setTooltipText(menuItem.getTitle());
-            } else {
-                menuItemButton.setTooltipText(tooltipText);
+    private static View createMenuItemButton(
+            Context context, MenuItem menuItem, int iconTextSpacing) {
+        final View menuItemButton = LayoutInflater.from(context)
+                .inflate(R.layout.floating_popup_menu_button, null);
+        if (menuItem != null) {
+            updateMenuItemButton(menuItemButton, menuItem, iconTextSpacing);
+        }
+        return menuItemButton;
+    }
+
+    /**
+     * Updates the specified menu item button with the specified menu item data.
+     */
+    private static void updateMenuItemButton(
+            View menuItemButton, MenuItem menuItem, int iconTextSpacing) {
+        final TextView buttonText = (TextView) menuItemButton.findViewById(
+                R.id.floating_toolbar_menu_item_text);
+        if (TextUtils.isEmpty(menuItem.getTitle())) {
+            buttonText.setVisibility(View.GONE);
+        } else {
+            buttonText.setVisibility(View.VISIBLE);
+            buttonText.setText(menuItem.getTitle());
+        }
+        final ImageView buttonIcon = (ImageView) menuItemButton
+                .findViewById(R.id.floating_toolbar_menu_item_image);
+        if (menuItem.getIcon() == null) {
+            buttonIcon.setVisibility(View.GONE);
+            if (buttonText != null) {
+                buttonText.setPaddingRelative(0, 0, 0, 0);
             }
         } else {
-            menuItemButton = LayoutInflater.from(context)
-                    .inflate(R.layout.floating_popup_menu_button, null);
-            ((Button) menuItemButton).setText(menuItem.getTitle());
-            menuItemButton.setTooltipText(menuItem.getTooltipText());
+            buttonIcon.setVisibility(View.VISIBLE);
+            buttonIcon.setImageDrawable(menuItem.getIcon());
+            if (buttonText != null) {
+                buttonText.setPaddingRelative(iconTextSpacing, 0, 0, 0);
+            }
         }
         final CharSequence contentDescription = menuItem.getContentDescription();
         if (TextUtils.isEmpty(contentDescription)) {
@@ -1701,7 +1643,6 @@
         } else {
             menuItemButton.setContentDescription(contentDescription);
         }
-        return menuItemButton;
     }
 
     private static ViewGroup createContentContainer(Context context) {
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index 4ba19f4..cc1c65e 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -278,7 +278,8 @@
     public LockPatternView(Context context, AttributeSet attrs) {
         super(context, attrs);
 
-        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LockPatternView);
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LockPatternView,
+                R.attr.lockPatternStyle, R.style.Widget_LockPatternView);
 
         final String aspect = a.getString(R.styleable.LockPatternView_aspect);
 
@@ -298,12 +299,9 @@
         mPathPaint.setAntiAlias(true);
         mPathPaint.setDither(true);
 
-        mRegularColor = context.getColor(R.color.lock_pattern_view_regular_color);
-        mErrorColor = context.getColor(R.color.lock_pattern_view_error_color);
-        mSuccessColor = context.getColor(R.color.lock_pattern_view_success_color);
-        mRegularColor = a.getColor(R.styleable.LockPatternView_regularColor, mRegularColor);
-        mErrorColor = a.getColor(R.styleable.LockPatternView_errorColor, mErrorColor);
-        mSuccessColor = a.getColor(R.styleable.LockPatternView_successColor, mSuccessColor);
+        mRegularColor = a.getColor(R.styleable.LockPatternView_regularColor, 0);
+        mErrorColor = a.getColor(R.styleable.LockPatternView_errorColor, 0);
+        mSuccessColor = a.getColor(R.styleable.LockPatternView_successColor, 0);
 
         int pathColor = a.getColor(R.styleable.LockPatternView_pathColor, mRegularColor);
         mPathPaint.setColor(pathColor);
@@ -1489,21 +1487,10 @@
             return bounds;
         }
 
-        private boolean shouldSpeakPassword() {
-            final boolean speakPassword = Settings.Secure.getIntForUser(
-                    mContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD, 0,
-                    UserHandle.USER_CURRENT_OR_SELF) != 0;
-            final boolean hasHeadphones = mAudioManager != null ?
-                    (mAudioManager.isWiredHeadsetOn() || mAudioManager.isBluetoothA2dpOn())
-                    : false;
-            return speakPassword || hasHeadphones;
-        }
-
         private CharSequence getTextForVirtualView(int virtualViewId) {
             final Resources res = getResources();
-            return shouldSpeakPassword() ? res.getString(
-                R.string.lockscreen_access_pattern_cell_added_verbose, virtualViewId)
-                : res.getString(R.string.lockscreen_access_pattern_cell_added);
+            return res.getString(R.string.lockscreen_access_pattern_cell_added_verbose,
+                    virtualViewId);
         }
 
         /**
diff --git a/core/java/com/android/internal/widget/NotificationExpandButton.java b/core/java/com/android/internal/widget/NotificationExpandButton.java
index f4f49b1..c64ace4 100644
--- a/core/java/com/android/internal/widget/NotificationExpandButton.java
+++ b/core/java/com/android/internal/widget/NotificationExpandButton.java
@@ -20,6 +20,8 @@
 import android.content.Context;
 import android.graphics.Rect;
 import android.util.AttributeSet;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.widget.Button;
 import android.widget.ImageView;
 import android.widget.RemoteViews;
 
@@ -59,4 +61,10 @@
         rect.top = rect.centerY() - touchTargetSize / 2;
         rect.bottom = rect.top + touchTargetSize;
     }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(Button.class.getName());
+    }
 }
diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
index e84cc27..e224b17 100644
--- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java
+++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
@@ -748,6 +748,10 @@
         final int widthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY);
         final int heightSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY);
         final int widthPadding = getPaddingLeft() + getPaddingRight();
+
+        // Currently we allot more height than is really needed so that the entirety of the
+        // sheet may be pulled up.
+        // TODO: Restrict the height here to be the right value.
         int heightUsed = getPaddingTop() + getPaddingBottom();
 
         // Measure always-show children first.
@@ -757,7 +761,7 @@
             final LayoutParams lp = (LayoutParams) child.getLayoutParams();
             if (lp.alwaysShow && child.getVisibility() != GONE) {
                 measureChildWithMargins(child, widthSpec, widthPadding, heightSpec, heightUsed);
-                heightUsed += getHeightUsed(child);
+                heightUsed += child.getMeasuredHeight();
             }
         }
 
@@ -769,7 +773,7 @@
             final LayoutParams lp = (LayoutParams) child.getLayoutParams();
             if (!lp.alwaysShow && child.getVisibility() != GONE) {
                 measureChildWithMargins(child, widthSpec, widthPadding, heightSpec, heightUsed);
-                heightUsed += getHeightUsed(child);
+                heightUsed += child.getMeasuredHeight();
             }
         }
 
@@ -785,36 +789,6 @@
         setMeasuredDimension(sourceWidth, heightSize);
     }
 
-    private int getHeightUsed(View child) {
-        // This method exists because we're taking a fast path at measuring ListViews that
-        // lets us get away with not doing the more expensive wrap_content measurement which
-        // imposes double child view measurement costs. If we're looking at a ListView, we can
-        // check against the lowest child view plus padding and margin instead of the actual
-        // measured height of the ListView. This lets the ListView hang off the edge when
-        // all of the content would fit on-screen.
-
-        int heightUsed = child.getMeasuredHeight();
-        if (child instanceof AbsListView) {
-            final AbsListView lv = (AbsListView) child;
-            final int lvPaddingBottom = lv.getPaddingBottom();
-
-            int lowest = 0;
-            for (int i = 0, N = lv.getChildCount(); i < N; i++) {
-                final int bottom = lv.getChildAt(i).getBottom() + lvPaddingBottom;
-                if (bottom > lowest) {
-                    lowest = bottom;
-                }
-            }
-
-            if (lowest < heightUsed) {
-                heightUsed = lowest;
-            }
-        }
-
-        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-        return lp.topMargin + heightUsed + lp.bottomMargin;
-    }
-
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         final int width = getWidth();
diff --git a/core/java/com/android/internal/widget/WatchHeaderListView.java b/core/java/com/android/internal/widget/WatchHeaderListView.java
index 7e91537..0654454 100644
--- a/core/java/com/android/internal/widget/WatchHeaderListView.java
+++ b/core/java/com/android/internal/widget/WatchHeaderListView.java
@@ -91,13 +91,14 @@
     }
 
     @Override
-    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
+    protected <T extends View> T findViewByPredicateTraversal(
+            Predicate<View> predicate, View childToSkip) {
         View v = super.findViewByPredicateTraversal(predicate, childToSkip);
         if (v == null && mTopPanel != null && mTopPanel != childToSkip
                 && !mTopPanel.isRootNamespace()) {
-            return mTopPanel.findViewByPredicate(predicate);
+            return (T) mTopPanel.findViewByPredicate(predicate);
         }
-        return v;
+        return (T) v;
     }
 
     @Override
diff --git a/core/java/com/android/server/BootReceiver.java b/core/java/com/android/server/BootReceiver.java
index 5a50fbf..78e8797 100644
--- a/core/java/com/android/server/BootReceiver.java
+++ b/core/java/com/android/server/BootReceiver.java
@@ -35,6 +35,8 @@
 import android.util.Slog;
 import android.util.Xml;
 
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.XmlUtils;
 
@@ -46,6 +48,8 @@
 import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -83,6 +87,12 @@
     private static final File lastHeaderFile = new File(
             Environment.getDataSystemDirectory(), LAST_HEADER_FILE);
 
+    // example: fs_stat,/dev/block/platform/soc/by-name/userdata,0x5
+    private static final String FS_STAT_PATTERN = "fs_stat,[^,]*/([^/,]+),(0x[0-9a-fA-F]+)";
+    // ro.boottime.init.mount_all. + postfix for mount_all duration
+    private static final String[] MOUNT_DURATION_PROPS_POSTFIX =
+            new String[] { "early", "default", "late" };
+
     @Override
     public void onReceive(final Context context, Intent intent) {
         // Log boot events in the background to avoid blocking the main thread with I/O
@@ -200,10 +210,11 @@
             addFileToDropBox(db, timestamps, headers, "/cache/recovery/last_kmsg",
                     -LOG_SIZE, "SYSTEM_RECOVERY_KMSG");
             addAuditErrorsToDropBox(db, timestamps, headers, -LOG_SIZE, "SYSTEM_AUDIT");
-            addFsckErrorsToDropBox(db, timestamps, headers, -LOG_SIZE, "SYSTEM_FSCK");
         } else {
             if (db != null) db.addText("SYSTEM_RESTART", headers);
         }
+        addFsckErrorsToDropBoxAndLogFsStat(db, timestamps, headers, -LOG_SIZE, "SYSTEM_FSCK");
+        logFsMountTime();
 
         // Scan existing tombstones (in case any new ones appeared)
         File[] tombstoneFiles = TOMBSTONE_DIR.listFiles();
@@ -297,11 +308,14 @@
         db.addText(tag, headers + sb.toString());
     }
 
-    private static void addFsckErrorsToDropBox(DropBoxManager db,
+    private static void addFsckErrorsToDropBoxAndLogFsStat(DropBoxManager db,
             HashMap<String, Long> timestamps, String headers, int maxSize, String tag)
             throws IOException {
-        boolean upload_needed = false;
-        if (db == null || !db.isTagEnabled(tag)) return;  // Logging disabled
+        boolean uploadEnabled = true;
+        if (db == null || !db.isTagEnabled(tag)) {
+            uploadEnabled = false;
+        }
+        boolean uploadNeeded = false;
         Slog.i(TAG, "Checking for fsck errors");
 
         File file = new File("/dev/fscklogs/log");
@@ -310,14 +324,21 @@
 
         String log = FileUtils.readTextFile(file, maxSize, "[[TRUNCATED]]\n");
         StringBuilder sb = new StringBuilder();
-        for (String line : log.split("\n")) {
+        Pattern pattern = Pattern.compile(FS_STAT_PATTERN);
+        for (String line : log.split("\n")) { // should check all lines
             if (line.contains("FILE SYSTEM WAS MODIFIED")) {
-                upload_needed = true;
-                break;
+                uploadNeeded = true;
+            } else if (line.contains("fs_stat")){
+                Matcher matcher = pattern.matcher(line);
+                if (matcher.find()) {
+                    handleFsckFsStat(matcher);
+                } else {
+                    Slog.w(TAG, "cannot parse fs_stat:" + line);
+                }
             }
         }
 
-        if (upload_needed) {
+        if (uploadEnabled && uploadNeeded ) {
             addFileToDropBox(db, timestamps, headers, "/dev/fscklogs/log", maxSize, tag);
         }
 
@@ -325,6 +346,29 @@
         file.delete();
     }
 
+    private static void logFsMountTime() {
+        for (String propPostfix : MOUNT_DURATION_PROPS_POSTFIX) {
+            int duration = SystemProperties.getInt("ro.boottime.init.mount_all." + propPostfix, 0);
+            if (duration != 0) {
+                MetricsLogger.histogram(null, "boot_mount_all_duration_" + propPostfix, duration);
+            }
+        }
+    }
+
+    private static void handleFsckFsStat(Matcher match) {
+        String partition = match.group(1);
+        int stat;
+        try {
+            stat = Integer.decode(match.group(2));
+        } catch (NumberFormatException e) {
+            Slog.w(TAG, "cannot parse fs_stat: partition:" + partition + " stat:" + match.group(2));
+            return;
+        }
+
+        MetricsLogger.histogram(null, "boot_fs_stat_" + partition, stat);
+        Slog.i(TAG, "fs_stat, partition:" + partition + " stat:" + match.group(2));
+    }
+
     private static HashMap<String, Long> readTimestamps() {
         synchronized (sFile) {
             HashMap<String, Long> timestamps = new HashMap<String, Long>();
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index 3d012bf..67f9f8f 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -59,6 +59,7 @@
     private static final int ALLOW_LIBS = 0x02;
     private static final int ALLOW_PERMISSIONS = 0x04;
     private static final int ALLOW_APP_CONFIGS = 0x08;
+    private static final int ALLOW_PRIVAPP_PERMISSIONS = 0x10;
     private static final int ALLOW_ALL = ~0;
 
     // Group-ids that are given to all packages as read from etc/permissions/*.xml.
@@ -225,6 +226,13 @@
         // Read configuration from the old permissions dir
         readPermissions(Environment.buildPath(
                 Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL);
+        // Allow Vendor to customize system configs around libs, features, permissions and apps
+        int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PERMISSIONS |
+                ALLOW_APP_CONFIGS;
+        readPermissions(Environment.buildPath(
+                Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);
+        readPermissions(Environment.buildPath(
+                Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag);
         // Allow ODM to customize system configs around libs, features and apps
         int odmPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_APP_CONFIGS;
         readPermissions(Environment.buildPath(
@@ -313,6 +321,7 @@
             boolean allowFeatures = (permissionFlag & ALLOW_FEATURES) != 0;
             boolean allowPermissions = (permissionFlag & ALLOW_PERMISSIONS) != 0;
             boolean allowAppConfigs = (permissionFlag & ALLOW_APP_CONFIGS) != 0;
+            boolean allowPrivappPermissions = (permissionFlag & ALLOW_PRIVAPP_PERMISSIONS) != 0;
             while (true) {
                 XmlUtils.nextElement(parser);
                 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
@@ -553,7 +562,7 @@
                         associatedPkgs.add(pkgname);
                     }
                     XmlUtils.skipCurrentTag(parser);
-                } else if ("privapp-permissions".equals(name) && allowAppConfigs) {
+                } else if ("privapp-permissions".equals(name) && allowPrivappPermissions) {
                     readPrivAppPermissions(parser);
                 } else {
                     XmlUtils.skipCurrentTag(parser);
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 0c07192..c9f9d6f 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -220,7 +220,6 @@
     external/skia/src/effects \
     external/skia/src/image \
     external/skia/src/images \
-    external/skia/src/utils \
     external/sqlite/dist \
     external/sqlite/android \
     external/tremor/Tremor \
@@ -234,6 +233,8 @@
 LOCAL_STATIC_LIBRARIES := \
     libgif \
     libseccomp_policy \
+    libselinux \
+    libcrypto \
 
 LOCAL_SHARED_LIBRARIES := \
     libmemtrack \
@@ -248,6 +249,7 @@
     libbinder \
     libui \
     libgui \
+    libsensor \
     libinput \
     libcamera_client \
     libcamera_metadata \
@@ -284,11 +286,16 @@
     libhidltransport \
     libhwbinder \
     libvintf \
+    libnativewindow \
 
 LOCAL_SHARED_LIBRARIES += \
     libhwui \
     libdl \
 
+# our headers include libnativewindow's public headers
+LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := \
+    libnativewindow \
+
 # we need to access the private Bionic header
 # <bionic_tls.h> in com_google_android_gles_jni_GLImpl.cpp
 LOCAL_C_INCLUDES += bionic/libc/private
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 3ca455d..f852194 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -8,7 +8,10 @@
 #include "SkImageInfo.h"
 #include "SkColor.h"
 #include "SkColorPriv.h"
+#include "SkColorSpace.h"
+#include "SkColorSpaceXform.h"
 #include "SkHalf.h"
+#include "SkMatrix44.h"
 #include "SkPM4f.h"
 #include "SkPM4fPriv.h"
 #include "GraphicsJNI.h"
@@ -28,6 +31,7 @@
 #include "core_jni_helpers.h"
 
 #include <jni.h>
+#include <string.h>
 #include <memory>
 #include <string>
 
@@ -232,6 +236,73 @@
     return localBitmap->bitmap();
 }
 
+void imageInfo(JNIEnv* env, jobject bitmap, AndroidBitmapInfo* info) {
+    SkASSERT(info);
+    SkASSERT(env);
+    SkASSERT(bitmap);
+    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
+    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
+    LocalScopedBitmap localBitmap(bitmapHandle);
+
+    const SkImageInfo& imageInfo = localBitmap->info();
+    info->width = imageInfo.width();
+    info->height = imageInfo.height();
+    info->stride = localBitmap->rowBytes();
+    info->flags = 0;
+    switch (imageInfo.colorType()) {
+        case kN32_SkColorType:
+            info->format = ANDROID_BITMAP_FORMAT_RGBA_8888;
+            break;
+        case kRGB_565_SkColorType:
+            info->format = ANDROID_BITMAP_FORMAT_RGB_565;
+            break;
+        case kARGB_4444_SkColorType:
+            info->format = ANDROID_BITMAP_FORMAT_RGBA_4444;
+            break;
+        case kAlpha_8_SkColorType:
+            info->format = ANDROID_BITMAP_FORMAT_A_8;
+            break;
+        default:
+            info->format = ANDROID_BITMAP_FORMAT_NONE;
+            break;
+    }
+}
+
+void* lockPixels(JNIEnv* env, jobject bitmap) {
+    SkASSERT(env);
+    SkASSERT(bitmap);
+    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
+    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
+
+    LocalScopedBitmap localBitmap(bitmapHandle);
+    if (!localBitmap->valid()) return nullptr;
+
+    SkPixelRef& pixelRef = localBitmap->bitmap();
+    pixelRef.lockPixels();
+    if (!pixelRef.pixels()) {
+        pixelRef.unlockPixels();
+        return nullptr;
+    }
+    pixelRef.ref();
+    return pixelRef.pixels();
+}
+
+bool unlockPixels(JNIEnv* env, jobject bitmap) {
+    SkASSERT(env);
+    SkASSERT(bitmap);
+    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
+    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
+
+    LocalScopedBitmap localBitmap(bitmapHandle);
+    if (!localBitmap->valid()) return false;
+
+    SkPixelRef& pixelRef = localBitmap->bitmap();
+    pixelRef.notifyPixelsChanged();
+    pixelRef.unlockPixels();
+    pixelRef.unref();
+    return true;
+}
+
 } // namespace bitmap
 
 } // namespace android
@@ -380,11 +451,32 @@
 
     // reset to to actual choice from caller
     dst = dstBitmap.getAddr(x, y);
-    // now copy/convert each scanline
-    for (int y = 0; y < height; y++) {
-        proc(dst, src, width, x, y);
-        src += srcStride;
-        dst = (char*)dst + dstBitmap.rowBytes();
+
+    SkColorSpace* colorSpace = dstBitmap.colorSpace();
+    if (GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
+        // now copy/convert each scanline
+        for (int y = 0; y < height; y++) {
+            proc(dst, src, width, x, y);
+            src += srcStride;
+            dst = (char*)dst + dstBitmap.rowBytes();
+        }
+    } else {
+        auto sRGB = SkColorSpace::MakeSRGB();
+        auto xform = SkColorSpaceXform::New(sRGB.get(), colorSpace);
+
+        std::unique_ptr<SkColor[]> row(new SkColor[width]);
+
+        // now copy/convert each scanline
+        for (int y = 0; y < height; y++) {
+            memcpy(row.get(), src, sizeof(SkColor) * width);
+            xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, row.get(),
+                    SkColorSpaceXform::kBGRA_8888_ColorFormat, row.get(), width,
+                    SkAlphaType::kUnpremul_SkAlphaType);
+
+            proc(dst, row.get(), width, x, y);
+            src += srcStride;
+            dst = (char*)dst + dstBitmap.rowBytes();
+        }
     }
 
     dstBitmap.notifyPixelsChanged();
@@ -643,7 +735,7 @@
         if (!bitmap.get()) {
             return NULL;
         }
-        return createBitmap(env, bitmap.release(), kBitmapCreateFlag_None);
+        return createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(isMutable));
     }
 
     SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
@@ -856,7 +948,13 @@
     const bool        isMutable = p->readInt32() != 0;
     const SkColorType colorType = (SkColorType)p->readInt32();
     const SkAlphaType alphaType = (SkAlphaType)p->readInt32();
-    const bool        isSRGB = p->readInt32() != 0;
+    const uint32_t    colorSpaceSize = p->readUint32();
+    sk_sp<SkColorSpace> colorSpace;
+    if (kRGBA_F16_SkColorType == colorType) {
+        colorSpace = SkColorSpace::MakeSRGBLinear();
+    } else if (colorSpaceSize > 0) {
+        colorSpace = SkColorSpace::Deserialize(p->readInplace(colorSpaceSize), colorSpaceSize);
+    }
     const int         width = p->readInt32();
     const int         height = p->readInt32();
     const int         rowBytes = p->readInt32();
@@ -873,14 +971,6 @@
     }
 
     std::unique_ptr<SkBitmap> bitmap(new SkBitmap);
-
-    sk_sp<SkColorSpace> colorSpace;
-    if (kRGBA_F16_SkColorType == colorType) {
-        colorSpace = SkColorSpace::MakeSRGBLinear();
-    } else {
-        colorSpace = isSRGB ? SkColorSpace::MakeSRGB() : nullptr;
-    }
-
     if (!bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType, colorSpace),
             rowBytes)) {
         return NULL;
@@ -997,13 +1087,20 @@
     auto bitmapWrapper = reinterpret_cast<BitmapWrapper*>(bitmapHandle);
     bitmapWrapper->getSkBitmap(&bitmap);
 
-    sk_sp<SkColorSpace> sRGB = SkColorSpace::MakeSRGB();
-    bool isSRGB = bitmap.colorSpace() == sRGB.get();
-
     p->writeInt32(isMutable);
     p->writeInt32(bitmap.colorType());
     p->writeInt32(bitmap.alphaType());
-    p->writeInt32(isSRGB); // TODO: We should write the color space (b/32072280)
+    SkColorSpace* colorSpace = bitmap.colorSpace();
+    if (colorSpace != nullptr && bitmap.colorType() != kRGBA_F16_SkColorType) {
+        sk_sp<SkData> data = colorSpace->serialize();
+        size_t size = data->size();
+        p->writeUint32(size);
+        if (size > 0) {
+            p->write(data->data(), size);
+        }
+    } else {
+        p->writeUint32(0);
+    }
     p->writeInt32(bitmap.width());
     p->writeInt32(bitmap.height());
     p->writeInt32(bitmap.rowBytes());
@@ -1101,6 +1198,56 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
+static jboolean Bitmap_isSRGB(JNIEnv* env, jobject, jlong bitmapHandle) {
+    LocalScopedBitmap bitmapHolder(bitmapHandle);
+    if (!bitmapHolder.valid()) return JNI_TRUE;
+
+    SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
+    return GraphicsJNI::isColorSpaceSRGB(colorSpace);
+}
+
+static jboolean Bitmap_getColorSpace(JNIEnv* env, jobject, jlong bitmapHandle,
+        jfloatArray xyzArray, jfloatArray paramsArray) {
+
+    LocalScopedBitmap bitmapHolder(bitmapHandle);
+    if (!bitmapHolder.valid()) return JNI_FALSE;
+
+    SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
+    if (colorSpace == nullptr) return JNI_FALSE;
+
+    SkMatrix44 xyzMatrix(SkMatrix44::kUninitialized_Constructor);
+    if (!colorSpace->toXYZD50(&xyzMatrix)) return JNI_FALSE;
+
+    jfloat* xyz = env->GetFloatArrayElements(xyzArray, NULL);
+    xyz[0] = xyzMatrix.getFloat(0, 0);
+    xyz[1] = xyzMatrix.getFloat(1, 0);
+    xyz[2] = xyzMatrix.getFloat(2, 0);
+    xyz[3] = xyzMatrix.getFloat(0, 1);
+    xyz[4] = xyzMatrix.getFloat(1, 1);
+    xyz[5] = xyzMatrix.getFloat(2, 1);
+    xyz[6] = xyzMatrix.getFloat(0, 2);
+    xyz[7] = xyzMatrix.getFloat(1, 2);
+    xyz[8] = xyzMatrix.getFloat(2, 2);
+    env->ReleaseFloatArrayElements(xyzArray, xyz, 0);
+
+    SkColorSpaceTransferFn transferParams;
+    if (!colorSpace->isNumericalTransferFn(&transferParams)) return JNI_FALSE;
+
+    jfloat* params = env->GetFloatArrayElements(paramsArray, NULL);
+    params[0] = transferParams.fA;
+    params[1] = transferParams.fB;
+    params[2] = transferParams.fC;
+    params[3] = transferParams.fD;
+    params[4] = transferParams.fE;
+    params[5] = transferParams.fF;
+    params[6] = transferParams.fG;
+    env->ReleaseFloatArrayElements(paramsArray, params, 0);
+
+    return JNI_TRUE;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
 static jint Bitmap_getPixel(JNIEnv* env, jobject, jlong bitmapHandle,
         jint x, jint y) {
     SkBitmap bitmap;
@@ -1118,6 +1265,16 @@
 
     SkColor dst[1];
     proc(dst, src, 1, bitmap.getColorTable());
+
+    SkColorSpace* colorSpace = bitmap.colorSpace();
+    if (!GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
+        auto sRGB = SkColorSpace::MakeSRGB();
+        auto xform = SkColorSpaceXform::New(colorSpace, sRGB.get());
+        xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, &dst[0],
+                SkColorSpaceXform::kBGRA_8888_ColorFormat, &dst[0], 1,
+                SkAlphaType::kUnpremul_SkAlphaType);
+    }
+
     return static_cast<jint>(dst[0]);
 }
 
@@ -1140,11 +1297,30 @@
     SkColorTable* ctable = bitmap.getColorTable();
     jint* dst = env->GetIntArrayElements(pixelArray, NULL);
     SkColor* d = (SkColor*)dst + offset;
-    while (--height >= 0) {
-        proc(d, src, width, ctable);
-        d += stride;
-        src = (void*)((const char*)src + bitmap.rowBytes());
+
+    SkColorSpace* colorSpace = bitmap.colorSpace();
+    if (GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
+        while (--height >= 0) {
+            proc(d, src, width, ctable);
+            d += stride;
+            src = (void*)((const char*)src + bitmap.rowBytes());
+        }
+    } else {
+        auto sRGB = SkColorSpace::MakeSRGB();
+        auto xform = SkColorSpaceXform::New(colorSpace, sRGB.get());
+
+        while (--height >= 0) {
+            proc(d, src, width, ctable);
+
+            xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, d,
+                    SkColorSpaceXform::kBGRA_8888_ColorFormat, d, width,
+                    SkAlphaType::kUnpremul_SkAlphaType);
+
+            d += stride;
+            src = (void*)((const char*)src + bitmap.rowBytes());
+        }
     }
+
     env->ReleaseIntArrayElements(pixelArray, dst, 0);
 }
 
@@ -1165,6 +1341,15 @@
         return;
     }
 
+    SkColorSpace* colorSpace = bitmap.colorSpace();
+    if (!GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
+        auto sRGB = SkColorSpace::MakeSRGB();
+        auto xform = SkColorSpaceXform::New(sRGB.get(), colorSpace);
+        xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, &color,
+                SkColorSpaceXform::kBGRA_8888_ColorFormat, &color, 1,
+                SkAlphaType::kUnpremul_SkAlphaType);
+    }
+
     proc(bitmap.getAddr(x, y), &color, 1, x, y);
     bitmap.notifyPixelsChanged();
 }
@@ -1306,7 +1491,7 @@
         doThrowRE(env, "Could not copy a hardware bitmap.");
         return NULL;
     }
-    return createBitmap(env, allocator.getStorageObjAndReset(), kBitmapCreateFlag_None);
+    return createBitmap(env, allocator.getStorageObjAndReset(), getPremulBitmapCreateFlags(false));
 }
 
 static jobject Bitmap_createHardwareBitmap(JNIEnv* env, jobject, jobject graphicBuffer) {
@@ -1316,7 +1501,7 @@
         ALOGW("failed to create hardware bitmap from graphic buffer");
         return NULL;
     }
-    return bitmap::createBitmap(env, bitmap.release(), android::bitmap::kBitmapCreateFlag_None);
+    return bitmap::createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(false));
 }
 
 static jobject Bitmap_createGraphicBufferHandle(JNIEnv* env, jobject, jlong bitmapPtr) {
@@ -1392,7 +1577,9 @@
     {   "nativeCreateHardwareBitmap", "(Landroid/graphics/GraphicBuffer;)Landroid/graphics/Bitmap;",
         (void*) Bitmap_createHardwareBitmap },
     {   "nativeCreateGraphicBufferHandle", "(J)Landroid/graphics/GraphicBuffer;",
-        (void*) Bitmap_createGraphicBufferHandle }
+        (void*) Bitmap_createGraphicBufferHandle },
+    {   "nativeGetColorSpace",      "(J[F[F)Z", (void*)Bitmap_getColorSpace },
+    {   "nativeIsSRGB",             "(J)Z", (void*)Bitmap_isSRGB },
 };
 
 int register_android_graphics_Bitmap(JNIEnv* env)
diff --git a/core/jni/android/graphics/Bitmap.h b/core/jni/android/graphics/Bitmap.h
index 387a128..a4bfc94 100644
--- a/core/jni/android/graphics/Bitmap.h
+++ b/core/jni/android/graphics/Bitmap.h
@@ -17,6 +17,7 @@
 #define BITMAP_H_
 
 #include <jni.h>
+#include <android/bitmap.h>
 #include <SkBitmap.h>
 #include <SkColorTable.h>
 #include <SkImageInfo.h>
@@ -44,6 +45,13 @@
 Bitmap& toBitmap(JNIEnv* env, jobject bitmap);
 Bitmap& toBitmap(JNIEnv* env, jlong bitmapHandle);
 
+// NDK access
+void imageInfo(JNIEnv* env, jobject bitmap, AndroidBitmapInfo* info);
+// Returns a pointer to the pixels or nullptr if the bitmap is not valid
+void* lockPixels(JNIEnv* env, jobject bitmap);
+// Returns true if unlocked, false if the bitmap is no longer valid (destroyed)
+bool unlockPixels(JNIEnv* env, jobject bitmap);
+
 /** Reinitialize a bitmap. bitmap must already have its SkAlphaType set in
     sync with isPremultiplied
 */
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 2aa16b2..417ef8a0 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -8,7 +8,6 @@
 #include "SkBRDAllocator.h"
 #include "SkFrontBufferedStream.h"
 #include "SkMath.h"
-#include "SkOpts.h"
 #include "SkPixelRef.h"
 #include "SkStream.h"
 #include "SkUtils.h"
@@ -229,45 +228,6 @@
            needsFineScale(fullSize.height(), decodedSize.height(), sampleSize);
 }
 
-static inline SkAlphaType computeDecodeAlphaType(SkColorType colorType, SkAlphaType alphaType) {
-#ifndef ANDROID_ENABLE_LINEAR_BLENDING
-    // Skia premultiplies linearly.  Until the framework enables linear blending,
-    // it expects a legacy premultiply.
-    if (kPremul_SkAlphaType == alphaType && kRGBA_F16_SkColorType != colorType) {
-        return kUnpremul_SkAlphaType;
-    }
-#endif
-
-    return alphaType;
-}
-
-static inline void premultiplyIfNecessary(SkBitmap* bitmap, SkPMColor* colorPtr, int* colorCount,
-        SkAlphaType alphaType, bool requireUnpremultiplied) {
-#ifndef ANDROID_ENABLE_LINEAR_BLENDING
-    if (kUnpremul_SkAlphaType != alphaType || requireUnpremultiplied) {
-        return;
-    }
-
-    switch (bitmap->colorType()) {
-        case kN32_SkColorType:
-            for (int y = 0; y < bitmap->height(); y++) {
-                SkOpts::RGBA_to_rgbA(bitmap->getAddr32(0, y), bitmap->getAddr32(0, y),
-                    bitmap->width());
-            }
-
-            return;
-        case kIndex_8_SkColorType:
-            SkOpts::RGBA_to_rgbA(colorPtr, colorPtr, *colorCount);
-            return;
-        default:
-            // kRGBA_F16 will be premultiplied by the codec if necessary.
-            // kGray_8 (alias kAlpha_8) and k565 are opaque.
-            LOG_ALWAYS_FATAL("Should be unreachable - no need for legacy premultiply.");
-            return;
-    }
-#endif
-}
-
 static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding, jobject options) {
     // This function takes ownership of the input stream.  Since the SkAndroidCodec
     // will take ownership of the stream, we don't necessarily need to take ownership
@@ -450,15 +410,20 @@
     }
 
     SkAlphaType alphaType = codec->computeOutputAlphaType(requireUnpremultiplied);
-    SkAlphaType decodeAlphaType = computeDecodeAlphaType(decodeColorType, alphaType);
 
     const SkImageInfo decodeInfo = SkImageInfo::Make(size.width(), size.height(),
-            decodeColorType, decodeAlphaType, codec->computeOutputColorSpace(decodeColorType));
+            decodeColorType, alphaType, codec->computeOutputColorSpace(decodeColorType));
 
-    // When supported by the colorType, we will decode to sRGB (or linear sRGB).  However,
-    // we only want to mark the bitmap as sRGB when linear blending is enabled.
-    SkImageInfo bitmapInfo = decodeInfo.makeAlphaType(alphaType)
-            .makeColorSpace(GraphicsJNI::colorSpaceForType(decodeColorType));
+    // For wide gamut images, we will leave the color space on the SkBitmap.  Otherwise,
+    // use the default.
+    SkImageInfo bitmapInfo = decodeInfo;
+    sk_sp<SkColorSpace> srgb =
+            SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
+                                  SkColorSpace::kSRGB_Gamut,
+                                  SkColorSpace::kNonLinearBlending_ColorSpaceFlag);
+    if (decodeInfo.colorSpace() == srgb.get()) {
+        bitmapInfo = bitmapInfo.makeColorSpace(GraphicsJNI::colorSpaceForType(decodeColorType));
+    }
 
     if (decodeColorType == kGray_8_SkColorType) {
         // The legacy implementation of BitmapFactory used kAlpha8 for
@@ -495,8 +460,6 @@
         default:
             return nullObjectReturn("codec->getAndroidPixels() failed.");
     }
-    premultiplyIfNecessary(&decodingBitmap, colorPtr, colorCount, decodeAlphaType,
-            requireUnpremultiplied);
 
     jbyteArray ninePatchChunk = NULL;
     if (peeker.mPatch != NULL) {
diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp
index ce359dc..49024b6 100644
--- a/core/jni/android/graphics/FontFamily.cpp
+++ b/core/jni/android/graphics/FontFamily.cpp
@@ -63,27 +63,28 @@
         return 0;
     }
     NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr);
-    minikin::FontFamily* family = new minikin::FontFamily(
-            builder->langId, builder->variant, std::move(builder->fonts));
+    FontFamilyWrapper* family = new FontFamilyWrapper(
+            std::make_shared<minikin::FontFamily>(
+                    builder->langId, builder->variant, std::move(builder->fonts)));
     delete builder;
     return reinterpret_cast<jlong>(family);
 }
 
 static void FontFamily_abort(jlong builderPtr) {
     NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr);
-    minikin::Font::clearElementsWithLock(&builder->fonts);
     delete builder;
 }
 
 static void FontFamily_unref(jlong familyPtr) {
-    minikin::FontFamily* fontFamily = reinterpret_cast<minikin::FontFamily*>(familyPtr);
-    fontFamily->Unref();
+    FontFamilyWrapper* family = reinterpret_cast<FontFamilyWrapper*>(familyPtr);
+    delete family;
 }
 
 static void addSkTypeface(jlong builderPtr, sk_sp<SkTypeface> face, const void* fontData,
         size_t fontSize, int ttcIndex, jint givenWeight, jboolean givenItalic) {
-    minikin::MinikinFont* minikinFont =
-            new MinikinFontSkia(std::move(face), fontData, fontSize, ttcIndex);
+    std::shared_ptr<minikin::MinikinFont> minikinFont =
+            std::make_shared<MinikinFontSkia>(std::move(face), fontData, fontSize, ttcIndex,
+                    std::vector<minikin::FontVariation>());
     NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr);
     int weight = givenWeight / 100;
     bool italic = givenItalic;
@@ -95,8 +96,8 @@
         }
     }
 
-    builder->fonts.push_back(minikin::Font(minikinFont, minikin::FontStyle(weight, italic)));
-    minikinFont->Unref();
+    builder->fonts.push_back(minikin::Font(
+            std::move(minikinFont), minikin::FontStyle(weight, italic)));
 }
 
 static void release_global_ref(const void* /*data*/, void* context) {
@@ -207,12 +208,12 @@
         ALOGE("addFont failed to create font, invalid request");
         return false;
     }
-    minikin::MinikinFont* minikinFont =
-            new MinikinFontSkia(std::move(face), fontPtr, fontSize, ttcIndex);
+    std::shared_ptr<minikin::MinikinFont> minikinFont =
+            std::make_shared<MinikinFontSkia>(std::move(face), fontPtr, fontSize, ttcIndex,
+                    std::vector<minikin::FontVariation>());
     NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr);
-    builder->fonts.push_back(minikin::Font(minikinFont,
+    builder->fonts.push_back(minikin::Font(std::move(minikinFont),
             minikin::FontStyle(weight / 100, isItalic)));
-    minikinFont->Unref();
     return true;
 }
 
diff --git a/core/jni/android/graphics/FontUtils.h b/core/jni/android/graphics/FontUtils.h
index 8f44b1e..9eaaa49 100644
--- a/core/jni/android/graphics/FontUtils.h
+++ b/core/jni/android/graphics/FontUtils.h
@@ -18,9 +18,19 @@
 #define _ANDROID_GRAPHICS_FONT_UTILS_H_
 
 #include <jni.h>
+#include <memory>
+
+namespace minikin {
+class FontFamily;
+}  // namespace minikin
 
 namespace android {
 
+struct FontFamilyWrapper {
+  FontFamilyWrapper(std::shared_ptr<minikin::FontFamily>&& family) : family(family) {}
+  std::shared_ptr<minikin::FontFamily> family;
+};
+
 // Utility wrapper for java.util.List
 class ListHelper {
 public:
diff --git a/core/jni/android/graphics/GraphicBuffer.cpp b/core/jni/android/graphics/GraphicBuffer.cpp
index e661c21..73e53c6 100644
--- a/core/jni/android/graphics/GraphicBuffer.cpp
+++ b/core/jni/android/graphics/GraphicBuffer.cpp
@@ -30,8 +30,6 @@
 #include <ui/GraphicBuffer.h>
 #include <ui/PixelFormat.h>
 
-#include <gui/IGraphicBufferAlloc.h>
-#include <gui/ISurfaceComposer.h>
 #include <hwui/Bitmap.h>
 
 #include <SkCanvas.h>
@@ -111,21 +109,14 @@
 static jlong android_graphics_GraphicBuffer_create(JNIEnv* env, jobject clazz,
         jint width, jint height, jint format, jint usage) {
 
-    sp<ISurfaceComposer> composer(ComposerService::getComposerService());
-    sp<IGraphicBufferAlloc> alloc(composer->createGraphicBufferAlloc());
-    if (alloc == NULL) {
-        if (kDebugGraphicBuffer) {
-            ALOGW("createGraphicBufferAlloc() failed in GraphicBuffer.create()");
-        }
-        return NULL;
-    }
+    sp<GraphicBuffer> buffer = new GraphicBuffer(
+            uint32_t(width), uint32_t(height), PixelFormat(format), uint32_t(usage),
+            std::string("android_graphics_GraphicBuffer_create pid [") +
+                    std::to_string(getpid()) +"]");
 
-    status_t error;
-    sp<GraphicBuffer> buffer(alloc->createGraphicBuffer(width, height, format, 1, usage, &error));
-    if (buffer == NULL) {
-        if (kDebugGraphicBuffer) {
-            ALOGW("createGraphicBuffer() failed in GraphicBuffer.create()");
-        }
+    status_t error = buffer->initCheck();
+    if (error < 0) {
+        ALOGW_IF(kDebugGraphicBuffer, "createGraphicBuffer() failed in GraphicBuffer.create()");
         return NULL;
     }
 
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 5d73101..7c56c7b 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -460,6 +460,15 @@
     }
 }
 
+bool GraphicsJNI::isColorSpaceSRGB(SkColorSpace* colorSpace) {
+    return colorSpace == nullptr
+            || colorSpace == SkColorSpace::MakeSRGB().get()
+            || colorSpace == SkColorSpace::MakeRGB(
+                  SkColorSpace::kSRGB_RenderTargetGamma,
+                  SkColorSpace::kSRGB_Gamut,
+                  SkColorSpace::kNonLinearBlending_ColorSpaceFlag).get();
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 bool HeapAllocator::allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
     mStorage = android::Bitmap::allocateHeapBitmap(bitmap, ctable);
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index 8a1ef6e..7d7c881 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -111,6 +111,7 @@
     static sk_sp<SkColorSpace> defaultColorSpace();
     static sk_sp<SkColorSpace> linearColorSpace();
     static sk_sp<SkColorSpace> colorSpaceForType(SkColorType type);
+    static bool isColorSpaceSRGB(SkColorSpace* colorSpace);
 };
 
 class HeapAllocator : public SkBRDAllocator {
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index dfe809d..1846237 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -84,15 +84,15 @@
     }
 
     static jlong init(JNIEnv* env, jobject) {
-        static_assert(1 <<  0 == SkPaint::kAntiAlias_Flag,          "paint_flags_mismatch");
-        static_assert(1 <<  2 == SkPaint::kDither_Flag,             "paint_flags_mismatch");
-        static_assert(1 <<  3 == SkPaint::kUnderlineText_Flag,      "paint_flags_mismatch");
-        static_assert(1 <<  4 == SkPaint::kStrikeThruText_Flag,     "paint_flags_mismatch");
-        static_assert(1 <<  5 == SkPaint::kFakeBoldText_Flag,       "paint_flags_mismatch");
-        static_assert(1 <<  6 == SkPaint::kLinearText_Flag,         "paint_flags_mismatch");
-        static_assert(1 <<  7 == SkPaint::kSubpixelText_Flag,       "paint_flags_mismatch");
-        static_assert(1 <<  8 == SkPaint::kDevKernText_Flag,        "paint_flags_mismatch");
-        static_assert(1 << 10 == SkPaint::kEmbeddedBitmapText_Flag, "paint_flags_mismatch");
+        static_assert(1 <<  0 == SkPaint::kAntiAlias_Flag,             "paint_flags_mismatch");
+        static_assert(1 <<  2 == SkPaint::kDither_Flag,                "paint_flags_mismatch");
+        static_assert(1 <<  3 == SkPaint::kUnderlineText_ReserveFlag,  "paint_flags_mismatch");
+        static_assert(1 <<  4 == SkPaint::kStrikeThruText_ReserveFlag, "paint_flags_mismatch");
+        static_assert(1 <<  5 == SkPaint::kFakeBoldText_Flag,          "paint_flags_mismatch");
+        static_assert(1 <<  6 == SkPaint::kLinearText_Flag,            "paint_flags_mismatch");
+        static_assert(1 <<  7 == SkPaint::kSubpixelText_Flag,          "paint_flags_mismatch");
+        static_assert(1 <<  8 == SkPaint::kDevKernText_Flag,           "paint_flags_mismatch");
+        static_assert(1 << 10 == SkPaint::kEmbeddedBitmapText_Flag,    "paint_flags_mismatch");
 
         Paint* obj = new Paint();
         defaultSettingsForAndroid(obj);
@@ -300,8 +300,8 @@
 
     static void getTextPath(JNIEnv* env, Paint* paint, Typeface* typeface, const jchar* text,
             jint count, jint bidiFlags, jfloat x, jfloat y, SkPath* path) {
-        minikin::Layout layout;
-        MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, text, 0, count, count);
+        minikin::Layout layout = MinikinUtils::doLayout(
+                paint, bidiFlags, typeface, text, 0, count, count);
         size_t nGlyphs = layout.nGlyphs();
         uint16_t* glyphs = new uint16_t[nGlyphs];
         SkPoint* pos = new SkPoint[nGlyphs];
@@ -344,8 +344,8 @@
         SkRect  r;
         SkIRect ir;
 
-        minikin::Layout layout;
-        MinikinUtils::doLayout(&layout, &paint, bidiFlags, typeface, text, 0, count, count);
+        minikin::Layout layout = MinikinUtils::doLayout(
+                &paint, bidiFlags, typeface, text, 0, count, count);
         minikin::MinikinRect rect;
         layout.getBounds(&rect);
         r.fLeft = rect.mLeft;
@@ -459,9 +459,8 @@
             nChars++;
             prevCp = cp;
         }
-        minikin::Layout layout;
-        MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, str.get(), 0, str.size(),
-                str.size());
+        minikin::Layout layout = MinikinUtils::doLayout(
+                paint, bidiFlags, typeface, str.get(), 0, str.size(), str.size());
         size_t nGlyphs = countNonSpaceGlyphs(layout);
         if (nGlyphs != 1 && nChars > 1) {
             // multiple-character input, and was not a ligature
@@ -480,8 +479,8 @@
             // since ZZ is reserved for unknown or invalid territory.
             // U+1F1FF (REGIONAL INDICATOR SYMBOL LETTER Z) is \uD83C\uDDFF in UTF16.
             static const jchar ZZ_FLAG_STR[] = { 0xD83C, 0xDDFF, 0xD83C, 0xDDFF };
-            minikin::Layout zzLayout;
-            MinikinUtils::doLayout(&zzLayout, paint, bidiFlags, typeface, ZZ_FLAG_STR, 0, 4, 4);
+            minikin::Layout zzLayout = MinikinUtils::doLayout(
+                    paint, bidiFlags, typeface, ZZ_FLAG_STR, 0, 4, 4);
             if (zzLayout.nGlyphs() != 1 || layoutContainsNotdef(zzLayout)) {
                 // The font collection doesn't have a glyph for unknown flag. Just return true.
                 return true;
@@ -692,11 +691,25 @@
     }
 
     static void setUnderlineText(jlong paintHandle, jboolean underlineText) {
-        reinterpret_cast<Paint*>(paintHandle)->setUnderlineText(underlineText);
+        Paint* paint = reinterpret_cast<Paint*>(paintHandle);
+        uint32_t flags = paint->getFlags();
+        if (underlineText) {
+            flags |= Paint::kUnderlineText_ReserveFlag;
+        } else {
+            flags &= ~Paint::kUnderlineText_ReserveFlag;
+        }
+        paint->setFlags(flags);
     }
 
     static void setStrikeThruText(jlong paintHandle, jboolean strikeThruText) {
-        reinterpret_cast<Paint*>(paintHandle)->setStrikeThruText(strikeThruText);
+        Paint* paint = reinterpret_cast<Paint*>(paintHandle);
+        uint32_t flags = paint->getFlags();
+        if (strikeThruText) {
+            flags |= Paint::kStrikeThruText_ReserveFlag;
+        } else {
+            flags &= ~Paint::kStrikeThruText_ReserveFlag;
+        }
+        paint->setFlags(flags);
     }
 
     static void setFakeBoldText(jlong paintHandle, jboolean fakeBoldText) {
diff --git a/core/jni/android/graphics/PathEffect.cpp b/core/jni/android/graphics/PathEffect.cpp
index e801da3..a4992de 100644
--- a/core/jni/android/graphics/PathEffect.cpp
+++ b/core/jni/android/graphics/PathEffect.cpp
@@ -20,7 +20,7 @@
                                      jlong outerHandle, jlong innerHandle) {
         SkPathEffect* outer = reinterpret_cast<SkPathEffect*>(outerHandle);
         SkPathEffect* inner = reinterpret_cast<SkPathEffect*>(innerHandle);
-        SkPathEffect* effect = SkComposePathEffect::Make(sk_ref_sp(outer),
+        SkPathEffect* effect = SkPathEffect::MakeCompose(sk_ref_sp(outer),
                 sk_ref_sp(inner)).release();
         return reinterpret_cast<jlong>(effect);
     }
@@ -29,7 +29,7 @@
                                  jlong firstHandle, jlong secondHandle) {
         SkPathEffect* first = reinterpret_cast<SkPathEffect*>(firstHandle);
         SkPathEffect* second = reinterpret_cast<SkPathEffect*>(secondHandle);
-        SkPathEffect* effect = SkSumPathEffect::Make(sk_ref_sp(first),
+        SkPathEffect* effect = SkPathEffect::MakeSum(sk_ref_sp(first),
                 sk_ref_sp(second)).release();
         return reinterpret_cast<jlong>(effect);
     }
diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
index 0099673..14bad0f 100644
--- a/core/jni/android/graphics/SurfaceTexture.cpp
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -29,11 +29,13 @@
 
 #include "core_jni_helpers.h"
 
+#include <cutils/atomic.h>
 #include <utils/Log.h>
 #include <utils/misc.h>
 
 #include "jni.h"
 #include "JNIHelp.h"
+#include "ScopedLocalRef.h"
 
 // ----------------------------------------------------------------------------
 
@@ -385,7 +387,6 @@
 // ----------------------------------------------------------------------------
 
 static const JNINativeMethod gSurfaceTextureMethods[] = {
-    {"nativeClassInit",            "()V",   (void*)SurfaceTexture_classInit },
     {"nativeInit",                 "(ZIZLjava/lang/ref/WeakReference;)V", (void*)SurfaceTexture_init },
     {"nativeFinalize",             "()V",   (void*)SurfaceTexture_finalize },
     {"nativeSetDefaultBufferSize", "(II)V", (void*)SurfaceTexture_setDefaultBufferSize },
@@ -401,6 +402,10 @@
 
 int register_android_graphics_SurfaceTexture(JNIEnv* env)
 {
+    // Cache some fields.
+    ScopedLocalRef<jclass> klass(env, FindClassOrDie(env, kSurfaceTextureClassPathName));
+    SurfaceTexture_classInit(env, klass.get());
+
     return RegisterMethodsOrDie(env, kSurfaceTextureClassPathName, gSurfaceTextureMethods,
                                 NELEM(gSurfaceTextureMethods));
 }
diff --git a/core/jni/android/graphics/Typeface.cpp b/core/jni/android/graphics/Typeface.cpp
index 0a0fce3e..0cdc74f 100644
--- a/core/jni/android/graphics/Typeface.cpp
+++ b/core/jni/android/graphics/Typeface.cpp
@@ -67,9 +67,7 @@
 
 static void Typeface_unref(JNIEnv* env, jobject obj, jlong faceHandle) {
     Typeface* face = reinterpret_cast<Typeface*>(faceHandle);
-    if (face != NULL) {
-        face->unref();
-    }
+    delete face;
 }
 
 static jint Typeface_getStyle(JNIEnv* env, jobject obj, jlong faceHandle) {
@@ -79,12 +77,13 @@
 
 static jlong Typeface_createFromArray(JNIEnv *env, jobject, jlongArray familyArray) {
     ScopedLongArrayRO families(env, familyArray);
-    std::vector<minikin::FontFamily*> familyVec;
+    std::vector<std::shared_ptr<minikin::FontFamily>> familyVec;
+    familyVec.reserve(families.size());
     for (size_t i = 0; i < families.size(); i++) {
-        minikin::FontFamily* family = reinterpret_cast<minikin::FontFamily*>(families[i]);
-        familyVec.push_back(family);
+        FontFamilyWrapper* family = reinterpret_cast<FontFamilyWrapper*>(families[i]);
+        familyVec.emplace_back(family->family);
     }
-    return reinterpret_cast<jlong>(Typeface::createFromFamilies(familyVec));
+    return reinterpret_cast<jlong>(Typeface::createFromFamilies(std::move(familyVec)));
 }
 
 static void Typeface_setDefault(JNIEnv *env, jobject, jlong faceHandle) {
diff --git a/core/jni/android_database_CursorWindow.cpp b/core/jni/android_database_CursorWindow.cpp
index 3fc3aaf..f1fa76a 100644
--- a/core/jni/android_database_CursorWindow.cpp
+++ b/core/jni/android_database_CursorWindow.cpp
@@ -205,6 +205,10 @@
     if (type == CursorWindow::FIELD_TYPE_BLOB || type == CursorWindow::FIELD_TYPE_STRING) {
         size_t size;
         const void* value = window->getFieldSlotValueBlob(fieldSlot, &size);
+        if (!value) {
+            throw_sqlite3_exception(env, "Native could not read blob slot");
+            return NULL;
+        }
         jbyteArray byteArray = env->NewByteArray(size);
         if (!byteArray) {
             env->ExceptionClear();
@@ -240,6 +244,10 @@
     if (type == CursorWindow::FIELD_TYPE_STRING) {
         size_t sizeIncludingNull;
         const char* value = window->getFieldSlotValueString(fieldSlot, &sizeIncludingNull);
+        if (!value) {
+            throw_sqlite3_exception(env, "Native could not read string slot");
+            return NULL;
+        }
         if (sizeIncludingNull <= 1) {
             return gEmptyString;
         }
diff --git a/core/jni/android_hardware_HardwareBuffer.cpp b/core/jni/android_hardware_HardwareBuffer.cpp
index 5f0664b..ed0ab60 100644
--- a/core/jni/android_hardware_HardwareBuffer.cpp
+++ b/core/jni/android_hardware_HardwareBuffer.cpp
@@ -26,15 +26,15 @@
 #include <android_runtime/android_hardware_HardwareBuffer.h>
 #include <android_runtime/AndroidRuntime.h>
 #include <android_runtime/Log.h>
+#include <private/android/AHardwareBufferHelpers.h>
 
 #include <binder/Parcel.h>
-#include <gui/IGraphicBufferAlloc.h>
-#include <gui/ISurfaceComposer.h>
-#include <hardware/gralloc1.h>
-#include <ui/GraphicBuffer.h>
 
+#include <ui/GraphicBuffer.h>
 #include <private/gui/ComposerService.h>
 
+#include <hardware/gralloc1.h>
+
 #include "core_jni_helpers.h"
 
 using namespace android;
@@ -44,7 +44,7 @@
 // ----------------------------------------------------------------------------
 
 // Debug
-static const bool kDebugGraphicBuffer = false;
+static constexpr bool kDebugGraphicBuffer = false;
 
 // ----------------------------------------------------------------------------
 // Types
@@ -64,15 +64,6 @@
     sp<GraphicBuffer> buffer;
 };
 
-
-// ----------------------------------------------------------------------------
-// Helper functions
-// ----------------------------------------------------------------------------
-
-static inline bool containsBits(uint64_t mask, uint64_t bitsToCheck) {
-    return (mask & bitsToCheck) == bitsToCheck;
-}
-
 // ----------------------------------------------------------------------------
 // HardwareBuffer lifecycle
 // ----------------------------------------------------------------------------
@@ -80,15 +71,6 @@
 static jlong android_hardware_HardwareBuffer_create(JNIEnv* env, jobject clazz,
         jint width, jint height, jint format, jint layers, jlong usage) {
 
-    sp<ISurfaceComposer> composer(ComposerService::getComposerService());
-    sp<IGraphicBufferAlloc> alloc(composer->createGraphicBufferAlloc());
-    if (alloc == NULL) {
-        if (kDebugGraphicBuffer) {
-            ALOGW("createGraphicBufferAlloc() failed in HardwareBuffer.create()");
-        }
-        return NULL;
-    }
-
     // TODO: update createGraphicBuffer to take two 64-bit values.
     int pixelFormat = android_hardware_HardwareBuffer_convertToPixelFormat(format);
     if (pixelFormat == 0) {
@@ -99,14 +81,14 @@
     }
     uint64_t producerUsage = 0;
     uint64_t consumerUsage = 0;
-    android_hardware_HardwareBuffer_convertToGrallocUsageBits(usage, 0, &producerUsage,
-            &consumerUsage);
-    status_t error;
-    sp<GraphicBuffer> buffer(alloc->createGraphicBuffer(width, height, pixelFormat,
-            layers, producerUsage, consumerUsage,
-            std::string("HardwareBuffer pid [") + std::to_string(getpid()) +"]",
-            &error));
-    if (buffer == NULL) {
+    android_hardware_HardwareBuffer_convertToGrallocUsageBits(
+            &producerUsage, &consumerUsage, usage, 0);
+
+    sp<GraphicBuffer> buffer = new GraphicBuffer(width, height, pixelFormat, layers,
+            producerUsage, consumerUsage,
+            std::string("HardwareBuffer pid [") + std::to_string(getpid()) +"]");
+    status_t error = buffer->initCheck();
+    if (error < 0) {
         if (kDebugGraphicBuffer) {
             ALOGW("createGraphicBuffer() failed in HardwareBuffer.create()");
         }
@@ -121,8 +103,7 @@
     delete wrapper;
 }
 
-static jlong android_hardware_HardwareBuffer_getNativeFinalizer(JNIEnv* env,
-        jobject clazz) {
+static jlong android_hardware_HardwareBuffer_getNativeFinalizer(JNIEnv* env, jobject clazz) {
     return static_cast<jlong>(reinterpret_cast<uintptr_t>(&destroyWrapper));
 }
 
@@ -163,8 +144,11 @@
 static jlong android_hardware_HardwareBuffer_getUsage(JNIEnv* env,
     jobject clazz, jlong nativeObject) {
     GraphicBuffer* buffer = GraphicBufferWrapper_to_GraphicBuffer(nativeObject);
-    return android_hardware_HardwareBuffer_convertFromGrallocUsageBits(
+    uint64_t usage0 = 0;
+    uint64_t usage1 = 0;
+    android_hardware_HardwareBuffer_convertFromGrallocUsageBits(&usage0, &usage1,
             buffer->getUsage(), buffer->getUsage());
+    return usage0;
 }
 
 // ----------------------------------------------------------------------------
@@ -203,7 +187,8 @@
     if (env->IsInstanceOf(hardwareBufferObj, gHardwareBufferClassInfo.clazz)) {
         GraphicBuffer* buffer = GraphicBufferWrapper_to_GraphicBuffer(
                 env->GetLongField(hardwareBufferObj, gHardwareBufferClassInfo.mNativeObject));
-        return reinterpret_cast<AHardwareBuffer*>(buffer);
+        return AHardwareBuffer_from_GraphicBuffer(buffer);
+
     } else {
         return nullptr;
     }
@@ -211,7 +196,7 @@
 
 jobject android_hardware_HardwareBuffer_createFromAHardwareBuffer(
         JNIEnv* env, AHardwareBuffer* hardwareBuffer) {
-    GraphicBuffer* buffer = reinterpret_cast<GraphicBuffer*>(hardwareBuffer);
+    GraphicBuffer* buffer = AHardwareBuffer_to_GraphicBuffer(hardwareBuffer);
     GraphicBufferWrapper* wrapper = new GraphicBufferWrapper(buffer);
     jobject hardwareBufferObj = env->NewObject(gHardwareBufferClassInfo.clazz,
             gHardwareBufferClassInfo.ctor, reinterpret_cast<jlong>(wrapper));
@@ -228,103 +213,21 @@
 }
 
 uint32_t android_hardware_HardwareBuffer_convertFromPixelFormat(uint32_t format) {
-    switch (format) {
-        case HAL_PIXEL_FORMAT_RGBA_8888:
-            return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
-        case HAL_PIXEL_FORMAT_RGBX_8888:
-            return AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM;
-        case HAL_PIXEL_FORMAT_RGB_565:
-            return AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
-        case HAL_PIXEL_FORMAT_RGB_888:
-            return AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM;
-        case HAL_PIXEL_FORMAT_RGBA_FP16:
-            return AHARDWAREBUFFER_FORMAT_R16G16B16A16_SFLOAT;
-        case HAL_PIXEL_FORMAT_RGBA_1010102:
-            return AHARDWAREBUFFER_FORMAT_A2R10G10B10_UNORM_PACK32;
-        case HAL_PIXEL_FORMAT_BLOB:
-            return AHARDWAREBUFFER_FORMAT_BLOB;
-        default:
-            ALOGE("Unknown pixel format %u", format);
-            return 0;
-    }
+    return AHardwareBuffer_convertFromPixelFormat(format);
 }
 
 uint32_t android_hardware_HardwareBuffer_convertToPixelFormat(uint32_t format) {
-    switch (format) {
-        case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
-            return HAL_PIXEL_FORMAT_RGBA_8888;
-        case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
-            return HAL_PIXEL_FORMAT_RGBX_8888;
-        case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
-            return HAL_PIXEL_FORMAT_RGB_565;
-        case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
-            return HAL_PIXEL_FORMAT_RGB_888;
-        case AHARDWAREBUFFER_FORMAT_R16G16B16A16_SFLOAT:
-            return HAL_PIXEL_FORMAT_RGBA_FP16;
-        case AHARDWAREBUFFER_FORMAT_A2R10G10B10_UNORM_PACK32:
-            return HAL_PIXEL_FORMAT_RGBA_1010102;
-        case AHARDWAREBUFFER_FORMAT_BLOB:
-            return HAL_PIXEL_FORMAT_BLOB;
-        default:
-            ALOGE("Unknown AHardwareBuffer format %u", format);
-            return 0;
-    }
+    return AHardwareBuffer_convertToPixelFormat(format);
 }
 
-void android_hardware_HardwareBuffer_convertToGrallocUsageBits(uint64_t usage0,
-        uint64_t usage1, uint64_t* outProducerUsage,
-        uint64_t* outConsumerUsage) {
-    *outProducerUsage = 0;
-    *outConsumerUsage = 0;
-    if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_CPU_READ))
-        *outConsumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ;
-    if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_CPU_READ_OFTEN))
-        *outConsumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN;
-    if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_CPU_WRITE))
-        *outProducerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE;
-    if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_CPU_WRITE_OFTEN))
-        *outProducerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN;
-    if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_GPU_SAMPLED_IMAGE))
-        *outConsumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE;
-    if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_GPU_COLOR_OUTPUT))
-        *outProducerUsage |= GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET;
-    // Not sure what this should be.
-    //if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_GPU_CUBEMAP)) bits |= 0;
-    if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_GPU_DATA_BUFFER))
-        *outConsumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_DATA_BUFFER;
-    if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_VIDEO_ENCODE))
-        *outConsumerUsage |= GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER;
-    if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_PROTECTED_CONTENT))
-        *outProducerUsage |= GRALLOC1_PRODUCER_USAGE_PROTECTED;
-    if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_SENSOR_DIRECT_DATA))
-        *outProducerUsage |= GRALLOC1_PRODUCER_USAGE_SENSOR_DIRECT_DATA;
+void android_hardware_HardwareBuffer_convertToGrallocUsageBits(uint64_t* outProducerUsage,
+        uint64_t* outConsumerUsage, uint64_t usage0, uint64_t usage1) {
+    AHardwareBuffer_convertToGrallocUsageBits(outProducerUsage, outConsumerUsage, usage0, usage1);
 }
 
-uint64_t android_hardware_HardwareBuffer_convertFromGrallocUsageBits(
-        uint64_t producerUsage, uint64_t consumerUsage) {
-    uint64_t bits = 0;
-    if (containsBits(consumerUsage, GRALLOC1_CONSUMER_USAGE_CPU_READ))
-        bits |= AHARDWAREBUFFER_USAGE0_CPU_READ;
-    if (containsBits(consumerUsage, GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN))
-        bits |= AHARDWAREBUFFER_USAGE0_CPU_READ_OFTEN;
-    if (containsBits(producerUsage, GRALLOC1_PRODUCER_USAGE_CPU_WRITE))
-        bits |= AHARDWAREBUFFER_USAGE0_CPU_WRITE;
-    if (containsBits(producerUsage, GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN))
-        bits |= AHARDWAREBUFFER_USAGE0_CPU_WRITE_OFTEN;
-    if (containsBits(consumerUsage, GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE))
-        bits |= AHARDWAREBUFFER_USAGE0_GPU_SAMPLED_IMAGE;
-    if (containsBits(producerUsage, GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET))
-        bits |= AHARDWAREBUFFER_USAGE0_GPU_COLOR_OUTPUT;
-    if (containsBits(consumerUsage, GRALLOC1_CONSUMER_USAGE_GPU_DATA_BUFFER))
-        bits |= AHARDWAREBUFFER_USAGE0_GPU_DATA_BUFFER;
-    if (containsBits(consumerUsage, GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER))
-        bits |= AHARDWAREBUFFER_USAGE0_VIDEO_ENCODE;
-    if (containsBits(producerUsage, GRALLOC1_PRODUCER_USAGE_PROTECTED))
-        bits |= AHARDWAREBUFFER_USAGE0_PROTECTED_CONTENT;
-    if (containsBits(producerUsage, GRALLOC1_PRODUCER_USAGE_SENSOR_DIRECT_DATA))
-        bits |= AHARDWAREBUFFER_USAGE0_SENSOR_DIRECT_DATA;
-
-    return bits;
+void android_hardware_HardwareBuffer_convertFromGrallocUsageBits(uint64_t* outUsage0,
+        uint64_t* outUsage1, uint64_t producerUsage, uint64_t consumerUsage) {
+    AHardwareBuffer_convertFromGrallocUsageBits(outUsage0, outUsage1, producerUsage, consumerUsage);
 }
 
 }  // namespace android
@@ -336,19 +239,21 @@
 const char* const kClassPathName = "android/hardware/HardwareBuffer";
 
 static const JNINativeMethod gMethods[] = {
-    { "nCreateHardwareBuffer",  "(IIIIJ)J", (void*) android_hardware_HardwareBuffer_create },
-    { "nGetNativeFinalizer", "()J",          (void*) android_hardware_HardwareBuffer_getNativeFinalizer },
+    { "nCreateHardwareBuffer",  "(IIIIJ)J",
+            (void*) android_hardware_HardwareBuffer_create },
+    { "nGetNativeFinalizer", "()J",
+            (void*) android_hardware_HardwareBuffer_getNativeFinalizer },
     { "nWriteHardwareBufferToParcel",  "(JLandroid/os/Parcel;)V",
             (void*) android_hardware_HardwareBuffer_write },
     { "nReadHardwareBufferFromParcel", "(Landroid/os/Parcel;)J",
             (void*) android_hardware_HardwareBuffer_read },
 
     // --------------- @FastNative ----------------------
-    { "nGetWidth", "(J)I",                   (void*) android_hardware_HardwareBuffer_getWidth },
-    { "nGetHeight", "(J)I",                  (void*) android_hardware_HardwareBuffer_getHeight },
-    { "nGetFormat", "(J)I",                  (void*) android_hardware_HardwareBuffer_getFormat },
-    { "nGetLayers", "(J)I",                  (void*) android_hardware_HardwareBuffer_getLayers },
-    { "nGetUsage", "(J)J",                  (void*) android_hardware_HardwareBuffer_getUsage },
+    { "nGetWidth", "(J)I",      (void*) android_hardware_HardwareBuffer_getWidth },
+    { "nGetHeight", "(J)I",     (void*) android_hardware_HardwareBuffer_getHeight },
+    { "nGetFormat", "(J)I",     (void*) android_hardware_HardwareBuffer_getFormat },
+    { "nGetLayers", "(J)I",     (void*) android_hardware_HardwareBuffer_getLayers },
+    { "nGetUsage", "(J)J",      (void*) android_hardware_HardwareBuffer_getUsage },
 };
 
 int register_android_hardware_HardwareBuffer(JNIEnv* env) {
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index bc2fc1c..dae4310 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -23,9 +23,10 @@
 #include <ScopedUtfChars.h>
 #include <ScopedLocalRef.h>
 #include <android_runtime/AndroidRuntime.h>
-#include <gui/Sensor.h>
-#include <gui/SensorEventQueue.h>
-#include <gui/SensorManager.h>
+#include <android_runtime/android_hardware_HardwareBuffer.h>
+#include <sensor/Sensor.h>
+#include <sensor/SensorEventQueue.h>
+#include <sensor/SensorManager.h>
 #include <cutils/native_handle.h>
 #include <utils/Log.h>
 #include <utils/Looper.h>
@@ -245,39 +246,28 @@
 }
 
 static jint nativeCreateDirectChannel(JNIEnv *_env, jclass _this, jlong sensorManager,
-        jlong size, jint channelType, jlongArray channelData) {
-    jint ret = -1;
-    jsize len = _env->GetArrayLength(channelData);
-    if (len > 2) {
-        jlong *data = _env->GetLongArrayElements(channelData, NULL);
-        if (data != nullptr) {
-            // construct native handle from jlong*
-            jlong numFd = data[0];
-            jlong numInt = data[1];
-            if ((numFd + numInt + 2) == len) {
-                native_handle_t *nativeHandle = native_handle_create(numFd, numInt);
-                if (nativeHandle != nullptr) {
-                    const jlong *readPointer = data + 2;
-                    int *writePointer = nativeHandle->data;
-                    size_t n = static_cast<size_t>(numFd + numInt);
-                    while (n--) {
-                        // native type of data is int, jlong is just to ensure Java does not
-                        // truncate data on 64-bit system. The cast here is safe.
-                        *writePointer++ = static_cast<int>(*readPointer++);
-                    }
+        jlong size, jint channelType, jint fd, jobject hardwareBufferObj) {
+    const native_handle_t *nativeHandle = nullptr;
+    NATIVE_HANDLE_DECLARE_STORAGE(ashmemHandle, 1, 0);
 
-                    SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
-                    ret = mgr->createDirectChannel(size, channelType, nativeHandle);
-
-                    // do not native_handle_close() here as handle is owned by java
-                    native_handle_delete(nativeHandle);
-                }
-            }
-            // unidirectional parameter passing, thus JNI_ABORT
-            _env->ReleaseLongArrayElements(channelData, data, JNI_ABORT);
+    if (channelType == SENSOR_DIRECT_MEM_TYPE_ASHMEM) {
+        native_handle_t *handle = native_handle_init(ashmemHandle, 1, 0);
+        handle->data[0] = fd;
+        nativeHandle = handle;
+    } else if (channelType == SENSOR_DIRECT_MEM_TYPE_GRALLOC) {
+        AHardwareBuffer *hardwareBuffer =
+                android_hardware_HardwareBuffer_getNativeHardwareBuffer(_env, hardwareBufferObj);
+        if (hardwareBuffer != nullptr) {
+            nativeHandle = AHardwareBuffer_getNativeHandle(hardwareBuffer);
         }
     }
-    return ret;
+
+    if (nativeHandle == nullptr) {
+        return BAD_VALUE;
+    }
+
+    SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
+    return mgr->createDirectChannel(size, channelType, nativeHandle);
 }
 
 static void nativeDestroyDirectChannel(JNIEnv *_env, jclass _this, jlong sensorManager,
@@ -499,7 +489,7 @@
             (void*)nativeIsDataInjectionEnabled },
 
     {"nativeCreateDirectChannel",
-            "(JJI[J)I",
+            "(JJIILandroid/hardware/HardwareBuffer;)I",
             (void*)nativeCreateDirectChannel },
 
     {"nativeDestroyDirectChannel",
diff --git a/core/jni/android_hardware_camera2_CameraMetadata.cpp b/core/jni/android_hardware_camera2_CameraMetadata.cpp
index 518f99e..78a5735 100644
--- a/core/jni/android_hardware_camera2_CameraMetadata.cpp
+++ b/core/jni/android_hardware_camera2_CameraMetadata.cpp
@@ -161,7 +161,6 @@
 
 extern "C" {
 
-static void CameraMetadata_classInit(JNIEnv *env, jobject thiz);
 static jobject CameraMetadata_getAllVendorKeys(JNIEnv* env, jobject thiz, jclass keyType);
 static jint CameraMetadata_getTagFromKey(JNIEnv *env, jobject thiz, jstring keyName);
 static jint CameraMetadata_getTypeFromTag(JNIEnv *env, jobject thiz, jint tag);
@@ -529,9 +528,6 @@
 
 static const JNINativeMethod gCameraMetadataMethods[] = {
 // static methods
-  { "nativeClassInit",
-    "()V",
-    (void *)CameraMetadata_classInit },
   { "nativeGetAllVendorKeys",
     "(Ljava/lang/Class;)Ljava/util/ArrayList;",
     (void *)CameraMetadata_getAllVendorKeys},
@@ -581,35 +577,6 @@
     (void *)CameraMetadata_writeToParcel },
 };
 
-struct field {
-    const char *class_name;
-    const char *field_name;
-    const char *field_type;
-    jfieldID   *jfield;
-};
-
-static int find_fields(JNIEnv *env, field *fields, int count)
-{
-    for (int i = 0; i < count; i++) {
-        field *f = &fields[i];
-        jclass clazz = env->FindClass(f->class_name);
-        if (clazz == NULL) {
-            ALOGE("Can't find %s", f->class_name);
-            return -1;
-        }
-
-        jfieldID field = env->GetFieldID(clazz, f->field_name, f->field_type);
-        if (field == NULL) {
-            ALOGE("Can't find %s.%s", f->class_name, f->field_name);
-            return -1;
-        }
-
-        *(f->jfield) = field;
-    }
-
-    return 0;
-}
-
 // Get all the required offsets in java class and register native functions
 int register_android_hardware_camera2_CameraMetadata(JNIEnv *env)
 {
@@ -651,6 +618,9 @@
     gMetadataOffsets.mArrayListAdd = GetMethodIDOrDie(env, gMetadataOffsets.mArrayList,
             "add", "(Ljava/lang/Object;)Z");
 
+    jclass cameraMetadataClazz = FindClassOrDie(env, CAMERA_METADATA_CLASS_NAME);
+    fields.metadata_ptr = GetFieldIDOrDie(env, cameraMetadataClazz, "mMetadataPtr", "J");
+
     // Register native functions
     return RegisterMethodsOrDie(env,
             CAMERA_METADATA_CLASS_NAME,
@@ -660,22 +630,6 @@
 
 extern "C" {
 
-static void CameraMetadata_classInit(JNIEnv *env, jobject thiz) {
-    // XX: Why do this separately instead of doing it in the register function?
-    ALOGV("%s", __FUNCTION__);
-
-    field fields_to_find[] = {
-        { CAMERA_METADATA_CLASS_NAME, "mMetadataPtr", "J", &fields.metadata_ptr },
-    };
-
-    // Do this here instead of in register_native_methods,
-    // since otherwise it will fail to find the fields.
-    if (find_fields(env, fields_to_find, NELEM(fields_to_find)) < 0)
-        return;
-
-    env->FindClass(CAMERA_METADATA_CLASS_NAME);
-}
-
 static jobject CameraMetadata_getAllVendorKeys(JNIEnv* env, jobject thiz, jclass keyType) {
 
     // Get all vendor tags
diff --git a/core/jni/android_opengl_GLES10.cpp b/core/jni/android_opengl_GLES10.cpp
index 64c9fe8..5bcb800 100644
--- a/core/jni/android_opengl_GLES10.cpp
+++ b/core/jni/android_opengl_GLES10.cpp
@@ -272,6 +272,19 @@
  */
 static int getNeededCount(GLint pname) {
     int needed = 1;
+#ifdef GL_ES_VERSION_3_0
+    // GLES 3.x pnames
+    switch (pname) {
+        case GL_MAX_VIEWPORT_DIMS:
+            needed = 2;
+            break;
+
+        case GL_PROGRAM_BINARY_FORMATS:
+            glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &needed);
+            break;
+    }
+#endif
+
 #ifdef GL_ES_VERSION_2_0
     // GLES 2.x pnames
     switch (pname) {
diff --git a/core/jni/android_opengl_GLES10Ext.cpp b/core/jni/android_opengl_GLES10Ext.cpp
index 533bda4..38f7ba6 100644
--- a/core/jni/android_opengl_GLES10Ext.cpp
+++ b/core/jni/android_opengl_GLES10Ext.cpp
@@ -272,6 +272,19 @@
  */
 static int getNeededCount(GLint pname) {
     int needed = 1;
+#ifdef GL_ES_VERSION_3_0
+    // GLES 3.x pnames
+    switch (pname) {
+        case GL_MAX_VIEWPORT_DIMS:
+            needed = 2;
+            break;
+
+        case GL_PROGRAM_BINARY_FORMATS:
+            glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &needed);
+            break;
+    }
+#endif
+
 #ifdef GL_ES_VERSION_2_0
     // GLES 2.x pnames
     switch (pname) {
diff --git a/core/jni/android_opengl_GLES11.cpp b/core/jni/android_opengl_GLES11.cpp
index 923f7a8..014672d 100644
--- a/core/jni/android_opengl_GLES11.cpp
+++ b/core/jni/android_opengl_GLES11.cpp
@@ -272,6 +272,19 @@
  */
 static int getNeededCount(GLint pname) {
     int needed = 1;
+#ifdef GL_ES_VERSION_3_0
+    // GLES 3.x pnames
+    switch (pname) {
+        case GL_MAX_VIEWPORT_DIMS:
+            needed = 2;
+            break;
+
+        case GL_PROGRAM_BINARY_FORMATS:
+            glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &needed);
+            break;
+    }
+#endif
+
 #ifdef GL_ES_VERSION_2_0
     // GLES 2.x pnames
     switch (pname) {
diff --git a/core/jni/android_opengl_GLES11Ext.cpp b/core/jni/android_opengl_GLES11Ext.cpp
index f7498d5..b4a1ab6 100644
--- a/core/jni/android_opengl_GLES11Ext.cpp
+++ b/core/jni/android_opengl_GLES11Ext.cpp
@@ -272,6 +272,19 @@
  */
 static int getNeededCount(GLint pname) {
     int needed = 1;
+#ifdef GL_ES_VERSION_3_0
+    // GLES 3.x pnames
+    switch (pname) {
+        case GL_MAX_VIEWPORT_DIMS:
+            needed = 2;
+            break;
+
+        case GL_PROGRAM_BINARY_FORMATS:
+            glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &needed);
+            break;
+    }
+#endif
+
 #ifdef GL_ES_VERSION_2_0
     // GLES 2.x pnames
     switch (pname) {
diff --git a/core/jni/android_opengl_GLES20.cpp b/core/jni/android_opengl_GLES20.cpp
index 791233b..c1ffa81 100644
--- a/core/jni/android_opengl_GLES20.cpp
+++ b/core/jni/android_opengl_GLES20.cpp
@@ -272,6 +272,19 @@
  */
 static int getNeededCount(GLint pname) {
     int needed = 1;
+#ifdef GL_ES_VERSION_3_0
+    // GLES 3.x pnames
+    switch (pname) {
+        case GL_MAX_VIEWPORT_DIMS:
+            needed = 2;
+            break;
+
+        case GL_PROGRAM_BINARY_FORMATS:
+            glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &needed);
+            break;
+    }
+#endif
+
 #ifdef GL_ES_VERSION_2_0
     // GLES 2.x pnames
     switch (pname) {
diff --git a/core/jni/android_opengl_GLES30.cpp b/core/jni/android_opengl_GLES30.cpp
index 736fd99..1d12b0a 100644
--- a/core/jni/android_opengl_GLES30.cpp
+++ b/core/jni/android_opengl_GLES30.cpp
@@ -272,6 +272,19 @@
  */
 static int getNeededCount(GLint pname) {
     int needed = 1;
+#ifdef GL_ES_VERSION_3_0
+    // GLES 3.x pnames
+    switch (pname) {
+        case GL_MAX_VIEWPORT_DIMS:
+            needed = 2;
+            break;
+
+        case GL_PROGRAM_BINARY_FORMATS:
+            glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &needed);
+            break;
+    }
+#endif
+
 #ifdef GL_ES_VERSION_2_0
     // GLES 2.x pnames
     switch (pname) {
diff --git a/core/jni/android_opengl_GLES31.cpp b/core/jni/android_opengl_GLES31.cpp
index 0e596dc..e0750e4 100644
--- a/core/jni/android_opengl_GLES31.cpp
+++ b/core/jni/android_opengl_GLES31.cpp
@@ -270,6 +270,19 @@
  */
 static int getNeededCount(GLint pname) {
     int needed = 1;
+#ifdef GL_ES_VERSION_3_0
+    // GLES 3.x pnames
+    switch (pname) {
+        case GL_MAX_VIEWPORT_DIMS:
+            needed = 2;
+            break;
+
+        case GL_PROGRAM_BINARY_FORMATS:
+            glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &needed);
+            break;
+    }
+#endif
+
 #ifdef GL_ES_VERSION_2_0
     // GLES 2.x pnames
     switch (pname) {
diff --git a/core/jni/android_opengl_GLES31Ext.cpp b/core/jni/android_opengl_GLES31Ext.cpp
index 9f2b0c5..8212eb1 100644
--- a/core/jni/android_opengl_GLES31Ext.cpp
+++ b/core/jni/android_opengl_GLES31Ext.cpp
@@ -271,6 +271,19 @@
  */
 static int getNeededCount(GLint pname) {
     int needed = 1;
+#ifdef GL_ES_VERSION_3_0
+    // GLES 3.x pnames
+    switch (pname) {
+        case GL_MAX_VIEWPORT_DIMS:
+            needed = 2;
+            break;
+
+        case GL_PROGRAM_BINARY_FORMATS:
+            glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &needed);
+            break;
+    }
+#endif
+
 #ifdef GL_ES_VERSION_2_0
     // GLES 2.x pnames
     switch (pname) {
diff --git a/core/jni/android_opengl_GLES32.cpp b/core/jni/android_opengl_GLES32.cpp
index aa917a0..91b573b 100644
--- a/core/jni/android_opengl_GLES32.cpp
+++ b/core/jni/android_opengl_GLES32.cpp
@@ -270,6 +270,19 @@
  */
 static int getNeededCount(GLint pname) {
     int needed = 1;
+#ifdef GL_ES_VERSION_3_0
+    // GLES 3.x pnames
+    switch (pname) {
+        case GL_MAX_VIEWPORT_DIMS:
+            needed = 2;
+            break;
+
+        case GL_PROGRAM_BINARY_FORMATS:
+            glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &needed);
+            break;
+    }
+#endif
+
 #ifdef GL_ES_VERSION_2_0
     // GLES 2.x pnames
     switch (pname) {
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index eaf9e91..4322105 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -1021,17 +1021,13 @@
         env->ReleaseStringCritical(fileName, str);
     }
 
-    int fd = open(fileName8.string(), O_CREAT | O_WRONLY | O_NOFOLLOW, 0666);  /* -rw-rw-rw- */
+    int fd = open(fileName8.string(), O_CREAT | O_WRONLY | O_NOFOLLOW | O_CLOEXEC | O_APPEND, 0666);
     if (fd < 0) {
         fprintf(stderr, "Can't open %s: %s\n", fileName8.string(), strerror(errno));
         return;
     }
 
-    if (lseek(fd, 0, SEEK_END) < 0) {
-        fprintf(stderr, "lseek: %s\n", strerror(errno));
-    } else {
-        dump_backtrace_to_file_timeout(pid, fd, timeoutSecs);
-    }
+    dump_backtrace_to_file_timeout(pid, fd, timeoutSecs);
 
     close(fd);
 }
diff --git a/core/jni/android_os_HwBinder.cpp b/core/jni/android_os_HwBinder.cpp
index 989a557..15b2f35 100644
--- a/core/jni/android_os_HwBinder.cpp
+++ b/core/jni/android_os_HwBinder.cpp
@@ -49,12 +49,6 @@
 
 namespace android {
 
-static jclass gArrayListClass;
-static struct {
-    jmethodID size;
-    jmethodID get;
-} gArrayListMethods;
-
 static jclass gErrorClass;
 
 static struct fields_t {
@@ -239,7 +233,6 @@
 static void JHwBinder_native_registerService(
         JNIEnv *env,
         jobject thiz,
-        jobject interfaceChainArrayList,
         jstring serviceNameObj) {
     if (serviceNameObj == NULL) {
         jniThrowException(env, "java/lang/NullPointerException", NULL);
@@ -251,24 +244,6 @@
         return;  // XXX exception already pending?
     }
 
-    jint numInterfaces = env->CallIntMethod(interfaceChainArrayList,
-                                            gArrayListMethods.size);
-    hidl_string *strings = new hidl_string[numInterfaces];
-
-    for (jint i = 0; i < numInterfaces; i++) {
-        jstring strObj = static_cast<jstring>(
-            env->CallObjectMethod(interfaceChainArrayList,
-                                  gArrayListMethods.get,
-                                  i)
-        );
-        const char * str = env->GetStringUTFChars(strObj, nullptr);
-        strings[i] = hidl_string(str);
-        env->ReleaseStringUTFChars(strObj, str);
-    }
-
-    hidl_vec<hidl_string> interfaceChain;
-    interfaceChain.setToExternal(strings, numInterfaces, true /* shouldOwn */);
-
     sp<hardware::IBinder> binder = JHwBinder::GetNativeContext(env, thiz);
 
     /* TODO(b/33440494) this is not right */
@@ -282,7 +257,7 @@
         return;
     }
 
-    Return<bool> ret = manager->add(interfaceChain, serviceName, base);
+    Return<bool> ret = manager->add(serviceName, base);
 
     env->ReleaseStringUTFChars(serviceNameObj, serviceName);
     serviceName = NULL;
@@ -346,7 +321,7 @@
               << serviceName;
 
     ::android::vintf::Transport transport =
-            ::android::hardware::getTransport(ifaceName);
+            ::android::hardware::getTransport(ifaceName, serviceName);
     if (   transport != ::android::vintf::Transport::EMPTY
         && transport != ::android::vintf::Transport::HWBINDER) {
         LOG(ERROR) << "service " << ifaceName << " declares transport method "
@@ -385,7 +360,7 @@
         "(IL" PACKAGE_PATH "/HwParcel;L" PACKAGE_PATH "/HwParcel;I)V",
         (void *)JHwBinder_native_transact },
 
-    { "registerService", "(Ljava/util/ArrayList;Ljava/lang/String;)V",
+    { "registerService", "(Ljava/lang/String;)V",
         (void *)JHwBinder_native_registerService },
 
     { "getService", "(Ljava/lang/String;Ljava/lang/String;)L" PACKAGE_PATH "/IHwBinder;",
@@ -395,11 +370,6 @@
 namespace android {
 
 int register_android_os_HwBinder(JNIEnv *env) {
-    jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList");
-    gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass);
-    gArrayListMethods.size = GetMethodIDOrDie(env, arrayListClass, "size", "()I");
-    gArrayListMethods.get = GetMethodIDOrDie(env, arrayListClass, "get", "(I)Ljava/lang/Object;");
-
     jclass errorClass = FindClassOrDie(env, "java/lang/Error");
     gErrorClass = MakeGlobalRefOrDie(env, errorClass);
 
diff --git a/core/jni/android_os_seccomp.cpp b/core/jni/android_os_seccomp.cpp
index 45d5061..4502371 100644
--- a/core/jni/android_os_seccomp.cpp
+++ b/core/jni/android_os_seccomp.cpp
@@ -14,233 +14,25 @@
  * limitations under the License.
  */
 
-#include "JNIHelp.h"
 #include "core_jni_helpers.h"
 #include "JniConstants.h"
 #include "utils/Log.h"
-#include "utils/misc.h"
-
-#if defined __arm__ || defined __aarch64__
-
-#include <vector>
-
-#include <sys/prctl.h>
-
-#include <linux/unistd.h>
-#include <linux/audit.h>
-#include <linux/filter.h>
-#include <linux/seccomp.h>
+#include <selinux/selinux.h>
 
 #include "seccomp_policy.h"
 
-#define syscall_nr (offsetof(struct seccomp_data, nr))
-#define arch_nr (offsetof(struct seccomp_data, arch))
-
-typedef std::vector<sock_filter> filter;
-
-// We want to keep the below inline functions for debugging and future
-// development even though they are not all sed currently.
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wunused-function"
-
-static inline void Kill(filter& f) {
-    f.push_back(BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL));
-}
-
-static inline void Trap(filter& f) {
-    f.push_back(BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRAP));
-}
-
-static inline void Error(filter& f, __u16 retcode) {
-    f.push_back(BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO + retcode));
-}
-
-inline static void Trace(filter& f) {
-    f.push_back(BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE));
-}
-
-inline static void Allow(filter& f) {
-    f.push_back(BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW));
-}
-
-#pragma clang diagnostic pop
-
-inline static void AllowSyscall(filter& f, __u32 num) {
-    f.push_back(BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, num, 0, 1));
-    Allow(f);
-}
-
-inline static void ExamineSyscall(filter& f) {
-    f.push_back(BPF_STMT(BPF_LD|BPF_W|BPF_ABS, syscall_nr));
-}
-
-inline static int SetValidateArchitectureJumpTarget(size_t offset, filter& f) {
-    size_t jump_length = f.size() - offset - 1;
-    auto u8_jump_length = (__u8) jump_length;
-    if (u8_jump_length != jump_length) {
-        ALOGE("Can't set jump greater than 255 - actual jump is %zu",
-              jump_length);
-        return -1;
-    }
-    f[offset] = BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, AUDIT_ARCH_ARM, u8_jump_length, 0);
-    return 0;
-}
-
-inline static size_t ValidateArchitectureAndJumpIfNeeded(filter& f) {
-    f.push_back(BPF_STMT(BPF_LD|BPF_W|BPF_ABS, arch_nr));
-
-    f.push_back(BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, AUDIT_ARCH_AARCH64, 2, 0));
-    f.push_back(BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, AUDIT_ARCH_ARM, 1, 0));
-    Trap(f);
-    return f.size() - 2;
-}
-
-static bool install_filter(filter const& f) {
-    struct sock_fprog prog = {
-        (unsigned short) f.size(),
-        (struct sock_filter*) &f[0],
-    };
-
-    if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) < 0) {
-        ALOGE("SECCOMP: Could not set seccomp filter of size %zu: %s", f.size(), strerror(errno));
-        return false;
-    }
-
-    ALOGI("SECCOMP: Global filter of size %zu installed", f.size());
-    return true;
-}
-
-bool set_seccomp_filter() {
-    filter f;
-
-    // Note that for mixed 64/32 bit architectures, ValidateArchitecture inserts a
-    // jump that must be changed to point to the start of the 32-bit policy
-    // 32 bit syscalls will not hit the policy between here and the call to SetJump
-    auto offset_to_32bit_filter =
-        ValidateArchitectureAndJumpIfNeeded(f);
-
-    // 64-bit filter
-    ExamineSyscall(f);
-
-    // arm64-only filter - autogenerated from bionic syscall usage
-    for (size_t i = 0; i < arm64_filter_size; ++i)
-        f.push_back(arm64_filter[i]);
-
-    // Syscalls needed to boot Android
-    AllowSyscall(f, 41);  // __NR_pivot_root
-    AllowSyscall(f, 31);  // __NR_ioprio_get
-    AllowSyscall(f, 30);  // __NR_ioprio_set
-    AllowSyscall(f, 178); // __NR_gettid
-    AllowSyscall(f, 98);  // __NR_futex
-    AllowSyscall(f, 220); // __NR_clone
-    AllowSyscall(f, 139); // __NR_rt_sigreturn
-    AllowSyscall(f, 240); // __NR_rt_tgsigqueueinfo
-    AllowSyscall(f, 128); // __NR_restart_syscall
-    AllowSyscall(f, 278); // __NR_getrandom
-
-    // Needed for performance tools
-    AllowSyscall(f, 241); // __NR_perf_event_open
-
-    // Needed for strace
-    AllowSyscall(f, 130); // __NR_tkill
-
-    // Needed for kernel to restart syscalls
-    AllowSyscall(f, 128); // __NR_restart_syscall
-
-    // b/35034743
-    AllowSyscall(f, 267); // __NR_syncfs
-
-    // b/34763393
-    AllowSyscall(f, 277); // __NR_seccomp
-
-    Trap(f);
-
-    if (SetValidateArchitectureJumpTarget(offset_to_32bit_filter, f) != 0)
-        return -1;
-
-    // 32-bit filter
-    ExamineSyscall(f);
-
-    // arm32 filter - autogenerated from bionic syscall usage
-    for (size_t i = 0; i < arm_filter_size; ++i)
-        f.push_back(arm_filter[i]);
-
-    // Syscalls needed to boot android
-    AllowSyscall(f, 120); // __NR_clone
-    AllowSyscall(f, 240); // __NR_futex
-    AllowSyscall(f, 119); // __NR_sigreturn
-    AllowSyscall(f, 173); // __NR_rt_sigreturn
-    AllowSyscall(f, 363); // __NR_rt_tgsigqueueinfo
-    AllowSyscall(f, 224); // __NR_gettid
-
-    // Syscalls needed to run Chrome
-    AllowSyscall(f, 383); // __NR_seccomp - needed to start Chrome
-    AllowSyscall(f, 384); // __NR_getrandom - needed to start Chrome
-
-    // Syscalls needed to run GFXBenchmark
-    AllowSyscall(f, 190); // __NR_vfork
-
-    // Needed for strace
-    AllowSyscall(f, 238); // __NR_tkill
-
-    // Needed for kernel to restart syscalls
-    AllowSyscall(f, 0);   // __NR_restart_syscall
-
-    // Needed for debugging 32-bit Chrome
-    AllowSyscall(f, 42);  // __NR_pipe
-
-    // b/34732712
-    AllowSyscall(f, 364); // __NR_perf_event_open
-
-    // b/34651972
-    AllowSyscall(f, 33);  // __NR_access
-    AllowSyscall(f, 195); // __NR_stat64
-
-    // b/34813887
-    AllowSyscall(f, 5);   // __NR_open
-    AllowSyscall(f, 141); // __NR_getdents
-    AllowSyscall(f, 217); // __NR_getdents64
-
-    // b/34719286
-    AllowSyscall(f, 351); // __NR_eventfd
-
-    // b/34817266
-    AllowSyscall(f, 252); // __NR_epoll_wait
-
-    // Needed by sanitizers (b/34606909)
-    // 5 (__NR_open) and 195 (__NR_stat64) are also required, but they are
-    // already allowed.
-    AllowSyscall(f, 85);  // __NR_readlink
-
-    // b/34908783
-    AllowSyscall(f, 250); // __NR_epoll_create
-
-    // b/34979910
-    AllowSyscall(f, 8);   // __NR_creat
-    AllowSyscall(f, 10);  // __NR_unlink
-
-    // b/35059702
-    AllowSyscall(f, 196); // __NR_lstat64
-
-    Trap(f);
-
-    return install_filter(f);
-}
-
 static void Seccomp_setPolicy(JNIEnv* /*env*/) {
+    if (security_getenforce() == 0) {
+        ALOGI("seccomp disabled by setenforce 0");
+        return;
+    }
+
     if (!set_seccomp_filter()) {
         ALOGE("Failed to set seccomp policy - killing");
         exit(1);
     }
 }
 
-#else // #if defined __arm__ || defined __aarch64__
-
-static void Seccomp_setPolicy(JNIEnv* /*env*/) {
-}
-
-#endif
-
 static const JNINativeMethod method_table[] = {
     NATIVE_METHOD(Seccomp, setPolicy, "()V"),
 };
diff --git a/core/jni/android_text_StaticLayout.cpp b/core/jni/android_text_StaticLayout.cpp
index c05ef26..4a445d8 100644
--- a/core/jni/android_text_StaticLayout.cpp
+++ b/core/jni/android_text_StaticLayout.cpp
@@ -121,7 +121,8 @@
     b->finish();
 }
 
-static jlong nLoadHyphenator(JNIEnv* env, jclass, jobject buffer, jint offset) {
+static jlong nLoadHyphenator(JNIEnv* env, jclass, jobject buffer, jint offset,
+        jint minPrefix, jint minSuffix) {
     const uint8_t* bytebuf = nullptr;
     if (buffer != nullptr) {
         void* rawbuf = env->GetDirectBufferAddress(buffer);
@@ -131,7 +132,8 @@
             ALOGE("failed to get direct buffer address");
         }
     }
-    minikin::Hyphenator* hyphenator = minikin::Hyphenator::loadBinary(bytebuf);
+    minikin::Hyphenator* hyphenator = minikin::Hyphenator::loadBinary(
+            bytebuf, minPrefix, minSuffix);
     return reinterpret_cast<jlong>(hyphenator);
 }
 
@@ -159,11 +161,12 @@
     minikin::LineBreaker* b = reinterpret_cast<minikin::LineBreaker*>(nativePtr);
     Paint* paint = reinterpret_cast<Paint*>(nativePaint);
     Typeface* typeface = reinterpret_cast<Typeface*>(nativeTypeface);
-    minikin::FontCollection *font;
     minikin::MinikinPaint minikinPaint;
-    minikin::FontStyle style = MinikinUtils::prepareMinikinPaint(&minikinPaint, &font, paint,
+    Typeface* resolvedTypeface = Typeface::resolveDefault(typeface);
+    minikin::FontStyle style = MinikinUtils::prepareMinikinPaint(&minikinPaint, paint,
             typeface);
-    return b->addStyleRun(&minikinPaint, font, style, start, end, isRtl);
+    return b->addStyleRun(&minikinPaint, resolvedTypeface->fFontCollection, style, start, end,
+            isRtl);
 }
 
 // Accept width measurements for the run, passed in from Java
@@ -190,7 +193,7 @@
     {"nNewBuilder", "()J", (void*) nNewBuilder},
     {"nFreeBuilder", "(J)V", (void*) nFreeBuilder},
     {"nFinishBuilder", "(J)V", (void*) nFinishBuilder},
-    {"nLoadHyphenator", "(Ljava/nio/ByteBuffer;I)J", (void*) nLoadHyphenator},
+    {"nLoadHyphenator", "(Ljava/nio/ByteBuffer;III)J", (void*) nLoadHyphenator},
     {"nSetLocale", "(JLjava/lang/String;J)V", (void*) nSetLocale},
     {"nSetupParagraph", "(J[CIFIF[IIIIZ)V", (void*) nSetupParagraph},
     {"nSetIndents", "(J[I)V", (void*) nSetIndents},
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 723dce6..373bda9 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -1671,10 +1671,8 @@
         (void*) android_content_AssetManager_readAsset },
     { "seekAsset",      "(JJI)J",
         (void*) android_content_AssetManager_seekAsset },
-    // @FastNative
     { "getAssetLength", "(J)J",
         (void*) android_content_AssetManager_getAssetLength },
-    // @FastNative
     { "getAssetRemainingLength", "(J)J",
         (void*) android_content_AssetManager_getAssetRemainingLength },
     { "addAssetPathNative", "(Ljava/lang/String;Z)I",
@@ -1691,34 +1689,24 @@
         (void*) android_content_AssetManager_getNonSystemLocales },
     { "getSizeConfigurations", "()[Landroid/content/res/Configuration;",
         (void*) android_content_AssetManager_getSizeConfigurations },
-    // @FastNative
     { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIIIII)V",
         (void*) android_content_AssetManager_setConfiguration },
-    // @FastNative
     { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
         (void*) android_content_AssetManager_getResourceIdentifier },
-    // @FastNative
     { "getResourceName","(I)Ljava/lang/String;",
         (void*) android_content_AssetManager_getResourceName },
-    // @FastNative
     { "getResourcePackageName","(I)Ljava/lang/String;",
         (void*) android_content_AssetManager_getResourcePackageName },
-    // @FastNative
     { "getResourceTypeName","(I)Ljava/lang/String;",
         (void*) android_content_AssetManager_getResourceTypeName },
-    // @FastNative
     { "getResourceEntryName","(I)Ljava/lang/String;",
         (void*) android_content_AssetManager_getResourceEntryName },
-    // @FastNative
     { "loadResourceValue","(ISLandroid/util/TypedValue;Z)I",
         (void*) android_content_AssetManager_loadResourceValue },
-    // @FastNative
     { "loadResourceBagValue","(IILandroid/util/TypedValue;Z)I",
         (void*) android_content_AssetManager_loadResourceBagValue },
-    // @FastNative
     { "getStringBlockCount","()I",
         (void*) android_content_AssetManager_getStringBlockCount },
-    // @FastNative
     { "getNativeStringBlock","(I)J",
         (void*) android_content_AssetManager_getNativeStringBlock },
     { "getCookieName","(I)Ljava/lang/String;",
@@ -1737,27 +1725,20 @@
         (void*) android_content_AssetManager_copyTheme },
     { "clearTheme", "(J)V",
         (void*) android_content_AssetManager_clearTheme },
-    // @FastNative
     { "loadThemeAttributeValue", "(JILandroid/util/TypedValue;Z)I",
         (void*) android_content_AssetManager_loadThemeAttributeValue },
-    // @FastNative
     { "getThemeChangingConfigurations", "(J)I",
         (void*) android_content_AssetManager_getThemeChangingConfigurations },
     { "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
         (void*) android_content_AssetManager_dumpTheme },
-    // @FastNative
     { "applyStyle","(JIIJ[IIJJ)V",
         (void*) android_content_AssetManager_applyStyle },
-    // @FastNative
     { "resolveAttrs","(JII[I[I[I[I)Z",
         (void*) android_content_AssetManager_resolveAttrs },
-    // @FastNative
     { "retrieveAttributes","(J[I[I[I)Z",
         (void*) android_content_AssetManager_retrieveAttributes },
-    // @FastNative
     { "getArraySize","(I)I",
         (void*) android_content_AssetManager_getArraySize },
-    // @FastNative
     { "retrieveArray","(I[I)I",
         (void*) android_content_AssetManager_retrieveArray },
 
@@ -1768,13 +1749,10 @@
     // Arrays.
     { "getArrayStringResource","(I)[Ljava/lang/String;",
         (void*) android_content_AssetManager_getArrayStringResource },
-    // @FastNative
     { "getArrayStringInfo","(I)[I",
         (void*) android_content_AssetManager_getArrayStringInfo },
-    // @FastNative
     { "getArrayIntResource","(I)[I",
         (void*) android_content_AssetManager_getArrayIntResource },
-    // @FastNative
     { "getStyleAttributes","(I)[I",
         (void*) android_content_AssetManager_getStyleAttributes },
 
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index b57f2362..a03d3c5 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -252,25 +252,26 @@
             if (t_pri >= ANDROID_PRIORITY_BACKGROUND) {
                 // This task wants to stay at background
                 // update its cpuset so it doesn't only run on bg core(s)
-#ifdef ENABLE_CPUSETS
-                int err = set_cpuset_policy(t_pid, sp);
-                if (err != NO_ERROR) {
-                    signalExceptionForGroupError(env, -err, t_pid);
-                    break;
+                if (cpusets_enabled()) {
+                    int err = set_cpuset_policy(t_pid, sp);
+                    if (err != NO_ERROR) {
+                        signalExceptionForGroupError(env, -err, t_pid);
+                        break;
+                    }
                 }
-#endif
                 continue;
             }
         }
         int err;
-#ifdef ENABLE_CPUSETS
-        // set both cpuset and cgroup for general threads
-        err = set_cpuset_policy(t_pid, sp);
-        if (err != NO_ERROR) {
-            signalExceptionForGroupError(env, -err, t_pid);
-            break;
+
+        if (cpusets_enabled()) {
+            // set both cpuset and cgroup for general threads
+            err = set_cpuset_policy(t_pid, sp);
+            if (err != NO_ERROR) {
+                signalExceptionForGroupError(env, -err, t_pid);
+                break;
+            }
         }
-#endif
 
         err = set_sched_policy(t_pid, sp);
         if (err != NO_ERROR) {
@@ -291,7 +292,6 @@
     return (int) sp;
 }
 
-#ifdef ENABLE_CPUSETS
 /** Sample CPUset list format:
  *  0-3,4,6-8
  */
@@ -367,7 +367,6 @@
     }
     return;
 }
-#endif
 
 
 /**
@@ -376,22 +375,21 @@
  * them in the passed in cpu_set_t
  */
 void get_exclusive_cpuset_cores(SchedPolicy policy, cpu_set_t *cpu_set) {
-#ifdef ENABLE_CPUSETS
-    int i;
-    cpu_set_t tmp_set;
-    get_cpuset_cores_for_policy(policy, cpu_set);
-    for (i = 0; i < SP_CNT; i++) {
-        if ((SchedPolicy) i == policy) continue;
-        get_cpuset_cores_for_policy((SchedPolicy)i, &tmp_set);
-        // First get cores exclusive to one set or the other
-        CPU_XOR(&tmp_set, cpu_set, &tmp_set);
-        // Then get the ones only in cpu_set
-        CPU_AND(cpu_set, cpu_set, &tmp_set);
+    if (cpusets_enabled()) {
+        int i;
+        cpu_set_t tmp_set;
+        get_cpuset_cores_for_policy(policy, cpu_set);
+        for (i = 0; i < SP_CNT; i++) {
+            if ((SchedPolicy) i == policy) continue;
+            get_cpuset_cores_for_policy((SchedPolicy)i, &tmp_set);
+            // First get cores exclusive to one set or the other
+            CPU_XOR(&tmp_set, cpu_set, &tmp_set);
+            // Then get the ones only in cpu_set
+            CPU_AND(cpu_set, cpu_set, &tmp_set);
+        }
+    } else {
+        CPU_ZERO(cpu_set);
     }
-#else
-    (void) policy;
-    CPU_ZERO(cpu_set);
-#endif
     return;
 }
 
diff --git a/core/jni/android_view_InputChannel.cpp b/core/jni/android_view_InputChannel.cpp
index c7998a1..1c6ead0 100644
--- a/core/jni/android_view_InputChannel.cpp
+++ b/core/jni/android_view_InputChannel.cpp
@@ -111,11 +111,12 @@
 }
 
 static jobject android_view_InputChannel_createInputChannel(JNIEnv* env,
-        NativeInputChannel* nativeInputChannel) {
+        std::unique_ptr<NativeInputChannel> nativeInputChannel) {
     jobject inputChannelObj = env->NewObject(gInputChannelClassInfo.clazz,
             gInputChannelClassInfo.ctor);
     if (inputChannelObj) {
-        android_view_InputChannel_setNativeInputChannel(env, inputChannelObj, nativeInputChannel);
+        android_view_InputChannel_setNativeInputChannel(env, inputChannelObj,
+                 nativeInputChannel.release());
     }
     return inputChannelObj;
 }
@@ -143,13 +144,13 @@
     }
 
     jobject serverChannelObj = android_view_InputChannel_createInputChannel(env,
-            new NativeInputChannel(serverChannel));
+            std::make_unique<NativeInputChannel>(serverChannel));
     if (env->ExceptionCheck()) {
         return NULL;
     }
 
     jobject clientChannelObj = android_view_InputChannel_createInputChannel(env,
-            new NativeInputChannel(clientChannel));
+            std::make_unique<NativeInputChannel>(clientChannel));
     if (env->ExceptionCheck()) {
         return NULL;
     }
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 0171562..a81901d 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -356,9 +356,9 @@
 }
 
 static void nativeSetMatrix(JNIEnv* env, jclass clazz, jlong nativeObject,
-        jfloat dsdx, jfloat dtdx, jfloat dsdy, jfloat dtdy) {
+        jfloat dsdx, jfloat dtdx, jfloat dtdy, jfloat dsdy) {
     SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
-    status_t err = ctrl->setMatrix(dsdx, dtdx, dsdy, dtdy);
+    status_t err = ctrl->setMatrix(dsdx, dtdx, dtdy, dsdy);
     if (err < 0 && err != NO_INIT) {
         doThrowIAE(env);
     }
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index d37f96a..37eae48a 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -43,7 +43,6 @@
 #include <FrameInfo.h>
 #include <FrameMetricsObserver.h>
 #include <IContextFactory.h>
-#include <JankTracker.h>
 #include <PropertyValuesAnimatorSet.h>
 #include <RenderNode.h>
 #include <renderthread/CanvasContext.h>
@@ -587,10 +586,13 @@
     return atoi(prop) > 0 ? JNI_TRUE : JNI_FALSE;
 }
 
+static void android_view_ThreadedRenderer_rotateProcessStatsBuffer(JNIEnv* env, jobject clazz) {
+    RenderProxy::rotateProcessStatsBuffer();
+}
+
 static void android_view_ThreadedRenderer_setProcessStatsBuffer(JNIEnv* env, jobject clazz,
-        jlong proxyPtr, jint fd) {
-    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    proxy->setProcessStatsBuffer(fd);
+        jint fd) {
+    RenderProxy::setProcessStatsBuffer(fd);
 }
 
 static jint android_view_ThreadedRenderer_getRenderThreadTid(JNIEnv* env, jobject clazz,
@@ -817,15 +819,6 @@
     proxy->dumpProfileInfo(fd, dumpFlags);
 }
 
-static void android_view_ThreadedRenderer_dumpProfileData(JNIEnv* env, jobject clazz,
-        jbyteArray jdata, jobject javaFileDescriptor) {
-    int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
-    ScopedByteArrayRO buffer(env, jdata);
-    if (buffer.get()) {
-        JankTracker::dumpBuffer(buffer.get(), buffer.size(), fd);
-    }
-}
-
 static void android_view_ThreadedRenderer_addRenderNode(JNIEnv* env, jobject clazz,
         jlong proxyPtr, jlong renderNodePtr, jboolean placeFront) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
@@ -910,7 +903,8 @@
 
 static const JNINativeMethod gMethods[] = {
     { "nSupportsOpenGL", "()Z", (void*) android_view_ThreadedRenderer_supportsOpenGL },
-    { "nSetProcessStatsBuffer", "(JI)V", (void*) android_view_ThreadedRenderer_setProcessStatsBuffer },
+    { "nRotateProcessStatsBuffer", "()V", (void*) android_view_ThreadedRenderer_rotateProcessStatsBuffer },
+    { "nSetProcessStatsBuffer", "(I)V", (void*) android_view_ThreadedRenderer_setProcessStatsBuffer },
     { "nGetRenderThreadTid", "(J)I", (void*) android_view_ThreadedRenderer_getRenderThreadTid },
     { "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode },
     { "nCreateProxy", "(ZJ)J", (void*) android_view_ThreadedRenderer_createProxy },
@@ -943,7 +937,6 @@
     { "nNotifyFramePending", "(J)V", (void*) android_view_ThreadedRenderer_notifyFramePending },
     { "nSerializeDisplayListTree", "(J)V", (void*) android_view_ThreadedRenderer_serializeDisplayListTree },
     { "nDumpProfileInfo", "(JLjava/io/FileDescriptor;I)V", (void*) android_view_ThreadedRenderer_dumpProfileInfo },
-    { "nDumpProfileData", "([BLjava/io/FileDescriptor;)V", (void*) android_view_ThreadedRenderer_dumpProfileData },
     { "setupShadersDiskCache", "(Ljava/lang/String;)V",
                 (void*) android_view_ThreadedRenderer_setupShadersDiskCache },
     { "nAddRenderNode", "(JJZ)V", (void*) android_view_ThreadedRenderer_addRenderNode},
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index c3f0e9d..0ab27f2 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -155,24 +155,6 @@
   }
 }
 
-// Resets nice priority for zygote process. Zygote priority can be set
-// to high value during boot phase to speed it up. We want to ensure
-// zygote is running at normal priority before childs are forked from it.
-//
-// This ends up being called repeatedly before each fork(), but there's
-// no real harm in that.
-static void ResetNicePriority(JNIEnv* env) {
-  errno = 0;
-  int prio = getpriority(PRIO_PROCESS, 0);
-  if (prio == -1 && errno != 0) {
-    ALOGW("getpriority failed: %s\n", strerror(errno));
-  }
-  if (prio != 0 && setpriority(PRIO_PROCESS, 0, 0) != 0) {
-    ALOGE("setpriority(%d, 0, 0) failed: %s", PRIO_PROCESS, strerror(errno));
-    RuntimeAbort(env, __LINE__, "setpriority failed");
-  }
-}
-
 // Sets the SIGCHLD handler back to default behavior in zygote children.
 static void UnsetSigChldHandler() {
   struct sigaction sa;
@@ -526,8 +508,6 @@
     RuntimeAbort(env, __LINE__, "Unable to restat file descriptor table.");
   }
 
-  ResetNicePriority(env);
-
   pid_t pid = fork();
 
   if (pid == 0) {
@@ -806,10 +786,6 @@
     UnmountTree("/storage");
 }
 
-static void com_android_internal_os_Zygote_nativeResetNicePriority(JNIEnv* env, jclass) {
-    ResetNicePriority(env);
-}
-
 static const JNINativeMethod gMethods[] = {
     { "nativeForkAndSpecialize",
       "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[ILjava/lang/String;Ljava/lang/String;)I",
@@ -819,9 +795,7 @@
     { "nativeAllowFileAcrossFork", "(Ljava/lang/String;)V",
       (void *) com_android_internal_os_Zygote_nativeAllowFileAcrossFork },
     { "nativeUnmountStorageOnInit", "()V",
-      (void *) com_android_internal_os_Zygote_nativeUnmountStorageOnInit },
-    { "nativeResetNicePriority", "()V",
-      (void *) com_android_internal_os_Zygote_nativeResetNicePriority }
+      (void *) com_android_internal_os_Zygote_nativeUnmountStorageOnInit }
 };
 
 int register_com_android_internal_os_Zygote(JNIEnv* env) {
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index 59a536b..9660de4 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -26,8 +26,8 @@
 #include <sys/un.h>
 #include <unistd.h>
 
+#include <android-base/logging.h>
 #include <android-base/strings.h>
-#include <cutils/log.h>
 
 // Static whitelist of open paths that the zygote is allowed to keep open.
 static const char* kPathWhitelist[] = {
@@ -137,7 +137,7 @@
   // This should never happen; the zygote should always have the right set
   // of permissions required to stat all its open files.
   if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) {
-    ALOGE("Unable to stat fd %d : %s", fd, strerror(errno));
+    PLOG(ERROR) << "Unable to stat fd " << fd;
     return NULL;
   }
 
@@ -150,7 +150,8 @@
     }
 
     if (!whitelist->IsAllowed(socket_name)) {
-      ALOGE("Socket name not whitelisted : %s (fd=%d)", socket_name.c_str(), fd);
+      LOG(ERROR) << "Socket name not whitelisted : " << socket_name
+                 << " (fd=" << fd << ")";
       return NULL;
     }
 
@@ -168,7 +169,7 @@
   // with the child process across forks but those should have been closed
   // before we got to this point.
   if (!S_ISCHR(f_stat.st_mode) && !S_ISREG(f_stat.st_mode)) {
-    ALOGE("Unsupported st_mode %d", f_stat.st_mode);
+    LOG(ERROR) << "Unsupported st_mode " << f_stat.st_mode;
     return NULL;
   }
 
@@ -178,7 +179,7 @@
   }
 
   if (!whitelist->IsAllowed(file_path)) {
-    ALOGE("Not whitelisted : %s", file_path.c_str());
+    LOG(ERROR) << "Not whitelisted : " << file_path;
     return NULL;
   }
 
@@ -187,7 +188,7 @@
   // there won't be any races.
   const int fd_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFD));
   if (fd_flags == -1) {
-    ALOGE("Failed fcntl(%d, F_GETFD) : %s", fd, strerror(errno));
+    PLOG(ERROR) << "Failed fcntl(" << fd << ", F_GETFD)";
     return NULL;
   }
 
@@ -205,7 +206,7 @@
   //   their presence and pass them in to open().
   int fs_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL));
   if (fs_flags == -1) {
-    ALOGE("Failed fcntl(%d, F_GETFL) : %s", fd, strerror(errno));
+    PLOG(ERROR) << "Failed fcntl(" << fd << ", F_GETFL)";
     return NULL;
   }
 
@@ -224,6 +225,7 @@
 bool FileDescriptorInfo::Restat() const {
   struct stat f_stat;
   if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) {
+    PLOG(ERROR) << "Unable to restat fd " << fd;
     return false;
   }
 
@@ -241,31 +243,31 @@
   const int new_fd = TEMP_FAILURE_RETRY(open(file_path.c_str(), open_flags));
 
   if (new_fd == -1) {
-    ALOGE("Failed open(%s, %d) : %s", file_path.c_str(), open_flags, strerror(errno));
+    PLOG(ERROR) << "Failed open(" << file_path << ", " << open_flags << ")";
     return false;
   }
 
   if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFD, fd_flags)) == -1) {
     close(new_fd);
-    ALOGE("Failed fcntl(%d, F_SETFD, %x) : %s", new_fd, fd_flags, strerror(errno));
+    PLOG(ERROR) << "Failed fcntl(" << new_fd << ", F_SETFD, " << fd_flags << ")";
     return false;
   }
 
   if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFL, fs_flags)) == -1) {
     close(new_fd);
-    ALOGE("Failed fcntl(%d, F_SETFL, %x) : %s", new_fd, fs_flags, strerror(errno));
+    PLOG(ERROR) << "Failed fcntl(" << new_fd << ", F_SETFL, " << fs_flags << ")";
     return false;
   }
 
   if (offset != -1 && TEMP_FAILURE_RETRY(lseek64(new_fd, offset, SEEK_SET)) == -1) {
     close(new_fd);
-    ALOGE("Failed lseek64(%d, SEEK_SET) : %s", new_fd, strerror(errno));
+    PLOG(ERROR) << "Failed lseek64(" << new_fd << ", SEEK_SET)";
     return false;
   }
 
   if (TEMP_FAILURE_RETRY(dup2(new_fd, fd)) == -1) {
     close(new_fd);
-    ALOGE("Failed dup2(%d, %d) : %s", fd, new_fd, strerror(errno));
+    PLOG(ERROR) << "Failed dup2(" << fd << ", " << new_fd << ")";
     return false;
   }
 
@@ -312,7 +314,10 @@
   // ext2 and ext4 both have PAGE_SIZE limitations, so we assume that here.
   char buf[4096];
   ssize_t len = readlink(path, buf, sizeof(buf));
-  if (len == -1) return false;
+  if (len == -1) {
+    PLOG(ERROR) << "Readlink on " << fd << " failed.";
+    return false;
+  }
 
   result->assign(buf, len);
   return true;
@@ -325,12 +330,12 @@
   socklen_t addr_len = sizeof(ss);
 
   if (TEMP_FAILURE_RETRY(getsockname(fd, addr, &addr_len)) == -1) {
-    ALOGE("Failed getsockname(%d) : %s", fd, strerror(errno));
+    PLOG(ERROR) << "Failed getsockname(" << fd << ")";
     return false;
   }
 
   if (addr->sa_family != AF_UNIX) {
-    ALOGE("Unsupported socket (fd=%d) with family %d", fd, addr->sa_family);
+    LOG(ERROR) << "Unsupported socket (fd=" << fd << ") with family " << addr->sa_family;
     return false;
   }
 
@@ -339,13 +344,13 @@
   size_t path_len = addr_len - offsetof(struct sockaddr_un, sun_path);
   // This is an unnamed local socket, we do not accept it.
   if (path_len == 0) {
-    ALOGE("Unsupported AF_UNIX socket (fd=%d) with empty path.", fd);
+    LOG(ERROR) << "Unsupported AF_UNIX socket (fd=" << fd << ") with empty path.";
     return false;
   }
 
   // This is a local socket with an abstract address, we do not accept it.
   if (unix_addr->sun_path[0] == '\0') {
-    ALOGE("Unsupported AF_UNIX socket (fd=%d) with abstract address.", fd);
+    LOG(ERROR) << "Unsupported AF_UNIX socket (fd=" << fd << ") with abstract address.";
     return false;
   }
 
@@ -363,17 +368,17 @@
 bool FileDescriptorInfo::DetachSocket() const {
   const int dev_null_fd = open("/dev/null", O_RDWR);
   if (dev_null_fd < 0) {
-    ALOGE("Failed to open /dev/null : %s", strerror(errno));
+    PLOG(ERROR) << "Failed to open /dev/null";
     return false;
   }
 
   if (dup2(dev_null_fd, fd) == -1) {
-    ALOGE("Failed dup2 on socket descriptor %d : %s", fd, strerror(errno));
+    PLOG(ERROR) << "Failed dup2 on socket descriptor " << fd;
     return false;
   }
 
   if (close(dev_null_fd) == -1) {
-    ALOGE("Failed close(%d) : %s", dev_null_fd, strerror(errno));
+    PLOG(ERROR) << "Failed close(" << dev_null_fd << ")";
     return false;
   }
 
@@ -384,7 +389,7 @@
 FileDescriptorTable* FileDescriptorTable::Create(const std::vector<int>& fds_to_ignore) {
   DIR* d = opendir(kFdPath);
   if (d == NULL) {
-    ALOGE("Unable to open directory %s: %s", kFdPath, strerror(errno));
+    PLOG(ERROR) << "Unable to open directory " << std::string(kFdPath);
     return NULL;
   }
   int dir_fd = dirfd(d);
@@ -397,14 +402,14 @@
       continue;
     }
     if (std::find(fds_to_ignore.begin(), fds_to_ignore.end(), fd) != fds_to_ignore.end()) {
-      ALOGI("Ignoring open file descriptor %d", fd);
+      LOG(INFO) << "Ignoring open file descriptor " << fd;
       continue;
     }
 
     FileDescriptorInfo* info = FileDescriptorInfo::CreateFromFd(fd);
     if (info == NULL) {
       if (closedir(d) == -1) {
-        ALOGE("Unable to close directory : %s", strerror(errno));
+        PLOG(ERROR) << "Unable to close directory";
       }
       return NULL;
     }
@@ -412,7 +417,7 @@
   }
 
   if (closedir(d) == -1) {
-    ALOGE("Unable to close directory : %s", strerror(errno));
+    PLOG(ERROR) << "Unable to close directory";
     return NULL;
   }
   return new FileDescriptorTable(open_fd_map);
@@ -424,7 +429,7 @@
   // First get the list of open descriptors.
   DIR* d = opendir(kFdPath);
   if (d == NULL) {
-    ALOGE("Unable to open directory %s: %s", kFdPath, strerror(errno));
+    PLOG(ERROR) << "Unable to open directory " << std::string(kFdPath);
     return false;
   }
 
@@ -436,7 +441,7 @@
       continue;
     }
     if (std::find(fds_to_ignore.begin(), fds_to_ignore.end(), fd) != fds_to_ignore.end()) {
-      ALOGI("Ignoring open file descriptor %d", fd);
+      LOG(INFO) << "Ignoring open file descriptor " << fd;
       continue;
     }
 
@@ -444,7 +449,7 @@
   }
 
   if (closedir(d) == -1) {
-    ALOGE("Unable to close directory : %s", strerror(errno));
+    PLOG(ERROR) << "Unable to close directory";
     return false;
   }
 
diff --git a/core/jni/include/android_runtime/android_hardware_HardwareBuffer.h b/core/jni/include/android_runtime/android_hardware_HardwareBuffer.h
index a5d0596..3545c56 100644
--- a/core/jni/include/android_runtime/android_hardware_HardwareBuffer.h
+++ b/core/jni/include/android_runtime/android_hardware_HardwareBuffer.h
@@ -41,12 +41,13 @@
 
 /* Convert from AHARDWAREBUFFER_USAGE* flags to to gralloc usage flags. */
 extern void android_hardware_HardwareBuffer_convertToGrallocUsageBits(
-      uint64_t usage0, uint64_t usage1, uint64_t* outProducerUsage,
-      uint64_t* outConsumerUsage);
+      uint64_t* outProducerUsage, uint64_t* outConsumerUsage, uint64_t usage0,
+      uint64_t usage1);
 
 /* Convert from gralloc usage flags to to AHARDWAREBUFFER_USAGE0* flags. */
-extern uint64_t android_hardware_HardwareBuffer_convertFromGrallocUsageBits(
-      uint64_t producerUsage, uint64_t consumerUsage);
+extern void android_hardware_HardwareBuffer_convertFromGrallocUsageBits(
+      uint64_t* outUsage0, uint64_t* outUsage1, uint64_t producerUsage,
+      uint64_t consumerUsage);
 
 } // namespace android
 
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index ba1d664..a2f07d9 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -21,6 +21,7 @@
 
 import "frameworks/base/libs/incident/proto/android/privacy.proto";
 import "frameworks/base/core/proto/android/service/appwidget.proto";
+import "frameworks/base/core/proto/android/service/graphicsstats.proto";
 import "frameworks/base/core/proto/android/service/fingerprint.proto";
 import "frameworks/base/core/proto/android/service/netstats.proto";
 import "frameworks/base/core/proto/android/service/notification.proto";
@@ -57,4 +58,5 @@
     android.providers.settings.SettingsServiceDumpProto settings = 3002;
     android.service.appwidget.AppWidgetServiceDumpProto appwidget = 3003;
     android.service.notification.NotificationServiceDumpProto notification = 3004;
+    android.service.GraphicsStatsServiceDumpProto graphicsstats = 3005;
 }
diff --git a/core/java/com/android/internal/logging/legacy/Util.java b/core/proto/android/os/looper.proto
similarity index 66%
copy from core/java/com/android/internal/logging/legacy/Util.java
copy to core/proto/android/os/looper.proto
index 99f71ca..9fcc781 100644
--- a/core/java/com/android/internal/logging/legacy/Util.java
+++ b/core/proto/android/os/looper.proto
@@ -13,13 +13,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.internal.logging.legacy;
 
-/**
- * Created by cwren on 11/21/16.
- */
-public class Util {
-    public static boolean debug() {
-        return false;
-    }
+syntax = "proto3";
+
+package android.os;
+
+option java_multiple_files = true;
+
+import "frameworks/base/core/proto/android/os/messagequeue.proto";
+
+message LooperProto {
+    string thread_name = 1;
+    int64 thread_id = 2;
+    int32 identity_hash_code = 3;
+    android.os.MessageQueueProto queue = 4;
 }
diff --git a/core/proto/android/os/message.proto b/core/proto/android/os/message.proto
new file mode 100644
index 0000000..604935d
--- /dev/null
+++ b/core/proto/android/os/message.proto
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+syntax = "proto3";
+
+package android.os;
+
+option java_multiple_files = true;
+
+message MessageProto {
+    int64 when = 1;
+    // Name of callback class.
+    string callback = 2;
+    // User-defined message code so that the recipient can identify what this
+    // message is about.
+    int32 what = 3;
+    int32 arg1 = 4;
+    int32 arg2 = 5;
+    // String representation of an arbitrary object to send to the recipient.
+    string obj = 6;
+    // Name of target class.
+    string target = 7;
+    int32 barrier = 8;
+}
diff --git a/core/java/com/android/internal/logging/legacy/Util.java b/core/proto/android/os/messagequeue.proto
similarity index 68%
copy from core/java/com/android/internal/logging/legacy/Util.java
copy to core/proto/android/os/messagequeue.proto
index 99f71ca..9bff13e 100644
--- a/core/java/com/android/internal/logging/legacy/Util.java
+++ b/core/proto/android/os/messagequeue.proto
@@ -13,13 +13,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.internal.logging.legacy;
 
-/**
- * Created by cwren on 11/21/16.
- */
-public class Util {
-    public static boolean debug() {
-        return false;
-    }
+syntax = "proto3";
+
+package android.os;
+
+option java_multiple_files = true;
+
+import "frameworks/base/core/proto/android/os/message.proto";
+
+message MessageQueueProto {
+    repeated android.os.MessageProto messages = 1;
+    bool is_polling_locked = 2;
+    bool is_quitting = 3;
 }
diff --git a/core/java/com/android/internal/logging/legacy/Util.java b/core/proto/android/os/worksource.proto
similarity index 70%
copy from core/java/com/android/internal/logging/legacy/Util.java
copy to core/proto/android/os/worksource.proto
index 99f71ca..c2aa5cb 100644
--- a/core/java/com/android/internal/logging/legacy/Util.java
+++ b/core/proto/android/os/worksource.proto
@@ -13,13 +13,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.internal.logging.legacy;
 
-/**
- * Created by cwren on 11/21/16.
- */
-public class Util {
-    public static boolean debug() {
-        return false;
+syntax = "proto3";
+
+package android.os;
+
+option java_multiple_files = true;
+
+message WorkSourceProto {
+    message WorkSourceContentProto {
+        int32 uid = 1;
+        string name = 2;
     }
-}
+
+    repeated WorkSourceContentProto work_source_contents = 1;
+}
\ No newline at end of file
diff --git a/core/proto/android/service/graphicsstats.proto b/core/proto/android/service/graphicsstats.proto
new file mode 100644
index 0000000..6dbfe48
--- /dev/null
+++ b/core/proto/android/service/graphicsstats.proto
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+syntax = "proto3";
+
+package android.service;
+
+option java_multiple_files = true;
+option java_outer_classname = "GraphicsStatsServiceProto";
+
+message GraphicsStatsServiceDumpProto {
+    repeated GraphicsStatsProto stats = 1;
+}
+
+message GraphicsStatsProto {
+
+    // The package name of the app
+    string package_name = 1;
+
+    // The version code of the app
+    int32 version_code = 2;
+
+    // The start & end timestamps in UTC as
+    // milliseconds since January 1, 1970
+    // Compatible with java.util.Date#setTime()
+    int64 stats_start = 3;
+    int64 stats_end = 4;
+
+    // The aggregated statistics for the package
+    GraphicsStatsJankSummaryProto summary = 5;
+
+    // The frame time histogram for the package
+    repeated GraphicsStatsHistogramBucketProto histogram = 6;
+}
+
+message GraphicsStatsJankSummaryProto {
+    // Distinct frame count.
+    int32 total_frames = 1;
+
+    // Number of frames with slow render time. Frames are considered janky if
+    // they took more than a vsync interval (typically 16.667ms) to be rendered.
+    int32 janky_frames = 2;
+
+    // Number of "missed vsync" events.
+    int32 missed_vsync_count = 3;
+
+    // Number of "high input latency" events.
+    int32 high_input_latency_count = 4;
+
+    // Number of "slow UI thread" events.
+    int32 slow_ui_thread_count = 5;
+
+    // Number of "slow bitmap upload" events.
+    int32 slow_bitmap_upload_count = 6;
+
+    // Number of "slow draw" events.
+    int32 slow_draw_count = 7;
+}
+
+message GraphicsStatsHistogramBucketProto {
+    // Lower bound of render time in milliseconds.
+    int32 render_millis = 1;
+    // Number of frames in the bucket.
+    int32 frame_count = 2;
+}
diff --git a/core/proto/android/service/package.proto b/core/proto/android/service/package.proto
new file mode 100644
index 0000000..326b0eb
--- /dev/null
+++ b/core/proto/android/service/package.proto
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+
+syntax = "proto3";
+
+package android.service.pm;
+
+option java_multiple_files = true;
+option java_outer_classname = "PackageServiceProto";
+
+message PackageServiceDumpProto {
+    message PackageShortProto {
+        // Name of package. e.g. "com.android.providers.telephony".
+        string name = 1;
+        // UID for this package as assigned by Android OS.
+        int32 uid = 2;
+    }
+    message SharedLibraryProto {
+        string name = 1;
+        // True if library path is not null (jar), false otherwise (apk)
+        bool is_jar = 2;
+        // Should be filled if is_jar is true
+        string path = 3;
+        // Should be filled if is_jar is false
+        string apk = 4;
+    }
+    message FeatureProto {
+        string name = 1;
+        int32 version = 2;
+    }
+    message SharedUserProto {
+        int32 user_id = 1;
+        string name = 2;
+    }
+
+    // Installed packages.
+    PackageShortProto required_verifier_package = 1;
+    PackageShortProto verifier_package = 2;
+    repeated SharedLibraryProto shared_libraries = 3;
+    repeated FeatureProto features = 4;
+    repeated PackageProto packages = 5;
+    repeated SharedUserProto shared_users = 6;
+    // Messages from the settings problem file
+    repeated string messages = 7;
+}
+
+message PackageProto {
+    message SplitProto {
+        string name = 1;
+        int32 revision_code = 2;
+    }
+    message UserInfoProto {
+        enum InstallType {
+            NOT_INSTALLED_FOR_USER = 0;
+            FULL_APP_INSTALL = 1;
+            INSTANT_APP_INSTALL = 2;
+        }
+        // Enum values gotten from PackageManger.java
+        enum EnabledState {
+            // This component or application is in its default enabled state
+            // (as specified in its manifest).
+            COMPONENT_ENABLED_STATE_DEFAULT = 0;
+            // This component or application has been explictily enabled, regardless
+            // of what it has specified in its manifest.
+            COMPONENT_ENABLED_STATE_ENABLED = 1;
+            // This component or application has been explicitly disabled, regardless of
+            // what it has specified in its manifest.
+            COMPONENT_ENABLED_STATE_DISABLED = 2;
+            // The user has explicitly disabled the application, regardless of what it has
+            // specified in its manifest.
+            COMPONENT_ENABLED_STATE_DISABLED_USER = 3;
+            // This application should be considered, until the point where the user actually
+            // wants to use it.
+            COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED = 4;
+        }
+
+        int32 id = 1;
+        InstallType install_type = 2;
+        // Is the app restricted by owner / admin
+        bool is_hidden = 3;
+        bool is_suspended = 4;
+        bool is_stopped = 5;
+        bool is_launched = 6;
+        EnabledState enabled_state = 7;
+        string last_disabled_app_caller = 8;
+    }
+
+    // Name of package. e.g. "com.android.providers.telephony".
+    string name = 1;
+    // UID for this package as assigned by Android OS.
+    int32 uid = 2;
+    // Package's reported version.
+    int32 version_code = 3;
+    // Package's reported version string (what's displayed to the user).
+    string version_string = 4;
+    // UTC timestamp of install
+    int64 install_time_ms = 5;
+    // Millisecond UTC timestamp of latest update adjusted to Google's server clock.
+    int64 update_time_ms = 6;
+    // From "dumpsys package" - name of package which installed this one.
+    // Typically "" if system app or "com.android.vending" if Play Store.
+    string installer_name = 7;
+    // Split APKs.
+    repeated SplitProto splits = 8;
+    // Per-user package info.
+    repeated UserInfoProto users = 9;
+}
diff --git a/core/proto/android/service/power.proto b/core/proto/android/service/power.proto
new file mode 100644
index 0000000..1830dbf
--- /dev/null
+++ b/core/proto/android/service/power.proto
@@ -0,0 +1,408 @@
+/*
+ * 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.
+ */
+
+syntax = "proto3";
+
+package android.service.power;
+
+option java_multiple_files = true;
+option java_outer_classname = "PowerServiceProto";
+
+import "frameworks/base/core/proto/android/os/looper.proto";
+import "frameworks/base/core/proto/android/os/worksource.proto";
+import "frameworks/base/core/proto/android/service/wirelesschargerdetector.proto";
+
+message PowerServiceDumpProto {
+    message ConstantsProto {
+        bool is_no_cached_wake_locks = 1;
+    }
+    message ActiveWakeLocksProto {
+        bool is_cpu = 1;
+        bool is_screen_bright = 2;
+        bool is_screen_dim = 3;
+        bool is_button_bright = 4;
+        bool is_proximity_screen_off = 5;
+        // only set if already awake
+        bool is_stay_awake = 6;
+        bool is_doze = 7;
+        bool is_draw = 8;
+    }
+    message UserActivityProto {
+        bool is_screen_bright = 1;
+        bool is_screen_dim = 2;
+        bool is_screen_dream = 3;
+    }
+    message UidProto {
+        // Enum values gotten from ActivityManager.java
+        enum ProcessState {
+            // Process is a persistent system process.
+            PROCESS_STATE_PERSISTENT = 0;
+            // Process is a persistent system process and is doing UI.
+            PROCESS_STATE_PERSISTENT_UI = 1;
+            // Process is hosting the current top activities. Note that this
+            // covers all activities that are visible to the user.
+            PROCESS_STATE_TOP = 2;
+            // Process is hosting a foreground service due to a system binding.
+            PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 3;
+            // Process is hosting a foreground service.
+            PROCESS_STATE_FOREGROUND_SERVICE = 4;
+            // Same as {@link #PROCESS_STATE_TOP} but while device is sleeping.
+            PROCESS_STATE_TOP_SLEEPING = 5;
+            // Process is important to the user, and something they are aware of.
+            PROCESS_STATE_IMPORTANT_FOREGROUND = 6;
+            // Process is important to the user, but not something they are aware of.
+            PROCESS_STATE_IMPORTANT_BACKGROUND = 7;
+            // Process is in the background running a backup/restore operation.
+            PROCESS_STATE_BACKUP = 8;
+            // Process is in the background, but it can't restore its state so
+            // we want to try to avoid killing it.
+            PROCESS_STATE_HEAVY_WEIGHT = 9;
+            // Process is in the background running a service.
+            PROCESS_STATE_SERVICE = 10;
+            // Process is in the background running a receiver.
+            PROCESS_STATE_RECEIVER = 11;
+            // Process is in the background but hosts the home activity.
+            PROCESS_STATE_HOME = 12;
+            // Process is in the background but hosts the last shown activity.
+            PROCESS_STATE_LAST_ACTIVITY = 13;
+            // Process is being cached for later use and contains activities.
+            PROCESS_STATE_CACHED_ACTIVITY = 14;
+            // Process is being cached for later use and is a client of another
+            // cached process that contains activities.
+            PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 15;
+            // Process is being cached for later use and is empty.
+            PROCESS_STATE_CACHED_EMPTY = 16;
+            // Process does not exist.
+            PROCESS_STATE_NONEXISTENT = 17;
+        }
+        int32 uid = 1;
+        string uid_string = 2;
+        bool is_active = 3;
+        int32 num_wake_locks = 4;
+        bool is_process_state_unknown = 5;
+        ProcessState process_state = 6;
+    }
+
+    // Enum values gotten from PowerManagerInternal.java
+    enum Wakefulness {
+        WAKEFULNESS_ASLEEP = 0;
+        WAKEFULNESS_AWAKE = 1;
+        WAKEFULNESS_DREAMING = 2;
+        WAKEFULNESS_DOZING = 3;
+        WAKEFULNESS_UNKNOWN = 4;
+    }
+    // Enum values gotten from BatteryManager.java
+    enum PlugType {
+        PLUG_TYPE_NONE = 0;
+        PLUG_TYPE_PLUGGED_AC = 1;
+        PLUG_TYPE_PLUGGED_USB = 2;
+        PLUG_TYPE_PLUGGED_WIRELESS = 4;
+    }
+    // Enum values gotten from Intent.java
+    enum DockState {
+        DOCK_STATE_UNDOCKED = 0;
+        DOCK_STATE_DESK = 1;
+        DOCK_STATE_CAR = 2;
+        DOCK_STATE_LE_DESK = 3;
+        DOCK_STATE_HE_DESK = 4;
+    }
+
+    ConstantsProto constants = 1;
+    // A bitfield that indicates what parts of the power state have
+    // changed and need to be recalculated.
+    int32 dirty = 2;
+    // Indicates whether the device is awake or asleep or somewhere in between.
+    Wakefulness wakefulness = 3;
+    bool is_wakefulness_changing = 4;
+    // True if the device is plugged into a power source.
+    bool is_powered = 5;
+    // The current plug type
+    PlugType plug_type = 6;
+    // The current battery level percentage.
+    int32 battery_level = 7;
+    // The battery level percentage at the time the dream started.
+    int32 battery_level_when_dream_started = 8;
+    // The current dock state.
+    DockState dock_state = 9;
+    // True if the device should stay on.
+    bool is_stay_on = 10;
+    // True if the proximity sensor reads a positive result.
+    bool is_proximity_positive = 11;
+    // True if boot completed occurred.  We keep the screen on until this happens.
+    bool is_boot_completed = 12;
+    // True if systemReady() has been called.
+    bool is_system_ready = 13;
+    // True if auto-suspend mode is enabled.
+    bool is_hal_auto_suspend_mode_enabled = 14;
+    // True if interactive mode is enabled.
+    bool is_hal_auto_interactive_mode_enabled = 15;
+    // Summarizes the state of all active wakelocks.
+    ActiveWakeLocksProto active_wake_locks = 16;
+    // Have we scheduled a message to check for long wake locks?  This is when
+    // we will check. (In milliseconds timestamp)
+    int64 notify_long_scheduled_ms = 17;
+    // Last time we checked for long wake locks. (In milliseconds timestamp)
+    int64 notify_long_dispatched_ms = 18;
+    // The time we decided to do next long check. (In milliseconds timestamp)
+    int64 notify_long_next_check_ms = 19;
+    // Summarizes the effect of the user activity timer.
+    UserActivityProto user_activity = 20;
+    // If true, instructs the display controller to wait for the proximity
+    // sensor to go negative before turning the screen on.
+    bool is_request_wait_for_negative_proximity = 21;
+    // True if MSG_SANDMAN has been scheduled.
+    bool is_sandman_scheduled = 22;
+    // True if the sandman has just been summoned for the first time since entering
+    // the dreaming or dozing state.  Indicates whether a new dream should begin.
+    bool is_sandman_summoned = 23;
+    // If true, the device is in low power mode.
+    bool is_low_power_mode_enabled = 24;
+    // True if the battery level is currently considered low.
+    bool is_battery_level_low = 25;
+    // True if we are currently in light device idle mode.
+    bool is_light_device_idle_mode = 26;
+    // True if we are currently in device idle mode.
+    bool is_device_idle_mode = 27;
+    // Set of app ids that we will always respect the wake locks for.
+    repeated int32 device_idle_whitelist = 28;
+    // Set of app ids that are temporarily allowed to acquire wakelocks due to
+    // high-pri message
+    repeated int32 device_idle_temp_whitelist = 29;
+    // Timestamp of the last time the device was awoken.
+    int64 last_wake_time_ms = 30;
+    // Timestamp of the last time the device was put to sleep.
+    int64 last_sleep_time_ms = 31;
+    // Timestamp of the last call to user activity.
+    int64 last_user_activity_time_ms = 32;
+    int64 last_user_activity_time_no_change_lights_ms = 33;
+    // Timestamp of last interactive power hint.
+    int64 last_interactive_power_hint_time_ms = 34;
+    // Timestamp of the last screen brightness boost.
+    int64 last_screen_brightness_boost_time_ms = 35;
+    // True if screen brightness boost is in progress.
+    bool is_screen_brightness_boost_in_progress = 36;
+    // True if the display power state has been fully applied, which means the
+    // display is actually on or actually off or whatever was requested.
+    bool is_display_ready = 37;
+    // True if the wake lock suspend blocker has been acquired.
+    bool is_holding_wake_lock_suspend_blocker = 38;
+    // The suspend blocker used to keep the CPU alive when the display is on, the
+    // display is getting ready or there is user activity (in which case the
+    // display must be on).
+    bool is_holding_display_suspend_blocker = 39;
+    // Settings and configuration
+    PowerServiceSettingsAndConfigurationDumpProto settings_and_configuration = 40;
+    // Sleep timeout in ms
+    sint32 sleep_timeout_ms = 41;
+    // Screen off timeout in ms
+    int32 screen_off_timeout_ms = 42;
+    // Screen dim duration in ms
+    int32 screen_dim_duration_ms = 43;
+    // We are currently in the middle of a batch change of uids.
+    bool are_uids_changing = 44;
+    // Some uids have actually changed while mUidsChanging was true.
+    bool are_uids_changed = 45;
+    // List of UIDs and their states
+    repeated UidProto uids = 46;
+    android.os.LooperProto looper = 47;
+    // List of all wake locks acquired by applications.
+    repeated WakeLockProto wake_locks = 48;
+    // List of all suspend blockers.
+    repeated SuspendBlockerProto suspend_blockers = 49;
+    WirelessChargerDetectorProto wireless_charger_detector = 50;
+}
+
+message SuspendBlockerProto {
+    string name = 1;
+    int32 reference_count = 2;
+}
+
+message WakeLockProto {
+    message WakeLockFlagsProto {
+        // Turn the screen on when the wake lock is acquired.
+        bool is_acquire_causes_wakeup = 1;
+        // When this wake lock is released, poke the user activity timer
+        // so the screen stays on for a little longer.
+        bool is_on_after_release = 2;
+    }
+
+    // Enum values gotten from PowerManager.java
+    enum LockLevel {
+        WAKE_LOCK_INVALID = 0;
+        // Ensures that the CPU is running.
+        PARTIAL_WAKE_LOCK = 1;
+        // Ensures that the screen is on (but may be dimmed).
+        SCREEN_DIM_WAKE_LOCK = 6;
+        // Ensures that the screen is on at full brightness.
+        SCREEN_BRIGHT_WAKE_LOCK = 10;
+        // Ensures that the screen and keyboard backlight are on at full brightness.
+        FULL_WAKE_LOCK = 26;
+        // Turns the screen off when the proximity sensor activates.
+        PROXIMITY_SCREEN_OFF_WAKE_LOCK = 32;
+        // Put the screen in a low power state and allow the CPU to suspend
+        // if no other wake locks are held.
+        DOZE_WAKE_LOCK = 64;
+        // Keep the device awake enough to allow drawing to occur.
+        DRAW_WAKE_LOCK = 128;
+    }
+
+    LockLevel lock_level = 1;
+    string tag = 2;
+    WakeLockFlagsProto flags = 3;
+    bool is_disabled = 4;
+    // Acquire time in ms
+    int64 acq_ms = 5;
+    bool is_notified_long = 6;
+    // Owner UID
+    int32 uid = 7;
+    // Owner PID
+    int32 pid = 8;
+    android.os.WorkSourceProto work_source = 9;
+}
+
+message PowerServiceSettingsAndConfigurationDumpProto {
+    message StayOnWhilePluggedInProto {
+        bool is_stay_on_while_plugged_in_ac = 1;
+        bool is_stay_on_while_plugged_in_usb = 2;
+        bool is_stay_on_while_plugged_in_wireless = 3;
+    }
+    message ScreenBrightnessSettingLimitsProto {
+        int32 setting_minimum = 1;
+        int32 setting_maximum = 2;
+        int32 setting_default = 3;
+        int32 setting_for_vr_default = 4;
+    }
+
+    // Enum values gotten from Settings.java
+    enum ScreenBrightnessMode {
+        SCREEN_BRIGHTNESS_MODE_MANUAL = 0;
+        SCREEN_BRIGHTNESS_MODE_AUTOMATIC = 1;
+    }
+    // Enum values gotten from Display.java
+    enum DisplayState {
+        DISPLAY_STATE_UNKNOWN = 0;
+        DISPLAY_STATE_OFF = 1;
+        DISPLAY_STATE_ON = 2;
+        DISPLAY_STATE_DOZE = 3;
+        DISPLAY_STATE_DOZE_SUSPEND = 4;
+        DISPLAY_STATE_VR = 5;
+    }
+
+
+    // True to decouple auto-suspend mode from the display state.
+    bool is_decouple_hal_auto_suspend_mode_from_display_config = 1;
+    // True to decouple interactive mode from the display state.
+    bool is_decouple_hal_interactive_mode_from_display_config = 2;
+    // True if the device should wake up when plugged or unplugged.
+    bool is_wake_up_when_plugged_or_unplugged_config = 3;
+    // True if the device should wake up when plugged or unplugged in theater mode.
+    bool is_wake_up_when_plugged_or_unplugged_in_theater_mode_config = 4;
+    // True if theater mode is enabled
+    bool is_theater_mode_enabled = 5;
+    // True if the device should suspend when the screen is off due to proximity.
+    bool is_suspend_when_screen_off_due_to_proximity_config = 6;
+    // True if dreams are supported on this device.
+    bool are_dreams_supported_config = 7;
+    // Default value for dreams enabled
+    bool are_dreams_enabled_by_default_config = 8;
+    // Default value for dreams activate-on-sleep
+    bool are_dreams_activated_on_sleep_by_default_config = 9;
+    // Default value for dreams activate-on-dock
+    bool are_dreams_activated_on_dock_by_default_config = 10;
+    // True if dreams can run while not plugged in.
+    bool are_dreams_enabled_on_battery_config = 11;
+    // Minimum battery level to allow dreaming when powered.
+    // Use -1 to disable this safety feature.
+    sint32 dreams_battery_level_minimum_when_powered_config = 12;
+    // Minimum battery level to allow dreaming when not powered.
+    // Use -1 to disable this safety feature.
+    sint32 dreams_battery_level_minimum_when_not_powered_config = 13;
+    // If the battery level drops by this percentage and the user activity
+    // timeout has expired, then assume the device is receiving insufficient
+    // current to charge effectively and terminate the dream.  Use -1 to disable
+    // this safety feature.
+    sint32 dreams_battery_level_drain_cutoff_config = 14;
+    // True if dreams are enabled by the user.
+    bool are_dreams_enabled_setting = 15;
+    // True if dreams should be activated on sleep.
+    bool are_dreams_activate_on_sleep_setting = 16;
+    // True if dreams should be activated on dock.
+    bool are_dreams_activate_on_dock_setting = 17;
+    // True if doze should not be started until after the screen off transition.
+    bool is_doze_after_screen_off_config = 18;
+    // If true, the device is in low power mode.
+    bool is_low_power_mode_setting = 19;
+    // Current state of whether the settings are allowing auto low power mode.
+    bool is_auto_low_power_mode_configured = 20;
+    // The user turned off low power mode below the trigger level
+    bool is_auto_low_power_mode_snoozing = 21;
+    // The minimum screen off timeout, in milliseconds.
+    int32 minimum_screen_off_timeout_config_ms = 22;
+    // The screen dim duration, in milliseconds.
+    int32 maximum_screen_dim_duration_config_ms = 23;
+    // The maximum screen dim time expressed as a ratio relative to the screen off timeout.
+    float maximum_screen_dim_ratio_config = 24;
+    // The screen off timeout setting value in milliseconds.
+    int32 screen_off_timeout_setting_ms = 25;
+    // The sleep timeout setting value in milliseconds.
+    sint32 sleep_timeout_setting_ms = 26;
+    // The maximum allowable screen off timeout according to the device administration policy.
+    int32 maximum_screen_off_timeout_from_device_admin_ms = 27;
+    bool is_maximum_screen_off_timeout_from_device_admin_enforced_locked = 28;
+    // The stay on while plugged in setting.
+    // A set of battery conditions under which to make the screen stay on.
+    StayOnWhilePluggedInProto stay_on_while_plugged_in = 29;
+    // The screen brightness setting, from 0 to 255.
+    // Use -1 if no value has been set.
+    sint32 screen_brightness_setting = 30;
+    // The screen auto-brightness adjustment setting, from -1 to 1.
+    // Use 0 if there is no adjustment.
+    float screen_auto_brightness_adjustment_setting = 31;
+    // The screen brightness mode.
+    ScreenBrightnessMode screen_brightness_mode_setting = 32;
+    // The screen brightness setting override from the window manager
+    // to allow the current foreground activity to override the brightness.
+    // Use -1 to disable.
+    sint32 screen_brightness_override_from_window_manager = 33;
+    // The user activity timeout override from the window manager
+    // to allow the current foreground activity to override the user activity
+    // timeout. Use -1 to disable.
+    sint64 user_activity_timeout_override_from_window_manager_ms = 34;
+    // The window manager has determined the user to be inactive via other means.
+    // Set this to false to disable.
+    bool is_user_inactive_override_from_window_manager = 35;
+    // The screen brightness setting override from the settings application
+    // to temporarily adjust the brightness until next updated,
+    // Use -1 to disable.
+    sint32 temporary_screen_brightness_setting_override = 36;
+    // The screen brightness adjustment setting override from the settings
+    // application to temporarily adjust the auto-brightness adjustment factor
+    // until next updated, in the range -1..1.
+    // Use NaN to disable.
+    float temporary_screen_auto_brightness_adjustment_setting_override = 37;
+    // The screen state to use while dozing.
+    DisplayState doze_screen_state_override_from_dream_manager = 38;
+    // The screen brightness to use while dozing.
+    float dozed_screen_brightness_override_from_dream_manager = 39;
+    // Screen brightness settings limits.
+    ScreenBrightnessSettingLimitsProto screen_brightness_setting_limits = 40;
+    // The screen brightness setting, from 0 to 255, to be used while in VR Mode.
+    int32 screen_brightness_for_vr_setting = 41;
+    // True if double tap to wake is enabled
+    bool is_double_tap_wake_enabled = 42;
+    // True if we are currently in VR Mode.
+    bool is_vr_mode_enabled = 43;
+}
diff --git a/core/proto/android/service/wirelesschargerdetector.proto b/core/proto/android/service/wirelesschargerdetector.proto
new file mode 100644
index 0000000..7ba7c17
--- /dev/null
+++ b/core/proto/android/service/wirelesschargerdetector.proto
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+syntax = "proto3";
+
+package android.service.power;
+
+option java_multiple_files = true;
+
+message WirelessChargerDetectorProto {
+    message VectorProto {
+        float x = 1;
+        float y = 2;
+        float z = 3;
+    }
+
+    // Previously observed wireless power state.
+    bool is_powered_wirelessly = 1;
+    // True if the device is thought to be at rest on a wireless charger.
+    bool is_at_rest = 2;
+    // The gravity vector most recently observed while at rest.
+    VectorProto rest = 3;
+    // True if detection is in progress.
+    bool is_detection_in_progress = 4;
+    // The time when detection was last performed.
+    int64 detection_start_time_ms = 5;
+    // True if the rest position should be updated if at rest.
+    bool is_must_update_rest_position = 6;
+    // The total number of samples collected.
+    int32 total_samples = 7;
+    // The number of samples collected that showed evidence of not being at rest.
+    int32 moving_samples = 8;
+    // The value of the first sample that was collected.
+    VectorProto first_sample = 9;
+    // The value of the last sample that was collected.
+    VectorProto last_sample = 10;
+}
\ No newline at end of file
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 3ca2208..c2a2e69 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -520,6 +520,9 @@
     <!-- TODO: temporary broadcast used by AutoFillManagerServiceImpl; will be removed -->
     <protected-broadcast android:name="com.android.internal.autofill.action.REQUEST_AUTOFILL" />
     <protected-broadcast android:name="android.app.action.APPLICATION_DELEGATION_SCOPES_CHANGED" />
+    <protected-broadcast android:name="com.android.server.wm.ACTION_REVOKE_SYSTEM_ALERT_WINDOW_PERMISSION" />
+
+    <protected-broadcast android:name="android.content.pm.action.SESSION_COMMITTED" />
 
     <!-- ====================================================================== -->
     <!--                          RUNTIME PERMISSIONS                           -->
@@ -894,6 +897,17 @@
         android:description="@string/permdesc_processOutgoingCalls"
         android:protectionLevel="dangerous" />
 
+
+    <!-- Allows the app to answer an incoming phone call.
+         <p>Protection level: dangerous
+    -->
+    <permission android:name="android.permission.ANSWER_PHONE_CALLS"
+        android:permissionGroup="android.permission-group.PHONE"
+        android:label="@string/permlab_answerPhoneCalls"
+        android:description="@string/permdesc_answerPhoneCalls"
+        android:protectionLevel="dangerous" />
+
+
     <!-- ====================================================================== -->
     <!-- Permissions for accessing the device microphone                        -->
     <!-- ====================================================================== -->
@@ -1271,7 +1285,7 @@
     <permission android:name="android.permission.SCORE_NETWORKS"
         android:protectionLevel="signature|privileged" />
 
-    <!-- @SystemApi Allows applications to request network
+    <!-- Allows applications to request network
          recommendations and scores from the NetworkScoreService.
          <p>Not for use by third-party applications. @hide -->
     <permission android:name="android.permission.REQUEST_NETWORK_SCORES"
@@ -1794,7 +1808,7 @@
     <eat-comment />
 
     <!-- Allows an app to create windows using the type
-         {@link android.view.WindowManager.LayoutParams#TYPE_SYSTEM_ALERT},
+         {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY},
          shown on top of all other apps.  Very few apps
          should use this permission; these windows are intended for
          system-level interaction with the user.
@@ -2137,7 +2151,7 @@
          runtime resource overlays.
          @hide -->
     <permission android:name="android.permission.CHANGE_OVERLAY_PACKAGES"
-        android:protectionLevel="signature|privileged|development" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- ========================================= -->
     <!-- Permissions for special development tools -->
@@ -3108,6 +3122,13 @@
     <permission android:name="android.permission.BIND_DREAM_SERVICE"
         android:protectionLevel="signature" />
 
+    <!-- Must be required by an {@link android.app.usage.CacheQuotaService} to ensure that only the
+         system can bind to it.
+         @hide This is not a third-party API (intended for OEMs and system apps).
+    -->
+    <permission android:name="android.permission.BIND_CACHE_QUOTA_SERVICE"
+                android:protectionLevel="signature" />
+
     <!-- @SystemApi Allows an application to call into a carrier setup flow. It is up to the
          carrier setup application to enforce that this permission is required
          @hide This is not a third-party API (intended for OEMs and system apps). -->
@@ -3205,7 +3226,7 @@
     <!-- Allows the holder to access the instant applications on the device.
     @hide -->
     <permission android:name="android.permission.ACCESS_INSTANT_APPS"
-            android:protectionLevel="signature|installer" />
+            android:protectionLevel="signature|installer|verifier" />
 
     <!-- Allows receiving the usage of media resource e.g. video/audio codec and
          graphic memory.
@@ -3481,7 +3502,7 @@
         <receiver android:name="com.android.server.updates.ApnDbInstallReceiver"
                 android:permission="android.permission.UPDATE_CONFIG">
             <intent-filter>
-                <action android:name="android.intent.action.UPDATE_APN_DB" />
+                <action android:name="com.android.internal.intent.action.UPDATE_APN_DB" />
                 <data android:scheme="content" android:host="*" android:mimeType="*/*" />
             </intent-filter>
         </receiver>
diff --git a/core/res/res/drawable-ldpi/sym_def_app_icon.png b/core/res/res/drawable-ldpi/sym_def_app_icon.png
deleted file mode 100644
index 2c205c8..0000000
--- a/core/res/res/drawable-ldpi/sym_def_app_icon.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-nodpi/alert_window_layer.xml b/core/res/res/drawable-nodpi/alert_window_layer.xml
new file mode 100644
index 0000000..f9b38c8
--- /dev/null
+++ b/core/res/res/drawable-nodpi/alert_window_layer.xml
@@ -0,0 +1,24 @@
+<!--
+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="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+<path
+        android:fillColor="#FF000000"
+        android:pathData="M11.99,18.54l-7.37,-5.73L3,14.07l9,7 9,-7 -1.63,-1.27 -7.38,5.74zM12,16l7.36,-5.73L21,9l-9,-7 -9,7 1.63,1.27L12,16z"/>
+</vector>
diff --git a/core/res/res/drawable-xxxhdpi/sym_def_app_icon.png b/core/res/res/drawable-xxxhdpi/sym_def_app_icon.png
deleted file mode 100644
index aee44e1..0000000
--- a/core/res/res/drawable-xxxhdpi/sym_def_app_icon.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable/scrollbar_handle_material.xml b/core/res/res/drawable/scrollbar_handle_material.xml
index 33efbba..f020112 100644
--- a/core/res/res/drawable/scrollbar_handle_material.xml
+++ b/core/res/res/drawable/scrollbar_handle_material.xml
@@ -19,7 +19,4 @@
        android:shape="rectangle">
     <solid
         android:color="#84ffffff" />
-    <size
-        android:width="4dp"
-        android:height="4dp" />
 </shape>
diff --git a/core/res/res/drawable/sym_def_app_icon.xml b/core/res/res/drawable/sym_def_app_icon.xml
new file mode 100644
index 0000000..8a2b13b
--- /dev/null
+++ b/core/res/res/drawable/sym_def_app_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@android:color/white" />
+    <foreground android:drawable="@mipmap/sym_def_app_icon_maskable" />
+</adaptive-icon>
diff --git a/core/res/res/layout/app_permission_item_money.xml b/core/res/res/layout/app_permission_item_money.xml
index 2056285..764c883 100644
--- a/core/res/res/layout/app_permission_item_money.xml
+++ b/core/res/res/layout/app_permission_item_money.xml
@@ -57,14 +57,14 @@
             android:layout_alignParentStart="true"
             android:layout_alignBottom="@+id/perm_money_label"
             android:scaleType="fitCenter"
-            android:tint="@color/perms_costs_money"
+            android:tint="?android:attr/colorError"
             android:tintMode="src_in"
             android:src="@android:drawable/ic_coins_s" />
         <TextView
             android:id="@+id/perm_money_label"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:textSize="16sp"
-            android:textColor="@color/perms_costs_money"
+            android:textColor="?android:attr/colorError"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_toEndOf="@id/perm_money_icon"
diff --git a/core/res/res/layout/autofill_dataset_picker.xml b/core/res/res/layout/autofill_dataset_picker.xml
new file mode 100644
index 0000000..9b90de6
--- /dev/null
+++ b/core/res/res/layout/autofill_dataset_picker.xml
@@ -0,0 +1,23 @@
+<?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.
+-->
+
+<ListView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/autofill_dataset_picker"
+    android:layout_width="wrap_content"
+    android:layout_height="fill_parent"
+    android:divider="?android:attr/listDivider"
+    android:background="#ffffffff">
+</ListView>
diff --git a/core/res/res/layout/autofill_save.xml b/core/res/res/layout/autofill_save.xml
index d55a012..a6892c6 100644
--- a/core/res/res/layout/autofill_save.xml
+++ b/core/res/res/layout/autofill_save.xml
@@ -14,44 +14,87 @@
      limitations under the License.
 -->
 
-<!-- TODO(b/33197203) remove hardcoded color once color is final -->
-<RelativeLayout
+<LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
+    android:id="@+id/autofill_save"
+    android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:paddingStart="16dip"
     android:paddingEnd="16dip"
     android:paddingTop="16dip"
     android:paddingBottom="16dip"
-    android:background="#FDF8C8">
+    android:elevation="16dp"
+    android:background="?android:attr/colorBackground"
+    android:orientation="vertical">
 
-  <!-- TODO(b/33197203) use.R.string once final wording is done -->
-  <TextView
-      android:id="@+id/autofill_save_title"
-      android:layout_width="match_parent"
-      android:layout_height="wrap_content"
-      android:text="Save for autofill?"
-      android:singleLine="true"/>
+    <LinearLayout
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal">
 
-  <TextView
-      android:id="@+id/autofill_save_no"
-      android:layout_width="wrap_content"
-      android:layout_height="wrap_content"
-      android:layout_below="@+id/autofill_save_title"
-      android:layout_toLeftOf="@+id/autofill_save_yes"
-      android:layout_marginRight="16dip"
-      android:text="No thanks"
-      android:textAllCaps="true"
-      android:singleLine="true"/>
+        <TextView
+            android:id="@+id/autofill_save_title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/autofill_save_title"
+            android:singleLine="true">
+        </TextView>
+
+        <Space
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:layout_weight="1"
+            android:visibility="invisible" >
+        </Space>
+
+        <ImageView
+            android:id="@+id/autofill_save_close"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:src="@android:drawable/ic_close"
+            android:background="?android:attr/selectableItemBackgroundBorderless">
+        </ImageView>
+
+    </LinearLayout>
 
     <TextView
-      android:id="@+id/autofill_save_yes"
-      android:layout_width="wrap_content"
-      android:layout_height="wrap_content"
-      android:layout_below="@+id/autofill_save_title"
-      android:layout_alignParentRight="true"
-      android:text="Save"
-      android:textAllCaps="true"
-      android:singleLine="true"/>
+        android:id="@+id/autofill_save_subtitle"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:visibility="invisible" >
+    </TextView>
 
-</RelativeLayout>
+    <com.android.internal.widget.ButtonBarLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="end"
+        android:layout_marginTop="16dp"
+        android:layout_weight="1"
+        android:orientation="horizontal">
+
+        <Space
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:layout_weight="1"
+            android:visibility="invisible" >
+        </Space>
+
+        <Button
+            android:id="@+id/autofill_save_no"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            style="?android:attr/buttonBarButtonStyle"
+            android:text="@string/autofill_save_no" >
+        </Button>
+
+        <Button
+            android:id="@+id/autofill_save_yes"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            style="?android:attr/buttonBarButtonStyle"
+            android:text="@string/autofill_save_yes" >
+        </Button>
+
+   </com.android.internal.widget.ButtonBarLayout>
+
+</LinearLayout>
diff --git a/core/res/res/layout/floating_popup_menu_button.xml b/core/res/res/layout/floating_popup_menu_button.xml
index 482f91f..6cbe8c8 100644
--- a/core/res/res/layout/floating_popup_menu_button.xml
+++ b/core/res/res/layout/floating_popup_menu_button.xml
@@ -15,21 +15,48 @@
 ** limitations under the License.
 */
 -->
-<Button xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="wrap_content"
-    android:layout_height="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal"
     android:minWidth="@dimen/floating_toolbar_menu_button_minimum_width"
     android:minHeight="@dimen/floating_toolbar_height"
     android:paddingStart="@dimen/floating_toolbar_menu_button_side_padding"
     android:paddingEnd="@dimen/floating_toolbar_menu_button_side_padding"
     android:paddingTop="0dp"
     android:paddingBottom="0dp"
-    android:layout_margin="0dp"
-    android:gravity="center"
-    android:singleLine="true"
-    android:ellipsize="end"
-    android:fontFamily="sans-serif-medium"
-    android:textSize="@dimen/floating_toolbar_text_size"
-    android:textAllCaps="true"
-    android:textColor="?attr/floatingToolbarForegroundColor"
-    android:background="?attr/floatingToolbarItemBackgroundDrawable" />
+    android:background="?attr/floatingToolbarItemBackgroundDrawable">
+    <ImageView
+        android:id="@+id/floating_toolbar_menu_item_image"
+        android:layout_width="@dimen/floating_toolbar_menu_image_width"
+        android:layout_height="@dimen/floating_toolbar_height"
+        android:paddingTop="@dimen/floating_toolbar_menu_image_button_vertical_padding"
+        android:paddingStart="0dp"
+        android:paddingBottom="@dimen/floating_toolbar_menu_image_button_vertical_padding"
+        android:paddingEnd="0dp"
+        android:layout_margin="0dp"
+        android:scaleType="centerInside"
+        android:background="@null"
+        android:focusable="false"
+        android:focusableInTouchMode="false"
+        android:importantForAccessibility="no" />
+    <TextView
+        android:id="@+id/floating_toolbar_menu_item_text"
+        android:layout_width="wrap_content"
+        android:layout_height="@dimen/floating_toolbar_height"
+        android:textAppearance="?android:attr/textAppearanceListItemSmall"
+        android:padding="0dp"
+        android:paddingStart="@dimen/floating_toolbar_menu_button_side_padding"
+        android:layout_margin="0dp"
+        android:gravity="center"
+        android:singleLine="true"
+        android:ellipsize="end"
+        android:fontFamily="sans-serif-medium"
+        android:textSize="@dimen/floating_toolbar_text_size"
+        android:textAllCaps="true"
+        android:textColor="?attr/floatingToolbarForegroundColor"
+        android:background="@null"
+        android:focusable="false"
+        android:focusableInTouchMode="false"
+        android:importantForAccessibility="no" />
+</LinearLayout>
diff --git a/core/res/res/layout/floating_popup_menu_image_button.xml b/core/res/res/layout/floating_popup_menu_image_button.xml
deleted file mode 100644
index 1ba7848..0000000
--- a/core/res/res/layout/floating_popup_menu_image_button.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* Copyright 2015, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:minWidth="@dimen/floating_toolbar_menu_image_button_width"
-    android:minHeight="@dimen/floating_toolbar_height"
-    android:focusable="false"
-    android:focusableInTouchMode="false"
-    android:importantForAccessibility="no">
-    <ImageButton
-        android:id="@+id/floating_toolbar_menu_item_image_button"
-        android:layout_width="@dimen/floating_toolbar_menu_image_button_width"
-        android:layout_height="@dimen/floating_toolbar_height"
-        android:paddingStart="@dimen/floating_toolbar_menu_button_side_padding"
-        android:paddingTop="@dimen/floating_toolbar_menu_image_button_vertical_padding"
-        android:paddingEnd="@dimen/floating_toolbar_menu_button_side_padding"
-        android:paddingBottom="@dimen/floating_toolbar_menu_image_button_vertical_padding"
-        android:scaleType="centerInside"
-        android:background="?attr/floatingToolbarItemBackgroundDrawable" />
-</LinearLayout>
diff --git a/core/res/res/layout/floating_popup_overflow_image_list_item.xml b/core/res/res/layout/floating_popup_overflow_image_list_item.xml
deleted file mode 100644
index fc04b31..0000000
--- a/core/res/res/layout/floating_popup_overflow_image_list_item.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* Copyright 2015, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:minWidth="@dimen/floating_toolbar_overflow_image_button_width"
-    android:minHeight="@dimen/floating_toolbar_height"
-    android:focusable="false"
-    android:focusableInTouchMode="false"
-    android:importantForAccessibility="no">
-    <ImageView
-        android:id="@+id/floating_toolbar_menu_item_image_button"
-        android:layout_width="@dimen/floating_toolbar_overflow_image_button_width"
-        android:layout_height="@dimen/floating_toolbar_height"
-        android:paddingTop="@dimen/floating_toolbar_menu_image_button_vertical_padding"
-        android:paddingStart="@dimen/floating_toolbar_overflow_side_padding"
-        android:paddingBottom="@dimen/floating_toolbar_menu_image_button_vertical_padding"
-        android:paddingEnd="@dimen/floating_toolbar_overflow_side_padding"
-        android:layout_margin="0dp"
-        android:scaleType="centerInside"/>
-</LinearLayout>
diff --git a/core/res/res/layout/floating_popup_overflow_list_item.xml b/core/res/res/layout/floating_popup_overflow_list_item.xml
deleted file mode 100644
index 22f4e68..0000000
--- a/core/res/res/layout/floating_popup_overflow_list_item.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* Copyright 2015, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:textAppearance="?android:attr/textAppearanceListItemSmall"
-    android:gravity="start|center_vertical"
-    android:minWidth="@dimen/floating_toolbar_menu_button_side_padding"
-    android:minHeight="@dimen/floating_toolbar_height"
-    android:paddingStart="@dimen/floating_toolbar_overflow_side_padding"
-    android:paddingEnd="@dimen/floating_toolbar_overflow_side_padding"
-    android:paddingTop="0dp"
-    android:paddingBottom="0dp"
-    android:layout_margin="0dp"
-    android:singleLine="true"
-    android:ellipsize="end"
-    android:fontFamily="sans-serif-medium"
-    android:textSize="@dimen/floating_toolbar_text_size"
-    android:textColor="?attr/floatingToolbarForegroundColor"
-    android:textAllCaps="true" />
-
diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml
index 0dfeb62..448cd2e 100644
--- a/core/res/res/layout/notification_template_header.xml
+++ b/core/res/res/layout/notification_template_header.xml
@@ -97,7 +97,7 @@
         android:layout_height="wrap_content"
         android:paddingTop="1dp"
         android:visibility="gone"
-        android:contentDescription="@string/expand_button_content_description"
+        android:contentDescription="@string/expand_button_content_description_collapsed"
         />
     <ImageView android:id="@+id/profile_badge"
         android:layout_width="@dimen/notification_badge_size"
diff --git a/core/res/res/layout/notification_template_material_messaging.xml b/core/res/res/layout/notification_template_material_messaging.xml
index b910211..fd5154a 100644
--- a/core/res/res/layout/notification_template_material_messaging.xml
+++ b/core/res/res/layout/notification_template_material_messaging.xml
@@ -24,7 +24,7 @@
     <LinearLayout
             android:id="@+id/notification_action_list_margin_target"
             android:layout_width="match_parent"
-            android:layout_height="match_parent"
+            android:layout_height="wrap_content"
             android:layout_gravity="top"
             android:layout_marginTop="@dimen/notification_content_margin_top"
             android:clipToPadding="false"
@@ -38,6 +38,7 @@
             android:paddingStart="@dimen/notification_content_margin_start"
             android:paddingEnd="@dimen/notification_content_margin_end"
             android:minHeight="@dimen/notification_min_content_height"
+            android:layout_marginBottom="@dimen/notification_content_margin_bottom"
             android:clipToPadding="false"
             android:orientation="vertical"
             >
@@ -49,7 +50,6 @@
                 android:id="@+id/notification_messaging"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:paddingBottom="@dimen/notification_content_margin_bottom"
                 android:spacing="@dimen/notification_messaging_spacing" >
                 <com.android.internal.widget.ImageFloatingTextView android:id="@+id/inbox_text0"
                     style="@style/Widget.Material.Notification.MessagingText"
diff --git a/core/res/res/layout/resolver_list.xml b/core/res/res/layout/resolver_list.xml
index c4e8e9c..40c9941 100644
--- a/core/res/res/layout/resolver_list.xml
+++ b/core/res/res/layout/resolver_list.xml
@@ -45,7 +45,7 @@
             android:textColor="?attr/colorAccent"
             android:gravity="center_vertical"
             android:layout_alignParentTop="true"
-            android:layout_alignParentRight="true"
+            android:layout_alignParentEnd="true"
             android:singleLine="true" />
 
         <TextView
@@ -59,7 +59,7 @@
             android:paddingEnd="?attr/dialogPreferredPadding"
             android:paddingTop="8dp"
             android:layout_below="@id/profile_button"
-            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
             android:paddingBottom="8dp" />
     </RelativeLayout>
 
diff --git a/core/res/res/layout/time_picker_text_input_material.xml b/core/res/res/layout/time_picker_text_input_material.xml
index f17b80e..76ce826 100644
--- a/core/res/res/layout/time_picker_text_input_material.xml
+++ b/core/res/res/layout/time_picker_text_input_material.xml
@@ -44,6 +44,7 @@
             android:layout_height="wrap_content"
             android:layout_below="@id/input_hour"
             android:layout_alignStart="@id/input_hour"
+            android:labelFor="@+id/input_hour"
             android:text="@string/time_picker_hour_label"/>
 
         <TextView
@@ -68,6 +69,7 @@
             android:layout_height="wrap_content"
             android:layout_below="@id/input_minute"
             android:layout_alignStart="@id/input_minute"
+            android:labelFor="@+id/input_minute"
             android:text="@string/time_picker_minute_label"/>
 
         <TextView
@@ -77,7 +79,7 @@
             android:layout_height="wrap_content"
             android:layout_below="@id/input_hour"
             android:layout_alignStart="@id/input_hour"
-            android:textColor="?attr/textColorError"
+            android:textColor="?attr/colorError"
             android:text="@string/time_picker_input_error" />
     </RelativeLayout>
     <Spinner
@@ -87,4 +89,4 @@
         android:layout_alignBaseline="@id/input_block"
         android:layout_alignParentEnd="true"/>
 
-</merge>
\ No newline at end of file
+</merge>
diff --git a/core/res/res/mipmap-hdpi/sym_def_app_icon_maskable.png b/core/res/res/mipmap-hdpi/sym_def_app_icon_maskable.png
new file mode 100644
index 0000000..bf58413
--- /dev/null
+++ b/core/res/res/mipmap-hdpi/sym_def_app_icon_maskable.png
Binary files differ
diff --git a/core/res/res/mipmap-ldpi/sym_def_app_icon_maskable.png b/core/res/res/mipmap-ldpi/sym_def_app_icon_maskable.png
new file mode 100644
index 0000000..3bf4285
--- /dev/null
+++ b/core/res/res/mipmap-ldpi/sym_def_app_icon_maskable.png
Binary files differ
diff --git a/core/res/res/mipmap-mdpi/sym_def_app_icon_maskable.png b/core/res/res/mipmap-mdpi/sym_def_app_icon_maskable.png
new file mode 100644
index 0000000..47f6f81
--- /dev/null
+++ b/core/res/res/mipmap-mdpi/sym_def_app_icon_maskable.png
Binary files differ
diff --git a/core/res/res/mipmap-xhdpi/sym_def_app_icon_maskable.png b/core/res/res/mipmap-xhdpi/sym_def_app_icon_maskable.png
new file mode 100644
index 0000000..f60b896
--- /dev/null
+++ b/core/res/res/mipmap-xhdpi/sym_def_app_icon_maskable.png
Binary files differ
diff --git a/core/res/res/mipmap-xxhdpi/sym_def_app_icon_maskable.png b/core/res/res/mipmap-xxhdpi/sym_def_app_icon_maskable.png
new file mode 100644
index 0000000..6d4f315
--- /dev/null
+++ b/core/res/res/mipmap-xxhdpi/sym_def_app_icon_maskable.png
Binary files differ
diff --git a/core/res/res/mipmap-xxxhdpi/sym_def_app_icon_maskable.png b/core/res/res/mipmap-xxxhdpi/sym_def_app_icon_maskable.png
new file mode 100644
index 0000000..08e54d0
--- /dev/null
+++ b/core/res/res/mipmap-xxxhdpi/sym_def_app_icon_maskable.png
Binary files differ
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 5896450..08389b9 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Inhoud versteek"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Inhoud word versteek volgens beleid"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Sekuriteit"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Opletberigte"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Veiligmodus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-stelsel"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Skakel oor na persoonlik"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Laat die program toe om Tuisskerm-kortpaaie te verwyder sonder gebruikerinmenging."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"herlei uitgaande oproepe"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Laat die program toe om te sien watter nommer tydens \'n uitgaande oproep geskakel word, met die opsie om die oproep na \'n ander nommer te herlei of die oproep heeltemal te beëindig."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"ontvang teksboodskappe (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Laat die program toe om SMS-boodskappe te ontvang en te verwerk. Dit beteken dat die program boodskappe wat na jou toestel gestuur is, kan monitor of uitvee, sonder dat jy dit gesien het."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ontvang teksboodskappe (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Laat die program toe om agtergrondprosesse van ander programme te beëindig. Dit kan moontlik veroorsaak dat ander programme ophou werk."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Hierdie program kan bo-op ander programme verskyn"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Hierdie program kan bokant ander programme of ander dele van die skerm verskyn. Dit kan met normale programgebruik inmeng en die voorkoms van ander programme verander."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"loop op die agtergrond"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Hierdie program kan op die agtergrond loop. Dit kan die battery vinniger laat pap word."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"gebruik data op die agtergrond"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Hierdie program kan data op die agtergrond gebruik. Dit kan die datagebruik vergroot."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"laat program altyd loop"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Laat die program toe om dele van ditself deurdringend in die geheue te hou. Dit kan geheue wat aan ander programme beskikbaar is, beperk, en die tablet stadiger maak."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Laat die program toe om dele van homself blywend in die berging te maak. Dit kan die berging wat beskikbaar is vir ander programme beperk, wat die TV stadiger sal maak."</string>
@@ -1171,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tik om taal en uitleg te kies"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> teken oor ander programme"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g>-program verskyn bo-op."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Dele van hierdie program sal dalk altyd sigbaar wees. Skakel hierdie kenmerk af as dit nie reg werk nie."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"SKAKEL AF"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Berei tans <xliff:g id="NAME">%s</xliff:g> voor"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Kyk tans vir foute"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Nuwe <xliff:g id="NAME">%s</xliff:g> bespeur"</string>
@@ -1325,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Deel met <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Skyfievatsel. Raak en hou."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Sleep om te ontsluit."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Prop \'n kopfoon in om te hoor hoe wagwoordsleutels hardop gesê word."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punt."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Navigeer tuis"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Navigeer op"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Meer opsies"</string>
@@ -1710,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Tik tyd in"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Skakel oor na teksmodus vir die tydinvoer."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Skakel oor na horlosiemodus vir die tydinvoer."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Stoor na <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Stoor <xliff:g id="TYPE">%1$s</xliff:g> na <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Stoor"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Nee, dankie"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"wagwoord"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"adres"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kredietkaart"</string>
 </resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index c82b295..b5863fe 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"ይዘቶች ተደብቀዋል"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"ይዘቶች በመመሪያ ተደብቀዋል"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"ደህንነት"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"ማንቂያዎች"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"የሚያስተማምን ሁነታ"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android ስርዓት"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"ወደ የግል ቀይር"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"መተግበሪያው ያለተጠቃሚ ጣልቃ-ገብነት የመነሻ ማያ ገጽ አቋራጮችን እንዲያስወግድ ያስችለዋል።"</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"የወጪ ጥሪዎች አቅጣጫ ቀይር"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"በወጪ ጥሪ ጊዜ ጥሪውን ወደተለየ ቁጥር ከማዞር ወይም ጥሪውን በአጠቃላይ ከመተው አማራጭ ጋር እየተደወለለት ያለውን ቁጥር እንዲያይ ያስችለዋል።"</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"የፅሁፍ መልዕክቶችን ተቀበል (ኤስ.ኤም.ኤስ.)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"መተግበሪያው የኤስ.ኤም.ኤስ. መልዕክቶችን እንዲያነብ እና እንዲያካሂድ ይፈቅዳል። ይህ ማለት መተግበሪያው ወደ መሳሪያህ የተላኩ መልዕክቶችን ላንተ ሳያሳይህ ሊቆጣጠር ወይም ሊሰርዝ ይችላል።"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"የፅሁፍ መልዕክቶችን ተቀበል (ኤም.ኤም.ኤስ.)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"መተግበሪያው የሌሎች መተግበሪያዎችን የጀርባ ሂደት እንዲያቆም ይፈቅድለታል። ይህ ሌሎች መተግበሪያዎች መሄድ እንዲያቆሙ ሊያደርግ ይችላል።"</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"ይህ መተግበሪያ በሌሎች መተግበሪያዎች ላይ ከላይ ወጣ ብሎ ሊታይ ይችላል"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"ይህ መተግበሪያ ከሌሎች መተግበሪያዎች ወይም ሌሎች የማያ ገጹ ክፍሎች በላይ ወጣ ብሎ ሊታይ ይችላል። ይህ በመደበኛው የመተግበሪያ አጠቃቀም ላይ ጣልቃ ሊገባ እና ሌሎች መተግበሪያዎች የሚታዩበትን መንገድ ሊለውጥ ይችላል።"</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"በጀርባ ላይ አሂድ"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"ይህ መተግበሪያ በጀርባ ላይ ማሄድ ይችላል። ይሄ ባትሪውን በይበልጥ ሊጨርሰው ይችላል።"</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"በጀርባ ላይ ውሂብ ይጠቀማል"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"ይህ መተግበሪያ በጀርባ ላይ ውሂብ ሊጠቀም ይችላል። ይሄ የውሂብ ፍጆታን ሊጨምር ይችላል።"</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"ትግበራ ሁልጊዜ አሂድ ላይ አድርግ"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"መተግበሪያው የራሱን ክፍሎች በማህደረ ትውስታ ውስጥ በቋሚነት የሚቀጥሉ እንዲያደርግ ይፈቅድለታል። ይህ ለሌላ መተግበሪያዎች ያለውን ማህደረ ትውስታ በመገደብ ጡባዊ ተኮውን ሊያንቀራፍፈው ይችላል።"</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"መተግበሪያው የእራሱ ክፍሎች በማህደረትውስታ ውስጥ ዘላቂ እንዲያደርግ ያስችለዋል። ይሄ ሌሎች መተግበሪያዎች የሚገኘውን ማህደረትውስታ በመገደብ ቴሌቪዥኑን ሊያንቀራፍፈው ይችላል።"</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"ግቤት ስልት"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"የፅሁፍ እርምጃዎች"</string>
     <string name="email" msgid="4560673117055050403">"ኢሜይል"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"ስልክ"</string>
     <string name="map" msgid="5441053548030107189">"ካርታ"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"አስስ"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"የማከማቻ ቦታ እያለቀ ነው"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"አንዳንድ የስርዓት ተግባራት ላይሰሩ ይችላሉ"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"ለስርዓቱ የሚሆን በቂ ቦታ የለም። 250 ሜባ ነጻ ቦታ እንዳለዎት ያረጋግጡና ዳግም ያስጀምሩ።"</string>
@@ -1173,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ቋንቋ እና አቀማመጥን ለመምረጥ መታ ያድርጉ"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> በሌሎች መተግበሪያዎች ላይ ሣል"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> መተግበሪያ ከላይ እየታየ ያለ።"</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"የዚህ መተግበሪያ ክፍሎች በሁሉም ጊዜያት የሚታዩ እንደሆኑ ሊቆዩ ይችላሉ። ይህ ባህሪ በትክክል የማይሠራ ከሆነ ያጥፉት።"</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"አጥፋ"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g>ን በማዘጋጀት ላይ"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"ስህተቶች ካሉ በመፈተሽ ላይ"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"አዲስ <xliff:g id="NAME">%s</xliff:g> ተገኝቷል"</string>
@@ -1327,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"ከ <xliff:g id="APPLICATION_NAME">%s</xliff:g> ጋር ተጋራ"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"ባለስላይድ መያዣ፡፡ ዳስ&amp;ያዝ፡፡"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"ላለመቆለፍ አንሸራት፡፡"</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"የይለፍ ቃል ቁልፎች  ሲነገሩ ለመስማት የጆሮ ማዳመጫ ሰካ።"</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"ነጥብ."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"መነሻ ዳስስ"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"አስስ"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"ተጨማሪ አማራጮች"</string>
@@ -1712,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"ሰዓት ይተይቡ"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"ለጊዜ ግቤቱ ወደ የጽሑፍ ግቤት ሁነታ ቀይር።"</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"ለጊዜ ግቤቱ ወደ የሰዓት ሁነታ ቀይር።"</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"ወደ <xliff:g id="LABEL">%1$s</xliff:g> ይቀመጥ?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> ወደ <xliff:g id="LABEL">%2$s</xliff:g> ይቀመጥ?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"አስቀምጥ"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"አይ፣ አመሰግናለሁ"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"የይለፍ ቃል"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"አድራሻ"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"ክሬዲት ካርድ"</string>
 </resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index f649ce7..238c78b 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -256,6 +256,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"المحتويات مخفية"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"تم إخفاء المحتويات بواسطة السياسة"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"الأمان"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"التنبيهات"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"الوضع الآمن"</string>
     <string name="android_system_label" msgid="6577375335728551336">"‏نظام Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"التبديل إلى الشخصي"</string>
@@ -304,6 +330,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"للسماح للتطبيق بإزالة اختصارات من الشاشة الرئيسية بدون تدخل المستخدم."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"إعادة توجيه المكالمات الصادرة"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"للسماح للتطبيق بالاطلاع على الرقم الذي يتم الاتصال به عند إجراء مكالمة صادرة مع وجود الخيار لإعادة توجيه المكالمة إلى رقم آخر أو إنهاء المكالمة تمامًا."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"‏تلقي رسائل نصية (رسائل قصيرة SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"‏للسماح للتطبيق بتلقي ومعالجة الرسائل القصيرة SMS. وهذا يعني أنه يمكن للتطبيق مراقبة الرسائل التي يتم إرسالها إلى جهازك أو حذفها بدون عرضها لك."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"تلقي رسائل نصية (رسائل وسائط متعددة)"</string>
@@ -332,14 +362,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"للسماح للتطبيق بإنهاء عمليات التطبيقات الأخرى في الخلفية. وقد يؤدي هذا إلى توقف تطبيقات أخرى عن العمل."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"يمكن لهذا التطبيق الظهور في مقدمة التطبيقات الأخرى"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"يمكن لهذا التطبيق الظهور في مقدمة التطبيقات أو أجزاء الشاشة الأخرى. وقد يتداخل هذا مع الاستخدام العادي للتطبيقات أو يؤدي إلى تغيير طريقة ظهور التطبيقات الأخرى."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"العمل في الخلفية"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"يمكن أن يعمل هذا التطبيق في الخلفية. وهذا قد يستنفد البطارية بشكل أسرع."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"استخدام البيانات في الخلفية"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"يمكن أن يستخدم هذا التطبيق البيانات في الخلفية. وهذا قد يؤدي إلى زيادة استخدام البيانات."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"تشغيل التطبيق دائمًا"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"للسماح للتطبيق بجعل أجزاء منه ثابتة في الذاكرة. وقد يؤدي هذا إلى تقييد الذاكرة المتاحة للتطبيقات الأخرى مما يؤدي إلى حدوث بطء في الجهاز اللوحي."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"يتيح للتطبيق تعيين أجزاء من التطبيق نفسه لتظل ثابتة في الذاكرة. وقد يقيد هذا من الذاكرة المتاحة للتطبيقات الأخرى، مما يؤدي إلى بطء في التلفزيون."</string>
@@ -1251,6 +1277,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"انقر لاختيار لغة وتنسيق"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" أ ب ت ث ج ح خ د ذ ر ز س ش ص ض ط ظ ع غ ف ق ك ل م ن ه و ي"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789 أ ب ت ث ج ح خ د ذ ر ز س ش ص ض ط ظ ع غ ف ق ك ل م ن ه و ي"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"يتم عرض <xliff:g id="NAME">%s</xliff:g> فوق التطبيقات الأخرى"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"يتم عرض تطبيق <xliff:g id="NAME">%s</xliff:g> فوق التطبيقات."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"قد تظل أجزاء من هذا التطبيق مرئية في جميع الأوقات. فإذا كانت هذه الميزة لا تعمل بشكل صحيح، يمكنك إيقافها."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"إيقاف"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"جارٍ تحضير <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"جارٍ التحقق من الأخطاء"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"تم اكتشاف <xliff:g id="NAME">%s</xliff:g> جديدة"</string>
@@ -1409,8 +1439,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"مشاركة مع <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"مقبض التمرير. المس مع الاستمرار."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"مرر بسرعة لإلغاء التأمين."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"يمكنك توصيل سماعة رأس لسماع مفاتيح كلمة المرور عندما يتم نطقها."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"نقطة"</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"التنقل إلى الشاشة الرئيسية"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"التنقل إلى أعلى"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"المزيد من الخيارات"</string>
@@ -1834,4 +1862,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"يُرجى تحديد الوقت"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"يُرجى التبديل إلى وضع إدخال النص لإدخال الوقت."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"يُرجى التبديل إلى وضع الساعة لإدخال الوقت."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"هل تريد الحفظ في <xliff:g id="LABEL">%1$s</xliff:g>؟"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"هل تريد حفظ <xliff:g id="TYPE">%1$s</xliff:g> في <xliff:g id="LABEL">%2$s</xliff:g>؟"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"حفظ"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"لا، شكرًا"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"كلمة مرور"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"عنوان"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"بطاقة ائتمان"</string>
 </resources>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index d059240e..25f9ca9 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Məzmun gizlidir"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Məzmun siyasət tərəfindən gizlədilib"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Təhlükəsizlik"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Siqnallar"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Təhlükəsiz rejim"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android sistemi"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Şəxsi profilə keçirin"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"İstifadəçi müdaxiləsi olmadan tətbiqə İş Stolu qısayollarını silməyə icazə verir."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"gedən zənglərin marşrutunu dəyişmək"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Tətbiqə gedən zəng zamanı yığılan nömrəni görməyə imkan verir. Bu zaman zəngi başqa nömrəyə yönləndirmək və ya bütün zəngləri ləğv etmək funsiyası da təqdim olunur."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"SMS qəbul etmək"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Tətbiqə MMS mesajlarını almaq və emal etmək icazəsi verir. Bu o deməkdir ki, tətbiq sizin mesajlarınızı sizə göstərmədən monitorinq edə və ya silə bilər."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"mətn mesajlarını qəbul edir (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Tətbiqə başqa tətbiqlərin arxafon proseslərini dayandırmaq icazəsi verir. Bu digər tətbiqlərin dayanmasına səbəb ola bilər."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Bu tətbiq digər tətbiqlərin üzərində görünə bilər"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Bu tətbiq digər tətbiqlərin və ya ekran hissələrinin üzərində görünə bilər. Bu, normal tətbiq istifadəsinə müdaxilə edə və digər tətbiqlərin görünüşünün dəyişməsinə səbəb ola bilər."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"arxa fonda işləmə"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Bu tətbiq arxa fonda işləsə, batareya daha tez qurtara bilər."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"datanın arxa fonda istifadəsi"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Bu tətbiq datanı arxa fonda istifadə etsə, data istifadəsi arta bilər."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"təbiqi həmişə çalışdır"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Tətbiqə öz komponentlərini yaddaşda saxlama icazəsi verir. Bu planşetin sürətini zəiflətməklə, digər tətbiqlər üçün mövcud olan yaddaşı limitləyə bilər."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Proqrama öz hissələrini yaddaşda davamlı etmək imkanı verir. Bu TV-ni zəiflədərək başqa proqramlar üçün mövcud olan yaddaşı məhdudlaşdıra bilər."</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"Daxiletmə metodu"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Mətn əməliyyatları"</string>
     <string name="email" msgid="4560673117055050403">"E-poçt"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"Telefon"</string>
     <string name="map" msgid="5441053548030107189">"Xəritə"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"Axtarış"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Yaddaş yeri bitir"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Bəzi sistem funksiyaları işləməyə bilər"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Sistem üçün yetərincə yaddaş ehtiyatı yoxdur. 250 MB yaddaş ehtiyatının olmasına əmin olun və yenidən başladın."</string>
@@ -1173,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dil və tərtibatı seçmək üçün tıklayın"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCÇDEƏFGĞHXIİJKQLMNOÖPRSŞTUÜVYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCÇDEƏFGĞHİIJKLMNOÖPQRSŞTUÜVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> digər tətbiqlərin üzərinə çəkilir"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> tətbiqi üstdə göstərilir."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Bu tətbiqin hissələri həmişə görünən qala bilər. Bu funksiya düzgün işləmirsə, onu deaktiv edin."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DEAKTİV EDİN"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> hazırlanır"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Səhvlər yoxlanılır"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Yeni <xliff:g id="NAME">%s</xliff:g> aşkarlandı"</string>
@@ -1327,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> ilə paylaşın"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Sürüşən qulp. Toxunaraq basılı tutun."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Kilidi açmaq üçün vurun."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Parolların səsləndirilməsi üçün qulaqlıqları taxın."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Nöqtə."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Evə naviqasiya et"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Yuxarı gedin"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Digər variantlar"</string>
@@ -1712,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Zamanı daxil edin"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Zamanı daxil etmək üçün mətnlə daxiletmə rejiminə keçin"</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Zamanı daxil etmək üçün saat rejiminə keçin"</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> etiketində yadda saxlanılsın?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> <xliff:g id="LABEL">%2$s</xliff:g> etiketində yadda saxlanılsın?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Yadda saxlayın"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Xeyr, çox sağ olun"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"parol"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"ünvan"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kredit kartı"</string>
 </resources>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 0f03ea4..9b727e6 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -247,6 +247,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Sadržaj je sakriven"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Sadržaj je sakriven smernicama"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Bezbednost"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Obaveštenja"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Bezbedni režim"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android sistem"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Pređi na Lični profil"</string>
@@ -295,6 +321,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Omogućava aplikaciji da uklanja prečice sa početnog ekrana bez intervencije korisnika."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"preusmeravanje odlaznih poziva"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Dozvoljava aplikaciji da vidi koji broj se bira pri odlaznom pozivu uz opciju da preusmeri poziv na drugi broj ili ga potpuno prekine."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"prijem tekstualnih poruka (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Dozvoljava aplikaciji da prima i obrađuje SMS poruke. To znači da aplikacija može da nadgleda ili briše poruke koje se šalju uređaju, a da vam ih ne prikaže."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"prijem tekstualnih poruka (MMS)"</string>
@@ -323,14 +353,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Dozvoljava aplikaciji da zaustavi pozadinske procese drugih aplikacija. Ovo može da zaustavi druge aplikacije."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Ova aplikacija može da se prikazuje preko drugih aplikacija"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Ova aplikacija može da se prikazuje preko drugih aplikacija ili drugih delova delova ekrana. To može da ometa standardno korišćenje aplikacija i način na koji se druge aplikacije prikazuju."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"pokretanje u pozadini"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Ova aplikacija može da se pokreće u pozadini. To može brže da istroši bateriju."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"korišćenje podataka u pozadini"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Ova aplikacija može da koristi podatke u pozadini. To može da poveća potrošnju podataka."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"omogućavanje neprekidne aktivnosti aplikacije"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Dozvoljava aplikaciji da učini sopstvene komponente trajnim u memoriji. Ovo može da ograniči memoriju dostupnu drugim aplikacijama i uspori tablet."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Dozvoljava aplikaciji da neke svoje delove trajno zadrži u memoriji. To može da ograniči memoriju dostupnu drugim aplikacijama i uspori TV."</string>
@@ -1191,6 +1217,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dodirnite da biste izabrali jezik i raspored"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"Aplikacija <xliff:g id="NAME">%s</xliff:g> se prikazuje preko drugih aplikacija"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"Aplikacija <xliff:g id="NAME">%s</xliff:g> se prikazuje preko."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Delovi ove aplikacije mogu da ostanu vidljivi u svakom trenutku. Ako ova funkcija ne radi ispravno, isključite je."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ISKLJUČI"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> se priprema"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Proverava se da li postoje greške"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Novi uređaj <xliff:g id="NAME">%s</xliff:g> je otkriven"</string>
@@ -1346,8 +1376,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Deli sa aplikacijom <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Klizna ručica. Dodirnite i zadržite."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Prevucite da biste otključali."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Priključite slušalice da biste čuli izgovorene tastere za lozinku."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Tačka."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Kretanje do Početne"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Kretanje nagore"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Još opcija"</string>
@@ -1741,4 +1769,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Unesite vreme"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Pređite u režim unosa teksta radi unosa vremena."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Pređite u režim sata radi unosa vremena."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Želite li da sačuvate u: <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Želite li da sačuvate stavku <xliff:g id="TYPE">%1$s</xliff:g> u: <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Sačuvaj"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Ne, hvala"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"lozinka"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"adresa"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kreditna kartica"</string>
 </resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 0be8e7a..6f9fd0b 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -250,6 +250,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Змесціва схавана"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Змесціва, схаванае ў адпаведнасці з палітыкай"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Бяспека"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Абвесткi"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Бяспечны рэжым"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Сістэма Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Пераключыцца на асабісты"</string>
@@ -298,6 +324,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Дазваляе праграме выдаляць ярлыкі з Галоўнага экрана без умяшання карыстальніка."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"перанакіраванне зыходзячых выклікіаў"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Дазваляе праграме бачыць набраны нумар падчас выходнага выкліку з магчымасцю перанакіравання выкліку на іншы нумар або спынення выкліку ў цэлым."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"атрыманне тэкставых паведамленняў (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Дазваляе прыкладанням атрымліваць і апрацоўваць SMS-паведамленні. Гэта значыць, што прыкладанне можа кантраляваць або выдаляць паведамленні, адпраўленыя на прыладу, не паказваючы іх вам."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"атрыманне тэкставых паведамленняў (MMS)"</string>
@@ -326,14 +356,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Дазваляе прыкладанню завяршаць фонавыя працэсы іншых прыкладанняў. Гэта можа спынiць працу iншых прыкладанняў."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Гэта праграма можа паказвацца паверх іншых праграм"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Гэта праграма можа паказвацца паверх іншых праграм ці іншых частак экрана. Гэта можа перашкодзіць нармальнаму выкарыстанню праграмы і змяніць выгляд іншых праграм."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"працаваць у фоне"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Гэта праграма можа працаваць у фоне. Гэта можа прывесці да хутчэйшага спажывання зараду акумулятара."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"выкарыстоўваць даныя ў фоне"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Гэта праграма можа выкарыстоўваць даныя ў фоне. Гэта можа прывесці да павелічэння аб\'ёму трафіка."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"прымусіць прыкладанне працаваць заўсёды"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Дазваляе прыкладанню захоўваць некаторыя пастаянныя часткi ў памяцi. Гэта можа абмежаваць аб\'ём памяці, даступнай для іншых прыкладанняў, i запаволiць працу планшэта."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Дазваляе праграме пастаянна захоўваць некаторыя свае часткi ў памяцi. Гэта можа абмежаваць аб\'ём памяці, даступнай для іншых праграм, i запаволiць працу тэлевізара."</string>
@@ -1211,6 +1237,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Дакраніцеся, каб выбраць мову і раскладку"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" АБВГДЕЁЖЗІЙКЛМНОПРСТУЎФХЦЧШ\'ЫЬЭЮЯ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> паверх іншых праграм"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"Праграма <xliff:g id="NAME">%s</xliff:g> паказваецца зверху."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Часткі гэтай праграмы могуць заставацца бачнымі ў любы час. Калі гэта функцыя не працуе належным чынам, адключыце яе."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"АДКЛЮЧЫЦЬ"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Падрыхтоўка <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Праверка на наяўнасць памылак"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Выяўлены новы носьбіт <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1367,8 +1397,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Адправiць з дапамогай прыкладання <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Ручка для перасоўвання. Націсніце і ўтрымлівайце."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Прагартайце, каб разблакаваць."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Каб праслухаць паролi, падключыце гарнiтуру."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Кропка."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Перайсці да пачатковай старонкі"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Перайсці ўверх"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Больш налад"</string>
@@ -1772,4 +1800,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Увядзіце час"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Пераключыцца на рэжым тэксту пры ўводзе часу."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Пераключыцца на рэжым гадзінніка пры ўводзе часу."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Захаваць у <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Захаваць наступнае: <xliff:g id="TYPE">%1$s</xliff:g> у <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Захаваць"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Не, дзякуй"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"пароль"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"адрас"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"крэдытная картка"</string>
 </resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index f8eb7f2..e583435 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Скрито съдържание"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Съдържанието е скрито чрез правило"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Сигурност"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Сигнали"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Безопасен режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Системно от Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Превключване към личния потребителски профил"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Разрешава на приложението да премахва преки пътища от началния екран без намеса на потребителя."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"пренасочване на изходящите обаждания"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Разрешава на приложението да вижда набирания номер по време на изходящо обаждане и му дава възможност да пренасочи обаждането към друг номер или да го прекрати изцяло."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"получаване на текстови съобщения (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Разрешава на приложението да получава и обработва SMS съобщения. Това означава, че то може да наблюдава или изтрива изпратените до устройството ви, без да ви ги покаже."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"получаване на текстови съобщения (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Разрешава на приложението да прекратява намиращи се на заден план процеси на други приложения. Това може да доведе до спиране на тяхното изпълняване."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Това приложение може да се показва върху други приложения"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Това приложение може да се показва върху други приложения или други части от екрана. Така може да се попречи на нормалната употреба на приложенията и да се промени начинът, по който се показват други приложения."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"работа на заден план"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Това приложение може да работи на заден план, което може да изразходи батерията по-бързо."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"използване на данни на заден план"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Това приложение може да използва данни на заден план, което може да увеличи преноса на данни."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"задаване на постоянно изпълнение на приложението"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Разрешава на приложението да прави части от себе си постоянни в паметта. Това може да ограничи наличната за другите приложения, забавяйки таблета."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Разрешава на приложението да прави части от себе си постоянни в паметта. Това може да ограничи наличната памет за останалите приложения и да забави телевизора."</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"Метод на въвеждане"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Действия с текста"</string>
     <string name="email" msgid="4560673117055050403">"Имейл"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"Телефон"</string>
     <string name="map" msgid="5441053548030107189">"Карта"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"Сърфиране"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Мястото в хранилището е на изчерпване"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Възможно е някои функции на системата да не работят"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"За системата няма достатъчно място в хранилището. Уверете се, че имате свободни 250 МБ, и рестартирайте."</string>
@@ -1173,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Докоснете, за да изберете език и подредба"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> се изобразява върху други приложения"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> се показва в/у други прилож."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Части от това приложение може да останат видими за постоянно. Ако функцията не работи правилно, изключете я."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ИЗКЛЮЧВАНЕ"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g>: Подготвя се"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Проверява се за грешки"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Открито е ново хранилище (<xliff:g id="NAME">%s</xliff:g>)"</string>
@@ -1327,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Споделяне със: <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Плъзгаща се дръжка. Докоснете и задръжте."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Прокарайте пръст, за да отключите."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Включете слушалки, за да чуете изговарянето на клавишите за паролата."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Точка."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Придвижване към „Начало“"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Придвижване нагоре"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Още опции"</string>
@@ -1712,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Въведете часа"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Превключете към режима за въвеждане на текст, за да въведете часа."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Превключете към режима за часовник, за да въведете часа."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Да се запази ли в/ъв „<xliff:g id="LABEL">%1$s</xliff:g>“?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> да се запази ли в/ъв „<xliff:g id="LABEL">%2$s</xliff:g>“?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Запазване"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Не, благодаря"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"Паролата"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"Адресът"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"Кредитната карта"</string>
 </resources>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index e660241..337a292 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -163,7 +163,7 @@
     <string name="httpErrorFile" msgid="2170788515052558676">"ফাইল অ্যাক্সেস করা যায়নি৷"</string>
     <string name="httpErrorFileNotFound" msgid="6203856612042655084">"অনুরোধ করা ফাইলটি খুঁজে পাওয়া যায়নি৷"</string>
     <string name="httpErrorTooManyRequests" msgid="1235396927087188253">"অনেকগুলি অনুরোধের প্রক্রিয়া করা হচ্ছে৷ পরে আবার চেষ্টা করুন৷"</string>
-    <string name="notification_title" msgid="8967710025036163822">"<xliff:g id="ACCOUNT">%1$s</xliff:g> এ প্রবেশ করুন ত্রুটি"</string>
+    <string name="notification_title" msgid="8967710025036163822">"<xliff:g id="ACCOUNT">%1$s</xliff:g> এ প্রবেশ করায় ত্রুটি"</string>
     <string name="contentServiceSync" msgid="8353523060269335667">"সিঙ্ক"</string>
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"সিঙ্ক"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"অনেকগুলি <xliff:g id="CONTENT_TYPE">%s</xliff:g> মুছে ফেলা হয়েছে৷"</string>
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"৯৯৯+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"লুকানো বিষয়বস্তু"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"নীতির কারণে সামগ্রী লুকানো আছে"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"নিরাপত্তা"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"সতর্কতাগুলি"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"নিরাপদ মোড"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android সিস্টেম"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"ব্যক্তিগততে পাল্টান"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"অ্যাপ্লিকেশানটিকে ব্যবহারকারীর হস্তক্ষেপ ছাড়াই হোমস্ক্রীণের শর্টকাটগুলি সরানোর অনুমতি দেয়৷"</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"আউটগোয়িং কলগুলি পুনঃচালিত করুন"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"অ্যাপ্লিকেশানকে কল চলাকালীন অন্য একটি নম্বরে কল পুনঃনির্দেশ বা কলটি একসথে বন্ধ করার সাথে ডায়াল করা নম্বরটি দেখতে দেয়৷"</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"পাঠ্য বার্তা পান (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"অ্যাপ্লিকেশানটিকে এসএমএস প্রাপ্ত করার এবং প্রক্রিয়া করার অনুমতি দেয়৷ এর মানে হল অ্যাপ্লিকেশানটি আপনার ডিভাইস থেকে পাঠানো বার্তাগুলিকে পর্যবেক্ষণ করতে পারে এবং মুছতে পারে সেগুলিকে আপনাকে না দেখিয়ে৷"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"পাঠ্য বার্তা পান (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"অন্যান্য অ্যাপ্লিকেশানগুলির নেপথ্যে চলা প্রক্রিয়াগুলির সমাপ্তি ঘটাতে অ্যাপ্লিকেশানটিকে মঞ্জুর করে৷ এর ফলে অন্যান্য অ্যাপ্লিকেশানগুলি বন্ধ হয়ে যেতে পারে৷"</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"এই অ্যাপটি অন্যান্য অ্যাপের উপরে প্রদর্শিত পারে"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"এই অ্যাপটি অন্যান্য অ্যাপের উপরে বা স্ক্রীনের অন্যান্য অংশে উপস্থিত হতে পারে৷ এটি সাধারণ অ্যাপ ব্যবহারের ক্ষেত্রে হস্তক্ষেপ করতে এবং অন্যান্য অ্যাপের প্রদর্শিত হওয়ার অবস্থাকে পরিবর্তিত করতে পারে৷"</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"পটভূমিতে চালু থাকুক"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"এই অ্যাপটি পটভূমিতে চালু থাকতে পারে। ফলে ব্যাটারি দ্রুত ফুরিয়ে যেতে পারে।"</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"পটভূমিতে ডেটা ব্যবহার করুক"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"এই অ্যাপটি পটভূমিতে ডেটা ব্যবহার করতে পারে। ফলে ডেটার ব্যবহার বেড়ে যেতে পারে।"</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"অ্যাপ্লিকেশানকে সবসময় চালিত রাখে"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"মেমরিতে নিজের জন্য প্রয়োজনীয় জায়গা আলাদা করে রাখতে অ্যাপ্লিকেশানটিকে মঞ্জুর করে৷ এর ফলে অন্যান্য অ্যাপ্লিকেশানগুলির জায়গা সীমিত হয়ে পড়তে পারে ও ট্যাবলেটটি অপেক্ষাকৃত ধীরগতির হয়ে পড়তে পারে৷"</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"অ্যাপ্লিকেশানটিকে মেমোরিতে থাকা সেটির নিজস্ব অধিকৃত স্থানের অংশগুলিকে অবিরত রাখতে করার অনুমতি দেয়৷ এটি টিভিকে ধীর করে এমন অন্য অ্যাপ্লিকেশানগুলির জন্য উপলব্ধ মেমোরি সীমিত করতে পারে৷"</string>
@@ -724,9 +750,9 @@
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"আপনি আপনার আনলকের প্যাটার্ন আঁকার ক্ষেত্রে <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুল করেছেন৷ \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন৷"</string>
     <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"আপনি আপনার পাসওয়ার্ড <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুল টাইপ করেছেন৷ \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন৷"</string>
     <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"আপনি আপনার পাসওয়ার্ড <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুল টাইপ করেছেন৷ \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন৷"</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুল করে আপনার আনলক প্যাটার্ন অঙ্কিত করেছেন৷ আপনি <xliff:g id="NUMBER_1">%2$d</xliff:g>টি অসফল প্রচেষ্টার পরে, আপনাকে Google প্রবেশ করুন দিয়ে আপনার ট্যাবলেট আনলক করার কথা বলা হবে৷\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> সেকেন্ড পরে আবার চেষ্টা করুন৷"</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="5316664559603394684">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুল করে আপনার আনলক প্যাটার্ন অঙ্কিত করেছেন৷ আপনি <xliff:g id="NUMBER_1">%2$d</xliff:g>টি অসফল প্রচেষ্টার পরে, আপনাকে Google প্রবেশ করুন দিয়ে আপনার টিভি আনলক করার কথা বলা হবে৷\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> সেকেন্ড পরে আবার চেষ্টা করুন৷"</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুল করে আপনার আনলক প্যাটার্ন অঙ্কিত করেছেন৷ আপনি <xliff:g id="NUMBER_1">%2$d</xliff:g>টি অসফল প্রচেষ্টার পরে, আপনাকে Google প্রবেশ করুন দিয়ে আপনার ফোন আনলক করার কথা বলা হবে৷\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> সেকেন্ড পরে আবার চেষ্টা করুন৷"</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুল করে আপনার আনলক প্যাটার্ন অঙ্কিত করেছেন৷ আপনি <xliff:g id="NUMBER_1">%2$d</xliff:g>টি অসফল প্রচেষ্টার পরে, আপনাকে Google এ প্রবেশ করে আপনার ট্যাবলেট আনলক করার কথা বলা হবে৷\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> সেকেন্ড পরে আবার চেষ্টা করুন৷"</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="5316664559603394684">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুল করে আপনার আনলক প্যাটার্ন অঙ্কিত করেছেন৷ আপনি <xliff:g id="NUMBER_1">%2$d</xliff:g>টি অসফল প্রচেষ্টার পরে, আপনাকে Google এ প্রবেশ করে আপনার টিভি আনলক করার কথা বলা হবে৷\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> সেকেন্ড পরে আবার চেষ্টা করুন৷"</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুল করে আপনার আনলক প্যাটার্ন অঙ্কিত করেছেন৷ আপনি <xliff:g id="NUMBER_1">%2$d</xliff:g>টি অসফল প্রচেষ্টার পরে, আপনাকে Google এ প্রবেশ করে আপনার ফোন আনলক করার কথা বলা হবে৷\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> সেকেন্ড পরে আবার চেষ্টা করুন৷"</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুল করে ট্যাবলেটটি আনলক করার চেষ্টা করেছেন৷ আরো <xliff:g id="NUMBER_1">%2$d</xliff:g>টি অসফল চেষ্টার পরে, ট্যাবলেটটি ফ্যাক্টরী ডিফল্টে রিসেট হবে এবং ব্যবহারকারীর সমস্ত ডেটা মুছে যাবে৷"</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="950408382418270260">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুল করে টিভি আনলক করার চেষ্টা করেছেন৷ <xliff:g id="NUMBER_1">%2$d</xliff:g>টি অসফল প্রচেষ্টার পরে, আপনার টিভি ফ্যাক্টরি ডিফল্টে পুনঃসেট হবে এবং সমস্ত ব্যবহারকারীর ডেটা মুছে যাবে৷"</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুল করে ফোনটি আনলক করার চেষ্টা করেছেন৷ আরো <xliff:g id="NUMBER_1">%2$d</xliff:g>টি অসফল চেষ্টার পরে, ফোনটি ফ্যাক্টরী ডিফল্টে রিসেট হবে এবং ব্যবহারকারীর সমস্ত ডেটা মুছে যাবে৷"</string>
@@ -737,7 +763,7 @@
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"প্যাটার্ন ভুলে গেছেন?"</string>
     <string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"অ্যাকাউন্ট আনলক করুন"</string>
     <string name="lockscreen_glogin_too_many_attempts" msgid="2751368605287288808">"বিভিন্ন প্যাটার্নের সাহায্যে খুব বেশি বার প্রচেষ্টা করা হয়ে গেছে"</string>
-    <string name="lockscreen_glogin_instructions" msgid="3931816256100707784">"আনলক করতে আপনার Google অ্যাকাউন্টের মাধ্যমে প্রবেশ করুন করুন৷"</string>
+    <string name="lockscreen_glogin_instructions" msgid="3931816256100707784">"আনলক করতে আপনার Google অ্যাকাউন্টের মাধ্যমে প্রবেশ করুন৷"</string>
     <string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"ব্যবহারকারীনাম (ইমেল)"</string>
     <string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"পাসওয়ার্ড"</string>
     <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"প্রবেশ করুন"</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"ইনপুট পদ্ধতি"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"পাঠ্য ক্রিয়াগুলি"</string>
     <string name="email" msgid="4560673117055050403">"ইমেল"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"ফোন করুন"</string>
     <string name="map" msgid="5441053548030107189">"মানচিত্র"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"ব্রাউজ করুন"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"সঞ্চয়স্থান পূর্ণ হতে চলেছে"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"কিছু কিছু সিস্টেম ক্রিয়াকলাপ কাজ নাও করতে পারে"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"সিস্টেমের জন্য যথেষ্ট সঞ্চয়স্থান নেই৷ আপনার কাছে ২৫০MB ফাঁকা স্থান রয়েছে কিনা সে বিষয়ে নিশ্চিত হওয়ার পর আবার চালু করুন৷"</string>
@@ -1174,6 +1198,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ভাষা এবং লেআউট নির্বাচন করুন আলতো চাপ দিন"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> অন্যান্য অ্যাপের উপরেও দেখা যায়"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> অ্যাপ সবার উপরে দেখা যাচ্ছে।"</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"এই অ্যাপের কিছু কিছু অংশ সব সময় স্ক্রিনে দেখা যেতে পারে। যদি এই বৈশিষ্ট্যটি ঠিক ভাবে কাজ না করে, তাহলে অ্যাপটি বন্ধ করে দিন।"</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"বন্ধ করুন"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> প্রস্তুত করা হচ্ছে"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"ত্রুটি রয়েছে কিনা পরীক্ষা করা হচ্ছে"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"নতুন <xliff:g id="NAME">%s</xliff:g> সনাক্ত করা হয়েছে"</string>
@@ -1328,8 +1356,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> এর সাথে শেয়ার করুন"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"স্লাইড নিয়ন্ত্রণ৷ স্পর্শ করুন ও ধরে রাখুন৷"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"আনলক করতে সোয়াইপ করুন৷"</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"উচ্চারিত পাসওয়ার্ডের কীগুলি শোনার জন্য একটি হেডসেট সংযুক্ত করুন৷"</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"বিন্দু৷"</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"হোম এ নেভিগেট করুন"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"উপরের দিকে নেভিগেট করুন"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"আরো বিকল্প"</string>
@@ -1423,7 +1449,7 @@
     <string name="kg_invalid_puk" msgid="3638289409676051243">"সঠিক PUK কোড পুনরায় লিখুন৷ বার বার প্রচেষ্টা করা হলে তা স্থায়ীভাবে সিমটিকে অক্ষম করে দেবে৷"</string>
     <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"পিন কোডগুলি মিলছে না"</string>
     <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"বিভিন্ন প্যাটার্নের সাহায্যে খুব বেশি বার প্রচেষ্টা করা হয়ে গেছে"</string>
-    <string name="kg_login_instructions" msgid="1100551261265506448">"আনলক করতে আপনার Google অ্যাকাউন্টের মাধ্যমে প্রবেশ করুন করুন৷"</string>
+    <string name="kg_login_instructions" msgid="1100551261265506448">"আনলক করতে আপনার Google অ্যাকাউন্টের মাধ্যমে প্রবেশ করুন৷"</string>
     <string name="kg_login_username_hint" msgid="5718534272070920364">"ব্যবহারকারী নাম (ইমেল)"</string>
     <string name="kg_login_password_hint" msgid="9057289103827298549">"পাসওয়ার্ড"</string>
     <string name="kg_login_submit_button" msgid="5355904582674054702">"প্রবেশ করুন"</string>
@@ -1713,4 +1739,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"সময় টাইপ করুন"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"সময় ইনপুট দেওয়ার জন্য পাঠ্য ইনপুট মোডে যান।"</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"সময় ইনপুট দেওয়ার জন্য ঘড়ি মোডে যান।"</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> এ সংরক্ষণ করবেন?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="LABEL">%2$s</xliff:g> এ <xliff:g id="TYPE">%1$s</xliff:g> সংরক্ষণ করবেন?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"সংরক্ষণ করুন"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"না থাক"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"পাসওয়ার্ড"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"ঠিকানা"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"ক্রেডিট কার্ড"</string>
 </resources>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index e17dab6..88f2509 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -247,6 +247,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Sadržaj je sakriven"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Sadržaj skriven u skladu sa pravilima"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Sigurnost"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Upozorenja"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Siguran način rada"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android sistem"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Prebacite se na lični"</string>
@@ -295,6 +321,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Omogućava aplikaciji uklanjanje prečice početnog ekrana bez intervencije korisnika."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"preusmjeravanje odlaznih poziva"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Dozvoljava aplikaciji da vidi birani broj prilikom odlaznog poziva uz opciju da poziv preusmjeri na drugi broj ili da ga skroz prekine."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"primanje tekstualnih poruka (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Omogućava aplikaciji primanje i obradu SMS poruka. Ovo znači da aplikacija može pratiti ili brisati poruke poslane na vaš uređaj, a da vam ih pritom ne prikazuje."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"primanje tekstualnih poruka (MMS)"</string>
@@ -323,14 +353,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Omogućava aplikaciji prekid pozadinskih procesa drugih aplikacija. Ovo može dovesti do prestanka rada drugih aplikacija."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Ova aplikacija se može pojaviti iznad drugih aplikacija"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Aplikacija se može pojaviti iznad ostalih aplikacija ili drugih dijelova ekrana. To može uticati na normalno korištenje aplikacije i promijeniti izgled drugih aplikacija."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"rad u pozadini"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Ova aplikacija može raditi u pozadini. To može brže istrošiti bateriju."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"prijenos podataka u pozadini"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Ova aplikacija može prenositi podatke u pozadini. To može povećati prijenos podataka."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"podešavanje aplikacije tako da je uvijek pokrenuta"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Omogućava aplikaciji da neke svoje dijelove pohrani trajno u memoriji. Ovo može ograničiti veličinu raspoložive memorije za druge aplikacije i tako usporiti tablet."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Dozvoljava aplikaciji da jednim dijelom trajno ostaje u memoriji. Time se ostalim aplikacijama dostupna memorija može ograničiti te usporiti rad TV-a."</string>
@@ -980,11 +1006,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"Način unosa"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Akcije za tekst"</string>
     <string name="email" msgid="4560673117055050403">"E-pošta"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"Telefon"</string>
     <string name="map" msgid="5441053548030107189">"Mapa"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"Pretraži"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Ponestaje prostora za pohranu"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Neke funkcije sistema možda neće raditi"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Nema dovoljno prostora za sistem. Obezbijedite 250MB slobodnog prostora i ponovo pokrenite uređaj."</string>
@@ -1196,6 +1220,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dodirnite za odabir jezika i rasporeda"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"Aplikacija <xliff:g id="NAME">%s</xliff:g> prekriva ostale aplikacije"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"Apl. <xliff:g id="NAME">%s</xliff:g> prikazana je na vrhu."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Dijelovi aplikacije mogu ostati vidljivi sve vrijeme. Ako ta funkcija ne radi ispravno, isključite je."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ISKLJUČI"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Priprema se <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Provjera grešaka"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Novi uređaj <xliff:g id="NAME">%s</xliff:g> je otkriven"</string>
@@ -1351,8 +1379,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Podijeli koristeći aplikaciju <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Klizni regulator. Dodirnite &amp; držite."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Prevucite za otključavanje ekrana."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Priključite slušalice kako biste čuli dugmad prilikom kucanja lozinke."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Tačka."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Vratite se na početnu stranicu"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Navigirajte prema gore"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Više opcija"</string>
@@ -1746,4 +1772,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Upišite vrijeme"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Prebacite u način unosa teksta za unos vremena."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Prebacite u način rada kao sat za unos vremena."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Želite li sačuvati u: <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Želite li sačuvati stavku <xliff:g id="TYPE">%1$s</xliff:g> u: <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Sačuvaj"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Ne, hvala"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"lozinka"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"adresa"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kreditna kartica"</string>
 </resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 47de685..66354e4 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"+999"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Contingut amagat"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Contingut amagat de conformitat amb la política"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Seguretat"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertes"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Mode segur"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Canvia al perfil personal"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Permet que l\'aplicació suprimeixi les dreceres de la pantalla d\'inici sense la intervenció de l\'usuari."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"desviació de les trucades sortints"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Permet que l\'aplicació vegi el número que s\'està marcant durant una trucada sortint, amb l\'opció de redirigir la trucada a un altre número o bé de cancel·lar-la completament."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"recepció de missatges de text (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permet que l\'aplicació rebi i processi missatges SMS. Això vol dir que l\'aplicació pot controlar o suprimir missatges que s\'han enviat al teu dispositiu sense mostrar-te\'ls."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"recepció de missatges de text (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Permet que l\'aplicació finalitzi processos d\'altres aplicacions en segon pla. Aquesta acció pot fer que altres aplicacions deixin d\'executar-se."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Aquesta aplicació pot mostrar-se a sobre d\'altres aplicacions"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Aquesta aplicació pot mostrar-se a sobre d\'altres aplicacions o d\'altres parts de la pantalla. Això pot interferir en l\'ús normal de les aplicacions i alterar la manera en què es mostren."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"Executar en segon pla"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Aquesta aplicació es pot executar en segon pla. Això consumeix la bateria més ràpidament."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"Utilitzar dades en segon pla"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Aquesta aplicació utilitza dades en segon pla. Això incrementa l\'ús de dades."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"fes que l\'aplicació s\'executi sempre"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Permet que l\'aplicació faci que parts de la seva memòria siguin persistents. Aquesta acció pot limitar la memòria disponible per a altres aplicacions i alentir la tauleta."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Permet que l\'aplicació faci que parts de la seva memòria siguin persistents. Aquesta acció pot limitar la memòria disponible per a altres aplicacions i alentir el televisor."</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"Mètode d\'introducció de text"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Accions de text"</string>
     <string name="email" msgid="4560673117055050403">"Correu electrònic"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"Truca"</string>
     <string name="map" msgid="5441053548030107189">"Mapa"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"Navega"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"L\'espai d\'emmagatzematge s\'està esgotant"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"És possible que algunes funcions del sistema no funcionin"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"No hi ha prou espai d\'emmagatzematge per al sistema. Comprova que tinguis 250 MB d\'espai lliure i reinicia."</string>
@@ -1173,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toca per seleccionar l\'idioma i el disseny"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> se superposa a altres aplicacions"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"L\'aplicació <xliff:g id="NAME">%s</xliff:g> s\'està superposant."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Algunes parts d\'aquesta aplicació seran visibles en tot moment. Si aquesta funció presenta problemes, desactiva-la."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DESACTIVA"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"S\'està preparant <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"S\'està comprovant si hi ha errors"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"S\'ha detectat <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1327,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Comparteix amb <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Llisca el dit. Mantén premut."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Llisca el dit per desbloquejar."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Connecta un auricular per escoltar les claus de la contrasenya en veu alta."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punt."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Torna a la pàgina d\'inici"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Mou cap a dalt"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Més opcions"</string>
@@ -1712,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Escriu l\'hora"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Canvia al mode d\'introducció de text per introduir l\'hora."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Canvia al mode de rellotge per introduir l\'hora."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Vols desar-ho a <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Vols desar la informació del camp <xliff:g id="TYPE">%1$s</xliff:g> a <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Desa"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"No, gràcies"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"contrasenya"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"adreça"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"targeta de crèdit"</string>
 </resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index bbe9632..048c7c6 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -250,6 +250,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Skrytý obsah"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Obsah skrytý zásadami"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Zabezpečení"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Upozornění"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Nouzový režim"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Systém Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Přepnout na osobní profil"</string>
@@ -298,6 +324,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Umožňuje aplikaci odebrat zástupce z plochy bez zásahu uživatele."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"přesměrování odchozích hovorů"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Umožňuje aplikaci sledovat při odchozích hovorech volaná čísla a přesměrovat hovor na jiné číslo nebo jej zcela zrušit."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"příjem textových zpráv (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Umožňuje aplikaci přijmout a zpracovat zprávy SMS. Znamená to, že aplikace může sledovat zprávy odeslané do vašeho zařízení nebo je smazat, aniž by se vám zobrazily."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"příjem textových zpráv (MMS)"</string>
@@ -326,14 +356,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Umožňuje aplikaci ukončit procesy na pozadí ostatních aplikací. Mohlo by dojít k zastavení ostatních aplikací."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Zobrazení přes ostatní aplikace"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Tato aplikace se může zobrazit přes ostatní aplikace a další části obrazovky. Může tak omezit použitelnost aplikací a změnit způsob jejich zobrazení."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"spuštění na pozadí"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Tato aplikace může být spuštěna na pozadí. Baterie se bude vybíjet rychleji."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"využití dat na pozadí"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Tato aplikace může využívat data na pozadí. Zvýší se využití dat."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"trvalé spuštění aplikace"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Umožňuje aplikaci uložit některé své části trvale do paměti. Může to omezit paměť dostupnou pro ostatní aplikace a zpomalit tak tablet."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Umožňuje aplikaci zapsat své jednotlivé části natrvalo do paměti. To může omezit paměť dostupnou pro ostatní aplikace a zpomalit tak televizi."</string>
@@ -1211,6 +1237,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Klepnutím vyberte jazyk a rozvržení"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AÁBCČDĎEÉĚFGHCHIÍJKLMNŇOÓPQRŘSŠTŤUÚVWXYÝZŽ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AÁBCČDĎEÉĚFGHCHIÍJKLMNŇOÓPQRŘSŠTŤUÚVWXYÝZŽ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"Aplikace <xliff:g id="NAME">%s</xliff:g> se může vykreslovat přes ostatní aplikace"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"Aplikace <xliff:g id="NAME">%s</xliff:g> se zobrazuje nahoře."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Části této aplikace mohou zůstat vždy viditelné. Pokud tato funkce nepracuje správně, vypněte ji."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"VYPNOUT"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Probíhá příprava úložiště <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Kontrola chyb"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Zjištěno nové úložiště <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1367,8 +1397,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Sdílet s aplikací <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Posuvník. Dotkněte se a podržte."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Odemknete posunutím prstu."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Chcete-li slyšet, které klávesy jste při zadávání hesla stiskli, připojte sluchátka."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Tečka."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Přejít na plochu"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Přejít nahoru"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Další možnosti"</string>
@@ -1772,4 +1800,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Zadejte čas"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Chcete-li zadat čas, přepněte na režim textu."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Chcete-li zadat čas, přepněte na režim hodin."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Uložit do služby <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Uložit položku <xliff:g id="TYPE">%1$s</xliff:g> do služby <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Uložit"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Ne, děkuji"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"heslo"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"adresa"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"platební karta"</string>
 </resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index d252f87..9939e91 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Indholdet er skjult"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Indholdet er skjult af politikken"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Sikkerhed"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Underretninger"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Sikker tilstand"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Skift til Tilpasset"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Tillader, at applikationen fjerner genveje på startskærmen uden brugerindgriben."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"omdirigere udgående opkald"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Tillader, at appen kan se det nummer, der ringes op til under et udgående opkald, og giver mulighed for at omdirigere opkaldet til et andet nummer eller afbryde opkaldet helt."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"modtage tekstbeskeder (sms)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Tillader, at appen kan modtage og behandle sms-beskeder. Det betyder, at appen kan overvåge eller slette de beskeder, der sendes til din enhed, uden at vise dem til dig."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"modtage tekstbeskeder (mms)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Tillader, at appen kan afslutte baggrundsprocesser for andre apps. Dette kan forårsage, at andre apps holder op med at virke."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Denne app kan vises oven på andre apps"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Denne app kan vises oven på andre apps eller andre dele af skærmen. Dette kan forstyrre den normale brug af appen og ændre visningen af andre apps."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"kør i baggrunden"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Denne app kan køre i baggrunden. Dette kan aflade batteriet hurtigere."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"brug data i baggrunden"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Denne app kan bruge data i baggrunden. Dette kan øge dataforbruget."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"sørge for, at appen altid kører"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Tillader, at appen gør dele af sig selv vedholdende i hukommelsen. Dette kan begrænse den tilgængelige hukommelse for andre apps, hvilket gør tabletten langsommere."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Giver appen lov til at gøre dele af sig selv vedholdende i hukommelsen. Dette kan begrænse den tilgængelige hukommelse for andre apps og derved gøre fjernsynet langsommere."</string>
@@ -1171,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tryk for at vælge sprog og layout"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> vises over andre apps"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"Appen <xliff:g id="NAME">%s</xliff:g> vises øverst."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Dele af denne app kan være synlig hele tiden. Deaktiver denne funktion, hvis den ikke fungerer korrekt."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"SLÅ FRA"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Forbereder <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Kontrollerer for fejl"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Der blev registreret et nyt <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1325,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Del med <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Glidende håndtag. Tryk og hold nede."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Glid hurtigt henover for at låse op."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Tilslut et headset for at høre tasterne blive læst højt ved angivelse af adgangskode."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punktum."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Naviger hjem"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Naviger op"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Flere valgmuligheder"</string>
@@ -1710,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Angiv klokkeslæt"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Skift til teksttilstand for at angive klokkeslæt."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Skift til urtilstand for at angive klokkeslæt."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Skal indholdet gemmes i <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Skal <xliff:g id="TYPE">%1$s</xliff:g> gemmes i <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Gem"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Nej tak"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"adgangskode"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"adresse"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kreditkort"</string>
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 013707b..507b358 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Inhalte ausgeblendet"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Inhalte aufgrund der Richtlinien ausgeblendet"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Sicherheit"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Warnmeldungen"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Abgesicherter Modus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-System"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Zu \"Privat\" wechseln"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Ermöglicht einer App das Entfernen von Verknüpfungen vom Startbildschirm ohne Eingriff des Nutzers"</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"Ausgehende Anrufe umleiten"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Ermöglicht der App die Erkennung der während eines ausgehenden Anrufs gewählten Nummer und gibt ihr die Möglichkeit, den Anruf an eine andere Nummer umzuleiten oder den Anruf ganz abzubrechen"</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"SMS empfangen"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Ermöglicht der App, SMS zu empfangen und zu verarbeiten. Das bedeutet, dass die App an dein Gerät gesendete Nachrichten überwachen und löschen kann, ohne sie dir anzuzeigen."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"MMS empfangen"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Ermöglicht der App, Hintergrundprozesse anderer Apps zu beenden. Das kann dazu führen, dass andere Apps nicht mehr ausgeführt werden."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"App kann über anderen Apps erscheinen"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Diese App kann über anderen Apps oder anderen Teilen des Bildschirms erscheinen. Dies kann sich auf die normale App-Nutzung und die Darstellung anderer Apps auswirken."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"Im Hintergrund ausführen"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Diese App kann im Hintergrund ausgeführt werden. Dadurch kann sich der Akku schneller entladen."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"Im Hintergrund Daten verwenden"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Diese App kann im Hintergrund Daten verwenden. Dadurch kann sich die Datennutzung erhöhen."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"App permanent ausführen"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Ermöglicht der App, Teile der eigenen App dauerhaft im Speicher abzulegen. Dies kann dazu führen, dass anderen Apps weniger Arbeitsspeicher zur Verfügung steht und das Tablet langsamer wird."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Ermöglicht der App, Teile der eigenen App dauerhaft im Speicher abzulegen. Dies kann dazu führen, dass anderen Apps weniger Arbeitsspeicher zur Verfügung steht und der Fernseher langsamer wird."</string>
@@ -1171,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Zum Auswählen von Sprache und Layout tippen"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> wird über anderen Apps eingeblendet"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"Die App \"<xliff:g id="NAME">%s</xliff:g>\" wird über anderen Apps angezeigt."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Teile dieser App werden die ganze Zeit eingeblendet. Wenn diese Funktion nicht richtig funktioniert, deaktiviere sie."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DEAKTIVIEREN"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> wird vorbereitet"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Nach Fehlern wird gesucht"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Neue <xliff:g id="NAME">%s</xliff:g> entdeckt"</string>
@@ -1325,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Mit <xliff:g id="APPLICATION_NAME">%s</xliff:g> teilen"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Schieberegler: Berühren und halten"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Zum Entsperren den Finger über den Bildschirm ziehen"</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Schließe ein Headset an, um das Passwort gesprochen zu hören."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punkt."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Zur Startseite navigieren"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Nach oben navigieren"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Weitere Optionen"</string>
@@ -1710,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Uhrzeit eingeben"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"In den Texteingabemodus wechseln, um die Uhrzeit einzugeben."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"In den Uhrzeitmodus wechseln, um die Uhrzeit einzugeben."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"In <xliff:g id="LABEL">%1$s</xliff:g> speichern?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> in <xliff:g id="LABEL">%2$s</xliff:g> speichern?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Speichern"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Nein danke"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"Passwort"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"Adresse"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"Kreditkarte"</string>
 </resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 525832c..fca99cb 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Κρυφό περιεχόμενο"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Το περιεχόμενο είναι κρυφό βάσει πολιτικής"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Ασφάλεια"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Ειδοποιήσεις"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Ασφαλής λειτουργία"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Σύστημα Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Μετάβαση σε προσωπικό προφίλ"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Επιτρέπει στην εφαρμογή την κατάργηση συντομεύσεων από την Αρχική οθόνη χωρίς την παρέμβαση του χρήστη."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"αναδρομολογεί τις εξερχόμενες κλήσεις"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Επιτρέπει στην εφαρμογή να βλέπει τον αριθμό που καλέσατε κατά τη διάρκεια μιας εξερχόμενης κλήσης με επιλογή ανακατεύθυνσης της κλήσης σε έναν διαφορετικό αριθμό ή διακοπής της κλήσης."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"λαμβάνει μηνύματα κειμένου (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Επιτρέπει στην εφαρμογή τη λήψη και την επεξεργασία μηνυμάτων SMS. Αυτό σημαίνει ότι η εφαρμογή θα μπορούσε να παρακολουθήσει ή να διαγράψει τα μηνύματα που αποστέλλονται στη συσκευή σας χωρίς αυτά να εμφανιστούν σε εσάς."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"λαμβάνει μηνύματα κειμένου (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Επιτρέπει στην εφαρμογή τον τερματισμό των διεργασιών παρασκηνίου άλλων εφαρμογών. Αυτό μπορεί να προκαλεί τη διακοπή λειτουργίας άλλων εφαρμογών."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Αυτή η εφαρμογή μπορεί να εμφανίζεται πάνω από άλλες εφαρμογές"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Αυτή η εφαρμογή μπορεί να εμφανίζεται πάνω από άλλες εφαρμογές ή άλλα τμήματα της οθόνης. Αυτό μπορεί να επηρεάσει την κανονική χρήση της εφαρμογής και να αλλάξει τον τρόπο με τον οποίο εμφανίζονται οι άλλες εφαρμογές."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"εκτέλεση στο παρασκήνιο"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Αυτή η εφαρμογή μπορεί να εκτελείται στο παρασκήνιο. Αυτό μπορεί να εξαντλήσει πιο γρήγορα την μπαταρία."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"χρήση δεδομένων στο παρασκήνιο"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Αυτή η εφαρμογή μπορεί να χρησιμοποιεί δεδομένα στο παρασκήνιο. Αυτό μπορεί να αυξήσει τη χρήση δεδομένων."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"επιτρέπει στην εφαρμογή να εκτελείται συνεχώς"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Επιτρέπει στην εφαρμογή να δημιουργεί μόνιμα τμήματα του εαυτού της στη μνήμη. Αυτό μπορεί να περιορίζει τη μνήμη που διατίθεται σε άλλες εφαρμογές, καθυστερώντας τη λειτουργία του tablet."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Επιτρέπει στην εφαρμογή να καθιστά τμήματά της μόνιμα στη μνήμη. Αυτό μπορεί να περιορίσει τη μνήμη που διατίθεται σε άλλες εφαρμογές, επιβραδύνοντας τη λειτουργία της τηλεόρασης."</string>
@@ -1171,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Πατήστε για να επιλέξετε γλώσσα και διάταξη"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"Η εφαρμογή <xliff:g id="NAME">%s</xliff:g> επικάλυψε άλλες εφαρμογές"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"Η εφαρμογή <xliff:g id="NAME">%s</xliff:g> επικαλύπτει άλλες."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Ορισμένα τμήματα αυτής της εφαρμογής μπορεί να παραμένουν συνεχώς ορατά. Εάν αυτή η λειτουργία δεν εκτελείται σωστά, απενεργοποιήστε την."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ΑΠΕΝΕΡΓΟΠΟΙΗΣΗ"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Προετοιμασία <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Έλεγχος για σφάλματα"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Εντοπίστηκε νέο μέσο αποθήκευσης <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1325,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Κοινή χρήση με <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Στοιχείο χειρισμού με δυνατότητα ολίσθησης. Αγγίξτε και πατήστε παρατεταμένα."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Σύρετε για ξεκλείδωμα."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Συνδέστε ακουστικά για να ακούσετε τα πλήκτρα του κωδικού πρόσβασης να εκφωνούνται."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Τελεία."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Πλοήγηση στην αρχική σελίδα"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Πλοήγηση προς τα επάνω"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Περισσότερες επιλογές"</string>
@@ -1710,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Πληκτρολογήστε την ώρα"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Κάντε εναλλαγή στη λειτουργία εισαγωγής κειμένου, για την εισαγωγή της ώρας."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Κάντε εναλλαγή στη λειτουργία ρολογιού, για την εισαγωγή της ώρας."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Αποθήκευση σε <xliff:g id="LABEL">%1$s</xliff:g>;"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Αποθήκευση <xliff:g id="TYPE">%1$s</xliff:g> σε <xliff:g id="LABEL">%2$s</xliff:g>;"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Αποθήκευση"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Όχι, ευχαριστώ"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"κωδικός πρόσβασης"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"διεύθυνση"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"πιστωτική κάρτα"</string>
 </resources>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 37fcfa1..d83f1fc 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Contents hidden"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Contents hidden by policy"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Security"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Alerts"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Switch to Personal"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Allows the application to remove Home screen shortcuts without user intervention."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"reroute outgoing calls"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Allows the app to see the number being dialled during an outgoing call with the option to redirect the call to a different number or abort the call altogether."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"receive text messages (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Allows the app to receive and process SMS messages. This means that the app could monitor or delete messages sent to your device without showing them to you."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"receive text messages (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Allows the app to end background processes of other apps. This may cause other apps to stop running."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"This app can appear on top of other apps"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"This app can appear on top of other apps or other parts of the screen. This may interfere with normal app usage and change the way that other apps appear."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"run in the background"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"This app can run in the background. This may drain battery faster."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"use data in the background"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"This app can use data in the background. This may increase data usage."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"make app always run"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Allows the app to make parts of itself persistent in memory. This can limit the memory available to other apps, slowing down the tablet."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Allows the app to make parts of itself persistent in memory. This can limit memory available to other apps slowing down the TV."</string>
@@ -1171,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tap to select language and layout"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> draw over other apps"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> app displaying on top."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Parts of this app may remain visible at all times. If this feature isn\'t working correctly, turn it off."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"TURN OFF"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Preparing <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Checking for errors"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"New <xliff:g id="NAME">%s</xliff:g> detected"</string>
@@ -1325,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Share with <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Sliding handle. Touch &amp; hold."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Swipe to unlock."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Plug in a headset to hear password keys spoken."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Dot"</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Navigate home"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Navigate up"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"More options"</string>
@@ -1710,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Type in time"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Switch to text input mode for the time input."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Switch to clock mode for the time input."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Save to <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Save <xliff:g id="TYPE">%1$s</xliff:g> to <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Save"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"No thanks"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"password"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"address"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"credit card"</string>
 </resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 37fcfa1..d83f1fc 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Contents hidden"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Contents hidden by policy"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Security"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Alerts"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Switch to Personal"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Allows the application to remove Home screen shortcuts without user intervention."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"reroute outgoing calls"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Allows the app to see the number being dialled during an outgoing call with the option to redirect the call to a different number or abort the call altogether."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"receive text messages (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Allows the app to receive and process SMS messages. This means that the app could monitor or delete messages sent to your device without showing them to you."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"receive text messages (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Allows the app to end background processes of other apps. This may cause other apps to stop running."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"This app can appear on top of other apps"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"This app can appear on top of other apps or other parts of the screen. This may interfere with normal app usage and change the way that other apps appear."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"run in the background"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"This app can run in the background. This may drain battery faster."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"use data in the background"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"This app can use data in the background. This may increase data usage."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"make app always run"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Allows the app to make parts of itself persistent in memory. This can limit the memory available to other apps, slowing down the tablet."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Allows the app to make parts of itself persistent in memory. This can limit memory available to other apps slowing down the TV."</string>
@@ -1171,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tap to select language and layout"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> draw over other apps"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> app displaying on top."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Parts of this app may remain visible at all times. If this feature isn\'t working correctly, turn it off."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"TURN OFF"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Preparing <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Checking for errors"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"New <xliff:g id="NAME">%s</xliff:g> detected"</string>
@@ -1325,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Share with <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Sliding handle. Touch &amp; hold."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Swipe to unlock."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Plug in a headset to hear password keys spoken."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Dot"</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Navigate home"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Navigate up"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"More options"</string>
@@ -1710,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Type in time"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Switch to text input mode for the time input."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Switch to clock mode for the time input."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Save to <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Save <xliff:g id="TYPE">%1$s</xliff:g> to <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Save"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"No thanks"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"password"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"address"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"credit card"</string>
 </resources>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 37fcfa1..d83f1fc 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Contents hidden"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Contents hidden by policy"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Security"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Alerts"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Switch to Personal"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Allows the application to remove Home screen shortcuts without user intervention."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"reroute outgoing calls"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Allows the app to see the number being dialled during an outgoing call with the option to redirect the call to a different number or abort the call altogether."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"receive text messages (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Allows the app to receive and process SMS messages. This means that the app could monitor or delete messages sent to your device without showing them to you."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"receive text messages (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Allows the app to end background processes of other apps. This may cause other apps to stop running."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"This app can appear on top of other apps"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"This app can appear on top of other apps or other parts of the screen. This may interfere with normal app usage and change the way that other apps appear."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"run in the background"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"This app can run in the background. This may drain battery faster."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"use data in the background"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"This app can use data in the background. This may increase data usage."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"make app always run"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Allows the app to make parts of itself persistent in memory. This can limit the memory available to other apps, slowing down the tablet."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Allows the app to make parts of itself persistent in memory. This can limit memory available to other apps slowing down the TV."</string>
@@ -1171,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tap to select language and layout"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> draw over other apps"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> app displaying on top."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Parts of this app may remain visible at all times. If this feature isn\'t working correctly, turn it off."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"TURN OFF"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Preparing <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Checking for errors"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"New <xliff:g id="NAME">%s</xliff:g> detected"</string>
@@ -1325,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Share with <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Sliding handle. Touch &amp; hold."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Swipe to unlock."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Plug in a headset to hear password keys spoken."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Dot"</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Navigate home"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Navigate up"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"More options"</string>
@@ -1710,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Type in time"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Switch to text input mode for the time input."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Switch to clock mode for the time input."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Save to <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Save <xliff:g id="TYPE">%1$s</xliff:g> to <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Save"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"No thanks"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"password"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"address"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"credit card"</string>
 </resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 74bfecb..42a92ad 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Contenidos ocultos"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Contenido oculto debido a la política"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Seguridad"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Cambiar al perfil personal"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Permite que la aplicación elimine accesos directos de la pantalla principal sin que el usuario intervenga."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"redireccionar llamadas salientes"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Permite que la aplicación vea el número marcado al realizar una llamada, con la opción de redirigir esta llamada a un número distinto o cancelarla completamente."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"recibir mensajes de texto (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permite que la aplicación reciba y procese mensajes SMS, lo que significa que podría controlar o eliminar mensajes enviados al dispositivo sin mostrártelos."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"recibir mensajes de texto (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Este permiso autoriza a la aplicación a interrumpir procesos en segundo plano de otras aplicaciones y puede hacer, por lo tanto, que esas aplicaciones dejen de ejecutarse."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Esta app puede superponerse a otras apps"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Esta app puede aparecer sobre otras apps o partes de la pantalla, lo que puede interferir con el uso normal de la app y cambiar la forma en que aparecen otras apps."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"ejecutarse en segundo plano"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Esta app puede ejecutarse en segundo plano, lo que podría agotar la batería más rápido."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"usar datos en segundo plano"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Esta app puede ejecutarse en segundo plano, lo que podría aumentar el uso de datos."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"hacer que la aplicación se ejecute siempre"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Permite que la aplicación haga que algunas de sus partes se mantengan persistentes en la memoria. Esto puede limitar la memoria disponible para otras aplicaciones y ralentizar la tablet."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Permite que la aplicación cree partes de sí misma que queden en la memoria. Esta opción puede limitar la memoria disponible para otras aplicaciones y reducir la velocidad de la TV."</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"Método de entrada"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Acciones de texto"</string>
     <string name="email" msgid="4560673117055050403">"Correo electrónico"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"Teléfono"</string>
     <string name="map" msgid="5441053548030107189">"Mapa"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"Explorar"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Queda poco espacio de almacenamiento"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Es posible que algunas funciones del sistema no estén disponibles."</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"No hay espacio suficiente para el sistema. Asegúrate de que haya 250 MB libres y reinicia el dispositivo."</string>
@@ -1173,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Presiona para seleccionar el idioma y el diseño"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> se muestra sobre otras apps"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> se muestra sobre otras apps"</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Es posible que ciertas partes de esta app permanezcan visibles todo el tiempo. Si esta función tiene problemas, desactívala."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DESACTIVAR"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Preparando el medio <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Verificando errores"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Se detectó un nuevo medio (<xliff:g id="NAME">%s</xliff:g>)."</string>
@@ -1327,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Compartir con <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Mantén presionado el controlador deslizante."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Desliza el dedo para desbloquear."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Conecta un auricular para escuchar las contraseñas."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punto"</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Desplazarse hasta la página principal"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Desplazarse hacia arriba"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Más opciones"</string>
@@ -1712,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Ingresa la hora"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Cambia al modo de entrada de texto para ingresar la hora."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Cambia al modo de reloj para ingresar la hora."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"¿Quieres guardar el contenido en <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"¿Quieres guardar el contenido de <xliff:g id="TYPE">%1$s</xliff:g> en <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Guardar"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"No, gracias"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"contraseña"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"dirección"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"tarjeta de crédito"</string>
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index eec4f15..c03e0d1 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt; 999"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Contenidos ocultos"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Contenidos ocultos por política"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Seguridad"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Cambiar a perfil personal"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Permite que la aplicación elimine accesos directos de la pantalla de inicio sin la intervención del usuario."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"redirigir llamadas salientes"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Permite que la aplicación vea el número que se marca al realizar una llamada con la opción de redirigir la llamada a otro número o cancelar la llamada."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"recibir mensajes de texto (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permite que la aplicación reciba y procese mensajes MMS, lo que significa que podría utilizar este permiso para controlar o eliminar mensajes enviados al dispositivo sin mostrárselos al usuario."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"recibir mensajes de texto (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Este permiso autoriza a la aplicación a interrumpir procesos en segundo plano de otras aplicaciones y puede hacer, por tanto, que esas aplicaciones dejen de ejecutarse."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Esta aplicación puede aparecer sobre otras aplicaciones"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Esta aplicación puede aparecer sobre otras aplicaciones u otras partes de la pantalla. Esto puede interferir con el uso normal de las aplicaciones y cambiar la forma en la que estas aparecen."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"ejecutarse en segundo plano"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Esta aplicación puede ejecutarse en segundo plano, pero es posible que la batería se agote más rápido."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"utilizar datos en segundo plano"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Esta aplicación puede utilizar datos en segundo plano, pero es posible que aumente el uso de datos."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"hacer que la aplicación se ejecute siempre"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Permite que la aplicación haga que algunas de sus partes se mantengan en la memoria. Esto puede limitar la cantidad de memoria disponible para otras aplicaciones y ralentizar el tablet."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Permite que la aplicación haga que algunas partes de sí misma queden persistentes en la memoria. Esto puede limitar la memoria disponible para otras aplicaciones, lo que podría ralentizar la TV."</string>
@@ -1171,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toca para seleccionar el idioma y el diseño"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> se muestra sobre otras aplicaciones"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> se muestra en primer plano."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Es posible que algunas partes de esta aplicación permanezcan visibles en todo momento. Desactiva esta función si no funciona correctamente."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DESACTIVAR"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Preparando <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Comprobando errores"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Nueva <xliff:g id="NAME">%s</xliff:g> detectada"</string>
@@ -1325,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Compartir con <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Mantén pulsado el icono de desbloqueo y deslízalo."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Desliza el dedo para desbloquear."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Conecta un auricular para escuchar las contraseñas."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punto"</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Ir al escritorio"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Desplazarse hacia arriba"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Más opciones"</string>
@@ -1710,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Escribe la hora"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Cambia al modo de introducción de texto para escribir la hora."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Cambia al modo de reloj para escribir la hora."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"¿Guardar en <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"¿Guardar <xliff:g id="TYPE">%1$s</xliff:g> en <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Guardar"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"No, gracias"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"contraseña"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"dirección"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"tarjeta de crédito"</string>
 </resources>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 704a6ae..4281c4f 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Sisu on peidetud"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Sisu on eeskirjadega peidetud"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Turvalisus"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Teatised"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Turvarežiim"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-süsteem"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Lülita isiklikule profiilile"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Lubab rakendusel eemaldada avaekraani otseteid ilma kasutaja sekkumiseta."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"marsruutige väljuvad kõned uuesti"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Lubab rakendusel näha, mis number valitakse väljahelistamisel, ning laseb suunata kõne teisele numbrile või selle üldse katkestada."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"võtke vastu tekstisõnumeid (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Võimaldab rakendusel vastu võtta ja töödelda SMS-sõnumeid. See tähendab, et rakendus võib jälgida või kustutada teie seadmele saadetud sõnumeid neid teile näitamata."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"võtke vastu tekstisõnumeid (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Võimaldab rakendusel lõpetada teiste rakenduste taustaprotsesse. See võib peatada teiste rakenduste töö."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"See rakendus võidakse kuvada teiste rakenduste peal"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"See rakendus võidakse kuvada teiste rakenduste või muude ekraani osade peal. See võib häirida tavapärast rakenduste kasutust ja muuta seda, kuidas teisi rakendusi kuvatakse."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"taustal käitamine"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Seda rakendust saab taustal käitada. See võib kiiremini akut kulutada."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"andmete taustal kasutamine"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"See rakendus saab andmeid taustal kasutada. See võib suurendada andmekasutust."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"Rakenduste pidev töös hoidmine"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Võimaldab rakendusel muuta oma osi mälus püsivaks. See võib piirata teistele (tahvelarvutit aeglasemaks muutvatele) rakendustele saadaolevat mälu."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Lubab rakendusel muuta enda osasid mälus püsiüksusteks. See võib piirata teistele rakendustele saadaolevat mälumahtu ja muuta teleri aeglasemaks."</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"Sisestusmeetod"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Tekstitoimingud"</string>
     <string name="email" msgid="4560673117055050403">"E-post"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"Telefon"</string>
     <string name="map" msgid="5441053548030107189">"Kaart"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"Sirvimine"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Talletusruum saab täis"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Mõned süsteemifunktsioonid ei pruugi töötada"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Süsteemis pole piisavalt talletusruumi. Veenduge, et seadmes oleks 250 MB vaba ruumi, ja käivitage seade uuesti."</string>
@@ -1173,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Puudutage keele ja paigutuse valimiseks"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSŠZŽTUVWÕÄÖÜXY"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSŠZŽTUVWÕÄÖÜXY"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"Rakendus <xliff:g id="NAME">%s</xliff:g> joonistab teiste rakenduste peale"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"Rakend. <xliff:g id="NAME">%s</xliff:g> kuvatakse kõige peal."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Selle rakenduse osad võivad alati nähtaval olla. Kui see funktsioon ei tööta korralikult, lülitage see välja."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"LÜLITA VÄLJA"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Üksuse <xliff:g id="NAME">%s</xliff:g> ettevalmistamine"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Vigade kontrollimine"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Tuvastati uus üksus <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1327,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Jaga rakendusega <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Libistamispide. Puudutage ja hoidke all."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Avamiseks tõmmake sõrmega."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Paroolide kuulamiseks ühendage peakomplekt."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punkt."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Liigu avalehele"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Liigu üles"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Rohkem valikuid"</string>
@@ -1712,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Sisestage kellaaeg"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Aktiveerige kellaaja sisestamiseks tekstisisestusrežiim."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Aktiveerige kellaaja sisestamiseks kellarežiim."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Kas salvestada sildiga <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Kas salvestada <xliff:g id="TYPE">%1$s</xliff:g> sildiga <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Salvesta"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Tänan, ei"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"parool"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"aadress"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"krediitkaart"</string>
 </resources>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 1803a95..fe45f88 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Edukiak ezkutatuta daude"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Gidalerro batzuk ezkutatu dira, gidalerroei jarraiki"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Segurtasuna"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Abisuak"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Modu segurua"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android sistema"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Aldatu profil pertsonalera"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Erabiltzaileak ezer egin gabe hasierako pantailako lasterbideak kentzeko aukera ematen die aplikazioei."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"irteerako deiak birbideratzea"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Irteerako deian markatutako zenbakia ikustea baimentzen die aplikazioei, deia beste zenbaki batera birbideratzeko edo deia bertan behera uzteko aukerarekin."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"testu-mezuak (SMSak) jasotzea"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"SMS mezuak jasotzeko eta prozesatzeko baimena ematen die aplikazioei. Horrela, aplikazioak gailura bidalitako mezuak kontrola eta ezaba ditzake zuri erakutsi gabe."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"testu-mezuak (MMSak) jasotzea"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Beste aplikazioen atzeko planoko prozesuak amaitzeko baimena ematen die aplikazioei. Horrela, agian aplikazio batzuk exekutatzeari utziko zaio."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Agertu beste aplikazio batzuen gainean"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Beste aplikazio batzuen edo pantailako beste zati batzuen gainean ager daiteke aplikazioa. Aplikazioaren funtzionamendu normala oztopa dezake eta beste aplikazio batzuen itxura alda dezake."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"atzeko planoan exekutatu"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Atzeko planoan exekuta liteke aplikazioa eta horrek bizkorrago agor lezake bateria."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"atzeko planoan datuak erabili"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Aplikazioak datuak erabil litzake atzeko planoan eta horrek datuen erabilera areago lezake."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"Izan aplikazioa beti abian"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Beren zati batzuk memoria modu iraunkorrean ezartzeko baimena ematen die aplikazioei. Horrela, beste aplikazioek erabilgarri duten memoria murritz daiteke eta tableta motel daiteke."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Beren zati batzuk memorian modu iraunkorrean aktibo uztea baimentzen die aplikazioei. Horrela, beste aplikazioek memoria gutxiago izan lezakete erabilgarri eta telebistak motelago funtziona lezake."</string>
@@ -1172,6 +1198,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Hizkuntza eta diseinua hautatzeko, sakatu hau"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> zerbitzuak beste aplikazio batzuk gainjarri ditu pantailan"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> gainjarri da pantailan."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Aplikazioaren atal batzuk ikusgai gera litezke uneoro. Eginbideak behar bezala funtzionatzen ez badu, desaktiba ezazu."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DESAKTIBATU"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> prestatzen"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Errorerik dagoen egiaztatzen"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"<xliff:g id="NAME">%s</xliff:g> berria hauteman da"</string>
@@ -1326,8 +1356,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Partekatu <xliff:g id="APPLICATION_NAME">%s</xliff:g> aplikazioarekin"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Lerratze-euskarria. Ukitu eta eutsi."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Pasatu hatza desblokeatzeko."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Konektatu entzungailua pasahitzaren teklak ozen entzuteko."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Puntu."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Nabigatu orri nagusira"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Nabigatu gora"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Aukera gehiago"</string>
@@ -1711,4 +1739,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Idatzi ordua"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Aldatu testu modura ordua zehazteko."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Aldatu erloju modura ordua zehazteko."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> zerbitzuan gorde?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="LABEL">%2$s</xliff:g> zerbitzuan gorde nahi duzu <xliff:g id="TYPE">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Gorde"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Ez, eskerrik asko"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"pasahitza"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"helbidea"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kreditu-txartela"</string>
 </resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index a23bf7e..345888d 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"بیشتر از 999"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"محتواها پنهان هستند"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"محتوا بر اساس خط‌مشی پنهان شده است"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"امنیت"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"هشدارها"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"حالت ایمن"</string>
     <string name="android_system_label" msgid="6577375335728551336">"‏سیستم Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"رفتن به نمایه شخصی"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"به برنامه اجازه می‌دهد میان‌برهای صفحه اصلی را بدون دخالت کاربر حذف کند."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"ترسیم مجدد مسیر تماس‌های خروجی"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"به برنامه اجازه می‌دهد عددی را که در طی یک تماس خروجی شماره‌گیری شده، ببیند و این اختیار را دارد که تماس را به شماره دیگری هدایت کند یا کلاً تماس را قطع کند."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"دریافت پیام‌های نوشتاری (پیامک)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"به برنامه اجازه می‌دهد پیامک‌ها را دریافت و پردازش کند. این یعنی برنامه می‌تواند پیام‌های ارسالی به دستگاه شما را بدون نمایش آن‌ها به شما حذف یا کنترل کند."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"دریافت پیام‌های نوشتاری (فراپیام)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"به برنامه امکان می‌دهد به فرآیندهای پس‌زمینه سایر برنامه‌ها پایان دهد. این ممکن است باعث شود سایر برنامه‌ها متوقف شوند."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"این برنامه می‌تواند روی برنامه‌های دیگر ظاهر شود"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"این برنامه می‌تواند روی برنامه‌های دیگر یا سایر قسمت‌های صفحه ظاهر شود. ممکن است در عملکرد معمول برنامه‌های دیگر اختلال ایجاد کند و شیوه نمایش آن‌ها را تغییر دهد."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"اجرا شدن در پس‌زمینه"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"این برنامه می‌تواند در پس‌زمینه اجرا شود. ممکن است شارژ باتری زودتر مصرف شود."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"مصرف داده در پس‌زمینه"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"این برنامه می‌تواند در پس‌زمینه داده مصرف کند. ممکن است مصرف داده افزایش یابد."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"همیشه برنامه اجرا شود"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"به برنامه امکان می‌دهد قسمت‌هایی از خود را در حافظه دائمی کند. این کار حافظه موجود را برای سایر برنامه‌ها محدود کرده و باعث کندی رایانهٔ لوحی می‌شود."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"به برنامه اجازه می‌دهد تا بخش‌هایی از خودش را در حافظه پایدار کند. ممکن است حافظه در دسترس سایر برنامه‌ها را محدود کند که باعث کند شدن تلویزیون می‌شود."</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"روش ورودی"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"عملکردهای متنی"</string>
     <string name="email" msgid="4560673117055050403">"رایانامه"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"تلفن"</string>
     <string name="map" msgid="5441053548030107189">"نقشه"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"مرور"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"حافظه درحال پر شدن است"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"برخی از عملکردهای سیستم ممکن است کار نکنند"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"فضای ذخیره‌سازی سیستم کافی نیست. اطمینان حاصل کنید که دارای ۲۵۰ مگابایت فضای خالی هستید و سیستم را راه‌اندازی مجدد کنید."</string>
@@ -1173,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"برای انتخاب زبان و چیدمان ضربه بزنید"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"نمایش <xliff:g id="NAME">%s</xliff:g> روی برنامه‌های دیگر"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"نمایش برنامه <xliff:g id="NAME">%s</xliff:g> در بالا."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"ممکن است قسمت‌هایی از این برنامه همیشه قابل مشاهده بمانند. اگر این قابلیت به‌درستی کار نمی‌کند، آن را خاموش کنید."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"خاموش کردن"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"در حال آماده‌سازی <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"در حال بررسی برای خطاها"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"<xliff:g id="NAME">%s</xliff:g> جدید شناسایی شد"</string>
@@ -1327,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"اشتراک‌گذاری با <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"اهرم کنترل حرکت. لمس کرده و نگهدارید."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"برای بازگشایی قفل، بلغزانید."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"برای شنیدن کلیدهای گذرواژه که با صدای بلند خوانده می‌شوند، هدست را وصل کنید."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"نقطه."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"رفتن به صفحهٔ اصلی"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"حرکت به بالا"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"سایر گزینه‌ها"</string>
@@ -1712,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"زمان را تایپ کنید"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"برای وارد کردن زمان، به حالت وارد کردن نوشتار تغییر وضعیت دهید."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"برای وارد کردن زمان، به حالت ساعت تغییر وضعیت دهید."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"در <xliff:g id="LABEL">%1$s</xliff:g> ذخیره شود؟"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> در <xliff:g id="LABEL">%2$s</xliff:g> ذخیره شود؟"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"ذخیره"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"نه سپاسگزارم"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"گذرواژه"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"نشانی"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"کارت‌ اعتباری"</string>
 </resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index bc036d8..b199b95 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Sisältö piilotettu"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Sisältö on piilotettu käytännön perusteella."</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Tietosuoja"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Ilmoitukset"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Suojattu tila"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-järjestelmä"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Siirry henkilökohtaiseen profiiliin"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Antaa sovelluksen poistaa aloitusruudun pikakuvakkeita ilman käyttäjän toimia."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"ohjaa uudelleen lähtevät puhelut"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Sallii sovelluksen nähdä numeron, joka valitaan lähtevää puhelua soitettaessa, ja antaa mahdollisuuden ohjata puhelun eri numeroon tai keskeyttää puhelun kokonaan."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"vastaanota tekstiviestejä (teksti)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Antaa sovelluksen vastaanottaa ja käsitellä tekstiviestejä. Sovellus voi valvoa tai poistaa laitteeseesi lähetettyjä viestejä näyttämättä niitä sinulle."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"vastaanota tekstiviestejä (multimedia)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Antaa sovelluksen sulkea muiden sovelluksien taustaprosesseja. Tämä voi sulkea muita sovelluksia."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Tämä sovellus voi näkyä muiden sovellusten päällä"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Tämä sovellus voi näkyä muiden sovellusten tai näytön muiden osien päällä. Tämä voi häiritä sovellusten tavallista käyttöä ja muuttaa tapaa, jolla muut sovellukset näkyvät."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"toimia taustalla"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Tämä sovellus voi toimia taustalla. Tämä saattaa kuluttaa enemmän akkua."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"käyttää dataa taustalla"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Tämä sovellus voi käyttää dataa taustalla. Tämä saattaa lisätä datankulutusta."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"sovelluksen asettaminen aina käynnissä olevaksi"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Antaa sovelluksen lisätä omia osiaan muistiin pysyvästi. Tämä voi rajoittaa muiden sovellusten käytettävissä olevaa muistia ja hidastaa tablet-laitteen toimintaa."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Antaa sovelluksen lisätä omia osiaan pysyvästi muistiin. Tämä voi rajoittaa muiden sovellusten käytettävissä olevaa muistia ja hidastaa television toimintaa."</string>
@@ -1171,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Valitse kieli ja asettelu koskettamalla."</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZÅÄÖ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> piirtää muiden sovellusten päälle"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"Sovellus <xliff:g id="NAME">%s</xliff:g> näkyy päällä"</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Osia sovelluksesta voi olla aina näkyvissä. Jos ominaisuus ei toimi oikein, poista se käytöstä."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"POISTA KÄYTÖSTÄ"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Valmistellaan kohdetta <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Tarkistetaan virheiden varalta."</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Uusi <xliff:g id="NAME">%s</xliff:g> on havaittu."</string>
@@ -1325,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Jaa sovelluksessa <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Liukuva valitsin. Kosketa pitkään."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Poista lukitus liu\'uttamalla."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Liitä kuulokkeet kuullaksesi, mitä näppäimiä painat kirjoittaessasi salasanaa."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Piste."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Siirry etusivulle"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Siirry ylös"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Lisää asetuksia"</string>
@@ -1710,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Kirjoita aika"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Vaihda ajan syöttämiseen tekstitilassa."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Vaihda ajan syöttämiseen kellotilassa."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Tallennetaanko kohteeseen <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Tallennetaanko <xliff:g id="TYPE">%1$s</xliff:g> kohteeseen <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Tallenna"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Ei kiitos"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"salasana"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"osoite"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"luottokortti"</string>
 </resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index aaeb685..1fd0f75 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Contenus masqués"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Contenu masqué conformément aux politiques"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Sécurité"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertes"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Mode sécurisé"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Système Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Passer au profil personnel"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Permet à l\'application de supprimer des raccourcis de la page d\'accueil sans intervention de l\'utilisateur."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"transférer les appels sortants"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Permet à l\'application de lire le numéro composé lors d\'un appel sortant et lui donne la possibilité de rediriger l\'appel vers un autre numéro ou d\'abandonner l\'appel."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"recevoir des messages texte"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permet à l\'application de recevoir et de traiter les messages texte. Cette autorisation lui donne la possibilité de surveiller ou de supprimer les messages envoyés à votre appareil sans vous les montrer."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"recevoir des messages multimédias"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Permet à l\'application de mettre fin aux processus d\'autres applications exécutés en arrière-plan. Cette autorisation peut interrompre l\'exécution d\'autres applications."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Cette application peut s\'afficher par-dessus d\'autres applications"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Cette application peut s\'afficher par-dessus d\'autres applications ou parties de l\'écran. Cela pourrait interférer avec l\'utilisation normale des applications et modifier la manière dont les autres applications s\'affichent à l\'écran."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"fonctionner en arrière-plan"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Cette application peut fonctionner en arrière-plan. Cela risque d\'épuiser la pile plus rapidement."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"utiliser des données en arrière-plan"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Cette application peut utiliser des données en arrière-plan. Cela risque d\'augmenter l\'utilisation des données."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"exécuter l\'application en continu"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Permet à l\'application de rendre certains de ces composants persistants dans la mémoire. Cette autorisation peut limiter la mémoire disponible pour d\'autres applications et ralentir la tablette."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Permet à l\'application de placer certaines de ses parties en permanence dans la mémoire. Cela peut limiter la mémoire disponible pour les autres applications et ralentir le téléviseur."</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"Mode de saisie"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Actions sur le texte"</string>
     <string name="email" msgid="4560673117055050403">"Courriel"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"Téléphone"</string>
     <string name="map" msgid="5441053548030107189">"Carte"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"Parcourir"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Espace de stockage bientôt saturé"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Il est possible que certaines fonctionnalités du système ne soient pas opérationnelles."</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Espace de stockage insuffisant pour le système. Assurez-vous de disposer de 250 Mo d\'espace libre, puis redémarrez."</string>
@@ -1173,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Touchez pour sélectionner la langue et la configuration du clavier"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> se superpose aux autres applications"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> s\'affiche par-dessus les autres"</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Certaines parties de cette application restent visibles en tout temps. Si cette option ne fonctionne pas correctement, désactivez-la."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DÉSACTIVER"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Préparation de « <xliff:g id="NAME">%s</xliff:g> » en cours"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Recherche d\'erreurs en cours..."</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Une nouvelle mémoire « <xliff:g id="NAME">%s</xliff:g> » a été détectée"</string>
@@ -1327,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Partager avec <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Poignée coulissante. Appuyez de manière prolongée."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Faites glisser votre doigt pour déverrouiller l\'appareil."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Branchez des écouteurs pour entendre l\'énoncé des touches lors de la saisie du mot de passe."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Point."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Revenir à l\'accueil"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Revenir en haut de la page"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Plus d\'options"</string>
@@ -1712,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Entrez l\'heure"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Passer au mode Entrée de texte pour entrer l\'heure."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Passer au mode Horloge pour entrer l\'heure."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Enregistrer sous <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Enregistrer <xliff:g id="TYPE">%1$s</xliff:g> sous <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Enregistrer"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Non, merci"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"mot de passe"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"adresse"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"carte de crédit"</string>
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index caebc32..aae5672 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Contenus masqués"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Contenu masqué conformément aux règles"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Sécurité"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertes"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Mode sécurisé"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Système Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Passer au profil personnel"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Permettre à l\'application de supprimer des raccourcis de l\'écran d\'accueil sans l\'intervention de l\'utilisateur"</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"transférer les appels sortants"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Permettre à l\'application de lire le numéro composé lors d\'un appel sortant, et lui donner la possibilité de rediriger l\'appel vers un autre numéro ou d\'abandonner l\'appel"</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"recevoir des messages texte (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permet à l\'application de recevoir et de traiter les SMS. Cette autorisation lui donne la possibilité de surveiller ou supprimer les messages envoyés à votre appareil sans vous les montrer."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"recevoir des messages texte (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Permet à l\'application de mettre fin aux processus d\'autres applications exécutés en arrière-plan. Cette autorisation peut interrompre l\'exécution d\'autres applications."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Cette application peut se superposer à d\'autres applications"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Cette application peut se superposer à d\'autres applications ou à d\'autres parties de l\'écran. Cela peut altérer l\'utilisation normale des applications et modifier l\'apparence des autres applications."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"s\'exécuter en arrière-plan"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Cette application peut s\'exécuter en arrière-plan, ce qui risque d\'épuiser la batterie plus rapidement."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"consommer des données en arrière-plan"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Cette application peut utiliser des données en arrière-plan, ce qui risque d\'augmenter la consommation des données."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"exécuter l\'application en continu"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Permet à l\'application de rendre certains de ces composants persistants dans la mémoire. Cette autorisation peut limiter la mémoire disponible pour d\'autres applications et ralentir la tablette."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Permet à l\'application d\'activer la persistance de certains de ces composants dans la mémoire. Cette fonctionnalité peut limiter l\'espace mémoire disponible pour les autres applications et ralentir ainsi le téléviseur."</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"Mode de saisie"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Actions sur le texte"</string>
     <string name="email" msgid="4560673117055050403">"E-mail"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"Téléphone"</string>
     <string name="map" msgid="5441053548030107189">"Carte"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"Parcourir"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Espace de stockage bientôt saturé"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Il est possible que certaines fonctionnalités du système ne soient pas opérationnelles."</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Espace de stockage insuffisant pour le système. Assurez-vous de disposer de 250 Mo d\'espace libre, puis redémarrez."</string>
@@ -1173,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Appuyer pour sélectionner la langue et la disposition"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> se superpose aux autres applications"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"Superposition de l\'application <xliff:g id="NAME">%s</xliff:g>"</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Certaines sections de cette application peuvent rester visibles en permanence. Si cette fonctionnalité ne s\'exécute pas correctement, désactivez-la."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DÉSACTIVER"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Préparation mémoire \"<xliff:g id="NAME">%s</xliff:g>\" en cours"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Recherche d\'erreurs"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Une nouvelle mémoire de stockage \"<xliff:g id="NAME">%s</xliff:g>\" a été détectée."</string>
@@ -1327,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Partager avec <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Poignée coulissante. Appuyez de manière prolongée."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Faites glisser votre doigt pour déverrouiller l\'appareil."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Branchez des écouteurs pour entendre l\'énoncé des touches lors de la saisie du mot de passe."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Point."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Retour à l\'accueil"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Parcourir vers le haut"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Plus d\'options"</string>
@@ -1712,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Indiquez l\'heure"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Passer en mode saisie de texte pour la saisie de l\'heure."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Passer en mode horloge pour la saisie de l\'heure."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Enregistrer dans \"<xliff:g id="LABEL">%1$s</xliff:g>\" ?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Enregistrer \"<xliff:g id="TYPE">%1$s</xliff:g>\" dans \"<xliff:g id="LABEL">%2$s</xliff:g>\" ?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Enregistrer"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Non, merci"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"mot de passe"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"adresse"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"carte de paiement"</string>
 </resources>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index c4bd1a8..bd1ee38 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Contido oculto"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Ocultouse contido por causa da política"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Seguranza"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Cambiar ao perfil persoal"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Permite á aplicación eliminar atallos da pantalla de inicio sen a intervención do usuario."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"redireccionar as chamadas saíntes"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Permite á aplicación ver o número que se está marcando durante unha chamada saínte coa opción de redirixir a chamada a un número diferente ou abortar a chamada."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"recibir mensaxes de texto (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permite á aplicación recibir e procesar mensaxes SMS. Isto significa que a aplicación pode supervisar ou eliminar mensaxes enviadas ao teu dispositivo sen mostrarchas."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"recibir mensaxes de texto (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Permite á aplicación finalizar procesos en segundo plano doutras aplicacións. É posible que esta acción provoque que outras aplicacións deixen de funcionar."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Esta aplicación pode aparecer sobre outras"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Esta aplicación pode aparecer sobre outras aplicacións ou outras partes da pantalla, polo que é posible que interfira no uso normal das aplicacións e modifique a forma en que se mostran."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"executar en segundo plano"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Esta aplicación pode executarse en segundo plano. Por este motivo, quizais se esgote antes a batería."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"usar datos en segundo plano"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Esta aplicación pode usar datos en segundo plano. Por este motivo, quizais aumente o uso de datos."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"facer que a aplicación se execute sempre"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Permite á aplicación converter partes súas como persistentes na memoria. Esta acción pode limitar a cantidade memoria dispoñible para outras aplicacións e reducir a velocidade de funcionamento da tableta."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Permite que a aplicación faga que algunhas das súas partes se manteñan na memoria. Esta acción pode limitar a cantidade de memoria dispoñible para outras aplicacións e reducir a velocidade da televisión."</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"Método de entrada"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Accións de texto"</string>
     <string name="email" msgid="4560673117055050403">"Correo electrónico"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"Teléfono"</string>
     <string name="map" msgid="5441053548030107189">"Mapa"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"Examinar"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Estase esgotando o espazo de almacenamento"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"É posible que algunhas funcións do sistema non funcionen"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Non hai almacenamento suficiente para o sistema. Asegúrate de ter un espazo libre de 250 MB e reinicia o dispositivo."</string>
@@ -1174,6 +1198,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toca para seleccionar o idioma e o deseño"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNÑOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNÑOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> superponse a outras aplicacións"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"A aplicación <xliff:g id="NAME">%s</xliff:g> móstrase enriba."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Partes desta aplicación poden permanecer visibles en todo momento. Se esta función non traballa correctamente, desactívaa."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DESACTIVAR"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Preparando a <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Comprobando se hai erros"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Detectouse unha <xliff:g id="NAME">%s</xliff:g> nova"</string>
@@ -1328,8 +1356,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Compartir con <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Mantén premida a icona de desbloqueo e pasa o dedo por ela."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Pasa o dedo para desbloquear."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Conecta uns auriculares para escoitar as teclas do contrasinal pronunciadas."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punto"</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Ir ao inicio"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Ir para arriba"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Máis opcións"</string>
@@ -1713,4 +1739,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Escribe a hora"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Cambia ao modo de entrada de texto para introducir a hora."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Cambiar ao modo de reloxo para introducir a hora."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Queres gardar o contido en: <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Queres gardar o contido (<xliff:g id="TYPE">%1$s</xliff:g>) en: <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Gardar"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Non, grazas"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"contrasinal"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"enderezo"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"tarxeta de crédito"</string>
 </resources>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 2662723..eb90c8c 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"સામગ્રીઓ છુપાવેલ છે"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"નીતિ દ્વારા સામગ્રી છુપાવાઈ"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"સુરક્ષા"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"ચેતવણીઓ"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"સુરક્ષિત મોડ"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android સિસ્ટમ"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"વ્યક્તિગત પર સ્વિચ કરો"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"એપ્લિકેશનને વપરાશકર્તા હસ્તક્ષેપ વગર હોમસ્ક્રીન શોર્ટકટ્સ દૂર કરવાની મંજૂરી આપે છે."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"આઉટગોઇંગ કૉલ્સને ફરીથી રૂટ કરો"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"એપ્લિકેશનને આઉટગોઇંગ કૉલ દરમિયાન કૉલને એક અલગ નંબર પર રીડાયરેક્ટ કરવા અથવા કૉલને સંપૂર્ણપણે છોડી દેવાનાં વિકલ્પ સાથે ડાયલ થઈ રહેલા નંબરને જોવાની મંજૂરી આપે છે."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"ટેક્સ્ટ સંદેશા (SMS) પ્રાપ્ત કરો"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"ઍપ્લિકેશનને SMS સંદેશા પ્રાપ્ત કરવાની અને તેના પર પ્રક્રિયા કરવાની મંજૂરી આપે છે. આનો અર્થ એ કે ઍપ્લિકેશન તમને દર્શાવ્યા વિના તમારા ઉપકરણ પર મોકલેલ સંદેશાઓનું નિરીક્ષણ કરી શકે છે અથવા કાઢી નાખી શકે છે."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ટેક્સ્ટ સંદેશા (MMS) પ્રાપ્ત કરો"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"એપ્લિકેશનને અન્ય ઍપ્લિકેશનોની પૃષ્ઠભૂમિ પ્રક્રિયા સમાપ્ત કરવાની મંજૂરી આપે છે. આનાથી અન્ય ઍપ્લિકેશનો ચાલવાથી બંધ થઈ શકે છે."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"આ ઍપ્લિકેશન, અન્ય ઍપ્લિકેશનોની ટોચ પર દેખાઈ શકે છે"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"આ ઍપ્લિકેશન, અન્ય ઍપ્લિકેશોની ટોચ પર અથવા સ્ક્રીનના અન્ય ભાગોમાં દેખાઈ શકે છે. આ સામાન્ય ઍપ્લિકેશન વપરાશમાં હસ્તક્ષેપ કરી શકે છે અને અન્ય ઍપ્લિકેશનોની દેખાવાની રીતને બદલી શકે છે."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"પૃષ્ઠભૂમિમાં ચલાવો"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"આ ઍપ્લિકેશન પૃષ્ઠભૂમિમાં ચાલી શકે છે. આનાથી બૅટરી ઝડપથી ખાલી થઈ શકે છે."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"પ઼ષ્ઠભૂમિમાં ડેટા વાપરો"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"આ ઍપ્લિકેશન પૃષ્ઠભૂમિમાં ડેટા વાપરી શકે છે. આનાથી ડેટાનો વપરાશ વધી શકે છે."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"એપ્લિકેશનને હંમેશા શરૂ રાખો"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"એપ્લિકેશનને મેમરીમાં પોતાના ભાગ સતત બનાવવાની મંજૂરી આપે છે. આ ટેબ્લેટને ધીમું કરીને અન્ય ઍપ્લિકેશનો પર ઉપલબ્ધ મેમરીને સીમિત કરી શકે છે."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"એપ્લિકેશનને મેમરીમાં પોતાના ભાગ સતત બનાવવાની મંજૂરી આપે છે. આ ટીવીને ધીમું કરીને અન્ય ઍપ્લિકેશનો પર ઉપલબ્ધ મેમરીને સીમિત કરી શકે છે."</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"ઇનપુટ પદ્ધતિ"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"ટેક્સ્ટ ક્રિયાઓ"</string>
     <string name="email" msgid="4560673117055050403">"ઇમેઇલ"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"ફોન"</string>
     <string name="map" msgid="5441053548030107189">"નકશો"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"બ્રાઉઝ કરો"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"સ્ટોરેજ સ્થાન સમાપ્ત થયું"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"કેટલાક સિસ્ટમ કાર્યો કામ કરી શકશે નહીં"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"સિસ્ટમ માટે પર્યાપ્ત સ્ટોરેજ નથી. ખાતરી કરો કે તમારી પાસે 250MB ખાલી સ્થાન છે અને ફરીથી પ્રારંભ કરો."</string>
@@ -1174,6 +1198,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ભાષા અને લેઆઉટ પસંદ કરવા માટે ટૅપ કરો"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> અન્ય ઍપ્લિકેશનો પર ડ્રો કરે છે"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> ઍપ્લિકેશન સૌથી ઉપર દેખાઈ રહી છે."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"આ ઍપ્લિકેશનના ભાગ હંમેશાં દૃશ્યક્ષમ રહી શકે છે. જો આ સુવિધા યોગ્ય રીતે કાર્ય કરી રહી ન હોય, તો તેને બંધ કરો."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"બંધ કરો"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> ને તૈયાર કરી રહ્યું છે"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"ભૂલો માટે તપાસી રહ્યું છે"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"નવું <xliff:g id="NAME">%s</xliff:g> મળ્યું"</string>
@@ -1328,8 +1356,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> સાથે શેર કરો"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"સ્લાઇડિંગ હેન્ડલ. ટચ કરો અને પકડો."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"અનલૉક કરવા માટે સ્વાઇપ કરો."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"પાસવર્ડ કીઝ બોલાતી સાંભળવા માટે હેડસેટ પ્લગ ઇન કરો."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"ડોટ."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"હોમ પર નેવિગેટ કરો"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"ઉપર નેવિગેટ કરો"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"વધુ વિકલ્પો"</string>
@@ -1713,4 +1739,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"સમય લખો"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"સમય દાખલ કરવા માટે ટેક્સ્ટ ઇનપુટ મોડમાં સ્વિચ કરો."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"સમય દાખલ કરવા માટે ઘડિયાળ મોડમાં સ્વિચ કરો."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> માં સાચવીએ?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> ને <xliff:g id="LABEL">%2$s</xliff:g> માં સાચવીએ?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"સાચવો"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"નહીં આભાર"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"પાસવર્ડ"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"સરનામું"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"ક્રેડિટ કાર્ડ"</string>
 </resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 287690a..bd1c585 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -148,7 +148,7 @@
     <string name="fcComplete" msgid="3118848230966886575">"सुविधा कोड पूर्ण."</string>
     <string name="fcError" msgid="3327560126588500777">"कनेक्‍शन समस्‍या या अमान्‍य सुविधा कोड."</string>
     <string name="httpErrorOk" msgid="1191919378083472204">"ठीक है"</string>
-    <string name="httpError" msgid="7956392511146698522">"कोई नेटवर्क त्रुटि हुई थी."</string>
+    <string name="httpError" msgid="7956392511146698522">"कोई नेटवर्क गड़बड़ी हुई थी."</string>
     <string name="httpErrorLookup" msgid="4711687456111963163">"URL नहीं मिल सका."</string>
     <string name="httpErrorUnsupportedAuthScheme" msgid="6299980280442076799">"साइट प्रमाणीकरण योजना समर्थित नहीं है."</string>
     <string name="httpErrorAuth" msgid="1435065629438044534">"प्रमाणीकृत नहीं किया जा सका."</string>
@@ -163,7 +163,7 @@
     <string name="httpErrorFile" msgid="2170788515052558676">"फ़ाइल पर नहीं पहुंचा जा सका."</string>
     <string name="httpErrorFileNotFound" msgid="6203856612042655084">"अनुरोधित फ़ाइल नहीं मिल सकी."</string>
     <string name="httpErrorTooManyRequests" msgid="1235396927087188253">"बहुत सारे अनुरोधों का संसाधन हो रहा है. बाद में पुन: प्रयास करें."</string>
-    <string name="notification_title" msgid="8967710025036163822">"<xliff:g id="ACCOUNT">%1$s</xliff:g> के लिए प्रवेश त्रुटि"</string>
+    <string name="notification_title" msgid="8967710025036163822">"<xliff:g id="ACCOUNT">%1$s</xliff:g> के लिए प्रवेश गड़बड़ी"</string>
     <string name="contentServiceSync" msgid="8353523060269335667">"समन्वयन"</string>
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"समन्वयन"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"बहुत से <xliff:g id="CONTENT_TYPE">%s</xliff:g> हटाए जाते हैं."</string>
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"छिपी हुई सामग्री"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"सामग्री पॉलिसी के द्वारा छिपी हुई है"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"सुरक्षा"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"सूचनाएं"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"सुरक्षित मोड"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android सिस्‍टम"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"व्यक्तिगत प्रोफ़ाइल में स्विच करें"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"एप्‍लिकेशन को उपयोगकर्ता के हस्‍तक्षेप के बिना होमस्‍क्रीन शॉर्टकट निकालने की अनुमति देता है."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"आउटगोइंग कॉल को कहीं और भेजें"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"ऐप्स को किसी कॉल को भिन्न नंबर पर रिडायरेक्ट करने या पूरी तरह से कॉल निरस्त करने के विकल्प के साथ आउटगोइंग कॉल के दौरान डायल किए जा रहे नंबर को देखने की अनुमति देती है."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"लेख संदेश (SMS) प्राप्त करें"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"ऐप्स  को SMS संदेशों को प्राप्‍त और संसाधित करने देता है. इसका अर्थ है कि ऐप्स  आपके डिवाइस पर भेजे गए संदेशों की निगरानी आपको दिखाए बिना कर सकता है और उन्‍हें हटा सकता है."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"लेख संदेश (MMS) प्राप्त करें"</string>
@@ -303,9 +333,9 @@
     <string name="permlab_sendSms" msgid="7544599214260982981">"SMS संदेश भेजें और देखें"</string>
     <string name="permdesc_sendSms" msgid="7094729298204937667">"ऐप्स  को SMS संदेशों को भेजने देता है. इसके परिणामस्वरूप अप्रत्‍याशित शुल्‍क लागू हो सकते हैं. दुर्भावनापूर्ण ऐप्स  आपकी पुष्टि के बिना संदेश भेजकर आपका धन व्‍यय कर सकते हैं."</string>
     <string name="permlab_readSms" msgid="8745086572213270480">"अपने लेख संदेश (SMS या MMS) पढ़ें"</string>
-    <string name="permdesc_readSms" product="tablet" msgid="4741697454888074891">"यह ऐप्लिकेशन आपके टैबलेट पर संग्रहीत सभी SMS (लेख) संदेश पढ़ सकता है."</string>
-    <string name="permdesc_readSms" product="tv" msgid="5796670395641116592">"यह ऐप्लिकेशन आपके टीवी पर संग्रहीत सभी SMS (लेख) संदेश पढ़ सकता है."</string>
-    <string name="permdesc_readSms" product="default" msgid="6826832415656437652">"यह ऐप्लिकेशन आपके फ़ोन पर संग्रहीत सभी SMS (लेख) संदेश पढ़ सकता है."</string>
+    <string name="permdesc_readSms" product="tablet" msgid="4741697454888074891">"यह ऐप्लिकेशन आपके टैबलेट पर संग्रहित सभी SMS (लेख) संदेश पढ़ सकता है."</string>
+    <string name="permdesc_readSms" product="tv" msgid="5796670395641116592">"यह ऐप्लिकेशन आपके टीवी पर संग्रहित सभी SMS (लेख) संदेश पढ़ सकता है."</string>
+    <string name="permdesc_readSms" product="default" msgid="6826832415656437652">"यह ऐप्लिकेशन आपके फ़ोन पर संग्रहित सभी SMS (लेख) संदेश पढ़ सकता है."</string>
     <string name="permlab_receiveWapPush" msgid="5991398711936590410">"लेख संदेश (WAP) प्राप्त करें"</string>
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"ऐप्स  को WAP संदेशों को प्राप्‍त और संसाधित करने देता है. इस अनुमति में आपको भेजे गए संदेशों की निगरानी आपको दिखाए बिना करने और हटाने की क्षमता शामिल है."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"चल रहे ऐप्स पुनर्प्राप्त करें"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"ऐप्स  को अन्‍य ऐप्स की पृष्ठभूमि प्रक्रियाओं को समाप्त करने देता है. यह अन्य ऐप्स  का चलना रोक सकता है."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"यह ऐप्लिकेशन दूसरे ऐप्लिकेशन के ऊपर दिखाई दे सकता है"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"यह ऐप्लिकेशन, दूसरे ऐप्लिकेशन के ऊपर या स्क्रीन के अन्य भागों पर दिखाई दे सकता है. इससे ऐप्लिकेशन के सामान्य उपयोग में बाधा आ सकती है और दूसरे ऐप्लिकेशन के दिखाई देने के तरीकों में बदलाव हो सकता है."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"बैकग्राउंड में चलता है"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"यह ऐप बैकग्राउंड में चल सकता है. इसके कारण बैटरी तेज़ी से खत्म हो सकती है."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"बैकग्राउंड में डेटा का उपयोग करता है"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"यह ऐप बैकग्राउंड में डेटा का उपयोग कर सकता है. इससे डेटा का उपयोग बढ़ सकता है."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"ऐप्स को हमेशा चलने वाला बनाएं"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"ऐप्स को मेमोरी में स्‍वयं के कुछ हिस्सों को लगातार बनाने की अनुमति देता है. यह अन्‍य ऐप्स  के लिए उपलब्‍ध स्‍मृति को सीमित कर टेबलेट को धीमा कर सकता है."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"ऐप को मेमोरी में स्‍वयं के दीर्घस्थायी भाग बनाने देती है. इससे अन्‍य ऐप्‍स के लिए उपलब्‍ध मेमोरी सीमित हो सकती है जिससे टीवी धीमा हो सकता है."</string>
@@ -345,13 +371,13 @@
     <string name="permdesc_broadcastSticky" product="tv" msgid="6839285697565389467">"ऐप को स्‍िटकी प्रसारण भेजने देती है, जो प्रसारण बंद होने के बाद भी बने रहते हैं. अत्‍यधिक उपयोग से टीवी धीमा या अस्‍थिर हो सकता है जिससे वह बहुत सारी मेमोरी का उपयोग कर सकता है."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"ऐप्स को स्‍टिकी प्रसारण भेजने देता है, जो प्रसारण समाप्त होने के बाद भी बने रहते हैं. अत्यधिक उपयोग, फ़ोन की बहुत अधिक मेमोरी का उपयोग करके उसे धीमा या अस्‍थिर कर सकता है."</string>
     <string name="permlab_readContacts" msgid="8348481131899886131">"अपने संपर्क पढ़ें"</string>
-    <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"ऐप्स  को आपके टेबलेट में संग्रहीत संपर्कों के डेटा को, साथ ही आपके द्वारा विशिष्ट व्यक्तियों को कॉल करने, ईमेल करने, या अन्‍य तरीके से डॉयलॉग करने की आवृत्ति को पढ़ने देता है. यह अनुमति ऐप्स  को आपके संपर्क डेटा को सहेजने देती है, और दुर्भावनापूर्ण ऐप्स  आपकी जानकारी के बिना संपर्क डेटा को साझा कर सकते हैं."</string>
-    <string name="permdesc_readContacts" product="tv" msgid="1839238344654834087">"ऐप को आपके टीवी पर संग्रहीत आपके संपर्कों का डेटा पढ़ने देती है, जिसमें आपके द्वारा विशिष्‍ट व्‍यक्‍तियों को कॉल करने, ईमेल भेजने या उनसे संचार करने की आवृत्‍ति भी शामिल होती है. यह अनुमति ऐप्‍स को आपका संपर्क डेटा सहेजने देती है और दुर्भावनापूर्ण ऐप्‍स संपर्क डेटा को आपकी जानकारी के बिना साझा कर सकते हैं."</string>
-    <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"ऐप्स  को आपके फ़ोन में संग्रहीत संपर्कों के डेटा को, साथ ही आपके द्वारा विशिष्ट व्यक्तियों को कॉल करने, ईमेल करने, या अन्‍य तरीके से डॉयलॉग करने की आवृत्ति को पढ़ने देता है. यह अनुमति ऐप्स  को आपके संपर्क डेटा को सहेजने देती है, और दुर्भावनापूर्ण ऐप्स  आपकी जानकारी के बिना संपर्क डेटा को साझा कर सकते हैं."</string>
+    <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"ऐप्स  को आपके टेबलेट में संग्रहित संपर्कों के डेटा को, साथ ही आपके द्वारा विशिष्ट व्यक्तियों को कॉल करने, ईमेल करने, या अन्‍य तरीके से डॉयलॉग करने की आवृत्ति को पढ़ने देता है. यह अनुमति ऐप्स  को आपके संपर्क डेटा को सहेजने देती है, और दुर्भावनापूर्ण ऐप्स  आपकी जानकारी के बिना संपर्क डेटा को साझा कर सकते हैं."</string>
+    <string name="permdesc_readContacts" product="tv" msgid="1839238344654834087">"ऐप को आपके टीवी पर संग्रहित आपके संपर्कों का डेटा पढ़ने देती है, जिसमें आपके द्वारा विशिष्‍ट व्‍यक्‍तियों को कॉल करने, ईमेल भेजने या उनसे संचार करने की आवृत्‍ति भी शामिल होती है. यह अनुमति ऐप्‍स को आपका संपर्क डेटा सहेजने देती है और दुर्भावनापूर्ण ऐप्‍स संपर्क डेटा को आपकी जानकारी के बिना साझा कर सकते हैं."</string>
+    <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"ऐप्स  को आपके फ़ोन में संग्रहित संपर्कों के डेटा को, साथ ही आपके द्वारा विशिष्ट व्यक्तियों को कॉल करने, ईमेल करने, या अन्‍य तरीके से डॉयलॉग करने की आवृत्ति को पढ़ने देता है. यह अनुमति ऐप्स  को आपके संपर्क डेटा को सहेजने देती है, और दुर्भावनापूर्ण ऐप्स  आपकी जानकारी के बिना संपर्क डेटा को साझा कर सकते हैं."</string>
     <string name="permlab_writeContacts" msgid="5107492086416793544">"अपने संपर्क बदलें"</string>
-    <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"ऐप्स  को आपके टेबलेट में संग्रहीत संपर्कों के डेटा को, साथ ही आपके द्वारा विशिष्ट व्यक्तियों को कॉल करने, ईमेल करने, या अन्‍य तरीके से डॉयलॉग करने की आवृत्ति को संशोधित करने देता है. यह अनुमति ऐप्स  को आपके संपर्क डेटा को हटाने देती है."</string>
-    <string name="permdesc_writeContacts" product="tv" msgid="5438230957000018959">"ऐप को आपके टीवी पर संग्रहीत आपके संपर्कों के बारे में संग्रहीत डेटा में बदलाव करने देती है, जिसमें आपके द्वारा विशिष्‍ट व्‍यक्‍तियों को कॉल करने, ईमेल भेजने या अन्‍य तरीकों से संचार किए जाने की आवृत्‍ति भी शामिल है. यह अनुमति ऐप्‍स को संपर्क डेटा हटाने देती है."</string>
-    <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"ऐप्स  को आपके फ़ोन में संग्रहीत संपर्कों के डेटा को, साथ ही आपके द्वारा विशिष्ट व्यक्तियों को कॉल करने, ईमेल करने, या अन्‍य तरीके से डॉयलॉग करने की आवृत्ति को संशोधित करने देता है. यह अनुमति ऐप्स  को आपके संपर्क डेटा को हटाने देती है."</string>
+    <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"ऐप्स  को आपके टेबलेट में संग्रहित संपर्कों के डेटा को, साथ ही आपके द्वारा विशिष्ट व्यक्तियों को कॉल करने, ईमेल करने, या अन्‍य तरीके से डॉयलॉग करने की आवृत्ति को संशोधित करने देता है. यह अनुमति ऐप्स  को आपके संपर्क डेटा को हटाने देती है."</string>
+    <string name="permdesc_writeContacts" product="tv" msgid="5438230957000018959">"ऐप को आपके टीवी पर संग्रहित आपके संपर्कों के बारे में संग्रहित डेटा में बदलाव करने देती है, जिसमें आपके द्वारा विशिष्‍ट व्‍यक्‍तियों को कॉल करने, ईमेल भेजने या अन्‍य तरीकों से संचार किए जाने की आवृत्‍ति भी शामिल है. यह अनुमति ऐप्‍स को संपर्क डेटा हटाने देती है."</string>
+    <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"ऐप्स  को आपके फ़ोन में संग्रहित संपर्कों के डेटा को, साथ ही आपके द्वारा विशिष्ट व्यक्तियों को कॉल करने, ईमेल करने, या अन्‍य तरीके से डॉयलॉग करने की आवृत्ति को संशोधित करने देता है. यह अनुमति ऐप्स  को आपके संपर्क डेटा को हटाने देती है."</string>
     <string name="permlab_readCallLog" msgid="3478133184624102739">"कॉल लॉग पढ़ें"</string>
     <string name="permdesc_readCallLog" msgid="3204122446463552146">"यह ऐप्लिकेशन आपका कॉल इतिहास पढ़ सकता है."</string>
     <string name="permlab_writeCallLog" msgid="8552045664743499354">"कॉल लॉग लिखें"</string>
@@ -361,9 +387,9 @@
     <string name="permlab_bodySensors" msgid="4683341291818520277">"शरीर संवेदक एक्सेस करें (जैसे हृदय गति मॉनीटर)"</string>
     <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"ऐप को आपकी शारीरिक स्‍थिति, जैसे आपकी हृदय गति पर नज़र रखने वाले संवेदकों का डेटा एक्‍सेस करने देती है."</string>
     <string name="permlab_readCalendar" msgid="6716116972752441641">"कैलेंडर इवेंट और विवरण पढ़ें"</string>
-    <string name="permdesc_readCalendar" product="tablet" msgid="4993979255403945892">"यह ऐप्लिकेशन आपके टैबलेट पर संग्रहीत सभी कैलेंडर इवेंट पढ़ सकता है और आपका कैलेंडर डेटा साझा कर सकता है या सहेज सकता है."</string>
-    <string name="permdesc_readCalendar" product="tv" msgid="8837931557573064315">"यह ऐप्लिकेशन आपके टीवी पर संग्रहीत सभी कैलेंडर इवेंट पढ़ सकता है और आपका कैलेंडर डेटा साझा कर सकता है या सहेज सकता है."</string>
-    <string name="permdesc_readCalendar" product="default" msgid="4373978642145196715">"यह ऐप्लिकेशन आपके फ़ोन पर संग्रहीत सभी कैलेंडर इवेंट पढ़ सकता है और आपका कैलेंडर डेटा साझा कर सकता है या सहेज सकता है."</string>
+    <string name="permdesc_readCalendar" product="tablet" msgid="4993979255403945892">"यह ऐप्लिकेशन आपके टैबलेट पर संग्रहित सभी कैलेंडर इवेंट पढ़ सकता है और आपका कैलेंडर डेटा साझा कर सकता है या सहेज सकता है."</string>
+    <string name="permdesc_readCalendar" product="tv" msgid="8837931557573064315">"यह ऐप्लिकेशन आपके टीवी पर संग्रहित सभी कैलेंडर इवेंट पढ़ सकता है और आपका कैलेंडर डेटा साझा कर सकता है या सहेज सकता है."</string>
+    <string name="permdesc_readCalendar" product="default" msgid="4373978642145196715">"यह ऐप्लिकेशन आपके फ़ोन पर संग्रहित सभी कैलेंडर इवेंट पढ़ सकता है और आपका कैलेंडर डेटा साझा कर सकता है या सहेज सकता है."</string>
     <string name="permlab_writeCalendar" msgid="8438874755193825647">"अपनी जानकारी के बि‍ना कैलेंडर इवेंट जोड़ें या संशोधि‍त करें और अति‍थि‍यों को ईमेल भेजें"</string>
     <string name="permdesc_writeCalendar" product="tablet" msgid="1675270619903625982">"यह ऐप्लिकेशन आपके टैबलेट पर मौजूद कैलेंडर इवेंट जोड़, निकाल या बदल सकता है. यह ऐप्लिकेशन ऐसे संदेश भेज सकता है जो कैलेंडर स्वामियों से आए हुए लग सकते हैं या यह स्वामियों को सूचित किए बिना इवेंट में बदलाव कर सकता है."</string>
     <string name="permdesc_writeCalendar" product="tv" msgid="9017809326268135866">"यह ऐप्लिकेशन आपके टीवी पर मौजूद कैलेंडर इवेंट जोड़, निकाल या बदल सकता है. यह ऐप्लिकेशन ऐसे संदेश भेज सकता है जो कैलेंडर स्वामियों से आए हुए लग सकते हैं या यह स्वामियों को सूचित किए बिना इवेंट में बदलाव कर सकता है."</string>
@@ -464,7 +490,7 @@
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"फ़िंगरप्रिंट हार्डवेयर उपलब्ध नहीं है."</string>
-    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"फ़िंगरप्रिंट को संग्रहीत नहीं किया जा सका. कृपया कोई मौजूदा फ़िंगरप्रिंट निकालें."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"फ़िंगरप्रिंट को संग्रहित नहीं किया जा सका. कृपया कोई मौजूदा फ़िंगरप्रिंट निकालें."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"फ़िंगरप्रिंट का समय समाप्त हो गया. पुनः प्रयास करें."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"फ़िंगरप्रिंट क्रियान्वयन रोक दिया गया."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"बहुत अधिक प्रयास कर लिए गए हैं. बाद में पुन: प्रयास करें."</string>
@@ -559,7 +585,7 @@
     <string name="policylab_expirePassword" msgid="5610055012328825874">"स्‍क्रीन लॉक पासवर्ड समाप्‍ति सेट करें"</string>
     <string name="policydesc_expirePassword" msgid="5367525762204416046">"यह बदलें कि स्‍क्रीन लॉक पासवर्ड, पिन या पैटर्न को कितने समय में बदला जाना चाहिए."</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"मेमोरी एन्‍क्रिप्‍शन सेट करें"</string>
-    <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"संग्रहीत ऐप्स डेटा को एन्क्रिप्ट किया जाना आवश्‍यक है."</string>
+    <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"संग्रहित ऐप्स डेटा को एन्क्रिप्ट किया जाना आवश्‍यक है."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"कैमरों को अक्षम करें"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"सभी डिवाइस कैमरों का उपयोग रोकें."</string>
     <string name="policylab_disableKeyguardFeatures" msgid="8552277871075367771">"कुछ स्‍क्रीन लॉक सुविधाओं को अक्षम करें"</string>
@@ -814,9 +840,9 @@
     <string name="permlab_readHistoryBookmarks" msgid="3775265775405106983">"अपने वेब बुकमार्क और इतिहास पढ़ें"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="8462378226600439658">"ऐप्स  को ब्राउज़र द्वारा विज़िट किए गए सभी URL के इतिहास, और सभी ब्राउज़र बुकमार्क पढ़ने देता है. ध्‍यान दें: यह अनुमति तृतीय-पक्ष ब्राउज़र या वेब ब्राउज़िंग क्षमताओं वाले अन्‍य ऐप्स  द्वारा लागू नहीं की जा सकती."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="3714785165273314490">"वेब बुकमार्क और इतिहास लिखें"</string>
-    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"ऐप्स  को आपके टेबलेट में संग्रहीत ब्राउज़र के इतिहास या बुकमार्क को संशोधित करने देता है. इससे ऐप्स  ब्राउज़र डेटा को मिटा सकता है या संशोधित कर सकता है. ध्‍यान दें: यह अनुमति तृतीय-पक्ष ब्राउज़र या वेब ब्राउज़िंग क्षमताओं वाले अन्‍य ऐप्स  द्वारा लागू नहीं की जा सकती."</string>
-    <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="7007393823197766548">"ऐप को आपके टीवी पर संग्रहीत ब्राउज़र के इतिहास या बुकमार्क में बदलाव करने देती है. इससे ऐप को ब्राउज़र डेटा में बदलाव करने या उसे हटाने की अनुमति मिल सकती है. ध्‍यान दें: यह अनुमति वेब ब्राउज़िंग क्षमताओं वाले तृतीय-पक्ष ब्राउज़र या अन्‍य ऐप्‍लिकेशन द्वारा लागू नहीं की जा सकती है."</string>
-    <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"ऐप्स  को आपके फ़ोन में संग्रहीत ब्राउज़र के इतिहास या बुकमार्क को संशोधित करने देता है. इससे ऐप्स  ब्राउज़र डेटा को मिटा सकता है या संशोधित कर सकता है. ध्‍यान दें: यह अनुमति तृतीय-पक्ष ब्राउज़र या वेब ब्राउज़िंग क्षमताओं वाले अन्‍य ऐप्स  द्वारा लागू नहीं की जा सकती."</string>
+    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"ऐप्स  को आपके टेबलेट में संग्रहित ब्राउज़र के इतिहास या बुकमार्क को संशोधित करने देता है. इससे ऐप्स  ब्राउज़र डेटा को मिटा सकता है या संशोधित कर सकता है. ध्‍यान दें: यह अनुमति तृतीय-पक्ष ब्राउज़र या वेब ब्राउज़िंग क्षमताओं वाले अन्‍य ऐप्स  द्वारा लागू नहीं की जा सकती."</string>
+    <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="7007393823197766548">"ऐप को आपके टीवी पर संग्रहित ब्राउज़र के इतिहास या बुकमार्क में बदलाव करने देती है. इससे ऐप को ब्राउज़र डेटा में बदलाव करने या उसे हटाने की अनुमति मिल सकती है. ध्‍यान दें: यह अनुमति वेब ब्राउज़िंग क्षमताओं वाले तृतीय-पक्ष ब्राउज़र या अन्‍य ऐप्‍लिकेशन द्वारा लागू नहीं की जा सकती है."</string>
+    <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"ऐप्स  को आपके फ़ोन में संग्रहित ब्राउज़र के इतिहास या बुकमार्क को संशोधित करने देता है. इससे ऐप्स  ब्राउज़र डेटा को मिटा सकता है या संशोधित कर सकता है. ध्‍यान दें: यह अनुमति तृतीय-पक्ष ब्राउज़र या वेब ब्राउज़िंग क्षमताओं वाले अन्‍य ऐप्स  द्वारा लागू नहीं की जा सकती."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"अलार्म सेट करें"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"ऐप्स को इंस्‍टॉल किए गए अलार्म घड़ी ऐप्स में अलार्म सेट करने देता है. हो सकता है कुछ अलार्म घड़ी ऐप्स में यह सुविधा न हो."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"ध्‍वनिमेल जोड़ें"</string>
@@ -1171,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"भाषा और लेआउट चुनने के लिए टैप करें"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> दूसरे ऐप पर आरेखण करते हैं"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> ऐप ऊपर दिखा रहा है."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"हो सकता है कि इस ऐप के कुछ हिस्से हर समय दिखाई पड़ें. अगर यह सुविधा ठीक तरह से काम नहीं कर रही है, तो इसे बंद कर दें."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"बंद करें"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> को तैयार किया जा रहा है"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"त्रुटियों की जांच कर रहा है"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"नए <xliff:g id="NAME">%s</xliff:g> का पता लगा"</string>
@@ -1254,7 +1284,7 @@
     <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"हमेशा-चालू VPN कनेक्ट हो रहा है…"</string>
     <string name="vpn_lockdown_connected" msgid="8202679674819213931">"हमेशा-चालू VPN कनेक्ट है"</string>
     <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"हमेशा-चालू VPN डिस्‍कनेक्‍ट है"</string>
-    <string name="vpn_lockdown_error" msgid="6009249814034708175">"हमेशा-चालू VPN त्रुटि"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"हमेशा-चालू VPN गड़बड़ी"</string>
     <string name="vpn_lockdown_config" msgid="5099330695245008680">"सेट करने के लिए टैप करें"</string>
     <string name="upload_file" msgid="2897957172366730416">"फ़ाइल चुनें"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"कोई फ़ाइल चुनी नहीं गई"</string>
@@ -1325,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> के साथ साझा करें"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"स्लाइडिंग हैंडल. स्पर्श करके रखें."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"अनलॉक करने के लिए स्‍वाइप करें."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"बोली गईं पासवर्ड कुंजियां सुनने के लिए हेडसेट प्‍लग इन करें."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"बिंदु."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"होम पर नेविगेट करें"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"ऊपर नेविगेट करें"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"अधिक विकल्प"</string>
@@ -1452,7 +1480,7 @@
     <string name="user_switching_message" msgid="2871009331809089783">"<xliff:g id="NAME">%1$s</xliff:g> पर स्विच किया जा रहा है…"</string>
     <string name="user_logging_out_message" msgid="8939524935808875155">"<xliff:g id="NAME">%1$s</xliff:g> द्वारा प्रस्‍थान किया जा रहा है…"</string>
     <string name="owner_name" msgid="2716755460376028154">"स्वामी"</string>
-    <string name="error_message_title" msgid="4510373083082500195">"त्रुटि"</string>
+    <string name="error_message_title" msgid="4510373083082500195">"गड़बड़ी"</string>
     <string name="error_message_change_not_allowed" msgid="1347282344200417578">"यह बदलाव आपके व्यवस्थापक द्वारा अनुमत नहीं है"</string>
     <string name="app_not_found" msgid="3429141853498927379">"इस कार्यवाही को प्रबंधित करने के लिए कोई ऐप्स  नहीं मिला"</string>
     <string name="revoke" msgid="5404479185228271586">"निरस्‍त करें"</string>
@@ -1540,7 +1568,7 @@
     <string name="mediasize_unknown_portrait" msgid="3088043641616409762">"अज्ञात पोर्ट्रेट"</string>
     <string name="mediasize_unknown_landscape" msgid="4876995327029361552">"अज्ञात लैंडस्केप"</string>
     <string name="write_fail_reason_cancelled" msgid="7091258378121627624">"रद्द कर दी गई"</string>
-    <string name="write_fail_reason_cannot_write" msgid="8132505417935337724">"सामग्री लिखने में त्रुटि"</string>
+    <string name="write_fail_reason_cannot_write" msgid="8132505417935337724">"सामग्री लिखने में गड़बड़ी"</string>
     <string name="reason_unknown" msgid="6048913880184628119">"अज्ञात"</string>
     <string name="reason_service_unavailable" msgid="7824008732243903268">"प्रिंट सेवा सक्षम नहीं है"</string>
     <string name="print_service_installed_title" msgid="2246317169444081628">"<xliff:g id="NAME">%s</xliff:g> सेवा इंस्टॉल की गई"</string>
@@ -1631,8 +1659,8 @@
     <string name="zen_mode_default_weekends_name" msgid="2786495801019345244">"सप्ताहांत"</string>
     <string name="zen_mode_default_events_name" msgid="8158334939013085363">"इवेंट"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> द्वारा म्यूट किया गया"</string>
-    <string name="system_error_wipe_data" msgid="6608165524785354962">"आपके डिवाइस के साथ कोई आंतरिक त्रुटि हुई और यह तब तक अस्‍थिर रह सकता है, जब तक आप फ़ैक्‍टरी डेटा रीसेट नहीं करते हैं."</string>
-    <string name="system_error_manufacturer" msgid="8086872414744210668">"आपके डिवाइस के साथ कोई आंतरिक त्रुटि हुई. विवरणों के लिए अपने निर्माता से संपर्क करें."</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"आपके डिवाइस के साथ कोई आंतरिक गड़बड़ी हुई और यह तब तक अस्‍थिर रह सकता है, जब तक आप फ़ैक्‍टरी डेटा रीसेट नहीं करते हैं."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"आपके डिवाइस के साथ कोई आंतरिक गड़बड़ी हुई. विवरणों के लिए अपने निर्माता से संपर्क करें."</string>
     <string name="stk_cc_ussd_to_dial" msgid="5202342984749947872">"USSD अनुरोध को DIAL अनुरोध में बदल दिया गया है."</string>
     <string name="stk_cc_ussd_to_ss" msgid="2345360594181405482">"USSD अनुरोध को SS अनुरोध में बदल दिया गया है."</string>
     <string name="stk_cc_ussd_to_ussd" msgid="7466087659967191653">"USSD अनुरोध को नए USSD अनुरोध में बदल दिया गया है."</string>
@@ -1710,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"समय लिखें"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"समय इनपुट के लिए लेख इनपुट मोड पर जाएं."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"समय इनपुट के लिए घड़ी मोड पर जाएं."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> में सहेजें?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> को <xliff:g id="LABEL">%2$s</xliff:g> में सहेजें?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"सहेजें"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"नहीं, धन्यवाद"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"पासवर्ड"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"पता"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"क्रेडिट कार्ड"</string>
 </resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 38148bf..26d54e4 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -247,6 +247,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Sadržaj je skriven"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Sadržaj je skriven prema pravilima"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Sigurnost"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Upozorenja"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Siguran način rada"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sustav Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Prijeđite na osobni"</string>
@@ -295,6 +321,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Aplikaciji omogućuje uklanjanje prečaca početnog zaslona bez intervencije korisnika."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"preusmjeravanje odlaznih poziva"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Omogućuje aplikaciji da vidi broj koji se bira prilikom odlaznog poziva uz opciju preusmjeravanja poziva na neki drugi broj ili prekidanja poziva."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"primanje tekstnih poruka (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Aplikaciji omogućuje primanje i obradu SMS poruka. To znači da aplikacija može nadzirati ili izbrisati poruke poslane na vaš uređaj, a da vam ih ne prikaže."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"primanje tekstnih poruka (MMS)"</string>
@@ -323,14 +353,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Aplikaciji omogućuje završavanje pozadinskih procesa drugih aplikacija. To može dovesti do prekida rada drugih aplikacija."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Aplikacija se može prikazivati povrh drugih aplikacija"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Aplikacija se može prikazivati povrh drugih aplikacija ili drugih dijelova zaslona. To može omesti uobičajenu upotrebu aplikacija i promijeniti način prikaza drugih aplikacija."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"izvoditi se u pozadini"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Aplikacija se može izvoditi u pozadini. To može brže trošiti bateriju."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"upotrebljavati podatke u pozadini"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Aplikacija može upotrebljavati podatke u pozadini. To može povećati potrošnju podataka."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"trajni rad aplikacije"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Aplikaciji omogućuje trajnu prisutnost nekih njenih dijelova u memoriji. To može ograničiti dostupnost memorije drugim aplikacijama i usporiti tabletno računalo."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Aplikaciji omogućuje trajnu ugradnju nekih svojih dijelova u memoriju. To može ograničiti memoriju raspoloživu drugim aplikacijama i usporiti televizor."</string>
@@ -1191,6 +1217,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dodirnite da biste odabrali jezik i raspored"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"Aplikacija <xliff:g id="NAME">%s</xliff:g> prikazuje se preko drugih aplikacija"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"Aplikacija <xliff:g id="NAME">%s</xliff:g> prikazuje se gore."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Dijelovi ove aplikacije mogu ostati vidljivi cijelo vrijeme. Ako ta značajka ne funkcionira pravilno, isključite je."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ISKLJUČI"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Priprema uređaja <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Traženje pogrešaka"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Otkriven je novi uređaj <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1346,8 +1376,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Dijeli s aplikacijom <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Klizna ručka. Dodirnite i držite."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Prijeđite prstima da biste otključali."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Priključite slušalice kako biste čuli izgovaranje tipki zaporke."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Točka."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Kreni na početnu"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Kreni gore"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Više opcija"</string>
@@ -1741,4 +1769,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Unesite vrijeme"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Prijeđite na način unosa teksta da biste unijeli vrijeme."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Prijeđite na način rada sata da biste unijeli vrijeme."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Želi te li to spremiti u aplikaciju <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Želite li spremiti <xliff:g id="TYPE">%1$s</xliff:g> u aplikaciju <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Spremi"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Ne, hvala"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"zaporku"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"adresu"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kreditnu karticu"</string>
 </resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index b172025..2e786e9 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Tartalom elrejtve"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"A tartalom irányelv miatt elrejtve"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Biztonság"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Értesítések"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Biztonsági üzemmód"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android rendszer"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Átváltás személyes profilra"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Lehetővé teszi egy alkalmazás számára, hogy felhasználói beavatkozás nélkül távolítson el parancsikonokat a kezdőképernyőről."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"kimenő hívások átirányítása"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Lehetővé teszi, hogy az alkalmazás kimenő híváskor lássa a tárcsázott számot, valamint a hívást átirányítsa egy másik számra, vagy megszakítsa."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"szöveges üzenetek (SMS) fogadása"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Lehetővé teszi az alkalmazás számára, hogy SMS-eket fogadjon és dolgozzon fel. Ez azt jelenti, hogy az alkalmazás megfigyelheti vagy törölheti a beérkező üzeneteket anélkül, hogy Ön látná azokat."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"szöveges üzenetek (MMS) fogadása"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Lehetővé teszi az alkalmazás számára, hogy megszüntesse más alkalmazások háttérben zajló folyamatait. Így előfordulhat, hogy egyes alkalmazások bezárulnak."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Az alkalmazás megjelenhet más alkalmazások fölött"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Az alkalmazás megjelenhet más alkalmazások fölött vagy a képernyő más részein. Ez befolyásolhatja a megszokott alkalmazáshasználatot, és módosíthatja más alkalmazások megjelenésének módját."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"futás a háttérben"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Ez az alkalmazás futhat a háttérben. Ez gyorsabban merítheti az akkumulátort."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"adathasználat a háttérben"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Ez az alkalmazás használhat adatkapcsolatot a háttérben. Ez növelheti az adathasználatot."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"az alkalmazás állandó futtatása"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Lehetővé teszi az alkalmazás számára, hogy egyes részeit állandó jelleggel eltárolja a memóriában. Ez korlátozhatja a többi alkalmazás számára rendelkezésre álló memóriát, és lelassíthatja a táblagépet."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Lehetővé teszi az alkalmazás számára azt, hogy egyes részeit állandóan a memóriában tartsa. Ez korlátozhatja a többi alkalmazás számára elérhető memóriát, ezáltal lelassulhat a tévé."</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"Beviteli mód"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Műveletek szöveggel"</string>
     <string name="email" msgid="4560673117055050403">"E-mail"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"Telefon"</string>
     <string name="map" msgid="5441053548030107189">"Térkép"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"Böngészés"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Kevés a szabad terület"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Előfordulhat, hogy néhány rendszerfunkció nem működik."</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Nincs elegendő tárhely a rendszerhez. Győződjön meg arról, hogy rendelkezik 250 MB szabad területtel, majd kezdje elölről."</string>
@@ -1173,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Koppintson a nyelv és a billentyűzetkiosztás kiválasztásához"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"A(z) <xliff:g id="NAME">%s</xliff:g> a többi alkalmazás felett jelenik meg"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"A(z) <xliff:g id="NAME">%s</xliff:g> legfelül jelenik meg."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Előfordulhat, hogy ezen alkalmazás egyes részei mindig láthatók maradnak. Ha ez a funkció nem működik megfelelően, kapcsolja ki."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"KIKAPCSOLÁS"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> előkészítése"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Hibák keresése"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Új <xliff:g id="NAME">%s</xliff:g> észlelve"</string>
@@ -1327,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Ossza meg a következő alkalmazással: <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Csúsztatható fogantyú. Érintse meg és tartsa."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"A feloldásához húzza végig az ujját."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Csatlakoztasson egy fülhallgatót, ha hallani szeretné a jelszó betűit felolvasva."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Pont."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Ugrás a főoldalra"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Felfele mozgás"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"További lehetőségek"</string>
@@ -1712,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Adja meg az időt"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Időbevitelhez váltson szövegbeviteli módba."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Időbevitelhez váltson óramódba."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Menti ide: <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> mentése ide: <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Mentés"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Nem, köszönöm"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"jelszó"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"cím"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"hitelkártya"</string>
 </resources>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 30a3330..0169647 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Բովանդակությունը թաքցված է"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Բովանդակությունը թաքցվել է ըստ քաղաքականության"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Անվտանգություն"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Ծանուցումներ"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Անվտանգ ռեժիմ"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android համակարգ"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Անցնել անհատական պրոֆիլին"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Հավելվածին թույլ է տալիս հեռացնել գլխավոր էկրանի դյուրանցումները՝ առանց օգտագործողի միջամտության:"</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"վերաուղղել ելքային զանգերը"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Թույլ է տալիս ծրագրին ելքային զանգի ընթացքում տեսնել արդեն հավաքած համարը՝ հնարավորություն տալով վերահղել կամ անջատել զանգը։"</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"ստանալ տեքստային հաղորդագրություններ (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Թույլ է տալիս հավելվածին ստանալ և մշակել SMS հաղորդագրությունները: Սա նշանակում է, որ հավելվածը կարող է ստուգել կամ ջնջել ձեր սարքին ուղարկված հաղորդագրությունները` առանց դրանք ձեզ ցուցադրելու:"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ստանալ տեքստային հաղորդագրություններ (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Թույլ է տալիս հավելվածին վերջ տալ այլ հավելվածների հետնաշերտի գործընթացները: Սա կարող է պատճառ դառնալ, որ այլ հավելվածները դադարեն աշխատել:"</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Այս հավելվածը կարող է ցուցադրվել այլ հավելվածների վերևում"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Այս հավելվածը կարող է ցուցադրվել այլ հավելվածների կամ էկրանի այլ հատվածների վերևում: Դա կարող է խոչընդոտել հավելվածի նորմալ օգտագործմանը և փոխել այլ հավելվածների տեսքը:"</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"աշխատել ֆոնում"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Այս հավելվածը կարող է աշխատել ֆոնում և ավելի արագ սպառել մարտկոցի լիցքը։"</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"տվյալներ օգտագործել ֆոնում"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Այս հավելվածը կարող է տվյալներ օգտագործել ֆոնում և ավելացնել տվյալների օգտագործման ծավալը։"</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"միշտ աշխատեցնել հավելվածը"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Թույլ է տալիս հավելվածին մնայուն դարձնել իր մասերը հիշողության մեջ: Սա կարող է սահմանափակել այլ հավելվածներին հասանելի հիշողությունը` դանդաղեցնելով պլանշետի աշխատանքը:"</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Թույլ է տալիս հավելվածին պահել իր տարրերը հիշողության մեջ: Սա կարող է սահմանափակել այլ հավելվածների համար հատկացված հիշողությունը և դանդաղեցնել հեռուստացույցի աշխատանքը:"</string>
@@ -727,9 +753,9 @@
     <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"Դուք <xliff:g id="NUMBER_0">%1$d</xliff:g> անգամ սխալ եք հավաքել ձեր ապակողպման սխեման: <xliff:g id="NUMBER_1">%2$d</xliff:g> անգամից ավել անհաջող փորձերից հետո ձեզ կառաջարկվի ապակողպել ձեր պլանշետը` օգտագործելով ձեր Google-ի մուտքի օգտանունը:\n \n Փորձեք կրկին <xliff:g id="NUMBER_2">%3$d</xliff:g> վայրկյանից:"</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="5316664559603394684">"Դուք <xliff:g id="NUMBER_0">%1$d</xliff:g> անգամ սխալ եք գծել ապակողպման նախշը: Եվս <xliff:g id="NUMBER_1">%2$d</xliff:g> անհաջող փորձից հետո հեռուստացույցը կկարողանաք ապակողպել միայն մուտք գործելով ձեր Google հաշիվ:\n\n Նորից փորձեք <xliff:g id="NUMBER_2">%3$d</xliff:g> վայրկյանից:"</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"Դուք <xliff:g id="NUMBER_0">%1$d</xliff:g> անգամ սխալ եք հավաքել ձեր ապակողպման սխեման: Եվս <xliff:g id="NUMBER_1">%2$d</xliff:g> անհաջող փորձից հետո ձեզ կառաջարկվի ապակողպել ձեր հեռախոսը` օգտագործելով Google-ի ձեր մուտքը:\n \n Փորձեք կրկին <xliff:g id="NUMBER_2">%3$d</xliff:g> վայրկյանից:"</string>
-    <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"Դուք <xliff:g id="NUMBER_0">%1$d</xliff:g> անգամ գրասալիկն ապակողպելու սխալ փորձ եք արել: Եվս <xliff:g id="NUMBER_1">%2$d</xliff:g> անհաջող փորձից հետո պլանշետը կվերակարգավորվի գործարանային լռելյայնի, և օգտատիրոջ բոլոր տվյալները կկորեն:"</string>
+    <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"Դուք <xliff:g id="NUMBER_0">%1$d</xliff:g> անգամ գրասալիկն ապակողպելու սխալ փորձ եք արել: Եվս <xliff:g id="NUMBER_1">%2$d</xliff:g> անհաջող փորձից հետո պլանշետը կվերակարգավորվի գործարանային լռելյայնի, և օգտատիրոջ բոլոր տվյալները կկորչեն:"</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="950408382418270260">"Դուք հեռուստացույցն ապակողպելու <xliff:g id="NUMBER_0">%1$d</xliff:g> սխալ փորձ եք կատարել: Եվս <xliff:g id="NUMBER_1">%2$d</xliff:g> անհաջող փորձից հետո հեռուստացույցի գործարանային կարգավորումները կվերականգնվեն և օգտատիրոջ բոլոր տվյալները կջնջվեն:"</string>
-    <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"Դուք <xliff:g id="NUMBER_0">%1$d</xliff:g> անգամ հեռախոսը ապակողպելու սխալ փորձ եք արել: Եվս <xliff:g id="NUMBER_1">%2$d</xliff:g> անհաջող փորձից հետո հեռախոսը կվերակարգավորվի գործարանային սկզբնադիր ռեժիմի, և օգտատիրոջ բոլոր տվյալները կկորեն:"</string>
+    <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"Դուք <xliff:g id="NUMBER_0">%1$d</xliff:g> անգամ հեռախոսը ապակողպելու սխալ փորձ եք արել: Եվս <xliff:g id="NUMBER_1">%2$d</xliff:g> անհաջող փորձից հետո հեռախոսը կվերակարգավորվի գործարանային սկզբնադիր ռեժիմի, և օգտատիրոջ բոլոր տվյալները կկորչեն:"</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="280873516493934365">"Դուք <xliff:g id="NUMBER">%d</xliff:g> անգամ սխալ փորձ եք արել գրասալիկն ապակողպելու համար: Գրասալիկն այժմ կվերակարգավորվի գործարանային լռելյայնի:"</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="3195755534096192191">"Դուք հեռուստացույցն ապակողպելու <xliff:g id="NUMBER">%d</xliff:g> սխալ փորձ եք կատարել: Այժմ կվերականգնվեն հեռուստացույցի գործարանային կարգավորումները:"</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"Դուք <xliff:g id="NUMBER">%d</xliff:g> անգամ հեռախոսը ապակողպելու սխալ փորձ եք արել: Հեռախոսն այժմ կվերակարգավորվի գործարանային սկզբնադիր ռեժիմի:"</string>
@@ -1171,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Հպեք՝ լեզուն և դասավորությունն ընտրելու համար"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉՊՋՌՍՎՏՐՑՈՒՓՔԵւՕՖ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> ցուցադրել այլ հավելվածների վերևում"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> հավելվածը ցուցադրվում է վերևում։"</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Այս հավելվածի որոշ հատվածներ կարող են միշտ տեսանելի լինել։ Եթե այս գործառույթն ինչպես հարկն է չի աշխատում, անջատեք այն։"</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ԱՆՋԱՏԵԼ"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g>-ի նախապատրաստում"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Սխալների ստուգում"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Հայտնաբերվել է նոր <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1325,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Կիսվել <xliff:g id="APPLICATION_NAME">%s</xliff:g>-ի հետ"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Սահող բռնակ: Հպել &amp; պահել:"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Սահեցրեք` ապակողպելու համար:"</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Միացրեք ականջակալները` արտասանվող գաղտնաբառը լսելու համար:"</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Կետ:"</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Ուղղվել տուն"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Ուղղվել վերև"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Ավելի շատ ընտրանքներ"</string>
@@ -1430,9 +1458,9 @@
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Դուք <xliff:g id="NUMBER_0">%1$d</xliff:g> անգամ սխալ եք մուտքագրել ձեր PIN-ը: \n\nՓորձեք կրկին <xliff:g id="NUMBER_1">%2$d</xliff:g> վայրկյանից:"</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Դուք սխալ եք մուտքագրել ձեր գաղտնաբառը <xliff:g id="NUMBER_0">%1$d</xliff:g> անգամ: \n\nՓորձեք կրկին <xliff:g id="NUMBER_1">%2$d</xliff:g> վայրկյանից:"</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Դուք <xliff:g id="NUMBER_0">%1$d</xliff:g> անգամ սխալ եք հավաքել ձեր ապակողպման սխեման: \n\nՓորձեք կրկին <xliff:g id="NUMBER_1">%2$d</xliff:g> վայրկյանից:"</string>
-    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Դուք <xliff:g id="NUMBER_0">%1$d</xliff:g> անգամ սխալ փորձ եք արել գրասալիկն ապակողպելու համար: <xliff:g id="NUMBER_1">%2$d</xliff:g> անգամից ավել անհաջող փորձերից հետո պլանշետը կվերակարգավորվի գործարանային լռելյայնի, և օգտատիրոջ բոլոր տվյալները կկորեն:"</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Դուք <xliff:g id="NUMBER_0">%1$d</xliff:g> անգամ սխալ փորձ եք արել գրասալիկն ապակողպելու համար: <xliff:g id="NUMBER_1">%2$d</xliff:g> անգամից ավել անհաջող փորձերից հետո պլանշետը կվերակարգավորվի գործարանային լռելյայնի, և օգտատիրոջ բոլոր տվյալները կկորչեն:"</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tv" msgid="5621231220154419413">"Դուք հեռուստացույցն ապակողպելու <xliff:g id="NUMBER_0">%1$d</xliff:g> սխալ փորձ եք կատարել: Եվս <xliff:g id="NUMBER_1">%2$d</xliff:g> անհաջող փորձից հետո հեռուստացույցի գործարանային կարգավորումները կվերականգնվեն և օգտատիրոջ բոլոր տվյալները կջնջվեն:"</string>
-    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Դուք <xliff:g id="NUMBER_0">%1$d</xliff:g> անգամ սխալ փորձ եք արել հեռախոսն ապակողպելու համար: <xliff:g id="NUMBER_1">%2$d</xliff:g> անգամից ավել անհաջող փորձերից հետո հեռախոսը կվերակարգավորվի գործարանային լռելյայնի, և օգտատիրոջ բոլոր տվյալները կկորեն:"</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Դուք <xliff:g id="NUMBER_0">%1$d</xliff:g> անգամ սխալ փորձ եք արել հեռախոսն ապակողպելու համար: <xliff:g id="NUMBER_1">%2$d</xliff:g> անգամից ավել անհաջող փորձերից հետո հեռախոսը կվերակարգավորվի գործարանային լռելյայնի, և օգտատիրոջ բոլոր տվյալները կկորչեն:"</string>
     <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Դուք <xliff:g id="NUMBER">%d</xliff:g> անգամ սխալ փորձ եք արել գրասալիկն ապակողպելու համար: Գրասալիկն այժմ կվերակարգավորվի գործարանային լռելյայնի:"</string>
     <string name="kg_failed_attempts_now_wiping" product="tv" msgid="4987878286750741463">"Դուք հեռուստացույցն ապակողպելու <xliff:g id="NUMBER">%d</xliff:g> սխալ փորձ եք կատարել: Այժմ կվերականգնվեն հեռուստացույցի գործարանային կարգավորումները:"</string>
     <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Դուք <xliff:g id="NUMBER">%d</xliff:g> անգամ սխալ փորձ եք արել հեռախոսն ապակողպելու համար: Հեռախոսն այժմ կվերակարգավորվի գործարանային լռելյայնի:"</string>
@@ -1710,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Մուտքագրեք ժամը"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Ժամը մուտքագրելու համար միացրեք տեքստի մուտքագրման ռեժիմը:"</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Ժամը մուտքագրելու համար միացրեք ժամացույցի ռեժիմը:"</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Պահե՞լ <xliff:g id="LABEL">%1$s</xliff:g>-ում։"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Պահե՞լ <xliff:g id="TYPE">%1$s</xliff:g> <xliff:g id="LABEL">%2$s</xliff:g>-ում։"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Պահել"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Ոչ"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"գաղտնաբառ"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"հասցե"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"վարկային քարտ"</string>
 </resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index d9a6b64..7363a78 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Konten tersembunyi"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Konten disembunyikan menurut kebijakan"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Keamanan"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Notifikasi"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Mode aman"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Beralih ke Pribadi"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Mengizinkan aplikasi menghapus pintasan Layar Utama tanpa tindakan dari pengguna."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"ubah rute panggilan keluar"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Memungkinkan aplikasi melihat nomor yang dihubungi saat melakukan panggilan keluar dengan opsi untuk mengalihkan panggilan ke nomor lain atau membatalkan panggilan sepenuhnya."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"terima pesan teks (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Memungkinkan aplikasi menerima dan memproses pesan SMS. Ini artinya aplikasi dapat memantau atau menghapus pesan yang dikirim ke perangkat Anda tanpa menunjukkannya kepada Anda."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"terima pesan teks (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Memungkinkan aplikasi mengakhiri proses latar belakang aplikasi lain. Izin ini dapat menyebabkan aplikasi lain berhenti berjalan."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Aplikasi ini dapat muncul di atas aplikasi lain"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Aplikasi ini dapat muncul di atas aplikasi lain atau bagian lain pada layar. Ini dapat mengganggu penggunaan aplikasi biasa dan mengubah kemunculan aplikasi lainnya."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"jalankan di latar belakang"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Aplikasi ini dapat berjalan di latar belakang. Dapat menghabiskan baterai lebih cepat."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"gunakan data di latar belakang"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Aplikasi ini dapat menggunakan data di latar belakang. Dapat meningkatkan penggunaan data."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"membuat apl selalu berjalan"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Memungkinkan aplikasi membuat bagian dari dirinya sendiri terus-menerus berada dalam memori. Izin ini dapat membatasi memori yang tersedia untuk aplikasi lain sehingga menjadikan tablet lambat."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Mengizinkan aplikasi untuk membuat bagian dirinya tetap berada dalam memori. Izin ini dapat membatasi memori yang tersedia untuk aplikasi lain yang membuat TV menjadi lambat."</string>
@@ -962,7 +988,7 @@
     <string name="email" msgid="4560673117055050403">"Email"</string>
     <string name="dial" msgid="4204975095406423102">"Telepon"</string>
     <string name="map" msgid="5441053548030107189">"Peta"</string>
-    <string name="browse" msgid="6079864138582486027">"Jelajahi"</string>
+    <string name="browse" msgid="6079864138582486027">"Buka browser"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Ruang penyimpanan hampir habis"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Beberapa fungsi sistem mungkin tidak dapat bekerja"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Penyimpanan tidak cukup untuk sistem. Pastikan Anda memiliki 250 MB ruang kosong, lalu mulai ulang."</string>
@@ -1171,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Ketuk untuk memilih bahasa dan tata letak"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> muncul di atas aplikasi lain"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"Aplikasi <xliff:g id="NAME">%s</xliff:g> muncul di atas."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Sebagian aplikasi ini mungkin selalu terlihat. Jika fitur ini tidak berfungsi dengan baik, nonaktifkan."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"NONAKTIFKAN"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Menyiapkan <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Memeriksa kesalahan"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"<xliff:g id="NAME">%s</xliff:g> baru terdeteksi"</string>
@@ -1325,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Berbagi dengan <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Gagang geser. Sentuh &amp; tahan."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Gesek untuk membuka kunci."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Pasang headset untuk mendengar tombol sandi yang diucapkan."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Titik."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Navigasi ke beranda"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Navigasi naik"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Opsi lainnya"</string>
@@ -1710,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Ketik waktu"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Beralih ke mode masukan teks untuk masukan waktu."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Beralih ke mode jam untuk masukan waktu."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Simpan ke <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Simpan <xliff:g id="TYPE">%1$s</xliff:g> ke <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Simpan"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Lain kali"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"sandi"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"alamat"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kartu kredit"</string>
 </resources>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 4d269b9e..3089d7a 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Innihald falið"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Efni falið með reglu"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Öryggi"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Tilkynningar"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Örugg stilling"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android kerfið"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Skipta yfir í persónulegt snið"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Leyfir forriti að fjarlægja flýtileiðir af heimaskjá án inngrips notanda."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"endurbeina hringdum símtölum"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Leyfir forriti að sjá símanúmerið þegar símtöl eru hringd, með möguleika á að beina símtalinu áfram á annað númer eða hætta alveg við símtalið."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"taka á móti textaskilaboðum (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Leyfir forriti að taka á móti og vinna úr SMS-skilaboðum. Þetta þýðir að forritið getur fylgst með eða eytt skilaboðum sem send eru í tækið án þess að birta þér þau."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"taka á móti textaskilaboðum (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Leyfir forriti að loka bakgrunnsferlum annarra forrita. Þetta getur valdið því að önnur forrit lokist."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Þetta forrit getur birst yfir öðrum forritum"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Þetta forrit getur birst yfir öðrum forritum eða öðrum hlutum skjásins. Þetta getur truflað venjulega notkun forrita og breytt því hvernig önnur forrit birtast."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"keyra í bakgrunni"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Þetta forrit getur verið í gangi í bakgrunni. Þetta gæti aukið á rafhlöðunotkunina."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"nota gögn í bakgrunni"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Þetta forrit getur notað gagnamagn í bakgrunni. Þetta gæti aukið notkun gagnamagns."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"láta forrit keyra stöðugt"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Leyfir forriti að gera hluta sjálfs sín varanlega í minni. Þetta getur takmarkað það minni sem býðst öðrum forritum og þannig hægt á spjaldtölvunni."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Leyfir forriti að gera hluta sjálfs sín varanlega í minni. Þetta getur takmarkað það minni sem býðst öðrum forritum og þannig hægt á sjónvarpinu."</string>
@@ -1172,6 +1198,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Ýttu til að velja tungumál og útlit"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AÁBCDÐEÉFGHIÍJKLMNOÓPQRSTUÚVWXYÝZÞÆÖ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AÁBCDÐEÉFGHIÍJKLMNOÓPQRSTUÚVWXYÝZÞÆÖ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> teiknar yfir önnur forrit"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> forritið birtist efst."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Hluti af þessu forriti gæti verið ávallt sýnilegur. Ef þessi eiginleiki virkar ekki sem skyldi skaltu slökkva á honum."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"SLÖKKVA"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Undirbýr <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Leitar að villum"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Nýtt <xliff:g id="NAME">%s</xliff:g> fannst"</string>
@@ -1326,8 +1356,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Deila með <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Sleði. Snertu og haltu."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Strjúktu til að opna."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Tengdu heyrnartól til að heyra stafi aðgangsorðsins lesna upphátt."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punktur."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Fara heim"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Fara upp"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Fleiri valkostir"</string>
@@ -1711,4 +1739,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Færðu inn tíma"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Skipta yfir í textastillingu til að færa inn tíma."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Skipta yfir í klukkustillingu til að færa inn tíma."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Vista í <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Vista <xliff:g id="TYPE">%1$s</xliff:g> í <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Vista"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Nei, takk"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"aðgangsorð"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"heimilisfang"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kreditkort"</string>
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 64d75a4..c7d1fa5 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Contenuti nascosti"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Contenuti nascosti in base alle norme"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Sicurezza"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Avvisi"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Modalità provvisoria"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Passa al profilo personale"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Consente all\'applicazione di rimuovere le scorciatoie della schermata Home automaticamente."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"reindirizzamento chiamate in uscita"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Consente all\'app di rilevare il numero digitato durante una chiamata in uscita, con la possibilità di reindirizzare la telefonata a un numero diverso o interromperla del tutto."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"ricezione messaggi di testo (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Consente all\'applicazione di ricevere ed elaborare messaggi SMS. Significa che l\'applicazione potrebbe monitorare o eliminare i messaggi inviati al tuo dispositivo senza mostrarteli."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ricezione messaggi di testo (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Consente all\'applicazione di terminare i processi in background di altre applicazioni. Ciò potrebbe causare l\'interruzione di altre applicazioni."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Questa app può essere visualizzata sopra ad altre app"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Questa app può essere visualizzata sopra ad altre app o altre parti dello schermo. Ciò potrebbe interferire con il normale utilizzo dell\'app e modificare la modalità di visualizzazione delle altre app."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"esecuzione in background"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Questa app può essere eseguita in background, velocizzando il consumo della batteria."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"utilizzo dei dati in background"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Questa app può usare dati in background, aumentando l\'utilizzo dei dati."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"esecuzione permanente delle applicazioni"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Consente all\'applicazione di rendere persistenti in memoria alcune sue parti. Ciò può limitare la memoria disponibile per altre applicazioni, rallentando il tablet."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Consente all\'app di rendere alcune sue parti persistenti nella memoria. Potrebbe così essere limitata la memoria a disposizione di altre app ed essere rallentata la TV."</string>
@@ -1171,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tocca per selezionare la lingua e il layout"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> visualizzata sopra altre app"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"App <xliff:g id="NAME">%s</xliff:g> visualizzata sulle altre."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Alcune parti di questa app possono rimanere sempre visibili. Disattiva la funzione qualora non funzionasse correttamente."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DISATTIVA"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Preparazione della <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Ricerca errori"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Nuova <xliff:g id="NAME">%s</xliff:g> rilevata"</string>
@@ -1325,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Condividi con <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Maniglia scorrevole. Tocca e tieni premuto."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Fai scorrere per sbloccare."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Collega gli auricolari per ascoltare la pronuncia dei tasti premuti per la password."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punto."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Vai alla home page"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Vai in alto"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Altre opzioni"</string>
@@ -1710,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Digita l\'ora"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Passa alla modalità di immissione testo per inserire l\'ora."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Passa alla modalità orologio per inserire l\'ora."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Salvare in <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Salvare <xliff:g id="TYPE">%1$s</xliff:g> in <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Salva"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"No, grazie"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"password"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"indirizzo"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"carta di credito"</string>
 </resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 0a6353b..12b2643 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -250,6 +250,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"התוכן מוסתר"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"התוכן מוסתר על ידי המדיניות"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"אבטחה"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"התראות"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"מצב בטוח"</string>
     <string name="android_system_label" msgid="6577375335728551336">"‏מערכת Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"עבור ל\'אישי\'"</string>
@@ -298,6 +324,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"מאפשר לאפליקציה להסיר קיצורי דרך במסך דף הבית ללא התערבות המשתמש."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"ניתוב מחדש של שיחות יוצאות"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"מאפשרת לאפליקציה לראות את המספר המחויג במהלך ביצוע שיחה יוצאת, עם האפשרות להפנות את השיחה למספר אחר או לבטל את השיחה לחלוטין."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"‏קבלת הודעות טקסט (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"‏מאפשר לאפליקציה לקבל ולעבד הודעות SMS. משמעות הדבר היא שהאפליקציה יכולה לעקוב אחר הודעות שנשלחו למכשיר או למחוק אותן מבלי להציג לך אותן."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"‏קבלת הודעות טקסט (MMS)"</string>
@@ -326,14 +356,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"מאפשר לאפליקציה להפסיק תהליכים ברקע המבוצעים על ידי אפליקציות אחרות. הדבר עשוי לגרום להפסקת פעולתם של אפליקציות אחרות."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"אפליקציה זו יכולה להופיע מעל אפליקציות אחרות."</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"אפליקציה זו יכולה להופיע מעל אפליקציות אחרות או בחלקים אחרים של המסך. ייתכן שהדבר יפריע לך להשתמש באפליקציות וישנה את הופעתן."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"פעולה ברקע"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"האפליקציה הזו יכולה לפעול ברקע. ייתכן שהסוללה תתרוקן מהר יותר במצב זה."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"שימוש בנתונים ברקע"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"האפליקציה הזו יכולה להשתמש בנתונים ברקע. ייתכן שצריכת הנתונים תעלה במצב זה."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"הגדרת האפליקציה לפעול תמיד"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"מאפשר לאפליקציה להפוך חלקים ממנו לקבועים בזיכרון. פעולה זו עשויה להגביל את הזיכרון הזמין לאפליקציות אחרים ולהאט את פעולת הטאבלט."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"מאפשרת לאפליקציה ליצור חלקים ממנה השמורים בזיכרון באופן עקבי. הדבר עלול להגביל את הזיכרון הזמין לאפליקציות אחרות וכתוצאה מכך להאט את פעולת הטלוויזיה."</string>
@@ -1000,11 +1026,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"שיטת קלט"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"פעולות טקסט"</string>
     <string name="email" msgid="4560673117055050403">"אימייל"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"טלפון"</string>
     <string name="map" msgid="5441053548030107189">"מפה"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"דפדף"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"שטח האחסון אוזל"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"ייתכן שפונקציות מערכת מסוימות לא יפעלו"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"‏אין מספיק שטח אחסון עבור המערכת. ודא שיש לך שטח פנוי בגודל 250MB התחל שוב."</string>
@@ -1213,6 +1237,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"הקש כדי לבחור שפה ופריסה"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> יכולה להופיע מעל אפליקציות אחרות"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> מופיעה מעל אפליקציות אחרות."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"חלקים באפליקציה הזו עשויים להופיע במסך כל הזמן. כבה את התכונה הזו אם היא לא עובדת כראוי."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"כבה"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"הכנת <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"בודק אם יש שגיאות"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"זוהה <xliff:g id="NAME">%s</xliff:g> חדש"</string>
@@ -1369,8 +1397,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"שתף עם <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"ידית להחלקה. גע והחזק."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"החלק לביטול נעילה."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"חבר אוזניות כדי לשמוע הקראה של מפתחות סיסמה."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"נקודה."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"נווט לדף הבית"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"נווט למעלה"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"אפשרויות נוספות"</string>
@@ -1774,4 +1800,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"הקלד את השעה"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"העבר למצב קלט טקסט לצורך הזנת השעה"</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"העבר למצב שעון לצורך הזנת השעה"</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"לשמור ב-<xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"לשמור <xliff:g id="TYPE">%1$s</xliff:g> ב-<xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"שמור"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"לא, תודה"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"סיסמה"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"כתובת"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"כרטיס אשראי"</string>
 </resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 70bb778..4f9f2c3 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"コンテンツが非表示"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"ポリシーによって非表示になっているコンテンツ"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"セキュリティ"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"通知"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"セーフモード"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Androidシステム"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"個人用に切り替える"</string>
@@ -292,12 +318,16 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"ユーザー操作なしでホーム画面のショートカットを削除することをアプリに許可します。"</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"発信先の変更"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"発信を別の番号に転送するか完全に中止するオプションで、発信中にダイヤルされた番号にアクセスすることをアプリに許可します。"</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"テキストメッセージ(SMS)の受信"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"SMSメッセージの受信と処理をアプリに許可します。これにより、アプリが端末に届いたメッセージを表示することなく監視または削除できるようになります。"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"テキストメッセージ(MMS)の受信"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"MMSメッセージの受信と処理をアプリに許可します。これにより、アプリが端末に届いたメッセージを表示することなく監視または削除できるようになります。"</string>
-    <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"緊急警報SMSの読み取り"</string>
-    <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"端末で受信した緊急警報SMSの読み取りをアプリに許可します。緊急警報は、緊急事態を警告する目的で一部の地域に配信されます。緊急警報の受信時に、悪意のあるアプリによって端末の動作や処理が妨害される恐れがあります。"</string>
+    <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"緊急速報メール SMS の読み取り"</string>
+    <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"端末で受信した緊急速報メール SMS の読み取りをアプリに許可します。緊急速報メールは、緊急事態を警告する目的で一部の地域に配信されます。緊急速報メールの受信時に、悪意のあるアプリによって端末の動作や処理が妨害される恐れがあります。"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"登録したフィードの読み取り"</string>
     <string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"現在同期されているフィードの詳細を取得することをアプリに許可します。"</string>
     <string name="permlab_sendSms" msgid="7544599214260982981">"SMSメッセージの送信と表示"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"他のアプリのバックグラウンドプロセスを終了することをアプリに許可します。これを許可すると、他のアプリの実行が停止する原因になることがあります。"</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"他のアプリの上に重ねて表示"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"このアプリは他のアプリの上に重ねて表示したり、画面の他の場所に表示したりできます。これにより、通常のアプリの使用が妨げられたり、他のアプリの表示が変わる場合があります。"</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"バックグラウンドでの実行"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"このアプリにバックグラウンドでの実行を許可します。許可すると電池消費量が増える場合があります。"</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"バックグラウンドでのデータ使用"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"このアプリにバックグラウンドでのデータ使用を許可します。許可するとデータ使用量が増える場合があります。"</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"アプリの常時実行"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"アプリにその一部をメモリに常駐させることを許可します。これにより他のアプリが使用できるメモリが制限されるため、タブレットの動作が遅くなることがあります。"</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"アプリにその一部をメモリに常駐させることを許可します。これにより他のアプリが使用できるメモリが制限されるため、テレビの動作が遅くなることがあります。"</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"入力方法"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"テキスト操作"</string>
     <string name="email" msgid="4560673117055050403">"メール"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"電話"</string>
     <string name="map" msgid="5441053548030107189">"地図"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"ブラウジング"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"空き容量わずか"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"一部のシステム機能が動作しない可能性があります"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"システムに十分な容量がありません。250MBの空き容量を確保して再起動してください。"</string>
@@ -1173,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"タップして言語とレイアウトを選択してください"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g>を他のアプリの上に重ねて表示"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g>を重ねて表示中"</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"このアプリの一部は常に表示され続けます。この機能が正常に動作しない場合は OFF にしてください。"</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"OFF にする"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g>を準備中"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"エラーを確認中"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"新しい<xliff:g id="NAME">%s</xliff:g>が検出されました"</string>
@@ -1327,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g>と共有"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"スライダーハンドルです。押し続けます。"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"ロック解除するにはスワイプします。"</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"パスワードのキーが音声出力されるのでヘッドセットを接続してください。"</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"ドット。"</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"ホームへ移動"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"上へ移動"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"その他のオプション"</string>
@@ -1712,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"時刻を入力"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"時刻をテキストで入力するモードに切り替えます。"</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"時刻を時計で入力するモードに切り替えます。"</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> に保存しますか?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g>を <xliff:g id="LABEL">%2$s</xliff:g> に保存しますか?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"はい"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"いいえ"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"パスワード"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"住所"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"クレジット カード"</string>
 </resources>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index e9e47af..1c974fe 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"შიგთავსი დამალულია"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"შიგთავსი დამალულია წესების შესაბამისად"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"უსაფრთხოება"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"გაფრთხილებები"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"უსაფრთხო რეჟიმი"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-ის სისტემა"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"პირად პროფილზე გადართვა"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"მთავარ ეკრანზე აპლიკაციისთვის მალსახმობების დამოუკიდებლად წაშლის უფლების მიცემა."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"გამავალი ზარების გადამისამართება"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"საშუალებას აძლევს აპს გამავალი ზარის დროს დაინახონ ზარის მიმღების ნომერი, ზარის სხვა მისამართზე გადამისამართებით ან ზარის საერთოდ შეწყვეტის საშუალებით."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"ტექსტური შეტყობინებების (SMS) მიღება"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"აპს შეეძლება SMS შეტყობინებების მიღება და დამუშავება. ეს ნიშნავს, რომ აპს შეეძლება თქვენ მოწყობილობაზე გამოგზავნილი შეტყობინებების მონიტორინგი და მათი წაშლა თქვენთვის ჩვენების გარეშე."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ტექსტური შეტყობინებების (MMS) მიღება"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"აპს შეეძლება, დაასრულოს სხვა აპების ფონური პროცესები. ამან შეიძლება სხვა აპების შეჩერება გამოიწვიოს."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"ამ აპს შეუძლია სხვა აპების ზემოდან გამოჩენა"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"ამ აპს შეუძლია სხვა აპების ზემოდან ან ეკრანის სხვა ნაწილებში გამოჩენა. ამან შეიძლება გავლენა იქონიოს აპის ნორმალურ გამოყენებაზე და სხვა აპების იერსახეზე."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"ფონურ რეჟიმში გაშვება"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"ამ აპს შეუძლია გაეშვას ფონურ რეჟიმში. ამან შეიძლება ბატარეა უფრო სწრაფად დაცალოს."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"მონაცემების ფონურ რეჟიმში გამოყენება"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"ამ აპს შეუძლია მონაცემების ფონურ რეჟიმში გამოყენება. ამან შეიძლება მონაცემთა მოხმარება გაზარდოს."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"დააყენოს აპი მუდმივად ჩართულად"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"აპს შეეძლება, საკუთარი ნაწილები მუდმივად ჩაწეროს მეხსიერებაში. ეს შეზღუდავს მეხსიერების ხელმისაწვდომობას სხვა აპებისთვის და შეანელებს ტაბლეტს."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"ნებას რთავს აპლიკაციას, მდგრადი გახადოს მეხსიერება. ამან შესაძლოა ტელევიზორის ფუნქიონირებისა და სხვა აპლიკაციების მეხსიერების შესუსტება გამოწივიოს."</string>
@@ -1171,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"შეეხეთ ენისა და განლაგების ასარჩევად"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g>-ის სხვა აპების ინტერფეისზე გადაწერა"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> აპის მიერ ზემოდან ჩვენება."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"აპის გარკვეული ნაწილები შესაძლოა ყოველთვის ხილული იყოს. თუ ეს ფუნქცია გამართულად არ მუშაობს, გამორთეთ."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"გამორთვა"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g>-ის მომზადება"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"შეცდომების შემოწმება"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"აღმოჩენილია ახალი <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1325,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"გაუზიარეთ <xliff:g id="APPLICATION_NAME">%s</xliff:g>-ს"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"გასრიალებით მართვა. შეეხეთ &amp; არ აუშვათ."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"განბლოკვისათვის გადაფურცლეთ"</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"შეაერთედ ყურსასმენები, პაროლის ღილაკები რომ გაიგოთ."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"წერტილი."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"მთავარზე ნავიგაცია"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"ზემოთ ნავიგაცია"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"მეტი ვარიანტები"</string>
@@ -1710,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"აკრიფეთ დრო"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"დროის შეყვანისთვის ტექსტის შეყვანის რეჟიმზე გადართვა."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"დროის შეყვანისთვის საათის რეჟიმზე გადართვა."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"გსურთ „<xliff:g id="LABEL">%1$s</xliff:g>“-ში შენახვა?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"გსურთ, შეინახოთ <xliff:g id="TYPE">%1$s</xliff:g> „<xliff:g id="LABEL">%2$s</xliff:g>“-ში?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"შენახვა"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"არა, გმადლობთ"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"პაროლი"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"მისამართი"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"საკრედიტო ბარათი"</string>
 </resources>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 2ff339c..c6bc07c 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Мазмұн жасырылған"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Мазмұн саясатқа сай жасырылған"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Қауіпсіздік"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Дабылдар"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Қауіпсіз режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android жүйесі"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Жекеге ауысу"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Қолданбаға Негізгі экранның төте пернелерін пайдаланушының қатысуынсыз алып тастау мүмкіндігін береді."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"шығыс қоңырауларды қайта бағыттау"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Қолданбаға шығыс қоңырау кезінде қоңырауды басқа нөмірге қайта бағыттау немесе қоңырауды мүлде доғару опциясы бар теріліп жатқан нөмірді көруге рұқсат береді."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"мәтін хабарларын алу (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Қолданбаға SMS хабарларын алу және өңдеу мүмкіндігін береді. Бұл қолданба құрылғыңызға жіберілген хабарларды сізге көрсетпестен қабылдай және жоя алады дегенді білдіреді."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"мәтін хабарларын алу (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Қолданбаға басқа қолданбалардың артқы шеп үрдістерін тоқтату мүмкіндігін береді. Бұл басқа қолданбалардың жұмысын тоқтатуы мүмкін."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Бұл қолданба өзге қолданбалардың үстінен шығуы мүмкін"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Бұл қолданба өзге қолданбалардың не экранның басқа бөліктерінің үстінен шығуы мүмкін. Бұл қолданбаны қалыпты пайдалануға кедергі келтіріп, өзге қолданбалардың басқаша шығуына әкелуі мүмкін."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"фондық режимде іске қосу"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Қолданба фондық режимде іске қосыла алады. Бұл – батарея зарядын тезірек бітіруі мүмкін."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"деректерді фондық режимде пайдалану"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Қолданба деректерді фондық режимде пайдалана алады. Бұл – деректер трафигін арттыруы мүмкін."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"қолданбаны әрқашан жұмыс істейтін ету"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Қолданбаға өзінің бөліктерін жадта бекіндіру мүмкіндігін береді. Бұл басқа қолданбалардың жадқа қол жетімділігін шектеп, планшетті баяулатуы мүмкін."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Қолданбаға өзінің бөліктерін жадта тұрақты етуге рұқсат етеді. Бұл басқа қолданбаларға қол жетімді жадты шектеп, ТД баяулатуы мүмкін."</string>
@@ -1172,6 +1198,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Тіл мен пернетақта схемасын таңдау үшін түртіңіз"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> басқа қолданбалардың үстінен көрсетіледі"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> қолданбасы жоғарғы жағында көрсетіледі."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Бұл қолданбаның бір бөлігі үнемі көрініп тұруы мүмкін. Егер бұл функция дұрыс жұмыс істемесе, оны өшіріңіз."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ӨШІРУ"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> дайындалуда"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Қателер тексерілуде"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Жаңа <xliff:g id="NAME">%s</xliff:g> анықталды"</string>
@@ -1326,8 +1356,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> қолданбасымен бөлісу"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Сырғитын тұтқа. Түртіп, ұстап тұрыңыз."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Бекітпесін ашу үшін сипап өтіңіз."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Құпия сөз пернелерін есту үшін құлақаспапты қосыңыз."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Нүкте."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Негізгі бетте жылжу"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Жоғары қарай жылжу"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Басқа опциялар"</string>
@@ -1711,4 +1739,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Уақытты енгізіңіз"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Уақытты енгізу үшін мәтін енгізу режиміне өтіңіз."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Уақытты енгізу үшін сағат режиміне өтіңіз."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> жүйесінде сақталсын ба?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> деректері <xliff:g id="LABEL">%2$s</xliff:g> жүйесінде сақталсын ба?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Сақтау"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Жоқ, рақмет"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"құпия сөз"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"мекенжай"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"несие картасы"</string>
 </resources>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 89559c7..aaeba97 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"បាន​លាក់​មាតិកា"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"មាតិកាត្រូវបានលាក់ដោយផ្អែកលើគោលការណ៍"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"សុវត្ថិភាព"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"ការ​ជូនដំណឹង"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"របៀប​​​សុវត្ថិភាព"</string>
     <string name="android_system_label" msgid="6577375335728551336">"ប្រព័ន្ធ​​ Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"ប្តូរទៅផ្ទាល់ខ្លួន"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"ឲ្យ​កម្មវិធី​លុប​ផ្លូវកាត់​អេក្រង់​ដើម​ដោយ​គ្មាន​អំពើ​ពី​អ្នកប្រើ។"</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"នាំ​ផ្លូវ​ការ​ហៅ​ចេញ​ឡើងវិញ"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"ឲ្យ​កម្មវិធី​ឃើញ​លេខ​ដែល​កំពុង​ត្រូវ​បាន​ហៅ​អំឡុង​ពេល​ហៅ​ចេញ​​ដោយ​ប្រើ​​ជម្រើស​ ដើម្បី​បញ្ជូន​​ការ​ហៅ​បន្ត​ទៅ​លេខ​ផ្សេង ឬ​បោះបង់​ការ​ហៅ​រួម​គ្នា។"</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"ទទួល​សារ​អត្ថបទ (សារ SMS​)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"ឲ្យ​កម្មវិធី​ទទួល និង​ដំណើរការ​​សារ MMS ។ មាន​ន័យ​ថា កម្មវិធី​អាច​ត្រួតពិនិត្យ​ ឬ​លុប​សារ​ដែល​បាន​ផ្ញើ​ទៅ​ឧបករណ៍​របស់​អ្នក ដោយ​​មិន​បង្ហាញ​អ្នក។"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ទទួល​សារ​អត្ថបទ (MMS​)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"ឲ្យ​កម្មវិធី​បញ្ឈប់​ដំណើរការ​​ផ្ទៃ​ខាង​ក្រោយ​នៃ​កម្មវិធី​ផ្សេងៗ​។ វា​អាច​ធ្វើ​ឲ្យ​កម្មវិធី​ផ្សេង​ឈប់​ដំណើរការ។"</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"កម្មវិធី​នេះ​អាច​បង្ហាញ​នៅ​ខាងលើ​កម្មវិធី​នានា"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"កម្មវិធី​នេះ​អាច​បង្ហាញ​​នៅ​ខាងលើ​កម្មវិធី​នានា​ ឬ​ខាងលើ​ផ្នែក​ផ្សេង​នៃ​អេក្រង់​។ វា​អាច​នឹង​មាន​ការ​រំខាន​ដល់​ការ​ប្រើប្រាស់​កម្មវិធី​ធម្មតា​ និង​ផ្លាស់ប្តូរ​របៀប​នៃ​ការ​បង្ហាញ​កម្មវិធី​ផ្សេងៗ​។"</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"ដំណើរការ​នៅផ្ទៃ​ខាងក្រោយ"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"កម្មវិធី​នេះ​អាច​ដំណើរការ​នៅផ្ទៃ​ខាងក្រោយ។ វា​អាច​បណ្តាល​ឲ្យ​ឆាប់​អស់​ថ្ម។"</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"ប្រើប្រាស់​ទិន្នន័យ​នៅផ្ទៃ​ខាង​ក្រោយ"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"កម្មវិធី​នេះ​អាច​ប្រើប្រាស់​ទិន្នន័យ​នៅផ្ទៃ​ខាង​ក្រោយ។ វា​អាច​បណ្តាល​ឲ្យ​ការប្រើប្រាស់​ទិន្នន័យ​កើន​ឡើង។"</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"ធ្វើ​ឲ្យ​កម្មវិធី​ដំណើរការ​ជា​និច្ច"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"ឲ្យ​កម្មវិធី​ធ្វើជា​ផ្នែក​​ស្ថិតស្ថេរ​ដោយ​ខ្លួន​ឯង​ក្នុង​អង្គ​ចងចាំ។ វា​អាច​កំណត់​អង្គ​ចងចាំ​ដែល​អាច​ប្រើ​បាន​ចំពោះ​កម្មវិធី​ផ្សេងៗ​ ដោយ​ធ្វើឲ្យ​កុំព្យូទ័រ​បន្ទះ​យឺត។"</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"អនុញ្ញាតឲ្យកម្មវិធីធ្វើឲ្យផ្នែកមួយចំនួនរបស់វាបន្តនៅក្នុងមេម៉ូរី។ វាអាចកម្រិតមេម៉ូរីដែលមានសម្រាប់កម្មវិធីផ្សេងទៀត ដែលធ្វើឲ្យទូរទស្សន៍ដើរយឺត។"</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"វិធីសាស្ត្រ​បញ្ចូល"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"សកម្មភាព​អត្ថបទ"</string>
     <string name="email" msgid="4560673117055050403">"អ៊ីមែល"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"ទូរសព្ទ"</string>
     <string name="map" msgid="5441053548030107189">"ផែនទី"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"រុក​រក"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"អស់​ទំហំ​ផ្ទុក"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"មុខងារ​ប្រព័ន្ធ​មួយ​ចំនួន​អាច​មិន​ដំណើរការ​"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"មិន​មាន​ទំហំ​ផ្ទុក​​គ្រប់​គ្រាន់​សម្រាប់​ប្រព័ន្ធ​។ សូម​ប្រាកដ​ថា​អ្នក​មាន​ទំហំ​ទំនេរ​ 250MB ហើយ​ចាប់ផ្ដើម​ឡើង​វិញ។"</string>
@@ -1175,6 +1199,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ប៉ះដើម្បីជ្រើសភាសា និងប្លង់"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> គូរ​ពីលើ​កម្មវិធី​ផ្សេង​ទៀត"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"កម្មវិធី <xliff:g id="NAME">%s</xliff:g> បង្ហាញ​នៅ​លើ​គេ។"</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"ផ្នែកខ្លះ​នៃ​កម្មវិធី​នេះនឹង​នៅតែ​អាច​មើល​ឃើញ​បានគ្រប់​ពេល។ ប្រសិនបើ​មុខងារនេះ​ដំណើរការ​មិន​ប្រក្រតី​ទេ សូម​បិទ​វា។"</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"បិទ"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"កំពុងរៀបចំ <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"កំពុងពិនិត្យរកកំហុស"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"បានរកឃើញ <xliff:g id="NAME">%s</xliff:g> ថ្មី"</string>
@@ -1329,8 +1357,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"ចែក​រំលែក​ជា​មួយ <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"គ្រប់គ្រង​ការ​រុញ។ ប៉ះ &amp; សង្កត់។"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"អូស​ ដើម្បី​ដោះ​សោ។"</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"ដោត​កាស​ដើម្បី​ស្ដាប់​ពាក្យ​សម្ងាត់​បាន​និយាយ។"</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Dot."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"រកមើល​ទៅ​ដើម"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"រកមើល​ឡើងលើ"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"ជម្រើស​ច្រើន​ទៀត"</string>
@@ -1714,4 +1740,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"វាយ​បញ្ចូល​ម៉ោង"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"ប្តូរ​ទៅ​មុខងារ​បញ្ចូល​អក្សរ​សម្រាប់​ការ​បញ្ចូល​ម៉ោង។"</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"ប្តូរ​ទៅ​មុខងារ​នាឡិកា​សម្រាប់​ការ​បញ្ចូល​ម៉ោង។"</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"រក្សា​ទុក​ទៅ​ក្នុង <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"រក្សាទុក <xliff:g id="TYPE">%1$s</xliff:g> ​ទៅ​ក្នុង <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"រក្សាទុក"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"ទេ អរគុណ"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"ពាក្យ​សម្ងាត់"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"អាសយដ្ឋាន"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"បណ្ណ​ឥណទាន"</string>
 </resources>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 7e942fd..4f14a55 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"ವಿಷಯಗಳನ್ನು ಮರೆಮಾಡಲಾಗಿದೆ"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"ನೀತಿಯಿಂದ ಮರೆಮಾಡಲಾಗಿರುವ ವಿಷಯಗಳು"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"ಭದ್ರತೆ"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"ಎಚ್ಚರಿಕೆಗಳು"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"ಸುರಕ್ಷಿತ ಮೋಡ್"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android ಸಿಸ್ಟಂ"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"ವೈಯಕ್ತಿಕಗೆ ಬದಲಿಸಿ"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"ಬಳಕೆದಾರರ ಮಧ್ಯಸ್ಥಿಕೆ ಇಲ್ಲದೆಯೇ ಹೋಮ್‌ಸ್ಕ್ರೀನ್ ಶಾರ್ಟ್‌ಕಟ್‌ಗಳನ್ನು ತೆಗೆದುಹಾಕಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"ಹೊರಹೋಗುವ ಕರೆಗಳ ಮಾರ್ಗ ಬದಲಿಸಿ"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"ಬೇರೊಂದು ಸಂಖ್ಯೆಗೆ ಕರೆಯನ್ನು ಮರುನಿರ್ದೇಶಿಸಲು ಆಯ್ಕೆಯ ಜೊತೆಗೆ ಹೊರ ಹೋಗುವ ಕರೆಯ ಸಮಯದಲ್ಲಿ ಡಯಲ್‌ ಮಾಡಿದ ಸಂಖ್ಯೆಯನ್ನು ನೋಡಲು ಅಪ್ಲಿಕೇಶನ್‌‌ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"ಪಠ್ಯ ಸಂದೇಶಗಳನ್ನು ಸ್ವೀಕರಿಸಿ (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"SMS ಸಂದೇಶಗಳನ್ನು ಸ್ವೀಕರಿಸಲು ಮತ್ತು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ. ಇದರರ್ಥ, ನಿಮ್ಮ ಸಾಧನಕ್ಕೆ ಕಳುಹಿಸಲಾಗಿರುವ ಸಂದೇಶಗಳನ್ನು ನಿಮಗೆ ತೋರಿಸದೆಯೇ, ಅಪ್ಲಿಕೇಶನ್ ಅವುಗಳನ್ನು ಮಾನಿಟರ್ ಮಾಡಬಹುದು ಅಥವಾ ಅಳಿಸಬಹುದು."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ಪಠ್ಯ ಸಂದೇಶಗಳನ್ನು ಸ್ವೀಕರಿಸಿ (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"ಇತರ ಅಪ್ಲಿಕೇಶನ್‍‍ಗಳ ಹಿನ್ನೆಲೆ ಪ್ರಕ್ರಿಯೆಗಳನ್ನು ಅಂತ್ಯಗೊಳಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ. ಇದು ಇತರ ಅಪ್ಲಿಕೇಶನ್‍‍ಗಳ ಚಾಲನೆಯನ್ನು ನಿಲ್ಲಿಸುವುದಕ್ಕೆ ಕಾರಣವಾಗಬಹುದು."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"ಈ ಅಪ್ಲಿಕೇಶನ್ ಇತರ ಅಪ್ಲಿಕೇಶನ್‌ಗಳ ಮೇಲೆ ಕಾಣಿಸಿಕೊಳ್ಳಬಹುದು"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"ಈ ಅಪ್ಲಿಕೇಶನ್ ಇತರ ಅಪ್ಲಿಕೇಶನ್‌ಗಳ ಅಥವಾ ಪರದೆಯ ಇತರೆ ಭಾಗಗಳ ಮೇಲೆ ಕಾಣಿಸಿಕೊಳ್ಳಬಹುದು. ಇದು ಸಾಮಾನ್ಯ ಅಪ್ಲಿಕೇಶನ್ ಬಳಕೆಯ ಮೂಲಕ ಹಸ್ತಕ್ಷೇಪ ಮಾಡಬಹುದು ಮತ್ತು ಇತರೆ ಅಪ್ಲಿಕೇಶನ್ ಗೋಚರಿಸುವ ರೀತಿಯಲ್ಲಿ ಬದಲಾಯಿಸಬಹುದು."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"ಹಿನ್ನಲೆಯಲ್ಲಿ ರನ್ ಮಾಡಿ"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"ಈ ಅಪ್ಲಿಕೇಶನ್ ಹಿನ್ನಲೆಯಲ್ಲಿ ರನ್ ಆಗಬಹುದು. ಇದು ಬ್ಯಾಟರಿಯನ್ನು ವೇಗವಾಗಿ ಬರಿದಾಗಿಸಬಹುದು."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"ಹಿನ್ನಲೆಯಲ್ಲಿ ಡೇಟಾ ಬಳಕೆ ಮಾಡಿ"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"ಈ ಅಪ್ಲಿಕೇಶನ್ ಹಿನ್ನಲೆಯಲ್ಲಿ ಡೇಟಾವನ್ನು ಬಳಸಬಹುದು. ಇದರಿಂದ ಡೇಟಾ ಬಳಕೆ ಹೆಚ್ಚಾಗಬಹುದು."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"ಅಪ್ಲಿಕೇಶನ್‌‌ ಅನ್ನು ಯಾವಾಗಲೂ ರನ್‌ ಆಗುವಂತೆ ಮಾಡಿ"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"ಸ್ಮರಣೆಯಲ್ಲಿ ನಿರಂತರವಾಗಿ ತನ್ನದೇ ಭಾಗಗಳನ್ನು ಮಾಡಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ. ಇದು ಟ್ಯಾಬ್ಲೆಟ್ ಕಾರ್ಯವನ್ನು ನಿಧಾನಗೊಳಿಸುವುದರ ಮೂಲಕ ಇತರ ಅಪ್ಲಿಕೇಶನ್‍‍ಗಳಿಗೆ ಲಭ್ಯವಿರುವ ಸ್ಮರಣೆಯನ್ನು ಮಿತಿಗೊಳಿಸುತ್ತದೆ."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"ಮೆಮೊರಿಯಲ್ಲಿ ಅದರ ಭಾಗಗಳನ್ನು ತಾನಾಗಿಯೇ ಮಾಡಿಕೊಳ್ಳಲು ಅನುಮತಿಸುತ್ತದೆ. ಇತರ ಅಪ್ಲಿಕೇಶನ್‌ಗಳಿಗೆ ಲಭ್ಯವಿರುವ ಮೆಮೊರಿಯನ್ನು ಮಿತಿಗೊಳಿಸಿ ಟಿವಿಯನ್ನು ಇದು ನಿಧಾನಗೊಳಿಸಬಹುದು."</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"ಇನ್‌ಪುಟ್ ವಿಧಾನ"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"ಪಠ್ಯದ ಕ್ರಮಗಳು"</string>
     <string name="email" msgid="4560673117055050403">"ಇಮೇಲ್"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"ಫೋನ್"</string>
     <string name="map" msgid="5441053548030107189">"ನಕ್ಷೆ"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"ಬ್ರೌಸ್ ಮಾಡಿ"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"ಸಂಗ್ರಹಣೆ ಸ್ಥಳವು ತುಂಬಿದೆ"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"ಕೆಲವು ಸಿಸ್ಟಂ ಕಾರ್ಯವಿಧಾನಗಳು ಕಾರ್ಯನಿರ್ವಹಿಸದೇ ಇರಬಹುದು"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"ಸಿಸ್ಟಂನಲ್ಲಿ ಸಾಕಷ್ಟು ಸಂಗ್ರಹಣೆಯಿಲ್ಲ. ನೀವು 250MB ನಷ್ಟು ಖಾಲಿ ಸ್ಥಳವನ್ನು ಹೊಂದಿರುವಿರಾ ಎಂಬುದನ್ನು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ ಹಾಗೂ ಮರುಪ್ರಾರಂಭಿಸಿ."</string>
@@ -1174,6 +1198,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ಭಾಷೆ ಮತ್ತು ವಿನ್ಯಾಸವನ್ನು ಆಯ್ಕೆ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"ಇತರ ಅಪ್ಲಿಕೇಶನ್‌ಗಳ ಮೇಲೆ <xliff:g id="NAME">%s</xliff:g> ಎಳೆಯಿರಿ"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> ಅಪ್ಲಿಕೇಶನ್ ಮೇಲೆ ಕಾಣಿಸುತ್ತಿದೆ."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"ಈ ಅಪ್ಲಿಕೇಶನ್‌ನ ಭಾಗಗಳು ಎಲ್ಲ ಸಮಯದಲ್ಲೂ ಕಾಣುತ್ತಿರುತ್ತದೆ. ಈ ವೈಶಿಷ್ಟ್ಯವು ಸರಿಯಾಗಿ ಕೆಲಸ ಮಾಡದಿದ್ದರೆ, ಆಫ್‌ ಮಾಡಿ."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ಆಫ್ ಮಾಡಿ"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> ಅನ್ನು ಸಿದ್ಧಪಡಿಸಲಾಗುತ್ತಿದೆ"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"ದೋಷಗಳನ್ನು ಪರಿಶೀಲಿಸಲಾಗುತ್ತಿದೆ"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"ಹೊಸ <xliff:g id="NAME">%s</xliff:g> ಪತ್ತೆಯಾಗಿದೆ"</string>
@@ -1328,8 +1356,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> ನೊಂದಿಗೆ ಹಂಚಿಕೊಳ್ಳಿ"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"ಸ್ಲೈಡಿಂಗ್ ಹ್ಯಾಂಡಲ್. ಸ್ಪರ್ಶಿಸಿ &amp; ಇರಿಸಿ."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"ಅನ್‍ಲಾಕ್ ಮಾಡಲು ಸ್ವೈಪ್ ಮಾಡಿ."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"ಹೇಳಲಾಗುವ ಪಾಸ್‌ವರ್ಡ್ ಕೀಗಳನ್ನು ಆಲಿಸಲು ಹೆಡ್‌ಸೆಟ್ ಪ್ಲಗ್ ಇನ್ ಮಾಡಿ."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"ಡಾಟ್."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"ಮುಖಪುಟ ನ್ಯಾವಿಗೇಟ್ ಮಾಡಿ"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"ಮೇಲಕ್ಕೆ ನ್ಯಾವಿಗೇಟ್ ಮಾಡಿ"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"ಇನ್ನಷ್ಟು ಆಯ್ಕೆಗಳು"</string>
@@ -1713,4 +1739,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"ಸಮಯದಲ್ಲಿ ಟೈಪ್ ಮಾಡಿ"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"ಸಮಯವನ್ನು ನಮೂದಿಸಲು ಪಠ್ಯದ ನಮೂನೆಗೆ ಬದಲಿಸಿ."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"ಸಮಯವನ್ನು ನಮೂದಿಸಲು ಗಡಿಯಾರದ ನಮೂನೆಗೆ ಬದಲಿಸಿ."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> ನಲ್ಲಿ ಉಳಿಸಬೇಕೆ?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> ಅನ್ನು <xliff:g id="LABEL">%2$s</xliff:g> ನಲ್ಲಿ ಉಳಿಸಬೇಕೆ?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"ಉಳಿಸಿ"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"ಬೇಡ"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"ಪಾಸ್‌ವರ್ಡ್"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"ವಿಳಾಸ"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"ಕ್ರೆಡಿಟ್ ಕಾರ್ಡ್"</string>
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 4ca2ce8..93ee599 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"숨겨진 콘텐츠"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"콘텐츠가 정책에 의해 숨겨졌습니다."</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"보안"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"알림"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"안전 모드"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android 시스템"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"개인으로 전환"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"애플리케이션이 사용자의 작업 없이 홈 화면 바로가기를 삭제할 수 있도록 허용합니다."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"발신전화 경로 전환"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"다른 번호로 다시 걸거나 중단시키는 옵션을 사용하여 발신한 번호를 볼 수 있게 허용합니다."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"문자 메시지 받기(SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"앱이 SMS 메시지를 수신하고 처리할 수 있도록 허용합니다. 앱이 사용자에게 표시하지 않고 기기로 전송된 메시지를 확인 또는 삭제할 수도 있습니다."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"문자 메시지 받기(MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"앱이 다른 앱의 백그라운드 프로세스를 종료할 수 있도록 허용합니다. 이 경우 다른 앱이 실행 중지될 수 있습니다."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"이 앱은 다른 앱 위에 표시될 수 있음"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"이 앱은 다른 앱이나 화면의 다른 부분 위에 표시될 수 있습니다. 이로 인해 일반적인 앱 사용이 방해받을 수 있으며 다른 앱이 표시되는 방식이 변경될 수 있습니다."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"백그라운드에서 실행"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"이 앱은 백그라운드에서 실행될 수 있으며 이로 인해 배터리가 더 빨리 소모될 수도 있습니다."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"백그라운드에서 데이터 사용"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"이 앱은 백그라운드에서 데이터를 사용할 수 있으며 이로 인해 데이터 사용량이 증가할 수도 있습니다."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"앱이 항상 실행되도록 설정"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"앱이 그 일부분을 영구적인 메모리로 만들 수 있도록 허용합니다. 이렇게 하면 다른 앱이 사용할 수 있는 메모리를 제한하여 태블릿의 속도를 저하시킬 수 있습니다."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"앱이 메모리를 지속적으로 사용할 수 있도록 허용합니다. 이는 TV의 속도를 늦춰 다른 앱에서 사용할 수 있는 메모리를 제한할 수 있습니다."</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"입력 방법"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"텍스트 작업"</string>
     <string name="email" msgid="4560673117055050403">"이메일"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"전화"</string>
     <string name="map" msgid="5441053548030107189">"지도"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"탐색"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"저장 공간이 부족함"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"일부 시스템 기능이 작동하지 않을 수 있습니다."</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"시스템의 저장 공간이 부족합니다. 250MB의 여유 공간이 확보한 후 다시 시작하세요."</string>
@@ -1173,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"탭하여 언어와 레이아웃을 선택하세요."</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g>이(가) 다른 앱 위에 표시됨"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> 앱이 상단에 표시됨"</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"이 앱의 일부는 항상 표시될 수도 있습니다. 기능이 제대로 작동되지 않으면 사용 중지하세요."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"사용 중지"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> 준비 중"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"오류 확인 중"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"새로운 <xliff:g id="NAME">%s</xliff:g> 감지됨"</string>
@@ -1327,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g>와(과) 공유"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"슬라이딩 핸들을 길게 터치하세요."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"스와이프하여 잠급니다."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"비밀번호 키를 음성으로 들으려면 헤드셋을 연결하세요."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"점"</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"홈 탐색"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"위로 탐색"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"옵션 더보기"</string>
@@ -1712,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"시간 입력"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"시간 입력을 위해 텍스트 입력 모드로 전환합니다."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"시간 입력을 위해 시계 모드로 전환합니다."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g>에 저장하시겠습니까?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g>을(를) <xliff:g id="LABEL">%2$s</xliff:g>에 저장하시겠습니까?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"저장"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"사용 안함"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"비밀번호"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"주소"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"신용카드"</string>
 </resources>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 564ff90..fe6e541 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Мазмундар жашырылган"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Тийиштүү саясат боюнча жашырылган мазмундар"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Коопсуздук"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Эскертүүлөр"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Коопсуз режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android тутуму"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Жеке профилге которулуу"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Колдонмого колдонуучунун катышуусусуз үй экранынын тез чакырмаларын жок кылуу мүмкүнчүлүгүн берет."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"чыгыш чалууларды кайра багыттоо"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Колдонмого кимдир-бирөөгө чалып жаткан учурда терилип жаткан номерди көрүү, ошондой эле чалууну башка номерге буруу же чалууну таптакыр токтотуп коюу мүмкүнчүлүгү берилет."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"билдирүүлөрдү (SMS) кабыл алуу"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Колдонмого SMS билдирүүлөрүн кабыл алууга жана аларды иштетип чыгууга уруксат берет. Бул, колдонмо сизге билгизбестен түзмөгүңүзгө жөнөтүлгөн билдирүүлөрдү мониторлой же жок кыла алат дегенди билдирет."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"билдирүүлөрдү (MMS) кабыл алуу"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Колдонмого башка колдонмолордун фондо иштеп жаткан процесстерин токтотуу уруксатын берет. Бул башка колдонмолордун иштебей калышына алып келиши мүмкүн."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Бул колдонмо башка колдонмолордун үстүнөн көрүнүшү мүмкүн"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Бул колдонмо башка колдонмолордун же экрандын башка бөлүгүнүн үстүндө көрүнүшү мүмкүн. Ал колдонмолорду пайдаланууга же алардын көрсөтүлүшүнө тоскоолдук жаратышы мүмкүн."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"фондо иштей берсин"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Бул колдонмо фондо иштей берет. Батареяңыз тез эле отуруп калышы мүмкүн."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"фондо дайындарды өткөрө берсин"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Бул колдонмо фондо дайындарды өткөрө берет. Дайындарды көбүрөөк өткөрүшү мүмкүн."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"колдонмону үзгүлтүксүз иштетүү"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Колдонмого өзүнүн бөлүктөрүн эстутумда туруктуу кармоого уруксат берет.Бул эстутумдун башка колдонмолорго жетиштүүлүгүн чектеши жана телефондун иштешин жайлатышы мүмкүн."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Колдонмого эстутумдагы өз бөлүктөрүн туруктуу кылуу мүмкүнчүлүгүн берет. Ушуну менен сыналгы жай иштеп, башка колдонмолорго жеткиликтүү эстутум чектелиши мүмкүн."</string>
@@ -1172,6 +1198,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Тил жана калып тандоо үчүн таптап коюңуз"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> колдонмосун башка терезелердин үстүнөн көрсөтүү"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> колд-сун эң үстүндө көрсөтүү"</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Бул колдонмонун бөлүктөрү дайыма көрүнүп турушу мүмкүн. Эгер бул функция туура иштебесе, аны өчүрүп коюңуз."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ӨЧҮРҮҮ"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> даярдалууда"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Каталар текшерилүүдө"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Жаңы <xliff:g id="NAME">%s</xliff:g> аныкталды"</string>
@@ -1326,8 +1356,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> менен бөлүшүү"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Сүрүү туткасы. Коё бербей &amp; тийип туруңуз."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Бөгөттөн чыгарыш үчүн сүртүңүз."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Айтылган сырсөз белгилерин угуш үчүн, кулакчын туташтырыңыз."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Чекит."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Башкы бетке чабыттоо"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Жогору чабыттоо"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Дагы параметрлер"</string>
@@ -1711,4 +1739,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Убакытты жазыңыз"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Убакытты текст киргизүү режиминде киргизиңиз."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Убакытты дубал саатынын режиминде киргизиңиз."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> кызматында сакталсынбы?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> <xliff:g id="LABEL">%2$s</xliff:g> кызматында сакталсынбы?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Сактоо"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Жок, рахмат"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"сырсөз"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"дарек"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"насыя картасы"</string>
 </resources>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index c6de33d..b7979f1 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"ເນື້ອຫາ​ຖືກ​ເຊື່ອງ​ໄວ້"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"ເນື້ອຫາຖືກເຊື່ອງຕາມນະໂຍບາຍ"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"ຄວາມປອດໄພ"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"ການເຕືອນ"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
     <string name="android_system_label" msgid="6577375335728551336">"ລະບົບ Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"ສະລັບໄປໂປຣໄຟລ໌ສ່ວນຕົວ"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັນລຶບທາງລັດໃນໜ້າຫຼັກໄດ້ ໂດຍບໍ່ຕ້ອງຮັບການຢືນຢັນຈາກຜູ່ໃຊ້."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"ປ່ຽນເສັ້ນທາງການໂທອອກ"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"ອະ​ນຸ​ຍາດ​ໃຫ້​ແອັບຯ​ເບິ່ງ​​ໝາຍ​ເລກເບີ​ໂທ ໃນ​ລະ​ຫວ່າງ​ການ​ໂທ​ອອກ ພ້ອມ​ທັງ​ໂຕ​ເລືອກ​ໃນ​ການ​ປ່ຽນ​ເສັ້ນ​ທາງ​ການ​ໂທ​ໄປ​ຫາ​ເບີ​ອື່ນ ຫຼື ລາຍ​ລະ​ອຽດກ່ຽວ​ກັບ​ເບີ​ໂທ​ລະ​ສັບ."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"ຮັບຂໍ້ຄວາມສັ້ນ (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"ອະນຸຍາດໃຫ້ແອັບຯຮັບ ແລະປະມວນຜົນຂໍ້ຄວາມ SMS. ນີ້ໝາຍຄວາມວ່າແອັບຯສາມາດຕິດຕາມ ຫຼືລຶບຂໍ້ຄວາມທີ່ສົ່ງເຂົ້າອຸປະກອນຂອງທ່ານ ໂດຍທີ່ບໍ່ສະແດງພວກມັນໃຫ້ທ່ານເຫັນ."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ຮັບຂໍ້ຄວາມ (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"ອະນຸຍາດໃຫ້ແອັບຯປິດໂປຣເຊສພື້ນຫຼັງຂອງແອັບຯອື່ນໄດ້. ນີ້ອາດເຮັດໃຫ້ແອັບຯອື່ນນັ້ນຢຸດການເຮັດວຽກໄປນຳ."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"This app can appear on top of other apps"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"This app can appear on top of other apps or other parts of the screen. This may interfere with normal app usage and change the way that other apps appear."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"ເຮັດວຽກໃນພື້ນຫຼັງ"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"ແອັບນີ້ສາມາດເຮັດວຽກໃນພື້ນຫຼັງໄດ້. ນີ້ອາດເຮັດໃຫ້ໃຊ້ແບັດເຕີຣີໝົດໄວຂຶ້ນ."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"ໃຊ້ອິນເຕີເນັດໃນພື້ນຫຼັງ"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"ແອັບນີ້ສາມາດໃຊ້ອິນເຕີເນັດໃນພື້ນຫຼັງໄດ້. ນີ້ອາດເຮັດໃຫ້ໃຊ້ອິນເຕີເນັດຫຼາຍຂຶ້ນ."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"ເຮັດໃຫ້ແອັບຯເຮັດວຽກຕະຫຼອດເວລາ"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"ອະນຸຍາດໃຫ້ແອັບຯ ສາມາດເຮັດໃຫ້ບາງພາກສ່ວນຂອງມັນເອັງ ຄົງໂຕໃນໜ່ວຍຄວາມຈຳ. ສິ່ງນີ້ສາມາດຈຳກັດໜ່ວຍຄວາມຈຳທີ່ສາມາດໃຊ້ໄດ້ໂດຍແອັບຯອື່ນ ເຮັດໃຫ້ແທັບເລັດຊ້າລົງ."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"ອະ​ນຸ​ຍາດ​ໃຫ້​ແອັບ​ເຮັດ​ສ່ວນ​ຕ່າງໆ​ຂອງ​ມັນ​ເອງ​ໃຫ້ຕໍ່ເນື່ອງຢູ່​ໃນ​ຄວາມ​ຈຳ. ອັນ​ນີ້​ສາ​ມາດ​ຈຳ​ກັດ​ຄວາມ​ຈຳ​ທີ່​ມີ​ຢູ່​ໃຫ້​ກັບ​ແອັບ​ອື່ນ​ທີ​ເຮັດ​ໃຫ້ໂທລະພາບຊ້າ​ລົງ."</string>
@@ -1171,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ແຕະເພື່ອເລືອກພາສາ ແລະ ໂຄງແປ້ນພິມ"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> ແຕ້ມທັບແອັບອື່ນ"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"ແອັບ <xliff:g id="NAME">%s</xliff:g> ກຳລັງສະແດງຢູ່ໜ້າສຸດ."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"ບາງພາກສ່ວນຂອງແອັບນີ້ຈະປາກົດຢູ່ຕະຫຼອດເວລາ. ຫາກຄຸນສົມບັດນີ້ໃຊ້ໄດ້ບໍ່ດີ, ໃຫ້ປິດມັນໄວ້."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ປິດໄວ້"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"ກຳ​ລັງ​ກຽມ <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"ກຳລັງກວດຫາຂໍ້ຜິດພາດ"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"ກວດ​ພົບ <xliff:g id="NAME">%s</xliff:g> ໃໝ່​ແລ້ວ"</string>
@@ -1325,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"ແບ່ງປັນໃຫ້ <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"ເລື່ອນບ່ອນຖື ແລ້ວແຕະຄ້າງໄວ້."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"ປັດເພື່ອປົດລັອກ."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"ສຽບສາຍຫູຟັງເພື່ອຟັງລະຫັດຜ່ານ."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"ຈໍ້າເມັດ."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"ກັບໄປໜ້າຫຼັກ"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"ຂຶ້ນເທິງ"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"ໂຕເລືອກອື່ນ"</string>
@@ -1710,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"ພິມເວລາໃສ່"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"ສະຫຼັບໄປໃຊ້ໂໝດປ້ອນຂໍ້ຄວາມສຳລັບການປ້ອນເວລາ."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"ສະຫຼັບໄປໃຊ້ໂໝດໂມງສຳລັບການປ້ອນເວລາ."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"ບັນທຶກໄປໃສ່ <xliff:g id="LABEL">%1$s</xliff:g> ບໍ?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"ບັນທຶກ <xliff:g id="TYPE">%1$s</xliff:g> ໄປໃສ່ <xliff:g id="LABEL">%2$s</xliff:g> ບໍ?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"ບັນທຶກ"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"ບໍ່, ຂອບໃຈ"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"​ລະ​ຫັດ​ຜ່ານ"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"ທີ່ຢູ່"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"ບັດເຄຣດິດ"</string>
 </resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 24e0192..f907836 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -250,6 +250,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Turinys paslėptas"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Turinys paslėptas vadovaujantis politika"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Sauga"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Įspėjimai"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Saugos režimas"</string>
     <string name="android_system_label" msgid="6577375335728551336">"„Android“ sistema"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Perjungti į asmeninį režimą"</string>
@@ -298,6 +324,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Programai leidžiama pašalinti sparčiuosius klavišus iš pagrindinio ekrano be naudotojo įsikišimo."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"peradresuoti išsiunčiamuosius skambučius"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Leidžiama programai peržiūrėti renkamą numerį siunčiamojo skambučio metu suteikiant galimybę peradresuoti skambutį kitu numeriu arba visiškai nutraukti skambutį."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"gauti teksto pranešimus (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Leidžiama programai gauti ir apdoroti SMS pranešimus. Tai reiškia, kad programa gali stebėti ir ištrinti į jūsų įrenginį siunčiamus pranešimus jums jų neparodžiusi."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"gauti teksto pranešimus (MMS)"</string>
@@ -326,14 +356,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Leidžiama programai baigti kitų programų fone vykdomus procesus. Dėl to gali būti sustabdytos kitos programos."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Ši programa gali būti rodoma virš kitų programų"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Ši programa gali būti rodoma virš kitų programų arba kitų ekrano sričių. Tai gali trukdyti įprastai naudoti programas ir pakeisti kitų programų rodymo būdą."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"vykdyti fone"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Ši programa gali būti vykdoma fone. Dėl to akumuliatorius gali būti greičiau išeikvojamas."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"naudoti duomenis fone"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Ši programa gali naudoti duomenis fone. Dėl to gali būti sunaudojama daugiau duomenų."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"nustatyti, kad programa būtų visada vykdoma"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Leidžiama programai savo dalis įrašyti į atmintį. Dėl to gali būti apribota kitomis programomis pasiekiama atmintis ir sulėtėti planšetinio kompiuterio veikimas."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Programai leidžiama nustatyti, kad tam tikros jos dalys nuolat išliktų atmintyje. Dėl to gali sumažėti kitoms programoms pasiekiamos atminties ir sulėtėti TV."</string>
@@ -1000,11 +1026,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"Įvesties būdas"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Teksto veiksmai"</string>
     <string name="email" msgid="4560673117055050403">"Siųsti el. laišką"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"Telefonas"</string>
     <string name="map" msgid="5441053548030107189">"Žemėlapis"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"Naršyti"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Mažėja laisvos saugyklos vietos"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Kai kurios sistemos funkcijos gali neveikti"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Sistemos saugykloje nepakanka vietos. Įsitikinkite, kad yra 250 MB laisvos vietos, ir paleiskite iš naujo."</string>
@@ -1213,6 +1237,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Palieskite, kad pasirinktumėte kalbą ir išdėstymą"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AĄBCČDEĘĖFGHIĮYJKLMNOPRSŠTUŲŪVZŽ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AĄBCČDEĘĖFGHIĮYJKLMNOPRSŠTUŲŪVZŽ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> programa rodoma virš kitų programų"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> programa rodoma virš kitų."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Šios programos dalys gali likti matomos visą laiką. Jei ši funkcija tinkamai neveikia, išjunkite ją."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"IŠJUNGTI"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Ruošiama <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Tikrinama, ar nėra klaidų"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Aptikta nauja <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1369,8 +1397,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Bendrinti su „<xliff:g id="APPLICATION_NAME">%s</xliff:g>“"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Slydimo valdymas. Palieskite ir laikykite."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Perbraukite pirštu, kad atrakintumėte."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Prijunkite ausines, kad išgirstumėte sakomus slaptažodžio klavišus."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Taškas."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Naršyti pagrindinį puslapį"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Naršyti į viršų"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Daugiau parinkčių"</string>
@@ -1774,4 +1800,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Įveskite laiką"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Laiko įvestį pateikti perjungus į teksto įvesties režimą."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Laiko įvestį pateikti perjungus į laikrodžio režimą."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Išsaugoti skiltyje „<xliff:g id="LABEL">%1$s</xliff:g>“?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Išsaugoti <xliff:g id="TYPE">%1$s</xliff:g> skiltyje „<xliff:g id="LABEL">%2$s</xliff:g>“?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Išsaugoti"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Ne, ačiū"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"slaptažodį"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"adresą"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kredito kortelę"</string>
 </resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 9994b9d..fe2fda8 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -247,6 +247,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"Pārsniedz"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Saturs paslēpts"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Saskaņā ar politiku saturs ir paslēpts."</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Drošība"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Brīdinājumi"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Drošais režīms"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android sistēma"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Pārslēgt personīgo profilu"</string>
@@ -295,6 +321,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Ļauj lietojumprogrammai noņemt saīsnes no sākuma ekrāna, nejautājot lietotājam."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"pārmaršrutēt izejošos zvanus"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Ļauj lietotnei skatīt ievadīto tālruņa numuru izejošā zvana laikā un piedāvā iespēju šo zvanu pāradresēt uz citu numuru vai vispār pārtraukt zvanu."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"saņemt īsziņas (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Ļauj lietotnei saņemt un apstrādāt īsziņas. Tas nozīmē, ka lietotne var pārraudzīt vai dzēst uz jūsu ierīci nosūtītos ziņojumus, neparādot tos jums."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"saņemt ziņojumus (MMS)"</string>
@@ -323,14 +353,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Ļauj lietotnei pabeigt citu lietotņu fonā darbinātos procesus. Rezultātā var tikt apturēta citu lietotņu darbība."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Šo lietotni var rādīt virs citām lietotnēm"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Šo lietotni var rādīt virs citām lietotnēm vai ekrāna daļām. Tādējādi var būt traucēta citu lietotņu izmantošana un var mainīties citu lietotņu izskats."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"darboties fonā"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Šī lietotne var darboties fonā. Tā var ātrāk pazemināt akumulatora uzlādes līmeni."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"izmantot datus fonā"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Šī lietotne var izmantot datus fonā. Tā var palielināt datu lietojuma apjomu."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"likt lietotnei vienmēr darboties"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Ļauj lietotnei nodrošināt atsevišķu tās daļu nepārtrauktu atrašanos atmiņā. Tas var ierobežot pieejamo atmiņas daudzumu citām lietotnēm, tādējādi palēninot planšetdatora darbību."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Ļauj lietotnei nodrošināt atsevišķu tās daļu nepārtrauktu atrašanos atmiņā. Tas var ierobežot pieejamo atmiņas daudzumu citām lietotnēm, tādējādi palēninot televizora darbību."</string>
@@ -980,11 +1006,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"Ievades metode"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Teksta darbības"</string>
     <string name="email" msgid="4560673117055050403">"E-pasts"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"Tālrunis"</string>
     <string name="map" msgid="5441053548030107189">"Maps"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"Pārlūkot"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Paliek maz brīvas vietas"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Dažas sistēmas funkcijas var nedarboties."</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Sistēmai pietrūkst vietas. Atbrīvojiet vismaz 250 MB vietas un restartējiet ierīci."</string>
@@ -1193,6 +1217,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Pieskarieties, lai atlasītu valodu un izkārtojumu"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AĀBCČDEĒFGĢHIĪJKĶLĻMNŅOPRSŠTUŪVZŽ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AĀBCČDEĒFGĢHIĪJKĶLĻMNŅOPRSŠTUŪVZŽ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"Lietotne <xliff:g id="NAME">%s</xliff:g> tiek rādīta pāri citām lietotnēm"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"Lietotne <xliff:g id="NAME">%s</xliff:g> ir redzama virspusē."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Šīs lietotnes daļas joprojām var būt redzamas visu laiku. Ja šī funkcija nedarbojas pareizi, izslēdziet to."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"IZSLĒGT"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Notiek <xliff:g id="NAME">%s</xliff:g> sagatavošana"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Tiek meklētas kļūdas"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Tika atrasta jauna <xliff:g id="NAME">%s</xliff:g>."</string>
@@ -1348,8 +1376,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Kopīgot ar lietojumprogrammu <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Bīdāms turis. Pieskarieties tam un turiet to nospiestu."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Velciet ar pirkstu, lai atbloķētu."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Pievienojiet austiņas, lai dzirdētu paroles taustiņu nosaukumus."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punkts."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Pārvietoties uz sākuma ekrānu"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Pārvietoties augšup"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Vairāk opciju"</string>
@@ -1743,4 +1769,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Ierakstiet laiku"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Lai ievadītu laiku, ieslēdziet teksta ievades režīmu."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Lai ievadītu laiku, ieslēdziet pulksteņa režīmu."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Vai saglabāt pakalpojumā <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Vai saglabāt <xliff:g id="TYPE">%1$s</xliff:g> pakalpojumā <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Saglabāt"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Nē, paldies"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"paroli"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"adresi"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kredītkartes informāciju"</string>
 </resources>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 806af3a..3cd56a3 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -83,10 +83,10 @@
     <string name="RuacMmi" msgid="7827887459138308886">"Одбивање несакани вознемирувачки повици"</string>
     <string name="CndMmi" msgid="3116446237081575808">"Испорака на повикувачки број"</string>
     <string name="DndMmi" msgid="1265478932418334331">"Не вознемирувај"</string>
-    <string name="CLIRDefaultOnNextCallOn" msgid="429415409145781923">"Стандардно, повикувачот со овој ИД е ограничен. Следен повик: ограничен"</string>
-    <string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"Стандардно, повикувачот со овој ИД е ограничен. Следен повик: не е ограничен"</string>
-    <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"Стандардно, повикувачот со овој ИД не е ограничен. Следен повик: ограничен"</string>
-    <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Стандардно, повикувачот со овој ИД не е ограничен. Следен повик: не е ограничен"</string>
+    <string name="CLIRDefaultOnNextCallOn" msgid="429415409145781923">"Стандардно, повикувачот со овој ID е ограничен. Следен повик: ограничен"</string>
+    <string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"Стандардно, повикувачот со овој ID е ограничен. Следен повик: не е ограничен"</string>
+    <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"Стандардно, повикувачот со овој ID не е ограничен. Следен повик: ограничен"</string>
+    <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Стандардно, повикувачот со овој ID не е ограничен. Следен повик: не е ограничен"</string>
     <string name="serviceNotProvisioned" msgid="8614830180508686666">"Услугата не е предвидена."</string>
     <string name="CLIRPermanent" msgid="3377371145926835671">"Не може да го промените поставувањето за ID на повикувач."</string>
     <string name="RestrictedOnData" msgid="8653794784690065540">"Услугата за податоци е блокирана."</string>
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Содржините се скриени"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Содржините се скриени поради политиката"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Безбедност"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Предупредувања"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Безбеден режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Систем Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Префрлете на личен профил"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Овозможува апликацијата да отстранува кратенки до почетниот екран без интервенција на корисникот."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"пренасочи појдовни повици"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Дозволува апликацијата да го види бројот што се повикува за време на појдовен повик, со опција да го пренасочи повикот кон друг број или да го прекине повикот."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"прими текстуални пораки (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Овозможува апликацијата да прима и да обработува SMS пораки. Тоа значи дека апликацијата може да следи или да брише пораки испратени до вашиот уред без да ви ги прикаже вам."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"прими текстуални пораки (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Овозможува апликацијата да заврши заднински процеси на други апликации. Ова може да предизвика други апликации да престанат да работат."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Апликацијава може да се појави врз други апликации"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Апликацијава може да се појави врз други апликации или делови од екранот. Тоа може да го попречи нормалното користење на апликацијата и да го смени начинот на кој се појавуваат другите апликации."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"извршување во заднина"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Апликацијава може да се извршува во заднина. Тоа може побрзо да ја троши батеријата."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"користење мобилен интернет во заднина"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Апликацијава може да користи мобилен интернет во заднина. Тоа може да го зголеми користењето мобилен интернет."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"направи апликацијата постојано да биде активна"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Овозможува апликацијата да прави трајни делови од себеси во меморијата. Ова може да ја ограничи расположливата меморија на други апликации што го забавува таблетот."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Дозволува апликацијата да направи нејзини делови да бидат постојани во меморијата. Ова може да ја ограничи меморијата достапна на другите апликации и да го забави телевизорот."</string>
@@ -1172,6 +1198,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Допрете за избирање јазик и распоред"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> пишува врз други апликации"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"Апликацијата <xliff:g id="NAME">%s</xliff:g> е одозгора."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Делови од апликацијава може да бидат видливи цело време. Ако функцијава не работи правилно, исклучете ја."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ИСКЛУЧИ"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Се подготвува <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Се проверува за грешки"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Откриена е нова <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1326,8 +1356,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Сподели со <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Рачка на лизгање. Допрете и задржете."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Помини со прст за да отклучиш."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Приклучи слушалки да ги слушнеш изговорените лозинки."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Dot."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Движи се кон дома"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Движи се нагоре"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Повеќе опции"</string>
@@ -1713,4 +1741,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Внесете време"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Префрлете се на режимот за внесување текст за да внесете време."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Префрлете се на режимот за часовник за да внесете време."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Да се зачува во <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Да се зачува <xliff:g id="TYPE">%1$s</xliff:g> во <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Зачувај"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Не, благодарам"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"лозинка"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"адреса"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"кредитна картичка"</string>
 </resources>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index ab3d0ba..404e5b8 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"കോൺടാക്‌റ്റുകൾ മറച്ചു"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"നയം അനുസരിച്ച് ഉള്ളടക്കം മറച്ചിരിക്കുന്നു"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"സുരക്ഷ"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"അലേർട്ടുകൾ"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"സുരക്ഷിത മോഡ്"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android സിസ്റ്റം"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"വ്യക്തിഗത പ്രൊഫൈലിലേക്ക് മാറുക"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"ഉപയോക്തൃ ഇടപെടലില്ലാതെ ഹോംസ്‌ക്രീൻ കുറുക്കുവഴികൾ നീക്കംചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"ഔട്ട്‌ഗോയിംഗ് കോളുകൾ വീണ്ടും റൂട്ടുചെയ്യുക"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"മറ്റ് നമ്പരിലേക്ക് കോൾ റീഡയറക്‌ടുചെയ്യുന്നതിനോ എല്ലാ കോളുകളും ഒപ്പം ഇല്ലാതാക്കുന്നതിനോ ഉള്ള ആയ ഓപ്‌ഷൻ ഉപയോഗിക്കുന്ന ഔട്ട്ഗോയിംഗ് കോളിൽ ഡയൽ ചെയ്യുന്ന നമ്പർ കാണുന്നതിന് അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"വാചക സന്ദേശം നേടുക (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"SMS സന്ദേശങ്ങൾ നേടാനും പ്രോസസ്സുചെയ്യാനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. നിങ്ങളുടെ ഉപകരണത്തിലേക്ക് അയയ്‌ക്കുന്ന സന്ദേശങ്ങൾ നിങ്ങൾക്ക് ദൃശ്യമാക്കാതെ തന്നെ അപ്ലിക്കേഷന് നിരീക്ഷിക്കാനോ ഇല്ലാതാക്കാനോ കഴിയുമെന്നാണ് ഇതിനർത്ഥം."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"വാചക സന്ദേശം നേടുക (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"മറ്റ് അപ്ലിക്കേഷനുകളുടെ പശ്ചാത്തല പ്രോസസ്സുകൾ അവസാനിപ്പിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഇത് മറ്റ് അപ്ലിക്കേഷനുകൾ പ്രവർത്തനം നിർത്താനിടയാക്കാം."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"ഈ ആപ്പിന്, മറ്റ് ആപ്‌സിന്റെ മുകളിൽ ദൃശ്യമാകാൻ കഴിയും"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"മറ്റ് ആപ്‌സിന് മുകളിലോ സ്ക്രീനിന്റെ മറ്റ് ഭാഗങ്ങളിലോ ദൃശ്യമാകാൻ ഈ ആപ്പിന് കഴിയും. സാധാരണ ആപ്പ് ഉപയോഗത്തെ ഇത് തടസ്സപ്പെടുത്താം, മറ്റ് ആപ്‌സ് ദൃശ്യമാകുന്ന രീതിയെയും ഇത് മാറ്റാം."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"പശ്ചാത്തലത്തിൽ പ്രവർത്തിക്കൽ"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"ഈ ആപ്പിന് പശ്ചാത്തലത്തിൽ പ്രവർത്തിക്കാൻ കഴിയും. ഇത് ബാറ്ററി വേഗത്തിൽ കുറയാൻ കാരണമായേക്കാം."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"പശ്ചാത്തലത്തിൽ ഡാറ്റ ഉപയോഗിക്കൽ"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"ഈ ആപ്പിന് പശ്ചാത്തലത്തിൽ ഡാറ്റ ഉപയോഗിക്കാൻ കഴിയും. ഇത് ഡാറ്റ ഉപയോഗം വർദ്ധിപ്പിച്ചേക്കാം."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"അപ്ലിക്കേഷൻ എപ്പോഴും പ്രവർത്തിക്കുന്നതാക്കുക"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"മെമ്മറിയിൽ അപ്ലിക്കേഷനുകളുടെ ഭാഗങ്ങൾ നിലനിർത്താൻ സ്വയം അനുവദിക്കുന്നു. ഇത് ടാബ്‌ലെറ്റിനെ മന്ദഗതിയിലാക്കുന്ന വിധത്തിൽ മറ്റ് അപ്ലിക്കേഷനുകൾക്ക് ലഭ്യമായ മെമ്മറി പരിമിതപ്പെടുത്താനിടയുണ്ട്."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"മെമ്മറിയിൽ സ്ഥിരതയുള്ളതാക്കുന്നതിന് അപ്ലിക്കേഷൻ അനുവദിക്കുന്നു. ടിവിയെ സാവധാനത്തിലാക്കുന്ന മറ്റ് അപ്ലിക്കേഷനുകളിലേക്കുള്ള മെമ്മറി ലഭ്യതയെ ഇതിന് പരിമിതമാക്കാനാവും."</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"ടൈപ്പുചെയ്യൽ രീതി"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"ടെക്‌സ്‌റ്റ് പ്രവർത്തനങ്ങൾ"</string>
     <string name="email" msgid="4560673117055050403">"ഇമെയിൽ"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"ഫോണ്‍"</string>
     <string name="map" msgid="5441053548030107189">"മാപ്പ്"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"ബ്രൗസുചെയ്യുക"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"സംഭരണയിടം കഴിഞ്ഞു"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"ചില സിസ്റ്റം പ്രവർത്തനങ്ങൾ പ്രവർത്തിക്കണമെന്നില്ല."</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"സിസ്‌റ്റത്തിനായി മതിയായ സംഭരണമില്ല. 250MB സൗജന്യ സംഭരണമുണ്ടെന്ന് ഉറപ്പുവരുത്തി പുനരാരംഭിക്കുക."</string>
@@ -1174,6 +1198,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ഭാഷയും ലേഔട്ടും തിരഞ്ഞെടുക്കുന്നതിന് ടാപ്പുചെയ്യുക"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> മറ്റ് ആപ്പുകൾക്ക് ‌മുകളിൽ പ്രവർത്തിക്കും"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> മുകളിൽ ദൃശ്യമാകുന്നു."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"ഈ ആപ്പിന്റെ ‌ഭാഗങ്ങൾ തുടർന്നും ദൃശ്യമായേക്കാം. ഈ ഫീച്ചർ ശരിയായി ‌പ്രവർത്തിക്കുന്നില്ലെങ്കിൽ അത് ഓഫ് ‌ചെയ്യുക."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ഓഫാക്കുക"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> തയ്യാറാകുന്നു"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"പിശകുകളുണ്ടോയെന്നു പരിശോധിക്കുന്നു"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"പുതിയ <xliff:g id="NAME">%s</xliff:g> എന്നതിനെ തിരിച്ചറിഞ്ഞു"</string>
@@ -1328,8 +1356,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g>-മായി പങ്കിടുക"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"സ്ലൈഡുചെയ്യുന്ന ഹാൻഡിൽ. സ്‌പർശിച്ച് പിടിക്കുക."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"അൺലോക്കുചെയ്യാൻ സ്വൈപ്പുചെയ്യുക."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"പറയുന്ന പാസ്‌വേഡ് കീകൾ കേൾക്കാൻ ഹെഡ്‌സെറ്റ് പ്ലഗ്ഗുചെയ്യുക."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"ഡോട്ട്."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"ഹോമിലേക്ക് നാവിഗേറ്റുചെയ്യുക"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"മുകളിലേക്ക് നാവിഗേറ്റുചെയ്യുക"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"കൂടുതൽ‍ ഓപ്‌ഷനുകള്‍"</string>
@@ -1713,4 +1739,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"സമയത്തിൽ ടൈപ്പുചെയ്യുക"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"സമയം നൽകുന്നതിന് ടെക്സ്റ്റ് ഇൻപുട്ട് ‌മോ‌ഡിലേക്ക് ‌മാറുക."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"‌സമയം നൽകുന്നതിന് ക്ലോക്ക് മോഡിലേക്ക് ‌മാറുക."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> എന്നതിലേക്ക് സംരക്ഷിക്കണോ?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> <xliff:g id="LABEL">%2$s</xliff:g> എന്നതിലേക്ക് സംരക്ഷിക്കണോ?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"സംരക്ഷിക്കുക"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"വേണ്ട, നന്ദി"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"പാസ്‌വേഡ്"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"വിലാസം"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"ക്രെഡിറ്റ് കാർഡ്"</string>
 </resources>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 849d676..ce3619c 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -220,7 +220,7 @@
     <string name="global_action_lock" msgid="2844945191792119712">"Дэлгэцний түгжээ"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Унтраах"</string>
     <string name="global_action_emergency" msgid="7112311161137421166">"Яаралтай тусламж"</string>
-    <string name="global_action_bug_report" msgid="7934010578922304799">"Алдаа мэдээллэх"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"Алдаа мэдээлэх"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"Согог репорт авах"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Энэ таны төхөөрөмжийн одоогийн статусын талаарх мэдээллийг цуглуулах ба имэйл мессеж болгон илгээнэ. Алдааны мэдэгдлээс эхэлж илгээхэд бэлэн болоход хэсэг хугацаа зарцуулагдана тэвчээртэй байна уу."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Интерактив тайлан"</string>
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Контентыг нуусан"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Удирдамжийн дагуу нуусан агуулга"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Аюулгүй байдал"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Сануулга"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Аюулгүй горим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Андройд систем"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"\"Хувийн\" руу шилжих"</string>
@@ -270,7 +296,7 @@
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Таны харилцан үйлчлэх цонхны контентоос шалгах."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Хүрч танихыг асаах"</string>
     <string name="capability_desc_canRequestTouchExploration" msgid="7543249041581408313">"Товшсон зүйлсийг чангаар хэлэх ба дэлгэцийг дохио ашиглан таних боломжтой."</string>
-    <string name="capability_title_canRequestEnhancedWebAccessibility" msgid="1739881766522594073">"Сайжруулсан веб хандалтыг асаах"</string>
+    <string name="capability_title_canRequestEnhancedWebAccessibility" msgid="1739881766522594073">"Сайжруулсан вэб хандалтыг асаах"</string>
     <string name="capability_desc_canRequestEnhancedWebAccessibility" msgid="7881063961507511765">"Апп контентод илүү хялбар хандуулахын тулд скриптыг суулгана."</string>
     <string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"Бичсэн текстээ ажиглах"</string>
     <string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Кредит картын дугаар болон нууц үг зэрэг хувийн датаг агуулж байна."</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Аппликешн нь хэрэглэгчийн оролцоогүйгээр Нүүр дэлгэцний товчлолыг устгаж чадна."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"гарсан дуудлагыг чиглэлийг өөрчлөх"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Гадагш дуудлага хийх үед залгасан дугаарыг харах, дуудлагыг өөр дугаар руу шилжүүлэх, таслах боломжтой болгоно."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"текст мессеж(SMS) хүлээж авах"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Апп нь SMS мессежийг хүлээн авах болон гүйцэтгэх боломжтой. Ингэснээр апп нь таны төхөөрөмжрүү илгээсэн мессежийг танд үзүүлэхгүйгээр хянах болон устгаж чадна."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"текст мессеж(МMS) хүлээж авах"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Апп нь бусад апп-н арын процессыг дуусгах боломжтой. Энэ бусад апп-г зогсоох боломжийг олгоно."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Энэ апп бусад аппын дээр харагдана"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Энэ апп бусад аппын дээр эсвэл дэлгэцийн өөр хэсэгт харагдана. Энэ нь энгийн апп хэрэглээ болон бусад аппын харагдах байдлыг өөрчилж болзошгүй."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"цаана ажиллах"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Энэ апп цаана ажиллах боломжтой. Энэ нь батерейг хурдан дуусгаж болзошгүй."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"датаг цаана ашиглах"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Энэ апп цаана ажиллах боломжтой. Энэ нь датаны хэрэглээг нэмэгдүүлж болзошгүй."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"апп-г байнга ажиллуулах"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Апп нь өөрийн хэсгийн санах ойд байнга байлгах боломжтой. Энэ нь бусад апп-уудын ашиглах санах ойг хязгаарлан таблетыг удаашруулах болно."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Апп-д өөрийн бүрэлдэхүүн хэсгийг санах ойд хадгалахыг зөвшөөрдөг. Энэ нь бусад аппликэйшнүүдийн ашиглах санах ойн хэмжээг хязгаарлахаас гадна, телевизийг удаашруулна."</string>
@@ -811,9 +837,9 @@
     <string name="autofill_parish" msgid="8202206105468820057">"Мөргөлч"</string>
     <string name="autofill_area" msgid="3547409050889952423">"Хэсэг"</string>
     <string name="autofill_emirate" msgid="2893880978835698818">"Эмират"</string>
-    <string name="permlab_readHistoryBookmarks" msgid="3775265775405106983">"өөрийн Веб хавчуурга болон түүхийг унших"</string>
+    <string name="permlab_readHistoryBookmarks" msgid="3775265775405106983">"өөрийн Вэб хавчуурга болон түүхийг унших"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="8462378226600439658">"Апп нь Хөтчийн зочилж байсан бүх URL-н түүх болон Хөтчийн бүх хавчуургыг унших боломжтой. Анхаар: Энэ зөвшөөрөл нь гуравдагч талын хөтөч эсвэл вебээр хөтөчлөх чадавхтай аппликешнүүдэд ашиглагдахгүй байх боломжтой."</string>
-    <string name="permlab_writeHistoryBookmarks" msgid="3714785165273314490">"веб хавчуурга болон түүхийг бичих"</string>
+    <string name="permlab_writeHistoryBookmarks" msgid="3714785165273314490">"вэб хавчуурга болон түүхийг бичих"</string>
     <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"Апп нь таны таблет дээр хадгалагдсан Хөтчийн түүх эсвэл хавчуургыг өөрчлөх боломжтой. Энэ нь апп-д Хөтчийн датаг арилгах эсвэл өөрчлөх боломжийг олгоно. Анхаар: Энэ зөвшөөрөл нь гуравдагч талын хөтөч эсвэл вебээр хөтөчлөх чадвартай аппликешнд ажиллахгүй байх боломжтой."</string>
     <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="7007393823197766548">"Апп-д телевиз-д хадгалагдсан Вэб хөтчийн түүх, хавчуургыг өөрчлөхийг зөвшөөрдөг. Энэ нь апп-д Вэб хөтчийн датаг устгах эсвэо өөрчлөхийг зөвшөөрч болох юм. Жич: энэ зөвшөөрөл нь гуравдагч вэб хөтөч эсвэл вэб хайлт хийх чадвартай апп-ны хувьд үйлчлэхгүй."</string>
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Апп нь таны утсан дээр хадгалагдсан Хөтчийн түүх эсвэл хавчуургыг өөрчлөх боломжтой. Энэ нь апп-д Хөтчийн датаг арилгах эсвэл өөрчлөх боломжийг олгоно. Анхаар: Энэ зөвшөөрөл нь гуравдагч талын хөтөч эсвэл вебээр хөтөчлөх чадвартай аппликешнд ажиллахгүй байх боломжтой."</string>
@@ -822,7 +848,7 @@
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"дуут шуудан нэмэх"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Таны дуут шуудангийн ирсэн мэйлд зурвас нэмэхийг апп-д зөвшөөрөх."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"Хөтчийн геобайршлын зөвшөөрлийг өөрчлөх"</string>
-    <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Апп нь Хөтчийн гео байршлын зөвшөөрлийг өөрчлөх боломжтой. Хортой апп нь энийг ашиглан дурын веб хуудасруу байршлын мэдээллийг илгээх боломжтой."</string>
+    <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Апп нь Хөтчийн гео байршлын зөвшөөрлийг өөрчлөх боломжтой. Хортой апп нь энийг ашиглан дурын вэб хуудасруу байршлын мэдээллийг илгээх боломжтой."</string>
     <string name="save_password_message" msgid="767344687139195790">"Та хөтчид энэ нууц үгийг сануулах уу?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Одоо биш"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Санах"</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"Оруулах арга"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Текст үйлдэл"</string>
     <string name="email" msgid="4560673117055050403">"Имэйл"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"Утас"</string>
     <string name="map" msgid="5441053548030107189">"Газрын зураг"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"Хөтлөх"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Сангийн хэмжээ дутагдаж байна"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Зарим систем функц ажиллахгүй байна"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Системд хангалттай сан байхгүй байна. 250MБ чөлөөтэй зай байгаа эсэхийг шалгаад дахин эхлүүлнэ үү."</string>
@@ -1173,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Хэл болон бүдүүвчийг сонгохын тулд дарна уу"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> бусад аппын дээр гарч ирсэн"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> апп дээр харагдаж байна."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Энэ аппын зарим хэсэг нь тогтмол харагдана. Энэ онцлог буруу ажиллаж байвал унтраана уу."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"УНТРААХ"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g>-ыг бэлдэж байна"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Алдааг шалгаж байна"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Шинэ <xliff:g id="NAME">%s</xliff:g> илэрлээ"</string>
@@ -1280,7 +1308,7 @@
     <string name="progress_erasing" product="default" msgid="6596988875507043042">"SD картыг цэвэрлэж байна…"</string>
     <string name="share" msgid="1778686618230011964">"Хуваалцах"</string>
     <string name="find" msgid="4808270900322985960">"Олох"</string>
-    <string name="websearch" msgid="4337157977400211589">"Веб хайлт"</string>
+    <string name="websearch" msgid="4337157977400211589">"Вэб хайлт"</string>
     <string name="find_next" msgid="5742124618942193978">"Дараагийнхыг хайх"</string>
     <string name="find_previous" msgid="2196723669388360506">"Өмнөхөөс олох"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"<xliff:g id="NAME">%s</xliff:g>-н байршлын хүсэлт"</string>
@@ -1327,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g>-тай хуваалцана уу"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Бариулыг гулсуулна. Хүрээд хүлээнэ."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Түгжээг тайлах бол татна уу"</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Нууц үгний дуудлагыг сонсох бол чихэвчийг залгана уу."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Цэг."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Нүүр хуудасруу шилжих"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Дээш шилжих"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Нэмэлт сонголтууд"</string>
@@ -1710,4 +1736,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Хугацааг бичнэ үү"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Цагийг оруулахын тулд текст оруулах горимд шилжүүлнэ үү."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Цагийг оруулахын тулд цагийн горимд шилжүүлнэ үү."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g>-д хадгалах уу?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g>-г <xliff:g id="LABEL">%2$s</xliff:g>-д хадгалах уу?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Хадгалах"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Үгүй, баярлалаа"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"нууц үг"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"хаяг"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"кредит карт"</string>
 </resources>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 1f040f1..1d1864a 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"लपविलेली सामग्री"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"धोरणाद्वारे सामग्री लपविली"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"सुरक्षितता"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"सूचना"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"सुरक्षित मोड"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android सिस्‍टम"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"वैयक्तिकवर स्विच करा"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"अनुप्रयोगाला वापरकर्ता हस्‍तक्षेपाशिवाय मुख्‍यस्‍क्रीन शॉर्टकट काढण्‍याची अनुमती देते."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"केले जाणारे कॉल पुन्हा मार्गस्थ करा"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"कॉल केला जात असताना कॉलला भिन्न नंबरवर पुनर्निर्देशित करण्‍याच्‍या किंवा संपूर्ण कॉल रद्द करण्‍याच्‍या पर्यायासह डायल केला जाणारा नंबर पाहण्‍याची अ‍ॅपला अनुमती देते"</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"मजकूर संदेश प्राप्त करा (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"SMS संदेश प्राप्त करण्याची आणि त्यावर प्रक्रिया करण्याची अॅप ला अनुमती देते. म्हणजेच अॅप आपल्या डिव्हाइसवर पाठविलेले संदेश आपल्याला न दर्शवता त्यांचे परीक्षण करू किंवा ते हटवू शकतो."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"मजकूर संदेश प्राप्त करा (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"अन्य अॅप्सच्या पार्श्वभूमी प्रक्रिया समाप्त करण्यासाठी अॅप ला अनुमती देते. यामुळे अन्य अॅप्स चालणे थांबू शकते."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"हा अॅप इतर अॅप्सच्या शीर्षस्थानी दिसू शकतो."</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"हा अॅप इतर अॅप्सच्या शीर्षस्थानी किंवा स्क्रीनच्या इतर भागांवर दिसू शकतो. हे सामान्य अॅप वापरात व्यत्यय आणू शकते किंवा इतर अॅप्सची प्रदर्शन पद्धत बदलू शकते."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"पार्श्वभूमीत चालवा"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"हे अॅप पार्श्वभूमीत चालू शकते. हे बॅटरी अधिक जलद संपवू शकते."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"पार्श्वभूमीत डेटा वापरा"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"हे अ‍ॅप पार्श्वभूमीत डेटा वापरू शकते. हे डेटाचा वापर वाढवू शकते."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"अॅप नेहमी चालवा"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"अॅप ला मेमरीमध्ये कायम असलेले त्याचे स्वतःचे भाग बनविण्यास अनुमती देते. हे टॅबलेट धीमा करून अन्य अॅप्सवर उपलब्ध असलेल्या मेमरीवर मर्यादा घालू शकते."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"अॅपला मेमरीमध्ये कायम असलेले त्याचे स्वतःचे भाग बनविण्यासाठी अनुमती देते. हे टीव्ही धीमा करून इतर अॅप्सवर उपलब्ध असलेली मेमरी मर्यादित करू शकते."</string>
@@ -519,8 +545,8 @@
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"होल्‍डरला वाहकद्वारे-प्रदान केलेल्या कॉन्फिगरेशन अ‍ॅपची विनंती करण्‍याची अनुमती देते. सामान्‍य अ‍ॅप्‍ससाठी कधीही आवश्‍यक नसावे."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"नेटवर्क स्‍थितींवरील निरीक्षणांसाठी ऐका"</string>
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"अनु्प्रयोगाला नेटवर्क स्‍थितींवरील निरीक्षणे ऐकण्‍यासाठी अनुमती देते. सामान्‍य अ‍ॅप्‍ससाठी कधीही आवश्‍यक नसावे."</string>
-    <string name="permlab_setInputCalibration" msgid="4902620118878467615">"इनपुट डिव्हाइस अंशांकन बदला"</string>
-    <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"स्पर्श स्क्रीनची मापन प्राचले सुधारित करण्यासाठी अॅप ला अनुमती देते. सामान्य अॅप्स साठी कधीही आवश्यक नसते."</string>
+    <string name="permlab_setInputCalibration" msgid="4902620118878467615">"इनपुट डिव्हाइस कॅलिब्रेशन बदला"</string>
+    <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"स्पर्श स्क्रीनची कॅलिब्रेशन प्राचले सुधारित करण्यासाठी अॅप ला अनुमती देते. सामान्य अॅप्स साठी कधीही आवश्यक नसते."</string>
     <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"DRM प्रमाणपत्रांवर प्रवेश करा"</string>
     <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"DRM प्रमाणपत्रांची तरतूद करण्यासाठी आणि वापरण्यासाठी अनुप्रयोगास अनुमती देते. सामान्य अॅप्सकरिता कधीही आवश्यकता नसते."</string>
     <string name="permlab_handoverStatus" msgid="7820353257219300883">"Android बीम स्थानांतरण स्थिती प्राप्त करा"</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"इनपुट पद्धत"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"मजकूर क्रिया"</string>
     <string name="email" msgid="4560673117055050403">"ईमेल"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"फोन"</string>
     <string name="map" msgid="5441053548030107189">"नकाशा"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"ब्राउझ करा"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"संचयन स्थान संपत आहे"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"काही सिस्टम कार्ये कार्य करू शकत नाहीत"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"सिस्टीमसाठी पुरेसे संचयन नाही. आपल्याकडे 250MB मोकळे स्थान असल्याचे सुनिश्चित करा आणि रीस्टार्ट करा."</string>
@@ -1174,6 +1198,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"भाषा आणि लेआउट निवडण्यासाठी टॅप करा"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> इतर अॅप्सवर काढा"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> अ‍ॅप शीर्षस्थानी प्रदर्शित होत आहे"</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"या अ‍ॅपचे भाग सर्व वेळी दृश्यमान असू शकतात. हे वैशिष्ट्य बरोबर काम करत नसल्यास, ते बंद करा."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"बंद करा"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> तयार करीत आहे"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"त्रुटींसाठी तपासत आहे"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"नवीन <xliff:g id="NAME">%s</xliff:g> आढळले"</string>
@@ -1328,8 +1356,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> सह सामायिक करा"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"स्लायडिंग हँडल. स्पर्श करा आणि धरुन ठेवा."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"अनलॉक करण्यासाठी स्वाइप करा."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"बोललेल्या संकेतशब्द की ऐकण्यासाठी हेडसेट लावा."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"बिंदू."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"मुख्‍यपृष्‍ठ नेव्‍हिगेट करा"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"वर नेव्‍हिगेट करा"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"अधिक पर्याय"</string>
@@ -1713,4 +1739,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"वेळ टाइप करा"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"वेळ इनपुटसाठी मजकूर इनपुट मोडवर स्विच करा."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"वेळ इनपुटसाठी घड्याळ मोडवर स्विच करा."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> वर जतन करायचे?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="LABEL">%2$s</xliff:g> वर <xliff:g id="TYPE">%1$s</xliff:g> जतन करायचे?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"जतन करा"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"नाही धन्यवाद"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"संकेतशब्द"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"पत्ता"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"क्रेडिट कार्ड"</string>
 </resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 6dedbb0..531df6b 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Kandungan tersembunyi"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Kandungan disembunyikan oleh dasar"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Keselamatan"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Makluman"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Mod selamat"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Beralih kepada Peribadi"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Membenarkan aplikasi mengalih keluar pintasan Skrin Laman Utama tanpa campur tangan pengguna."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"tukar laluan panggilan keluar"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Membenarkan apl melihat nombor yang didail semasa panggilan keluar dengan pilihan untuk mengubah hala panggilan ke nombor lain atau membatalkan terus panggilan."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"terima mesej teks (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Membenarkan apl menerima dan memproses mesej SMS. Ini bermakna apl boleh memantau atau memadam mesej yang dihantar ke peranti anda tanpa menunjukkannya kepada anda."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"terima mesej teks (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Membenarkan apl untuk menamatkan proses latar belakang apl lain. Ini boleh menyebabkan apl lain berhenti berjalan."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Apl ini boleh muncul di sebelah atas apl lain"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Apl ini boleh muncul di sebelah atas apl lain atau pada bahagian lain skrin. Hal ini mungkin mengganggu penggunaan biasa apl dan mengubah cara apl lain itu muncul."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"berjalan di latar belakang"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Apl ini boleh berjalan di latar belakang. Tindakan ini mungkin menyusutkan bateri dengan lebih pantas."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"gunakan data di latar belakang"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Apl ini boleh menggunakan data di latar belakang. Tindakan ini mungkin meningkatkan penggunaan data."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"buatkan apl sentiasa berjalan"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Membenarkan apl untuk membuat sebahagian dirinya berterusan dalam memori. Ini boleh mengehadkan memori yang tersedia kepada apl lain dan menjadikan tablet perlahan."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Membenarkan apl menjadikan sebahagian daripada apl kekal dalam memori. Ini boleh mengehadkan memori yang tersedia kepada apl lain dan menjadikan TV perlahan."</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"Kaedah input"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Tindakan teks"</string>
     <string name="email" msgid="4560673117055050403">"E-mel"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"Telefon"</string>
     <string name="map" msgid="5441053548030107189">"Peta"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"Semak imbas"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Ruang storan semakin berkurangan"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Beberapa fungsi sistem mungkin tidak berfungsi"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Tidak cukup storan untuk sistem. Pastikan anda mempunyai 250MB ruang kosong dan mulakan semula."</string>
@@ -1173,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Ketik untuk memilih bahasa dan susun atur"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> melukis di atas apl lain"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"Apl <xliff:g id="NAME">%s</xliff:g> dipaparkan di bahagian atas."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Sebahagian daripada apl ini mungkin kekal kelihatan pada sepanjang masa. Jika ciri ini tidak berfungsi dengan betul, matikan ciri ini."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"MATIKAN"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Menyediakan <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Menyemak untuk mengesan ralat"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"<xliff:g id="NAME">%s</xliff:g> baharu dikesan"</string>
@@ -1327,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Kongsi dengan <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Pemegang gelongsor. Sentuh &amp; tahan."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Leret untuk membuka kunci."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Pasangkan set kepala untuk mendengar kekunci kata laluan disebutkan."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Titik."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Navigasi laman utama"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Navigasi ke atas"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Lagi pilihan"</string>
@@ -1712,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Taipkan masa"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Beralih ke mod input teks untuk input masa."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Beralih ke mod jam untuk input masa."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Simpan ke <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Simpan <xliff:g id="TYPE">%1$s</xliff:g> ke <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Simpan"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Tidak, terima kasih"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"kata laluan"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"alamat"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kad kredit"</string>
 </resources>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 12a59a4..f50e650 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"၉၉၉+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"အကြောင်းအရာများ ဝှက်ထား"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"မူဝါဒမှ အကြောင်းအရာများကို ဝှက်ထားသည်"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"လုံခြုံရေး"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"သတိပေးချက်များ"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"အန္တရာယ်ကင်းမှု စနစ်(Safe mode)"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android စနစ်"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"ကိုယ်ပိုင်သီးသန့်အဖြစ် ပြောင်းပါ"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"အပလီကေးရှင်းအား အသုံးပြုသူ လုပ်ဆောင်ခြင်း မပါပဲ ပင်မ မြင်ကွင်းအား ဖယ်ရှားခွင့် ပေးခြင်း"</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"အထွက် ခေါ်ဆိုမှုများအား လမ်းလွှဲပြောင်းခြင်း"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"အက်ပ်အား အပြင်သို့ ဖုန်းခေါ်ဆိုမှု အတွင်းမှာ ဆက်ခဲ့သည့် နံပါတ်ကို ကြည့်နိုင်ကာ ခေါ်ဆိုမှုကို အခြား နံပါတ် တစ်ခုသို့ ပြောင်းလဲပစ်ခြင်း သို့မဟုတ် ခေါ်ဆိုမှုကို လုံးဝ ဖျက်သိမ်းခွင့် ပြုသည်။"</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"စာပို့ခြင်းအား လက်ခံရယူခြင်း (စာတိုစနစ်)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"အပလီကေးရှင်းအား စာတိုများ လက်ခံခြင်း၊ ဆောင်ရွက်ခြင်း ခွင့်ပြုပါ။ ဤခွင့်ပြုချက်တွင် အပလီကေးရှင်းအနေဖြင့် သင် လက်ခံရရှိသော စာများအား သင့်အား မပြပဲစောင့်ကြည့်ခွင့်နှင့် ဖျက်ပစ်ခွင့်များ ပါဝင်ပါသည်။"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"စာပို့ခြင်းအား လက်ခံရယူခြင်း (ရုပ်သံစာ)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"အပလီကေးရှင်းအား နောက်ကွယ်တွင် ဖွင့်ထားသော အခြားအပလီကေးရှင်းများရဲ့ လုပ်ဆောင်မှုများအား ရပ်ခွင့်ပေးပါ။ ဒီလိုလုပ်ခြင်းဖြင့် အခြား အပလီကေးရှင်းများ ရပ်တန့်သွားနိုင်ပါသည်"</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"ဤအက်ပ်သည် အခြားအက်ပ်များ၏ အပေါ်တွင် ဖွင့်နိုင်ပါသည်"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"ဤအက်ပ်သည် အခြားအက်ပ်များ၏အပေါ် သို့မဟုတ် မျက်နှာပြင်၏ အခြားအစိတ်အပိုင်းများ၏ အပေါ်တွင် ဖွင့်နိုင်ပါသည်။ ၎င်းသည် သာမန်အက်ပ်အသုံးပြုခြင်းကို အနှောင့်အယှက်ဖြစ်စေနိုင်ပြီး အခြားအက်ပ်များအား ဖွင့်ပုံကို ပြောင်းလဲစေနိုင်ပါသည်။"</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"နောက်ခံတွင် ဖွင့်ရန်"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"ဤအက်ပ်သည် နောက်ခံတွင် ပွင့်နေနိုင်သောကြောင့် ဘက်ထရီအကုန် မြန်စေနိုင်ပါသည်။"</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"နောက်ခံတွင် ဒေတာအသုံးပြုရန်"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"ဤအက်ပ်သည် နောက်ခံတွင် ဒေတာအသုံးပြုနေနိုင်သောကြောင့် ဒေတာအသုံးပြုမှု များစေနိုင်ပါသည်။"</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"အက်ပ်ကို အမြဲတမ်း အလုပ်လုပ်စေခြင်း"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"အပလီကေးရှင်းအား မှတ်ဉာဏ်ထဲတွင် ရေရှည်သိမ်းဆည်ထားရန် ခွင့်ပြုပါ။ ဒီခွင့်ပြုချက်ကြောင့် တခြားအပလီကေးရှင်းအများအတွက် မှတ်ဉာဏ်ရရှိမှု နည်းသွားနိုင်ပြီး တက်ဘလက်လည်း နှေးသွားနိုင်ပါသည်။"</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"မှတ်ဉာဏ်တွင် ၎င်း၏အစိတ်အပိုင်းများကိုယ်တိုင် တည်မြဲနေစေရန် အက်ပ်အား ခွင့်ပြုပါ။ ဤနည်းဖြင့် တီဗွီကို နှေးစေသော အခြား အက်ပ်များ၏ မှတ်ဉာဏ်ကို ကန့်သတ်ထားနိုင်သည်။"</string>
@@ -962,7 +988,7 @@
     <string name="email" msgid="4560673117055050403">"အီးမေးလ်"</string>
     <string name="dial" msgid="4204975095406423102">"ဖုန်း"</string>
     <string name="map" msgid="5441053548030107189">"မြေပုံ"</string>
-    <string name="browse" msgid="6079864138582486027">"ဖွင့်ရန်"</string>
+    <string name="browse" msgid="6079864138582486027">"အကြမ်းဖျင်း ကြည့်ရန်"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"သိမ်းဆည်သော နေရာ နည်းနေပါသည်"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"တချို့ စနစ်လုပ်ငန်းများ အလုပ် မလုပ်ခြင်း ဖြစ်နိုင်ပါသည်"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"စနစ်အတွက် သိုလှောင်ခန်း မလုံလောက်ပါ။ သင့်ဆီမှာ နေရာလွတ် ၂၅၀ MB ရှိတာ စစ်ကြည့်ပြီး စတင်ပါ။"</string>
@@ -1172,6 +1198,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ဘာသာစကားနှင့် အသွင်အပြင်ရွေးချယ်ရန် တို့ပါ"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> သည် အခြားအက်ပ်များအပေါ်တွင် ပေါ်ပါမည်"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> အက်ပ်ကို အပေါ်ဆုံးတွင် ပြမည်။"</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"ဤအက်ပ်၏ တစ်စိတ်တစ်ဒေသကို အမြဲမြင်တွေ့နိုင်ပါမည်။ အကယ်၍ ဤဝန်ဆောင်မှုသည် မှန်မှန်ကန်ကန် အလုပ်မလုပ်လျှင် ၎င်းကို ပိတ်လိုက်ပါ။"</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ပိတ်ပါ"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> ပြင်ဆင်နေသည်"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"အမှားအယွင်းများ စစ်ဆေးနေသည်"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"<xliff:g id="NAME">%s</xliff:g> အသစ်တွေ့ရှိပါသည်"</string>
@@ -1326,8 +1356,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g>နှင့် မျှဝေပါမည်"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"ဆွဲယူနိုင်သည့် လက်ကိုင်။ ထိပါ &amp; ကိုင်ထားပါ။"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"သော့ဖွင့်ရန် ပွတ်ဆွဲပါ"</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"စကားဝှက်ပြောဆိုမှုကို ကြားနိုင်ရန် မိုက်ခွက်ပါနားကြပ် တပ်ပြီး နားထောင်ပါ"</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"ဒေါ့"</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"ပင်မစာမျက်နှာကို ပြန်သွားရန်"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"အပေါ်သို့သွားရန်"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"ပိုမိုရွေးချယ်စရာများ"</string>
@@ -1711,4 +1739,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"အချိန်ကို ရိုက်ရန်"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"အချိန်ထည့်သွင်းရန် စာသားထည့်သွင်းမှုမုဒ်သို့ ပြောင်းပါ။"</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"အချိန်ထည့်သွင်းမှုအတွက် နာရီမုဒ်သို့ ပြောင်းပါ။"</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> သို့ သိမ်းဆည်းလိုပါသလား။"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> ကို <xliff:g id="LABEL">%2$s</xliff:g> သို့ သိမ်းဆည်းလိုပါသလား။"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"သိမ်းရန်"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"မလိုပါ"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"စကားဝှက်"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"လိပ်စာ"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"ခရက်တစ်ကတ်"</string>
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 12b7904..8ee44c8 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Innholdet er skjult"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Innholdet er skjult i henhold til retningslinjene"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Sikkerhet"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Varsler"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Sikkermodus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Bytt til den personlige profilen"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Lar appen fjerne snarveier på startsiden uten å involvere brukeren."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"omdirigere utgående anrop"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Lar appen se nummeret det ringes til under en utgående samtale, med mulighet for å omdirigere anropet til et annet nummer eller avbryte samtalen fullstendig."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"motta tekstmeldinger (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Lar appen motta og behandle tekstmeldinger. Dette betyr at appen kan overvåke eller slette meldinger som er sendt til enheten din uten at du har sett dem."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"motta tekstmeldinger (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Lar appen avslutte andre appers bakgrunnsprosesser. Dette kan føre til at andre apper slutter å kjøre."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Denne appen kan ligge over andre apper"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Denne appen kan vises over andre apper eller andre deler av skjermen. Dette kan påvirke normal bruk av apper og endre måten andre apper vises på."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"kjør i bakgrunnen"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Denne appen kan kjøre i bakgrunnen. Det kan øke batteribruken."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"bruk data i bakgrunnen"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Denne appen kan bruke data i bakgrunnen. Det kan øke databruken."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"angi at appen alltid skal kjøre"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Lar appen gjøre deler av seg selv vedvarende i minnet. Dette kan begrense minnet for andre apper og gjøre nettbrettet tregt."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Gjør at deler av appen kan legge seg vedvarende i minnet. Dette kan begrense minnets tilgjengelighet for andre apper, noe som gjør at TV-en går langsommere."</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"Inndatametode"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Teksthandlinger"</string>
     <string name="email" msgid="4560673117055050403">"E-post"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"Telefon"</string>
     <string name="map" msgid="5441053548030107189">"Kart"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"Bla gjennom"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Lite ledig lagringsplass"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Enkelte systemfunksjoner fungerer muligens ikke slik de skal"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Det er ikke nok lagringsplass for systemet. Kontrollér at du har 250 MB ledig plass, og start på nytt."</string>
@@ -1173,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Trykk for å velge språk og layout"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> ligger over andre apper"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g>-appen vises øverst."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Deler av denne appen kan være synlige til enhver tid. Slå denne funksjonen av hvis den ikke fungerer som den skal."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"SLÅ AV"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Forbereder <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Sjekker for feil"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"<xliff:g id="NAME">%s</xliff:g> ble oppdaget"</string>
@@ -1327,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Del med <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Glidebryter. Trykk og hold inne."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Sveip for å låse opp."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Koble til hodetelefoner for å høre opplesing av bokstavene i passordet."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punktum."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Gå til startsiden"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Gå opp"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Flere alternativer"</string>
@@ -1712,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Skriv inn klokkeslett"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Bytt til tekstinndatamodus for tidsinndata."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Bytt til klokkemodus for tidsinndata."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Vil du lagre i <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Vil du lagre <xliff:g id="TYPE">%1$s</xliff:g> i <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Lagre"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Nei takk"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"passord"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"adresse"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kredittkort"</string>
 </resources>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index d6fada6..4895ab6 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"९९९+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"लुकेका सामाग्रीहरू"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"नीतिद्वारा लुकाइएका सामग्री"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"सुरक्षा"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"अलर्टहरू"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"सुरक्षित मोड"</string>
     <string name="android_system_label" msgid="6577375335728551336">"एन्ड्रोइड प्रणाली"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"व्यक्तिगत प्रोफाइलमा स्विच गर्नुहोस्"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"प्रयोगकर्ताको हस्तक्षेप बिना एउटा अनुप्रयोगलाई सर्टकटमा हटाउनको लागि अनुमति दिन्छ।"</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"बहिर्गमन कलहरूलाई अर्को मार्ग दिनुहोस्"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"अनुप्रयोगलाई अन्य नम्बरमा कल पुर्ननिर्देश वा समग्र कल परित्याग विकल्प सहित बहिर्गमन कल समयमा डायल गर्दाको नम्बर हेर्न अनुमति दिन्छ।"</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"पाठ सन्देशहरू (SMS) प्राप्त गर्नुहोस्"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"अनुप्रयोगलाई SMS सन्देशहरू प्राप्त गर्न र प्रक्रिया गर्न अनुमति दिन्छ। यसको मतलब अनुप्रयोगले तपाईंको उपकरणमा पठाइएको सन्देशहरू तपाईंलाई नदेखाईनै मोनिटर गर्न वा मेटाउन सक्दछ।"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"पाठ सन्देश (MMS) प्राप्त गर्नुहोस्"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"अनुप्रयोगलाई अन्य अनुप्रयोगहरूको पृष्ठभूमि प्रक्रियाहरू बन्द गर्न अनुमति दिन्छ। यसले अन्य अनुप्रयोगहरूलाई चल्नबाट रोक्न सक्दछ।"</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"यो अनुप्रयोग अन्य अनुप्रयोगहरूमाथि देखा पर्न सक्छ"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"यो अनुप्रयोग अन्य अनुप्रयोगहरूमाथि वा स्क्रिनका अन्य भागहरूमा देखा पर्न सक्छ। यसले अनुप्रयोगको सामान्य प्रयोगमा अवरोध पुर्याउन सक्छ र अन्य अनुप्रयोगहरू देखा पर्ने तरिकालाई परिवर्तन गर्न सक्छ।"</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"पृष्ठभूमिमा चलाउनुहोस्"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"यो अनुप्रयोग पृष्ठभूमिमा चल्न सक्छ। यसले गर्दा छिट्टै ब्याट्रीको खपत हुनसक्छ।"</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"पृष्ठभूमिमा डेटा प्रयोग गर्नुहोस्"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"यो अनुप्रयोगले पृष्ठभूमिमा डेटा प्रयोग गर्नसक्छ। यसले गर्दा धेरै डेटा प्रयोग हुनसक्छ।"</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"अनुप्रयोगहरू जहिले पनि चल्ने बनाउनुहोस्"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"यसको आफ्नै मेमोरीमा दृढ भएकोको अंश बनाउनको लागि अनुप्रयोगलाई अनुमति दिन्छ। ट्याब्लेटलाई ढिलो गराउँदै गरेका अन्य अनुप्रयोगहरूलाई सीमित मात्रामा यसले मेमोरी उपलब्ध गराउन सक्छ।"</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"अनुप्रयोगलाई अनुमति दिन्छ मेमोरीमा आफैंलाई स्थायी भागका रूपमा प्रस्तुत गर्न। यसले अन्य अनुप्रयोगलाई उपलब्ध मेमोरीलाई सीमित गरी TV लाई ढिलो बनाउन सक्छ।"</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"निवेश विधि"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"पाठ कार्यहरू"</string>
     <string name="email" msgid="4560673117055050403">"इमेल"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"फोन गर्नुहोस्"</string>
     <string name="map" msgid="5441053548030107189">"नक्सा"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"ब्राउज गर्नुहोस्"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"भण्डारण ठाउँ सकिँदै छ"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"सायद केही प्रणाली कार्यक्रमहरूले काम गर्दैनन्"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"प्रणालीको लागि पर्याप्त भण्डारण छैन। तपाईँसँग २५० मेगा बाइट ठाउँ खाली भएको निश्चित गर्नुहोस् र फेरि सुरु गर्नुहोस्।"</string>
@@ -1179,6 +1203,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"भाषा र लेआउट चयन गर्न ट्याप गर्नुहोस्"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> लाई अन्य अनुप्रयोगहरूमा देखिन दिनुहोस्"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> अनुप्रयोग शीर्षमा देखाउँदै।"</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"यो अनुप्रयोगका केही अंशहरू सधैँ देखिरहन सक्छन्‌। यो सुविधाले सही ढंगले काम गरिरहेको छैन भने, यसलाई बन्द गर्नुहोस्‌।"</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"निष्क्रिय पार्नुहोस्"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"तयारी गर्दै <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"त्रुटिहरूको लागि जाँच गर्दै"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"नयाँ <xliff:g id="NAME">%s</xliff:g> भेटियो"</string>
@@ -1333,8 +1361,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> सँग साझेदारी गर्नुहोस्"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"धिसार्ने ह्यान्डल। छुनुहोस् &amp; समाउनुहोस्।"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"खोल्नलाइ हुत्त्याउनुहोस्।"</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"बोलिएको पासवर्ड कुञ्जीहरू सुन्नको लागि हेडसेट प्लग इन गर्नुहोस्।"</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"डट।"</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"गृह खोज्नुहोस्"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"माथि खोज्नुहोस्"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"थप विकल्पहरू"</string>
@@ -1718,4 +1744,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"समय टाइप गर्नुहोस्‌"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"समय इनपुट गर्न पाठ इनपुट मोडमा स्विच गर्नुहोस्।"</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"समय इनपुट गर्न घडी मोडमा स्विच गर्नुहोस्।"</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> मा सुरक्षित गर्ने हो?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> लाई <xliff:g id="LABEL">%2$s</xliff:g> मा सुरक्षित गर्ने हो?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"सुरक्षित गर्नुहोस्"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"पर्दैन, धन्यवाद"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"पासवर्ड"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"ठेगाना"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"क्रेडिट कार्ड"</string>
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index b5b133e..255ea72 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999 +"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Content verborgen"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Content verborgen op basis van beleid"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Beveiliging"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Meldingen"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Veilige modus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-systeem"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Overschakelen naar persoonlijk profiel"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"De app toestaan snelkoppelingen van het startscherm te verwijderen zonder tussenkomst van de gebruiker."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"uitgaande oproepen doorschakelen"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"De app toestaan het nummer te bekijken dat wordt gekozen voor een uitgaande oproep, met de mogelijkheid de oproep om te leiden naar een ander nummer of de oproep helemaal af te breken."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"tekstberichten (SMS) ontvangen"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Hiermee kan de app sms-berichten ontvangen en verwerken. Dit betekent dat de app berichten die naar je apparaat zijn verzonden, kan bijhouden of verwijderen zonder deze aan u weer te geven."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"tekstberichten (MMS) ontvangen"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Hiermee kan de app achtergrondprocessen van andere apps beëindigen. Hierdoor kunnen andere apps worden gestopt."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Deze app kan op de voorgrond vóór andere apps worden weergegeven"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Deze app kan op de voorgrond worden weergegeven vóór andere apps of andere gedeelten van het scherm. Dit kan het normale app-gebruik verstoren en de manier wijzigen waarop andere apps worden weergegeven."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"uitvoeren op de achtergrond"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Deze app kan op de achtergrond worden uitgevoerd. Dit kan meer batterijlading verbruiken."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"data gebruiken op de achtergrond"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Deze app kan op de achtergrond data verbruiken. Dit kan het datagebruik verhogen."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"app altijd laten uitvoeren"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Hiermee kan de app gedeelten van zichzelf persistent maken in het geheugen. Dit kan de hoeveelheid geheugen beperken die beschikbaar is voor andere apps, waardoor de tablet trager kan worden."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Hiermee kan de app gedeelten van zichzelf persistent maken in het geheugen. Dit kan de hoeveelheid geheugen beperken die beschikbaar is voor andere apps, waardoor de tv trager kan worden."</string>
@@ -1171,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tik om een taal en indeling te selecteren"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> wordt weergegeven over andere apps"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g>-app bovenop weergeven."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Delen van deze app blijven altijd zichtbaar. Als deze functie niet correct werkt, schakel je deze uit."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"UITSCHAKELEN"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> voorbereiden"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Controleren op fouten"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Nieuwe <xliff:g id="NAME">%s</xliff:g> gedetecteerd"</string>
@@ -1325,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Delen met <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Schuifgreep. Tikken en blijven aanraken."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Vegen om te ontgrendelen"</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Sluit een headset aan om wachtwoordtoetsen te laten voorlezen."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Stip."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Navigeren naar startpositie"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Omhoog navigeren"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Meer opties"</string>
@@ -1710,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Typ een tijd"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Schakel naar de tekstinvoermodus om de tijd in te voeren."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Schakel naar de klokmodus om de tijd in te voeren."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Opslaan in <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> opslaan in <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Opslaan"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Nee, bedankt"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"Wachtwoord"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"Adres"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"Creditcard"</string>
 </resources>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 104db35..d97a436 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"ਸਮੱਗਰੀਆਂ ਲੁਕਾਈਆਂ ਗਈਆਂ"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"ਨੀਤੀ ਦੁਆਰਾ ਸਮੱਗਰੀ ਲੁਕਾਈ ਗਈ"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"ਸੁਰੱਖਿਆ"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"ਸੁਚੇਤਨਾਵਾਂ"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"ਸੁਰੱਖਿਅਤ ਮੋਡ"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"ਨਿੱਜੀ \'ਤੇ ਸਵਿੱਚ ਕਰੋ"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"ਐਪਲੀਕੇਸ਼ਨ ਨੂੰ ਉਪਭੋਗਤਾ ਦਖ਼ਲ ਤੋਂ ਬਿਨਾਂ ਹੋਮਸਕ੍ਰੀਨ ਸ਼ਾਰਟਕੱਟ ਹਟਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"ਆਊਟਗੋਇੰਗ ਕਾਲਾਂ ਰੀਰੂਟ ਕਰੋ"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"ਐਪ ਨੂੰ ਇੱਕ ਵੱਖ ਨੰਬਰ ਨਾਲ ਕਾਲ ਰੀਡਾਇਰੈਕਟ ਕਰਨ ਜਾਂ ਕਾਲ ਨੂੰ ਪੂਰਾ ਰੋਕਣ ਦੀ ਚੋਣ ਨਾਲ ਇੱਕ ਆਊਟਗੋਇੰਗ ਕਾਲ ਦੇ ਦੌਰਾਨ ਡਾਇਲ ਕੀਤਾ ਜਾ ਰਿਹਾ ਨੰਬਰ ਦੇਖਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"ਟੈਕਸਟ ਸੁਨੇਹੇ (SMS) ਪ੍ਰਾਪਤ ਕਰੋ"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"ਐਪ ਨੂੰ SMS ਸੁਨੇਹੇ ਪ੍ਰਾਪਤ ਕਰਨ ਅਤੇ ਉਹਨਾਂ ਦੀ ਪ੍ਰਕਿਰਿਆ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਸਦਾ ਮਤਲਬ ਹੈ ਕਿ ਐਪ ਤੁਹਾਡੀ ਡੀਵਾਈਸ ਤੇ ਭੇਜੇ ਗਏ ਸੁਨੇਹਿਆਂ ਨੂੰ ਤੁਹਾਨੂੰ ਦਿਖਾਏ ਬਿਨਾਂ ਨਿਰੀਖਣ ਕਰ ਸਕਦਾ ਹੈ ਜਾਂ ਮਿਟਾ ਸਕਦਾ ਹੈ।"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ਟੈਕਸਟ ਸੁਨੇਹੇ (MMS) ਪੜ੍ਹੋ"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"ਐਪ ਨੂੰ ਹੋਰਾਂ ਐਪਸ ਦੀਆਂ ਪਿਛੋਕੜ ਪ੍ਰਕਿਰਿਆਵਾਂ ਖ਼ਤਮ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਸ ਨਾਲ ਹੋਰ ਚੱਲ ਰਹੇ ਐਪਸ ਰੁਕ ਸਕਦੇ ਹਨ।"</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"ਇਹ ਐਪ ਹੋਰ ਐਪਾਂ ਦੇ ਸਿਖਰ \'ਤੇ ਵਿਖਾਈ ਦੇ ਸਕਦੀ ਹੈ"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"ਇਹ ਐਪ ਹੋਰ ਐਪਾਂ ਦੇ ਸਿਖਰ \'ਤੇ ਜਾਂ ਸਕ੍ਰੀਨ ਦੇ ਹੋਰ ਭਾਗਾਂ \'ਤੇ ਵਿਖਾਈ ਦੇ ਸਕਦੀ ਹੈ। ਇਹ ਸਧਾਰਨ ਐਪ ਵਰਤੋਂ ਵਿੱਚ ਵਿਘਨ ਪਾ ਸਕਦੀ ਹੈ ਅਤੇ ਹੋਰ ਐਪਾਂ ਦੇ ਵਿਖਾਈ ਦੇਣ ਦੇ ਤਰੀਕੇ ਨੂੰ ਬਦਲ ਸਕਦੀ ਹੈ।"</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਚਲਾਓ"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"ਇਹ ਐਪ ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਚੱਲ ਸਕਦੀ ਹੈ। ਇਸ ਨਾਲ ਬੈਟਰੀ ਵਧੇਰੇ ਤੇਜ਼ੀ ਨਾਲ ਖਤਮ ਹੋ ਸਕਦੀ ਹੈ।"</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਡੈਟੇ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"ਇਹ ਐਪ ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਡੈਟੇ ਦੀ ਵਰਤੋਂ ਕਰ ਸਕਦੀ ਹੈ। ਇਸ ਨਾਲ ਡੈਟਾ ਉਪਯੋਗ ਵਧ ਸਕਦਾ ਹੈ।"</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"ਐਪ ਨੂੰ ਹਮੇਸ਼ਾਂ ਰਨ ਕਰੋ"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"ਐਪ ਨੂੰ ਮੈਮਰੀ ਵਿੱਚ ਖੁਦ ਦੇ ਭਾਗਾਂ ਨੂੰ ਸਥਾਈ ਬਣਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਟੈਬਲੇਟ ਨੂੰ ਹੌਲੀ ਕਰਦੇ ਹੋਏ ਹੋਰਾਂ ਐਪਸ ਤੇ ਉਪਲਬਧ ਮੈਮਰੀ ਨੂੰ ਸੀਮਿਤ ਕਰ ਸਕਦਾ ਹੈ।"</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"ਐਪ ਨੂੰ ਮੈਮਰੀ ਵਿੱਚ ਖੁਦ ਦੇ ਭਾਗਾਂ ਨੂੰ ਸਥਾਈ ਬਣਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ TV ਨੂੰ ਹੌਲੀ ਕਰਦੇ ਹੋਏ ਹੋਰਾਂ ਐਪਸ ਤੇ ਉਪਲਬਧ ਮੈਮਰੀ ਨੂੰ ਸੀਮਿਤ ਕਰ ਸਕਦਾ ਹੈ।"</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"ਇਨਪੁਟ ਵਿਧੀ"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"ਟੈਕਸਟ ਕਿਰਿਆਵਾਂ"</string>
     <string name="email" msgid="4560673117055050403">"ਈਮੇਲ ਕਰੋ"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"ਫ਼ੋਨ ਕਰੋ"</string>
     <string name="map" msgid="5441053548030107189">"ਨਕਸ਼ਾ ਖੋਲ੍ਹੋ"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"ਬ੍ਰਾਊਜ਼ ਕਰੋ"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"ਸਟੋਰੇਜ ਸਪੇਸ ਖ਼ਤਮ ਹੋ ਰਿਹਾ ਹੈ"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"ਕੁਝ ਸਿਸਟਮ ਫੰਕਸ਼ਨ ਕੰਮ ਨਹੀਂ ਵੀ ਕਰ ਸਕਦੇ"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"ਸਿਸਟਮ ਲਈ ਪੂਰੀ ਸਟੋਰੇਜ ਨਹੀਂ। ਯਕੀਨੀ ਬਣਾਓ ਕਿ ਤੁਹਾਡੇ ਕੋਲ 250MB ਖਾਲੀ ਸਪੇਸ ਹੈ ਅਤੇ ਰੀਸਟਾਰਟ ਕਰੋ।"</string>
@@ -1174,6 +1198,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ਭਾਸ਼ਾ ਅਤੇ ਖਾਕਾ ਚੁਣਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> ਹੋਰਾਂ ਐਪਾਂ ਉੱਤੇ ਪਸਰ ਸਕਦੀ ਹੈ"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> ਐਪ ਹੋਰ ਐਪਾਂ ਉੱਤੇ ਪਸਰੀ ਦਿਸ ਰਹੀ ਹੈ।"</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਇਸ ਐਪ ਦੇ ਕੁਝ ਹਿੱਸੇ ਹਰ ਸਮੇਂ ਵਿਖਾਈ ਦੇਣ। ਜੇਕਰ ਇਹ ਵਿਸ਼ੇਸ਼ਤਾ ਸਹੀ ਢੰਗ ਨਾਲ ਕੰਮ ਨਹੀਂ ਕਰ ਰਹੀ ਹੈ, ਤਾਂ ਇਸਨੂੰ ਬੰਦ ਕਰੋ।"</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ਬੰਦ ਕਰੋ"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> ਤਿਆਰ ਹੋ ਰਿਹਾ ਹੈ"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"ਤਰੁੱਟੀਆਂ ਦੀ ਜਾਂਚ ਕਰ ਰਿਹਾ ਹੈ"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"ਨਵੇਂ <xliff:g id="NAME">%s</xliff:g> ਦਾ ਪਤਾ ਲਗਾਇਆ ਗਿਆ"</string>
@@ -1328,8 +1356,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> ਨਾਲ ਸਾਂਝਾ ਕਰੋ"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"ਹੈਂਡਲ ਸਲਾਈਡ ਕਰ ਰਿਹਾ ਹੈ। ਸਪੱਰਸ਼ ਕਰੋ &amp; ਹੋਲਡ ਕਰੋ।"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"ਅਨਲੌਕ ਕਰਨ ਲਈ ਸਵਾਈਪ ਕਰੋ।"</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"ਬੋਲੀਆਂ ਗਈਆਂ ਪਾਸਵਰਡ ਕੁੰਜੀਆਂ ਸੁਣਨ ਲਈ ਇੱਕ ਹੈਡਸੈਟ ਪਲਗ ਇਨ ਕਰੋ।"</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"ਬਿੰਦੀ।"</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"ਹੋਮ ਨੈਵੀਗੇਟ ਕਰੋ"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"ਉੱਪਰ ਨੈਵੀਗੇਟ ਕਰੋ"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"ਹੋਰ ਚੋਣਾਂ"</string>
@@ -1713,4 +1739,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"ਸਮਾਂ ਟਾਈਪ ਕਰੋ"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"ਸਮਾਂ ਇਨਪੁੱਟ ਕਰਨ ਲਈ ਲਿਖਤ ਇਨਪੁੱਟ ਮੋਡ \'ਤੇ ਬਦਲੀ ਕਰੋ।"</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"ਸਮਾਂ ਇਨਪੁੱਟ ਕਰਨ ਲਈ ਘੜੀ ਮੋਡ \'ਤੇ ਬਦਲੀ ਕਰੋ।"</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> ਵਿੱਚ ਰੱਖਿਅਤ ਕਰੀਏ?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> ਨੂੰ <xliff:g id="LABEL">%2$s</xliff:g> ਵਿੱਚ ਰੱਖਿਅਤ ਕਰੀਏ?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"ਰੱਖਿਅਤ ਕਰੋ"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"ਨਹੀਂ ਧੰਨਵਾਦ"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"ਪਾਸਵਰਡ"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"ਪਤਾ"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"ਕ੍ਰੈਡਿਟ ਕਾਰਡ"</string>
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 9ac7124..f59c8c4 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -250,6 +250,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Treści ukryte"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Treść ukryta z powodu zasad"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Bezpieczeństwo"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Alerty"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Tryb awaryjny"</string>
     <string name="android_system_label" msgid="6577375335728551336">"System Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Włącz profil osobisty"</string>
@@ -298,6 +324,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Pozwala aplikacji usuwać skróty z ekranu głównego bez interwencji użytkownika."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"przekierowywanie połączeń wychodzących"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Pozwala aplikacji na sprawdzenie numeru wybieranego w trakcie połączenia wychodzącego, a także umożliwia przerwanie połączenia lub przekierowanie go pod inny numer."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"odbieranie wiadomości tekstowych (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Pozwala aplikacji na odbieranie i przetwarzanie SMS-ów. To oznacza, że aplikacja będzie mogła bez Twojej wiedzy monitorować i usuwać wiadomości wysyłane do Twojego urządzenia."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"odbieranie wiadomości tekstowych (MMS)"</string>
@@ -326,14 +356,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Pozwala aplikacji na kończenie procesów innych aplikacji działających w tle. Może to spowodować przerwanie działania innych aplikacji."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Ta aplikacja może wyświetlać się nad innymi aplikacjami"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Ta aplikacja może pojawić się nad innymi aplikacjami lub częściami ekranu. Może to przeszkadzać w jej zwykłym używaniu i zmieniać sposób wyświetlania innych aplikacji."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"działanie w tle"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Ta aplikacja może działać w tle. Bateria może się szybciej rozładowywać."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"transmisja danych w tle"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Ta aplikacja może przesyłać i odbierać dane w tle. Transmisja danych może się zwiększyć."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"sprawianie, że aplikacja jest cały czas uruchomiona"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Pozwala aplikacji na trwałe zapisywanie swoich fragmentów w pamięci. Może to zmniejszyć ilość pamięci dostępnej dla innych aplikacji i spowolnić działanie tabletu."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Pozwala aplikacji zapewnić nieusuwalność swoich fragmentów z pamięci. Może to ograniczyć ilość pamięci dostępną dla innych aplikacji i spowalniać działanie telewizora."</string>
@@ -1211,6 +1237,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Kliknij, by wybrać język i układ"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AĄBCĆDEĘFGHIJKLŁMNŃOÓPQRSŚTUVWXYZŹŻ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"Aplikacja <xliff:g id="NAME">%s</xliff:g> wyświetla się nad innymi"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"Aplikacja <xliff:g id="NAME">%s</xliff:g> jest nad innymi."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Fragmenty tej aplikacji mogą być widoczne przez cały czas. Jeśli ta funkcja nie działa prawidłowo, wyłącz ją."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"WYŁĄCZ"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Przygotowuję: <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Sprawdzanie w poszukiwaniu błędów"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Wykryto nowy nośnik: <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1367,8 +1397,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Udostępnij przez <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Uchwyt przesuwny. Dotknij i przytrzymaj."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Przesuń, aby odblokować."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Podłącz zestaw słuchawkowy, aby wysłuchać znaków hasła wypowiadanych na głos."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Kropka"</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Przejdź do strony głównej"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Przejdź wyżej"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Więcej opcji"</string>
@@ -1772,4 +1800,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Podaj czas"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Aby wprowadzić czas, włącz tryb wprowadzania tekstu."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Aby wprowadzić czas, włącz tryb zegara."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Zapisać w: <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Zapisać element <xliff:g id="TYPE">%1$s</xliff:g> w: <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Zapisz"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Nie, dziękuję"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"hasło"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"adres"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"karta kredytowa"</string>
 </resources>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 7cfd4c3..f05bab0 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Conteúdo oculto"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Conteúdo ocultado pela política"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Segurança"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Modo de segurança"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Alternar para \"Pessoal\""</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Permite que o app remova atalhos da tela inicial sem a intervenção do usuário."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"redirecionar as chamadas efetuadas"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Permite que o app veja o número discado ao realizar uma chamada, com a opção de redirecionar a chamada para outro número ou abortá-la."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"receber mensagens de texto (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permite que o app receba e processe mensagens SMS. Isso significa que o app pode monitorar ou excluir mensagens enviadas para o dispositivo sem mostrá-las para você."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"receber mensagens de texto (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Permite que o app encerre processos em segundo plano de outros apps. Pode ser que outros apps parem de funcionar."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Este app pode se sobrepor visualmente a outros apps"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Este app pode se sobrepor visualmente a outros apps ou a outras partes da tela. Isso pode interferir no uso normal do app e alterar a forma como os outros apps são exibidos."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"executar em segundo plano"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Este app pode ser executado em segundo plano, o que pode esgotar a bateria mais rapidamente."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"usar dados em segundo plano"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Este app pode usar dados em segundo plano, o que pode aumentar o uso de dados."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"sempre executar o app"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Permite que o app torne partes de si mesmo persistentes na memória. Pode limitar a memória disponível para outros apps, deixando o tablet mais lento."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Permite que o app torne partes de si mesmo persistentes na memória. Isso pode limitar a memória disponível para outros apps, deixando a TV mais lenta."</string>
@@ -1171,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toque para selecionar o idioma e o layout"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"Sobreposição do <xliff:g id="NAME">%s</xliff:g> a outros apps"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> exibido na parte superior da tela."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Partes desse app podem ficar sempre visíveis. Se esse recurso não estiver funcionando corretamente, desative-o."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DESATIVAR"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Preparando <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Procurando erros"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Novo <xliff:g id="NAME">%s</xliff:g> detectado"</string>
@@ -1325,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Compartilhar com <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Recurso deslizante. Toque e segure."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Deslize para desbloquear."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Conecte um fone de ouvido para ouvir as teclas da senha."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Ponto final."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Navegar na página inicial"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Navegar para cima"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Mais opções"</string>
@@ -1710,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Digite o horário"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Alterne para o modo de entrada de texto para informar o horário."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Alterne para o modo de relógio para informar o horário."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Salvar em <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Salvar <xliff:g id="TYPE">%1$s</xliff:g> em <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Salvar"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Não, obrigado"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"senha"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"endereço"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"cartão de crédito"</string>
 </resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index ec49411..1737b15 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Conteúdo oculto"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Conteúdo ocultado pela política"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Segurança"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Mudar para pessoal"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Permite que a aplicação remova atalhos do Ecrã principal sem a intervenção do utilizador."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"redirecionar as chamadas efetuadas"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Permite que a aplicação veja o número que é marcado durante uma chamada efetuada, com a opção de redirecionar a chamada para um número diferente ou terminar a chamada."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"receber mensagens de texto (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permite que a aplicação receba e processe mensagens SMS. Isto significa que a aplicação poderá monitorizar ou eliminar mensagens enviadas para o seu dispositivo sem as apresentar."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"receber mensagens de texto (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Permite que a aplicação termine processos em segundo plano de outras aplicações. Isto pode fazer com que outras aplicações deixem de funcionar."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Esta aplicação pode aparecer por cima de outras aplicações"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Esta aplicação pode aparecer por cima de outras aplicações ou de outras partes do ecrã. Tal pode interferir com a utilização normal das aplicações e alterar a forma como as outras aplicações aparecem."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"executar em segundo plano"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Esta aplicação pode ser executada em segundo plano, o que pode descarregar a bateria mais rapidamente."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"utilizar dados em segundo plano"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Esta aplicação pode utilizar dados em segundo plano, o que pode aumentar a utilização de dados."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"fazer com que a aplicação seja sempre executada"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Permite que a aplicação torne partes de si mesma persistentes na memória. Isto pode limitar a disponibilidade da memória para outras aplicações, tornando o tablet mais lento."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Permite à aplicação tornar partes de si própria persistentes na memória. Isto pode limitar a memória disponível para outras aplicações, o que torna a TV mais lenta."</string>
@@ -1171,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toque para selecionar o idioma e o esquema"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"Sobrepor a aplicação <xliff:g id="NAME">%s</xliff:g> a outras aplicações"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"Aplic. <xliff:g id="NAME">%s</xliff:g> apresentada por cima."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"É possível que partes desta aplicação permaneçam sempre visíveis. Se esta funcionalidade não estiver a funcionar corretamente, desative-a."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DESATIVAR"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"A preparar o <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"A verificar a presença de erros"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Novo <xliff:g id="NAME">%s</xliff:g> detetado"</string>
@@ -1325,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Compartilhar com <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Barra deslizante. Toque &amp; não solte."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Deslizar rapidamente para desbloquear."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Ligue os auscultadores com microfone integrado para ouvir as teclas da palavra-passe."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Ponto."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Navegar para página inicial"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Navegar para cima"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Mais opções"</string>
@@ -1710,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Introduza a hora"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Mude para o modo de introdução de texto para a introdução da hora."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Mude para o modo de relógio para a introdução da hora."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Pretende guardar no <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Pretende guardar o(a) <xliff:g id="TYPE">%1$s</xliff:g> no <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Guardar"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Não, obrigado"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"palavra-passe"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"endereço"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"cartão de crédito"</string>
 </resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 7cfd4c3..f05bab0 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Conteúdo oculto"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Conteúdo ocultado pela política"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Segurança"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Modo de segurança"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Alternar para \"Pessoal\""</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Permite que o app remova atalhos da tela inicial sem a intervenção do usuário."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"redirecionar as chamadas efetuadas"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Permite que o app veja o número discado ao realizar uma chamada, com a opção de redirecionar a chamada para outro número ou abortá-la."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"receber mensagens de texto (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permite que o app receba e processe mensagens SMS. Isso significa que o app pode monitorar ou excluir mensagens enviadas para o dispositivo sem mostrá-las para você."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"receber mensagens de texto (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Permite que o app encerre processos em segundo plano de outros apps. Pode ser que outros apps parem de funcionar."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Este app pode se sobrepor visualmente a outros apps"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Este app pode se sobrepor visualmente a outros apps ou a outras partes da tela. Isso pode interferir no uso normal do app e alterar a forma como os outros apps são exibidos."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"executar em segundo plano"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Este app pode ser executado em segundo plano, o que pode esgotar a bateria mais rapidamente."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"usar dados em segundo plano"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Este app pode usar dados em segundo plano, o que pode aumentar o uso de dados."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"sempre executar o app"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Permite que o app torne partes de si mesmo persistentes na memória. Pode limitar a memória disponível para outros apps, deixando o tablet mais lento."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Permite que o app torne partes de si mesmo persistentes na memória. Isso pode limitar a memória disponível para outros apps, deixando a TV mais lenta."</string>
@@ -1171,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toque para selecionar o idioma e o layout"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"Sobreposição do <xliff:g id="NAME">%s</xliff:g> a outros apps"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> exibido na parte superior da tela."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Partes desse app podem ficar sempre visíveis. Se esse recurso não estiver funcionando corretamente, desative-o."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DESATIVAR"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Preparando <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Procurando erros"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Novo <xliff:g id="NAME">%s</xliff:g> detectado"</string>
@@ -1325,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Compartilhar com <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Recurso deslizante. Toque e segure."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Deslize para desbloquear."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Conecte um fone de ouvido para ouvir as teclas da senha."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Ponto final."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Navegar na página inicial"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Navegar para cima"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Mais opções"</string>
@@ -1710,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Digite o horário"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Alterne para o modo de entrada de texto para informar o horário."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Alterne para o modo de relógio para informar o horário."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Salvar em <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Salvar <xliff:g id="TYPE">%1$s</xliff:g> em <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Salvar"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Não, obrigado"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"senha"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"endereço"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"cartão de crédito"</string>
 </resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 619e2da..11ca5fc 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -247,6 +247,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"˃999"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Conținutul este ascuns"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Conținutul este ascuns conform politicii"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Securitate"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Alerte"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Mod sigur"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistemul Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Comutați la Personal"</string>
@@ -295,6 +321,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Permite aplicației să elimine comenzi rapide de pe ecranul de pornire, fără intervenția utilizatorului."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"redirecționează apelurile efectuate"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Permite aplicației să vadă numărul format în timpul unui apel de ieșire, cu opțiunea de a redirecționa apelul către un alt număr sau de a întrerupe apelul."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"primește mesaje text (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permite aplicației să primească și să proceseze mesaje SMS. Acest lucru înseamnă că aplicația ar putea monitoriza sau șterge mesajele trimise pe dispozitivul dvs. fără a vi le arăta."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"primește mesaje text (MMS)"</string>
@@ -323,14 +353,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Permite aplicației să oprească procesele derulate în fundal de alte aplicații. Acest lucru poate face ca respectivele aplicații să nu mai ruleze."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Această aplicație poate apărea deasupra altor aplicații"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Această aplicație poate apărea deasupra altor aplicații sau a altor părți ale ecranului. Acest lucru poate să afecteze utilizarea normală a aplicației și să schimbe modul în care se afișează alte aplicații."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"să ruleze în fundal"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Această aplicație poate rula în fundal. Astfel, bateria se poate consuma mai repede."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"să utilizeze date în fundal"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Această aplicație poate utiliza date în fundal. Astfel, gradul de utilizare a datelor poate crește."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"rulare continuă a aplicației"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Permite aplicației să declare persistente în memorie anumite părți ale sale. Acest lucru poate limita memoria disponibilă pentru alte aplicații și poate încetini funcționarea tabletei."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Permite aplicației să declare persistente în memorie anumite părți ale sale. Acest lucru poate limita memoria disponibilă pentru alte aplicații și poate încetini funcționarea televizorului."</string>
@@ -1191,6 +1217,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Atingeți pentru a selecta limba și aspectul"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> afișează deasupra altor aplicații"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> se afișează deasupra."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Este posibil ca unele părți ale acestei aplicații să rămână vizibile permanent. Dacă această caracteristică nu funcționează corect, dezactivați-o."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DEZACTIVAȚI"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Se pregătește <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Se verifică dacă există erori"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"A fost detectat un nou <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1346,8 +1376,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Permiteți accesul pentru <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Mâner glisant. Atingeți și țineți apăsat."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Glisați pentru a debloca."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Conectați un set căști-microfon pentru a auzi tastele apăsate când introduceți parola."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punct."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Navigați la ecranul de pornire"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Navigați în sus"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Mai multe opțiuni"</string>
@@ -1741,4 +1769,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Introduceți ora"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Pentru a introduce ora, comutați la modul de introducere a textului."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Pentru a introduce ora, comutați la modul ceas."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Salvați în <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Salvați <xliff:g id="TYPE">%1$s</xliff:g> în <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Salvați"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Nu, mulțumesc"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"parolă"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"adresă"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"card de credit"</string>
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 1260d7d..a2e3795 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -250,6 +250,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Содержимое скрыто"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Содержимое скрыто в соответствии с заданными правилами"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Безопасность"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Уведомления"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Безопасный режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Система Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Перейти в личный профиль"</string>
@@ -298,6 +324,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Приложение сможет удалять ярлыки с главного экрана без вмешательства пользователя."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"Перенаправление исходящих вызовов"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Приложение сможет видеть набранный номер во время исходящего вызова и при необходимости перенаправлять вызов или завершать его."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"Прием SMS-сообщений"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Приложение сможет получать и обрабатывать SMS. Это значит, что оно сможет отслеживать и удалять отправленные на ваше устройство сообщения, не показывая их."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"Прием MMS-сообщений"</string>
@@ -326,14 +356,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Приложение сможет завершать фоновые процессы других приложений. Из-за этого другие приложения могут прекратить работу."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Показ поверх всех окон"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Приложение может открываться поверх других окон. Это может влиять на работу с другими приложениями."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"Работа в фоновом режиме"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Приложению разрешено работать в фоновом режиме. Заряд батареи может расходоваться быстрее."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"Передача данных в фоновом режиме"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Приложению разрешено передавать данные в фоновом режиме. Возможно увеличение расхода трафика."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"Поддержание приложения в рабочем режиме"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Приложение сможет постоянно хранить свои компоненты в памяти. Это может уменьшить объем памяти, доступный другим приложениям, и замедлить работу устройства."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Сохранение элементов приложения в памяти. Это может ограничить объем памяти, доступный другим приложениям, и замедлить работу телевизора."</string>
@@ -1000,11 +1026,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"Способ ввода"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Операции с текстом"</string>
     <string name="email" msgid="4560673117055050403">"Письмо"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"Телефон"</string>
     <string name="map" msgid="5441053548030107189">"Карта"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"Поиск"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Недостаточно памяти"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Некоторые функции могут не работать"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Недостаточно свободного места для системы. Освободите не менее 250 МБ дискового пространства и перезапустите устройство."</string>
@@ -1213,6 +1237,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Нажмите, чтобы выбрать язык и раскладку"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"Интерфейс этих приложений показывается поверх других окон: <xliff:g id="NAME">%s</xliff:g>"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g>: показ поверх других окон"</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Некоторые элементы интерфейса этого приложения могут всегда находиться поверх других окон. Если функция работает некорректно, отключите ее."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ОТКЛЮЧИТЬ"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Подготовка карты \"<xliff:g id="NAME">%s</xliff:g>\"…"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Поиск ошибок"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Обнаружена новая карта \"<xliff:g id="NAME">%s</xliff:g>\""</string>
@@ -1369,8 +1397,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Открыть доступ приложению \"<xliff:g id="APPLICATION_NAME">%s</xliff:g>\""</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Перетаскиваемый значок блокировки. Нажмите и удерживайте."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Проведите по экрану, чтобы разблокировать устройство."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Подключите гарнитуру, чтобы услышать пароль."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Точка"</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Перейти на главную"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Перейти вверх"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Ещё"</string>
@@ -1774,4 +1800,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Введите время"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Чтобы ввести время, перейдите в режим ввода текста."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Чтобы ввести время, перейдите в режим часов."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Сохранить в <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g>: сохранить в <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Сохранить"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Нет, спасибо"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"Пароль"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"Адрес"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"Банковская карта"</string>
 </resources>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 63b4e3b..40fbd2b 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"සැඟවුණු සම්බන්ධතා"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"ප්‍රතිපත්තිය විසින් අන්තර්ගතය සඟවන ලදී"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"ආරක්ෂාව"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"ඇඟවීම්"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"ආරක්‍ෂිත ආකාරය"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android පද්ධතිය"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"පුද්ගලික වෙත මාරු වන්න"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"පරිශීලක මැදිහත්වීමෙන් තොරව මුල්තිර කෙටිමං එක් කිරීමට යෙදුමකට අවසර දෙයි."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"පිටවන ඇමතුම් වල මග වෙනස් කිරීම"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"ඇමතුම වෙනත් අංකයකට හරවා යැවීම හෝ ඇමතුම මුළුමනින්ම නැවත්වීම වැනි විකල්ප සමඟ පිටතට යන ඇමතුමකදී අංකනය කළ අංකය බැලීමට යෙදුමට ඉඩ දෙයි."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"කෙටි පණිවිඩ ලබාගැනීම (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"SMS පණිවිඩ ලැබීමට සහ ක්‍රියාත්මක කිරීමට යෙදුමට අවසර දෙන්න. මෙහි තේරුම යෙදුමට ඔබගේ උපාංගයට ලැබෙන පණිවිඩ අධීක්ෂණය කිරීමට හැකිවීම වන අතර, ඒවා ඔබට නොපෙන්වා මකා දැමීමටද හැකි වීමයි."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"පෙළ පණිවුඩ ලබාගන්න (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"අනෙක් යෙදුම්වල පසුබිම් ක්‍රියාවලි අවසන් කිරීමට යෙදුමට අවසර දෙන්න. අනෙක් යෙදුම් ධාවනය නැවතීමට මෙය හේතුවක් වේ."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"මෙම යෙදුම වෙනත් යෙදුම්වලට ඉහළින් දිස් විය හැකිය"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"මෙම යෙදුම වෙනත් යෙදුම්වල හෝ තිරයේ වෙනත් කොටස්වලට ඉහළින් දිස් විය හැකිය. මෙය සාමාන්‍ය යෙදුම් භාවිතයට බාධා කළ හැකි අතර වෙනත් යෙදුම් දිස් වන ආකාරය වෙනස් කළ හැකිය."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"පසුබිමේ ධාවනය කරන්න"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"මෙම යෙදුම පසුබිමේ ධාවනය කිරීමට හැකිය. මෙය බැටරිය ‍වඩාත් වේගයෙන් වැය කළ හැකිය."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"පසුබිමේ දත්ත භාවිත කරන්න"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"මෙම යෙදුමට පසුබිමේ දත්ත භාවිත කිරීමට හැකිය. මෙය දත්ත භාවිතය වැඩි කළ හැකිය."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"යෙදුම සැමවිටම ධාවනය කරන්න"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"මතකයේ පවතින එහි කොටස් නොනැසී පැවතීමට යෙදුමට අවසර දෙන්න. වෙනත් යෙදුම් වලට මතකය සීමා කිරීමෙන් ටැබ්ලටය පමා කිරීම මගින්  මෙමගින් කළ හැක."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"යෙදුමේ කොටසක් මතකය තුළ එයට ස්ථාවර තබාගැනීමට යෙදුමට ඉඩ දෙන්න. මෙය වෙනත් යෙදුම් වලට තිබෙන මතකය සීමා කරයි සහ රූපවාහිනිය මන්දගාමී කරයි."</string>
@@ -962,11 +988,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"ආදාන ක්‍රමය"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"පෙළ ක්‍රියාවන්"</string>
     <string name="email" msgid="4560673117055050403">"ඊ-තැපෑල"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"දුරකථනය"</string>
     <string name="map" msgid="5441053548030107189">"සිතියම"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"සොයන්න"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"ආචයනය ඉඩ ප්‍රමාණය අඩු වී ඇත"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"සමහර පද්ධති කාර්යයන් ක්‍රියා නොකරනු ඇත"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"පද්ධතිය සඳහා ප්‍රමාණවත් ඉඩ නොමැත. ඔබට 250MB නිදහස් ඉඩක් තිබෙන ඔබට තිබෙන බව සහතික කරගෙන නැවත උත්සාහ කරන්න."</string>
@@ -1175,6 +1199,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"භාෂාව හා පිරිසැලසුම තේරීමට තට්ටු කරන්න"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"අනෙක් යෙදුම්වලට උඩින් <xliff:g id="NAME">%s</xliff:g> අදින්න"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> යෙදුම ඉහළින්ම සංදර්ශනය වේ."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"මෙම යෙදුමෙහි කොටස් සැම විටම දෘශ්‍යමානව පවතිනු ඇත. මෙම විශේෂාංගය නිවැරදිව ක්‍රියා නොකරන්නේ නම්, එය ක්‍රියාවිරහිත කරන්න."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ක්‍රියා විරහිත කරන්න"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> සූදානම් කරමින්"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"වැරදි සඳහා පරීක්ෂා කරමින්"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"නව <xliff:g id="NAME">%s</xliff:g> අනාවරණය කරන ලදි"</string>
@@ -1329,8 +1357,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> සමඟින් බෙදා ගන්න"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"සර්පණ හැඩලය. ස්පර්ශ කර රඳවා සිටීම."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"අගුළු ඇරීමට ස්වයිප් කරන්න."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"මුරපද යතුරු කියවනු ඇසීමට ඉස් බණුවක් සම්බන්ධ කරන්න."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"නැවතුම."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"මුල් පිටුවට සංචාලනය කරන්න"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"ඉහලට සංචාලනය කරන්න"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"තවත් විකල්ප"</string>
@@ -1714,4 +1740,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"වේලාව ටයිප් කරන්න"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"වේලා ආදානය සඳහා ආදාන ප්‍රකාරය වෙත මාරු වෙන්න."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"වේලා ආදානය සඳහා ඔරලෝසු ප්‍රකාරය වෙත මාරු වෙන්න."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> වෙත සුරකින්නද?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> <xliff:g id="LABEL">%2$s</xliff:g> වෙත සුරකින්නද?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"සුරකින්න"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"එපා ස්තූතියි"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"මුරපදය"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"ලිපිනය"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"ණය කාඩ්පත"</string>
 </resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 3302127..6c84da1 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -250,6 +250,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Skrytý obsah"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Obsah je na základe pravidiel skrytý"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Zabezpečenie"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Upozornenia"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Núdzový režim"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Systém Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Prepnúť na osobný"</string>
@@ -298,6 +324,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Povoľuje aplikácii odstrániť odkazy na ploche bez zásahu používateľa."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"presmerovať odchádzajúce hovory"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Umožňuje aplikácii počas odchádzajúceho hovoru rozpoznať vytáčané číslo a poskytuje možnosť presmerovať daný hovor na odlišné číslo alebo ho úplne zrušiť."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"prijímať textové správy (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Umožňuje aplikácii prijímať a spracovávať správy SMS. Znamená to, že aplikácia môže sledovať správy odoslané na vaše zariadenie alebo ich odstrániť bez toho, aby sa vám zobrazili."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"prijímať textové správy (MMS)"</string>
@@ -326,14 +356,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Umožňuje aplikácii ukončiť procesy na pozadí ostatných aplikácií. Môže to zapríčiniť zastavenie ostatných aplikácií."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Táto aplikácia sa môže zobraziť nad ostatnými aplikáciami"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Táto aplikácia sa môže zobraziť nad ostatnými aplikáciami alebo ďalšími časťami obrazovky. Môže tak narušovať normálne používanie aplikácií a zmeniť spôsob zobrazenia ďalších aplikácií."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"spustenie na pozadí"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Táto aplikácia sa môže spustiť na pozadí a rýchlejšie tak vybiť batériu."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"využívanie dát na pozadí"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Táto aplikácia môže využívať dáta na pozadí a zvýšiť tak spotrebu dát."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"nastaviť, aby bola aplikácia neustále spustená"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Umožňuje aplikácii uložiť niektoré svoje časti natrvalo do pamäte. Môže to obmedziť pamäť dostupnú pre ostatné aplikácie a spomaliť tak tablet."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Umožňuje aplikácii natrvalo uložiť svoje časti v pamäti. Môže to obmedziť pamäť dostupnú pre ďalšie aplikácie, čím sa spomaľuje televízor."</string>
@@ -1000,11 +1026,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"Metóda vstupu"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Operácie s textom"</string>
     <string name="email" msgid="4560673117055050403">"E-mail"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"Telefón"</string>
     <string name="map" msgid="5441053548030107189">"Mapa"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"Prehliadať"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Nedostatok ukladacieho priestoru"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Niektoré systémové funkcie nemusia fungovať"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"V úložisku nie je dostatok voľného miesta pre systém. Zaistite, aby ste mali 250 MB voľného miesta a zariadenie reštartujte."</string>
@@ -1213,6 +1237,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Klepnutím vyberte jazyk a rozloženie"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AÁÄBCČDĎDZDŽEÉFGHCHIÍJKLĽMNŇOÓÔPRŔSŠTŤUÚVWXYÝZŽ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"Aplikácia <xliff:g id="NAME">%s</xliff:g> sa vykreslí nad ostatnými aplikáciami"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"Apl. <xliff:g id="NAME">%s</xliff:g> sa zobrazuje navrchu."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Časti tejto aplikácie môžu zostať neustále viditeľné. Ak táto funkcia nepracuje správne, vypnite ju."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"VYPNÚŤ"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Pripravuje sa úložisko <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Prebieha kontrola chýb"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Bolo zistené nové úložisko <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1369,8 +1397,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Zdieľať s aplikáciou <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Posuvné tlačidlo. Dotknite sa a podržte."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Posunom odomknúť."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Ak si chcete vypočuť vyslovené klávesy hesla, pripojte náhlavnú súpravu."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Bodka."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Prejsť na plochu"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Prejsť na"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Viac možností"</string>
@@ -1774,4 +1800,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Zadajte čas"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Ak chcete zadať čas, prepnite na textový režim vstupu"</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Ak chcete zadať čas, prepnite na režim hodín."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Uložiť do zariadenia <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Uložiť <xliff:g id="TYPE">%1$s</xliff:g> do zariadenia <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Uložiť"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Nie, vďaka"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"heslo"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"adresa"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kreditná karta"</string>
 </resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 82fa2d8..97911f0 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -250,6 +250,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999 +"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Vsebina je skrita"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Pravilnik je skril vsebino"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Varnost"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Opozorila"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Varni način"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Preklop na osebni profil"</string>
@@ -298,6 +324,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Aplikaciji omogoča odstranjevanje bližnjic z začetnega zaslona brez posredovanja uporabnika."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"preusmeritev odhodnih klicev"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Aplikaciji dovoli ogled klicane številke pri odhodnem klicu in ji omogoča preusmeritev klica na drugo številko ali prekinitev klica."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"prejemanje sporočil (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Aplikaciji omogoča prejemanje in obdelavo SMS-ov. S tem lahko aplikacija nadzoruje ali izbriše sporočila, poslana v napravo, ne da bi vam jih pokazala."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"prejemanje sporočil (MMS)"</string>
@@ -326,14 +356,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Aplikaciji omogoča, da konča procese v ozadju drugih aplikacij. S tem lahko druge aplikacije nehajo delovati."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Prikaz aplikacije s prekrivanjem drugih aplikacij"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Ta aplikacija lahko prekrije druge aplikacije ali druge dele zaslona. To lahko vpliva na normalno delovanje aplikacije in na način prikaza drugih aplikacij."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"izvajanje v ozadju"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Ta aplikacija se lahko izvaja tudi v ozadju, kar lahko privede do hitrejšega praznjenja akumulatorja."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"prenos podatkov v ozadju"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Ta aplikacija lahko prenaša podatke tudi v ozadju, kar lahko privede do večje porabe prenosa podatkov."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"neprekinjeno izvajanje aplikacij"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Aplikaciji omogoča, da nekatere svoje dele naredi trajne v pomnilniku. S tem je lahko pomnilnik omejen za druge aplikacije, zaradi česar je delovanje tabličnega računalnika upočasnjeno."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Aplikaciji dovoljuje, da nekatere svoje dele naredi trajno prisotne v pomnilniku. S tem je lahko pomnilnik omejen za druge aplikacije, zaradi česar je delovanje televizorja upočasnjeno."</string>
@@ -1000,11 +1026,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"Način vnosa"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Besedilna dejanja"</string>
     <string name="email" msgid="4560673117055050403">"E-pošta"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"Telefon"</string>
     <string name="map" msgid="5441053548030107189">"Zemljevid"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"Brskanje"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Prostor za shranjevanje bo pošel"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Nekatere sistemske funkcije morda ne delujejo"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"V shrambi ni dovolj prostora za sistem. Sprostite 250 MB prostora in znova zaženite napravo."</string>
@@ -1213,6 +1237,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dotaknite se, če želite izbrati jezik in postavitev."</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"Aplikacija <xliff:g id="NAME">%s</xliff:g> riše čez druge aplikacije"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"Apl. <xliff:g id="NAME">%s</xliff:g> se prikazuje čez druge."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Deli te aplikacije lahko ostanejo vseskozi vidni. Če ta funkcija ne deluje pravilno, jo izklopite."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"IZKLOP"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Pripravljanje shrambe <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Iskanje napak"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Zaznana je bila nova shramba <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1369,8 +1397,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Delite z aplikacijo <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Drsna ročica. Dotaknite se in pridržite."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Povlecite, če želite odkleniti."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Priključite slušalke, če želite slišati izgovorjene tipke gesla."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Pika."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Krmarjenje domov"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Krmarjenje navzgor"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Več možnosti"</string>
@@ -1774,4 +1800,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Vnesite uro"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Preklopite na način za vnašanje besedila, da vnesete čas."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Preklopite na način ure, da vnesete čas."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Shrani v <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Shrani <xliff:g id="TYPE">%1$s</xliff:g> v <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Shrani"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Ne, hvala"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"geslo"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"naslov"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kreditno kartico"</string>
 </resources>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 39a393f..bdea7bf 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Përmbajtjet janë të fshehura"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Përmbajtja është e fshehur për shkak të politikës"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Siguria"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Sinjalizimet"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Modaliteti i sigurisë"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistemi \"android\""</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Ndryshoje te \"Personale\""</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Lejon aplikacionin të heqë shkurtore në ekranin bazë, pa ndërhyrjen e përdoruesit."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"ridrejto telefonatat dalëse"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Lejon aplikacionin të shohë numrin që telefonohet gjatë një telefonate dalëse me opsionin për ta ri-orientuar telefonatën drejt një numri tjetër ose për ta ndërprerë plotësisht telefonatën."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"merr mesazhe me tekst (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Lejon aplikacionin të marrë dhe përpunojë mesazhe SMS. Kjo do të thotë se aplikacioni mund të monitorojë ose fshijë mesazhe të dërguara në pajisjen tënde, pa t\'i treguar ato."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"prano mesazhe në tekst (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Lejon aplikacionin t\'u japë fund proceseve në sfond të aplikacioneve të tjera. Kjo mund të shkaktojë mosfunksionimin e aplikacioneve të tjera."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Ky aplikacion mund të shfaqet mbi aplikacionet e tjera"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Ky aplikacion mund të shfaqet mbi aplikacionet e tjera ose në pjesë të tjera të ekranit. Kjo mund të shkaktojë ndërhyrje në përdorimin normal të aplikacionit dhe në mënyrën se si shfaqen aplikacionet e tjera."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"ekzekuto në sfond"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Ky aplikacion mund të ekzekutohet në sfond. Kjo mund ta shkarkojë më shpejt baterinë."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"përdor të dhënat në sfond"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Ky aplikacion mund të përdorë të dhënat në sfond. Kjo mund të rritë përdorimin e të dhënave."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"bëje aplikacionin të qëndrojë gjithmonë në punë"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Lejon aplikacionin të zaptojë një pjesë të qëndrueshme në kujtesë. Kjo mund të kufizojë kujtesën e disponueshme për aplikacionet e tjera duke e ngadalësuar tabletin."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Lejon aplikacionin të zaptojë një pjesë të qëndrueshme në kujtesë. Kjo mund të kufizojë kujtesën e disponueshme për aplikacionet e tjera duke e ngadalësuar televizorin."</string>
@@ -1172,6 +1198,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Trokit për të zgjedhur gjuhën dhe strukturën"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> mbivendoset mbi aplikacionet e tjera"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"Aplikacioni <xliff:g id="NAME">%s</xliff:g> shfaqet në krye."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Disa pjesë të këtij aplikacioni mund të mbeten të dukshme gjatë të gjithë kohës. Nëse ky funksion nuk po funksionon si duhet, çaktivizoje atë."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ÇAKTIVIZO"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Po përgatit <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Po kontrollon për gabime"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"U zbulua karta e re <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1326,8 +1356,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Shpërnda me <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Dorezë me rrëshqitje. Preke dhe mbaje të shtypur."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Rrëshqit për të shkyçur."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Vendos kufjet për të dëgjuar fjalëkalimin"</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Pikë."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Orientohu për në shtëpi"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Ngjitu lart"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Opsione të tjera"</string>
@@ -1711,4 +1739,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Shkruaj kohën"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Kalo te modaliteti i hyrjes së tekstit për hyrjen e kohës."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Kalo te modaliteti i orës për hyrjen e kohës."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Të ruhet te <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Të ruhet <xliff:g id="TYPE">%1$s</xliff:g> te <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Ruaj"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Jo, faleminderit"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"fjalëkalimi"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"adresa"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"karta e kreditit"</string>
 </resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index b287baf..4623b48 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -247,6 +247,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Садржај је сакривен"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Садржај је сакривен смерницама"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Безбедност"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Обавештења"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Безбедни режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android систем"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Пређи на Лични профил"</string>
@@ -295,6 +321,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Омогућава апликацији да уклања пречице са почетног екрана без интервенције корисника."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"преусмеравање одлазних позива"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Дозвољава апликацији да види који број се бира при одлазном позиву уз опцију да преусмери позив на други број или га потпуно прекине."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"пријем текстуалних порука (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Дозвољава апликацији да прима и обрађује SMS поруке. То значи да апликација може да надгледа или брише поруке које се шаљу уређају, а да вам их не прикаже."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"пријем текстуалних порука (MMS)"</string>
@@ -323,14 +353,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Дозвољава апликацији да заустави позадинске процесе других апликација. Ово може да заустави друге апликације."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Ова апликација може да се приказује преко других апликација"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Ова апликација може да се приказује преко других апликација или других делова делова екрана. То може да омета стандардно коришћење апликација и начин на који се друге апликације приказују."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"покретање у позадини"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Ова апликација може да се покреће у позадини. То може брже да истроши батерију."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"коришћење података у позадини"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Ова апликација може да користи податке у позадини. То може да повећа потрошњу података."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"омогућавање непрекидне активности апликације"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Дозвољава апликацији да учини сопствене компоненте трајним у меморији. Ово може да ограничи меморију доступну другим апликацијама и успори таблет."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Дозвољава апликацији да неке своје делове трајно задржи у меморији. То може да ограничи меморију доступну другим апликацијама и успори ТВ."</string>
@@ -1191,6 +1217,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Додирните да бисте изабрали језик и распоред"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"Апликација <xliff:g id="NAME">%s</xliff:g> се приказује преко других апликација"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"Апликација <xliff:g id="NAME">%s</xliff:g> се приказује преко."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Делови ове апликације могу да остану видљиви у сваком тренутку. Ако ова функција не ради исправно, искључите је."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ИСКЉУЧИ"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> се припрема"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Проверава се да ли постоје грешке"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Нови уређај <xliff:g id="NAME">%s</xliff:g> је откривен"</string>
@@ -1346,8 +1376,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Дели са апликацијом <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Клизна ручица. Додирните и задржите."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Превуците да бисте откључали."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Прикључите слушалице да бисте чули изговорене тастере за лозинку."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Тачка."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Кретање до Почетне"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Кретање нагоре"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Још опција"</string>
@@ -1741,4 +1769,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Унесите време"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Пређите у режим уноса текста ради уноса времена."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Пређите у режим сата ради уноса времена."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Желите ли да сачувате у: <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Желите ли да сачувате ставку <xliff:g id="TYPE">%1$s</xliff:g> у: <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Сачувај"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Не, хвала"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"лозинка"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"адреса"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"кредитна картица"</string>
 </resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index f9cfe03..fa381fd 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Innehåll har dolts"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Innehåll har dolts p.g.a. en policy"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Säkerhet"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Varningar"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Säkert läge"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Byt till din personliga profil"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Tillåter att appen tar bort genvägar på startskärmen utan åtgärd från användaren."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"omdirigera utgående samtal"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Tillåter att appen ser numret du slår under ett utgående samtal och har möjlighet att koppla samtalet till ett annat nummer eller avbryta samtalet helt."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"ta emot textmeddelanden (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Tillåter att appen tar emot och hanterar SMS. Detta innebär att appen kan övervaka eller ta bort meddelanden som skickats till enheten utan att visa dem för dig."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ta emot textmeddelanden (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Tillåter att appen avslutar andra appars bakgrundsprocesser. Detta kan göra så att andra appar avslutas."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Appen kan visas ovanpå andra appar"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Appen kan visas ovanpå andra appar eller andra delar av skärmen. Detta kan störa den vanliga användningen av appar och påverka hur andra appar visas."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"kör i bakgrunden"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Appen kan köras i bakgrunden. Det kan minska batteritiden."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"använd data i bakgrunden"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Data kan användas i bakgrunden av appen. Det kan öka dataanvändningen."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"se till att appen alltid körs"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Tillåter att delar av appen läggs beständigt i minnet. Detta kan innebära att det tillgängliga minnet för andra appar begränsas, vilket gör surfplattan långsam."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Tillåter att en app gör vissa delar beständiga i minnet. Det kan begränsa mängden minne som är tillgänglig för andra appar och gör TV:n långsammare."</string>
@@ -1171,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tryck om du vill välja språk och layout"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> gör överlagringar på andra appar"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"Appen <xliff:g id="NAME">%s</xliff:g> visas ovanpå."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Delar av den här appen kanske alltid är synliga. Inaktivera funktionen om den inte fungerar som den ska."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"INAKTIVERA"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Förbereder ditt <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Söker efter fel"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Nytt <xliff:g id="NAME">%s</xliff:g> har hittats"</string>
@@ -1325,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Dela med <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Skärmlåsfunktion. Tryck och dra."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Lås upp genom att svepa."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Anslut ett headset för att få lösenordet uppläst."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punkt."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Visa startsidan"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Navigera uppåt"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Fler alternativ"</string>
@@ -1710,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Ange tid"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Byt till textinmatningsläget och ange tid."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Byt till klockläget och ange tid."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Vill du spara detta i <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Vill du spara <xliff:g id="TYPE">%1$s</xliff:g> i <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Spara"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Nej tack"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"lösenordet"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"adressen"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kreditkortet"</string>
 </resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 396ecbe..0e44f01 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -242,6 +242,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Maudhui yamefichwa"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Maudhui yamefichwa kulingana na sera"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Usalama"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Arifa"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Mtindo salama"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Mfumo wa Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Badili uweke wasifu wa Binafsi"</string>
@@ -290,6 +316,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Huruhusu programu kuondoa njia za mkato za Skrini ya kwanza bila mtumiaji kuingilia."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"panga upya simu zinazotoka"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Huruhusu programu kuona nambari inayopigwa wakati simu inapigwa ikiwa na chaguo la kuelekeza simu kwenye nambari tofauti au kukata simu kabisa."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"pokea ujumbe wa maandishi wa SMS"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Inaruhusu programu kupokea na kuchakata ujumbe wa SMS. Hii inamaanisha programu hii inaweza kuchunguza na kufuta ujumbe uliotumwa katika kifaa chako bila ya kukuonyesha."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"pokea ujumbe wa maandishi wa MMS"</string>
@@ -318,14 +348,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Inaruhusu programu kukamilisha michakato ya usuli ya programu nyingine. Hii inaweza kusababisha programu nyingine kukoma kufanyakazi."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Pogramu hii inaweza kuonekana juu ya programu zingine"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Programu hii inaweza kuonekana juu ya programu zingine au sehemu zingine za skrini. Hii huenda ikaathiri matumizi ya kawaida ya programu na kubadilisha jinsi ambavyo programu zingine zinavyoonekana."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"tumia chini chini"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Programu hii inaweza kutumika chini chini. Hali hii inaweza kumaliza chaji ya betri haraka."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"tumia data chini chini"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Programu hii inaweza kutumia data chini chini. Hali hii inaweza kuongeza matumizi ya data."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"Fanya programu kuendeshwa kila mara"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Inaruhusu programu kuendeleza vijisehemu vyake kwenye kumbukumbu. Hii inaweza kupunguza kumbukumbu inayopatikana katika programu nyingine ikipunguza kasi ya kompyuta ndogo."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Huruhusu programu kufanya vijisehemu vyake vidumu kwenye kumbukumbu. Hii inaweza kupunguza kumbukumbu inayopatikana katika programu nyingine ikipunguza kasi ya runinga."</string>
@@ -676,14 +702,14 @@
     <string name="sipAddressTypeWork" msgid="6920725730797099047">"Kazi"</string>
     <string name="sipAddressTypeOther" msgid="4408436162950119849">"Nyinginezo"</string>
     <string name="quick_contacts_not_available" msgid="746098007828579688">"Hakuna programu iliyopatikana ili kuona anwani hii."</string>
-    <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Ingiza msimbo wa PIN"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Ingiza PUK na msimbo mpya wa PIN"</string>
+    <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Weka nambari ya PIN"</string>
+    <string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Weka PUK na nambari mpya ya PIN"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Msimbo wa PUK"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="8027680321614196258">"Msimbo mpya wa PIN"</string>
+    <string name="keyguard_password_enter_pin_prompt" msgid="8027680321614196258">"Nambari mpya ya PIN"</string>
     <string name="keyguard_password_entry_touch_hint" msgid="2644215452200037944"><font size="17">"Gusa ili uandike nenosiri"</font></string>
     <string name="keyguard_password_enter_password_code" msgid="1054721668279049780">"Charaza nenosiri ili kufungua"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"Ingiza PIN ili kufungua"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"Msimbo wa PIN usio sahihi."</string>
+    <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"Nambari ya PIN uliyoweka si sahihi."</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Ili kufungua, bofya Menyu kisha 0."</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Nambari ya dharura"</string>
     <string name="lockscreen_carrier_default" msgid="6169005837238288522">"Hakuna huduma"</string>
@@ -931,7 +957,7 @@
       <item quantity="one">baada ya mwaka <xliff:g id="COUNT_0">%d</xliff:g></item>
     </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Shida ya video"</string>
-    <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Video hii si halali kutiririshwa kwa kifaa hiki."</string>
+    <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Video hii hairuhusiwi kutiririshwa kwenye kifaa hiki."</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Haiwezi kucheza video hii."</string>
     <string name="VideoView_error_button" msgid="2822238215100679592">"Sawa"</string>
     <string name="relative_time" msgid="1818557177829411417">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -958,11 +984,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"Mbinu ya uingizaji"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Vitendo vya maandishi"</string>
     <string name="email" msgid="4560673117055050403">"Barua pepe"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"Simu"</string>
     <string name="map" msgid="5441053548030107189">"Ramani"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"Vinjari"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Nafasi ya kuhafadhi inakwisha"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Baadhi ya vipengee vya mfumo huenda visifanye kazi"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Hifadhi haitoshi kwa ajili ya mfumo. Hakikisha una MB 250 za nafasi ya hifadhi isiyotumika na uanzishe upya."</string>
@@ -1171,6 +1195,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Gonga ili uchague lugha na muundo"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> huchomoza kwenye programu zingine"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"Programu ya <xliff:g id="NAME">%s</xliff:g> inaonekana juu ya zingine."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Huenda sehemu za programu hii zikaendelea kuonekana kila wakati. Zima kipengele hiki kama hakifanyi kazi vizuri."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ZIMA"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Inaandaa <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Inakagua hitilafu"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"<xliff:g id="NAME">%s</xliff:g> mpya imegunduliwa"</string>
@@ -1325,8 +1353,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Shiriki na <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Utambo unaosonga. Gusa &amp; shika"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Pitisha ili kufungua."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Chomeka kifaa cha sauti ili kusikiliza vibonye vya nenosiri vikizungumzwa."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Nukta."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Abiri nyumbani"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Ongoza"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Chaguo zaidi"</string>
@@ -1411,10 +1437,10 @@
     <string name="kg_pin_instructions" msgid="2377242233495111557">"Ingiza PIN"</string>
     <string name="kg_password_instructions" msgid="5753646556186936819">"Weka Nenosiri"</string>
     <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM sasa imelemazwa. Ingiza msimbo wa PUK ili kuendelea. Wasiliana na mtoa huduma kwa maelezo."</string>
-    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Ingiza msimbo wa PIN unaopendelewa"</string>
-    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Thibitisha msimbo wa PIN unaopendelewa"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Weka nambari yako ya PIN"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Thibitisha nambari ya PIN uliyoweka"</string>
     <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Inafungua SIM kadi..."</string>
-    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Msimbo wa PIN usio sahihi."</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Nambari ya PIN uliyoweka si sahihi."</string>
     <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Charaza PIN iliyo na tarakimu kati ya 4 na 8."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="6025069204539532000">"Msimbo wa PUK lazima uwe na tarakimu 8."</string>
     <string name="kg_invalid_puk" msgid="3638289409676051243">"Ingiza upya msimbo sahihi wa PUK. Majaribio yanayorudiwa yatalemaza SIM kabisa."</string>
@@ -1710,4 +1736,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Andika wakati"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Badilisha iwe katika hali ya maandishi wakati wa kuweka muda."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Badilisha umbo liwe la saa ya mishale wakati wa kuweka muda."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Ungependa kuhifadhi kwenye <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Ungependa kuhifadhi <xliff:g id="TYPE">%1$s</xliff:g> kwenye <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Hifadhi"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Hapana, asante"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"nenosiri"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"anwani"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kadi ya mikopo"</string>
 </resources>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 0eb28710..96eea4a 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"மறைந்துள்ள உள்ளடக்கம்"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"கொள்கையின்படி உள்ளடக்கம் மறைக்கப்பட்டது"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"பாதுகாப்பு"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"விழிப்பூட்டல்கள்"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"பாதுகாப்பு பயன்முறை"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android அமைப்பு"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"தனிப்பட்ட சுயவிவரத்திற்கு மாறு"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"பயனரின் அனுமதி இல்லாமல் முகப்புத்திரையின் குறுக்குவழிகளை அகற்ற பயன்பாட்டை அனுமதிக்கிறது."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"வெளிச்செல்லும் அழைப்புகளுக்கு மீண்டும் வழிகாட்டுதல்"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"மற்றொரு எண்ணிற்கு அழைப்பைத் திருப்பிவிடு அல்லது அழைப்பை முழுமையாக ரத்துசெய் என்னும் விருப்பத்துடன், வெளிச்செல்லும் அழைப்பை மேற்கொள்ளும்போது டயல் செய்யப்படுகின்ற எண்ணைப் பார்க்க, பயன்பாட்டை அனுமதிக்கிறது."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"உரைச் செய்திகளை (SMS) பெறுதல்"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"SMS செய்திகளைப் பெற, செயற்படுத்தப் பயன்பாட்டை அனுமதிக்கிறது. இதற்கு அர்த்தம் உங்கள் சாதனத்திற்கு அனுப்பப்படும் செய்திகளை உங்களுக்குக் காட்டாமல் கண்காணிப்பதற்கு அல்லது நீக்குவதற்குப் பயன்பாட்டால் முடியும் என்பதாகும்."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"உரைச் செய்திகளை (MMS) பெறுதல்"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"பிற பயன்பாடுகளின் பின்புலச் செயல்முறைகளை நிறுத்த பயன்பாட்டை அனுமதிக்கிறது. இதனால் பிற பயன்பாடுகள் இயங்குவதை நிறுத்தலாம்."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"இந்தப் பயன்பாடு பிற பயன்பாடுகளின் மேலே தோன்றலாம்"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"இந்தப் பயன்பாடு பிற பயன்பாடுகளின் மேலே அல்லது திரையின் பிற பகுதிகளில் தோன்றலாம். இது வழக்கமான பயன்பாட்டு உபயோகத்தில் குறுக்கிட்டு, பிற பயன்பாடுகள் தோன்றும் விதத்தை மாற்றக்கூடும்."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"பின்னணியில் இயக்கு"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"இந்தப் பயன்பாடு, பின்னணியில் இயங்கலாம். இதனால் பேட்டரி விரைவாகத் தீர்ந்துவிடக்கூடும்."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"பின்னணியில் தரவைப் பயன்படுத்து"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"இந்தப் பயன்பாடு, பின்னணியில் தரவைப் பயன்படுத்தலாம். இதனால் தரவுப் பயன்பாடு அதிகரிக்கக்கூடும்."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"பயன்பாட்டை எப்போதும் இயங்குமாறு செய்தல்"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"நினைவகத்தில் நிலையாக இருக்கும் தன்னுடைய பகுதிகளை உருவாக்கப் பயன்பாட்டை அனுமதிக்கிறது. இதனால பிற பயன்பாடுகளுக்குக் கிடைக்கும் நினைவகம் வரையறுக்கப்பட்டு, டேப்லெட்டின் வேகத்தைக் குறைக்கலாம்."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"பயன்பாடு தனது உள்ளடக்கத்தை நினைவகத்தில் தொடர்ந்து வைத்திருக்க, அனுமதிக்கிறது. பிற பயன்பாடுகளுக்கென இருக்கும் நினைவகத்தை இது கட்டுப்படுத்தி, டிவியின் செயல்திறனைக் குறைக்கலாம்."</string>
@@ -1172,6 +1198,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"மொழியையும் தளவமைப்பையும் தேர்ந்தெடுக்க, தட்டவும்"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"பிற பயன்பாடுகளின் மேல் <xliff:g id="NAME">%s</xliff:g> செயல்படும்"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"பிற பயன்பாடுகளின் மேலே <xliff:g id="NAME">%s</xliff:g> பயன்பாடு காட்டப்படுகிறது."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"இந்தப் பயன்பாட்டின் பகுதிகள், எல்லா நேரமும் காட்டப்படக்கூடும். இந்த அம்சம் சரியாகச் செயல்படவில்லை எனில், அதை முடக்கவும்."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"முடக்கு"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> தயாராகிறது"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"பிழைகள் உள்ளதா எனப் பார்க்கிறது"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"புதிய <xliff:g id="NAME">%s</xliff:g> கண்டறியப்பட்டது"</string>
@@ -1326,8 +1356,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> உடன் பகிர்"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"ஸ்லைடிங் ஹேன்டில். தொட்டுப் பிடிக்கவும்."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"திறக்க ஸ்வைப் செய்யவும்."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"கூறப்படும் கடவுச்சொல் விசைகளைக் கேட்பதற்கு ஹெட்செட்டைச் செருகவும்."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"புள்ளி."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"முகப்பிற்கு வழிசெலுத்து"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"மேலே வழிசெலுத்து"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"மேலும் விருப்பங்கள்"</string>
@@ -1711,4 +1739,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"நேரத்தை உள்ளிடவும்"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"உரை உள்ளீட்டிற்காக, கடிகாரப் பயன்முறைக்கு மாற்றும்."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"நேர உள்ளீட்டிற்காக, கடிகாரப் பயன்முறைக்கு மாற்றும்."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> இல் சேமிக்கவா?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g>ஐ <xliff:g id="LABEL">%2$s</xliff:g> இல் சேமிக்கவா?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"சேமி"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"வேண்டாம்"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"கடவுச்சொல்"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"முகவரி"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"கிரெடிட் கார்டு"</string>
 </resources>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 048fa8b..e3adbc5 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"కంటెంట్‌లు దాచబడ్డాయి"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"విధానం ద్వారా కంటెంట్‌లు దాచబడ్డాయి"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"భద్రత"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"హెచ్చరికలు"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"సురక్షిత మోడ్"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android సిస్టమ్"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"వ్యక్తిగతానికి మార్చు"</string>
@@ -255,7 +281,7 @@
     <string name="permgrouplab_calendar" msgid="5863508437783683902">"క్యాలెండర్"</string>
     <string name="permgroupdesc_calendar" msgid="3889615280211184106">"మీ క్యాలెండర్‌ను ప్రాప్యత చేయడానికి"</string>
     <string name="permgrouplab_sms" msgid="228308803364967808">"SMS"</string>
-    <string name="permgroupdesc_sms" msgid="4656988620100940350">"SMS సందేశాలను పంపడానికి మరియు వీక్షించడానికి"</string>
+    <string name="permgroupdesc_sms" msgid="4656988620100940350">"SMS సందేశాలను పంపడం మరియు వీక్షించడం"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"నిల్వ"</string>
     <string name="permgroupdesc_storage" msgid="637758554581589203">"మీ పరికరంలోని ఫోటోలు, మీడియా మరియు ఫైల్‌లను ప్రాప్యత చేయడానికి"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"మైక్రోఫోన్"</string>
@@ -263,7 +289,7 @@
     <string name="permgrouplab_camera" msgid="4820372495894586615">"కెమెరా"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"చిత్రాలను తీయడానికి మరియు వీడియోను రికార్డ్ చేయడానికి"</string>
     <string name="permgrouplab_phone" msgid="5229115638567440675">"ఫోన్"</string>
-    <string name="permgroupdesc_phone" msgid="6234224354060641055">"ఫోన్ కాల్‌లను చేయడానికి మరియు నిర్వహించడానికి"</string>
+    <string name="permgroupdesc_phone" msgid="6234224354060641055">"ఫోన్ కాల్‌లు చేయడం మరియు నిర్వహించడం"</string>
     <string name="permgrouplab_sensors" msgid="416037179223226722">"శరీర సెన్సార్‌లు"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"మీ అత్యంత కీలకమైన గుర్తుల గురించి సెన్సార్ డేటాని ప్రాప్యత చేస్తుంది"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"విండో కంటెంట్‍ను తిరిగి పొందుతుంది"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"వినియోగదారు ప్రమేయం లేకుండానే హోమ్‌స్క్రీన్ సత్వరమార్గాలను తీసివేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"అవుట్‌గోయింగ్ కాల్‌లను దారి మళ్లించడం"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"కాల్‌ను వేరే నంబర్‌కు దారి మళ్లించే లేదా మొత్తంగా కాల్‌ను ఆపివేసే ఎంపిక సహాయంతో అవుట్‌గోయింగ్ కాల్ సమయంలో డయల్ చేయబడుతున్న నంబర్‌ను చూడటానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"వచన సందేశాలను (SMS) స్వీకరించడం"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"SMS సందేశాలను స్వీకరించడానికి మరియు ప్రాసెస్ చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది. అనువర్తనం మీ పరికరానికి పంపబడిన సందేశాలను మీకు చూపకుండానే పర్యవేక్షించగలదని లేదా తొలగించగలదని దీని అర్థం."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"వచన సందేశాలను (MMS) స్వీకరించడం"</string>
@@ -300,7 +330,7 @@
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"మీ పరికరం స్వీకరించిన సెల్ ప్రసార సందేశాలను చదవడానికి అనువర్తనాన్ని అనుమతిస్తుంది. సెల్ ప్రసార హెచ్చరికలు అత్యవసర పరిస్థితుల గురించి మిమ్మల్ని హెచ్చరించడానికి కొన్ని స్థానాల్లో అందించబడతాయి. అత్యవసర సెల్ ప్రసారం స్వీకరించినప్పుడు హానికరమైన అనువర్తనాలు మీ పరికరం యొక్క పనితీరు లేదా నిర్వహణకు అంతరాయం కలిగించవచ్చు."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"చందా చేయబడిన ఫీడ్‌లను చదవడం"</string>
     <string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"ప్రస్తుతం సమకాలీకరించిన ఫీడ్‌ల గురించి వివరాలను పొందడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
-    <string name="permlab_sendSms" msgid="7544599214260982981">"SMS సందేశాలను పంపడానికి మరియు వీక్షించడానికి"</string>
+    <string name="permlab_sendSms" msgid="7544599214260982981">"SMS సందేశాలను పంపడం మరియు వీక్షించడం"</string>
     <string name="permdesc_sendSms" msgid="7094729298204937667">"SMS సందేశాలు పంపడానికి అనువర్తనాన్ని అనుమతిస్తుంది. దీని వలన ఊహించని ఛార్జీలు విధించబడవచ్చు. హానికరమైన అనువర్తనాలు మీ నిర్ధారణ లేకుండానే సందేశాలను పంపడం ద్వారా మీకు డబ్బు ఖర్చయ్యేలా చేయవచ్చు."</string>
     <string name="permlab_readSms" msgid="8745086572213270480">"మీ వచన సందేశాలు (SMS లేదా MMS) చదవడం"</string>
     <string name="permdesc_readSms" product="tablet" msgid="4741697454888074891">"ఈ అనువర్తనం మీ టాబ్లెట్‌లో నిల్వ చేసిన అన్ని SMS (వచన) సందేశాలను చదవగలదు."</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"ఇతర అనువర్తనాల నేపథ్య ప్రాసెస్‌లను ముగించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. దీని వలన ఇతర అనువర్తనాలు అమలు కాకుండా ఆపివేయబడవచ్చు."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"ఈ అనువర్తనం ఇతర అనువర్తనాల పైభాగాన కనిపించగలదు"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"ఈ అనువర్తనం ఇతర అనువర్తనాల పైభాగాన లేదా స్క్రీన్ యొక్క ఇతర భాగాలపైన కనిపించగలదు. ఇది సాధారణ అనువర్తన వినియోగానికి అంతరాయం కలిగించవచ్చు మరియు ఆ ఇతర అనువర్తనాలు కనిపించే విధానాన్ని మార్చవచ్చు."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"నేపథ్యంలో అమలు చేయండి"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"ఈ అనువర్తనం నేపథ్యంలో అమలు కావచ్చు. దీని వలన ఎక్కువ బ్యాటరీ శక్తి వినియోగం కావచ్చు."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"నేపథ్యంలో డేటాను ఉపయోగించండి"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"ఈ అనువర్తనం నేపథ్యంలో డేటాను ఉపయోగించవచ్చు. దీని వలన డేటా వినియోగం అధికం కావచ్చు."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"అనువర్తనాన్ని ఎల్లప్పుడూ అమలు చేయడం"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"అనువర్తనం, దాని భాగాలు మెమరీలో ఉండేలా చేయడానికి దానిని అనుమతిస్తుంది. ఇది ఇతర అనువర్తనాలకు అందుబాటులో ఉన్న మెమరీని ఆక్రమిస్తుంది, టాబ్లెట్ నెమ్మదిగా పని చేస్తుంది."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"అనువర్తనం దానిలోని కొన్ని భాగాలను మెమరీలో ఉంచడానికి దాన్ని అనుమతిస్తుంది. ఇది టీవీ నెమ్మదిగా పని చేసేలా చేస్తూ ఇతర అనువర్తనాలకు అందుబాటులో ఉన్న మెమరీని పరిమితం చేయవచ్చు."</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"ఇన్‌పుట్ పద్ధతి"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"వచనానికి సంబంధించిన చర్యలు"</string>
     <string name="email" msgid="4560673117055050403">"ఇమెయిల్"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"ఫోన్"</string>
     <string name="map" msgid="5441053548030107189">"మ్యాప్"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"బ్రౌజ్ చేయండి"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"నిల్వ ఖాళీ అయిపోతోంది"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"కొన్ని సిస్టమ్ కార్యాచరణలు పని చేయకపోవచ్చు"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"సిస్టమ్ కోసం తగినంత నిల్వ లేదు. మీకు 250MB ఖాళీ స్థలం ఉందని నిర్ధారించుకుని, పునఃప్రారంభించండి."</string>
@@ -1174,6 +1198,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"భాష మరియు లేఅవుట్‌ను ఎంచుకోవడానికి నొక్కండి"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g>ని ఇతర అనువర్తనాలపై గీయండి"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"ఎగువన <xliff:g id="NAME">%s</xliff:g> అనువర్తనం కనిపిస్తోంది."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"ఈ అనువర్తనంలోని భాగాలు అన్ని సమయాల్లో కనిపిస్తూ ఉండవచ్చు. ఈ లక్షణం సరిగ్గా పని చేయకపోతే, దీన్ని ఆఫ్ చేయండి."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ఆఫ్ చేయి"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g>ని సిద్ధం చేస్తోంది"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"లోపాల కోసం తనిఖీ చేస్తోంది"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"కొత్త <xliff:g id="NAME">%s</xliff:g> గుర్తించబడింది"</string>
@@ -1328,8 +1356,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g>తో భాగస్వామ్యం చేయండి"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"స్లైడింగ్ హ్యాండిల్. తాకి, ఆపై నొక్కి ఉంచండి."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"అన్‌లాక్ చేయడానికి స్వైప్ చేయండి."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"చదివి వినిపించే పాస్‌వర్డ్ కీలను వినడానికి హెడ్‌సెట్‌ను ప్లగిన్ చేయండి."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"చుక్క."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"హోమ్‌కు నావిగేట్ చేయండి"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"పైకి నావిగేట్ చేయండి"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"మరిన్ని ఎంపికలు"</string>
@@ -1713,4 +1739,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"సమయంలో టైప్ చేయండి"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"సమయాన్ని నమోదు చేయడం కోసం వచన నమోదు మోడ్‌కి మారండి."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"సమయాన్ని నమోదు చేయడం కోసం గడియారం మోడ్‌కు మారండి."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g>కు సేవ్ చేయాలా?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g>ని <xliff:g id="LABEL">%2$s</xliff:g>కు సేవ్ చేయాలా?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"సేవ్ చేయి"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"వద్దు, ధన్యవాదాలు"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"పాస్‌వర్డ్"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"చిరునామా"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"క్రెడిట్ కార్డ్"</string>
 </resources>
diff --git a/core/res/res/values-television/config.xml b/core/res/res/values-television/config.xml
index c27cb06..1987ac4 100644
--- a/core/res/res/values-television/config.xml
+++ b/core/res/res/values-television/config.xml
@@ -24,9 +24,10 @@
     <!-- Flags enabling default window features. See Window.java -->
     <bool name="config_defaultWindowFeatureOptionsPanel">false</bool>
 
-    <!-- Max default size [WIDTHxHEIGHT] on screen for picture-in-picture windows to fit inside.
-         These values are in DPs and will be converted to pixel sizes internally. -->
-    <string translatable="false" name="config_defaultPictureInPictureSize">240x135</string>
+    <!-- The percentage of the screen width to use for the default width or height of
+         picture-in-picture windows. Regardless of the percent set here, calculated size will never
+         be smaller than @dimen/default_minimal_size_pip_resizable_task. -->
+    <item name="config_pictureInPictureDefaultSizePercent" format="float" type="dimen">0.14</item>
 
     <!-- Default insets [LEFT/RIGHTxTOP/BOTTOM] from the screen edge for picture-in-picture windows.
          These values are in DPs and will be converted to pixel sizes internally. -->
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index fc8b858..95b5501 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"เนื้อหาถูกซ่อนไว้"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"มีการซ่อนเนื้อหาโดยนโยบาย"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"ความปลอดภัย"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"การแจ้งเตือน"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"โหมดปลอดภัย"</string>
     <string name="android_system_label" msgid="6577375335728551336">"ระบบ Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"เปลี่ยนไปใช้โปรไฟล์ส่วนตัว"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"อนุญาตให้แอปพลิเคชันลบทางลัดหน้าจอหลักโดยไม่ต้องให้ผู้ใช้จัดการ"</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"จัดเส้นทางการโทรออกใหม่"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"อนุญาตให้แอปดูหมายเลขที่โทรในระหว่างการโทรออกโดยสามารถเลือกเปลี่ยนเส้นทางการโทรไปยังหมายเลขอื่นหรือยกเลิกการโทรไปเลยได้"</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"รับข้อความ (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"อนุญาตให้แอปพลิเคชันรับและประมวลผลข้อความ SMS ซึ่งหมายความว่าแอปพลิเคชันจะสามารถตรวจสอบหรือลบข้อความที่ส่งมายังอุปกรณ์ของคุณได้โดยไม่ต้องแสดงให้คุณเห็น"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"รับข้อความ (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"อนุญาตให้แอปพลิเคชันหยุดการทำงานในพื้นหลังของแอปพลิเคชันอื่นๆ ซึ่งอาจทำให้แอปพลิเคชันอื่นๆ หยุดการทำงาน"</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"แอปนี้สามารถแสดงทับแอปอื่นๆ"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"แอปนี้สามารถปรากฏเหนือแอปอื่นๆ หรือส่วนอื่นของหน้าจอ ซึ่งอาจรบกวนการใช้งานตามปกติของแอปและทำให้ลักษณะการแสดงแอปอื่นๆ เปลี่ยนไป"</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"ทำงานในพื้นหลัง"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"แอปนี้สามารถทำงานในพื้นหลัง ซึ่งอาจทำให้แบตเตอรี่หมดเร็วขึ้น"</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"ใช้เน็ตในพื้นหลัง"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"แอปนี้สามารถใช้เน็ตในพื้นหลัง ซึ่งอาจเพิ่มปริมาณการใช้อินเทอร์เน็ต"</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"ทำให้แอปพลิเคชันทำงานเสมอ"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"อนุญาตให้แอปพลิเคชันทำให้ส่วนหนึ่งของตัวเองคงอยู่ถาวรในหน่วยความจำ ซึ่งจะจำกัดพื้นที่หน่วยความจำที่ใช้งานได้ของแอปพลิเคชันอื่นๆ และทำให้แท็บเล็ตทำงานช้าลง"</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"อนุญาตให้แอปทำให้บางส่วนของแอปนั้นอยู่ในหน่วยความจำเสมอ ซึ่งอาจจำกัดพื้นที่หน่วยความจำสำหรับแอปอื่นและทำให้ทีวีช้าลง"</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"วิธีป้อนข้อมูล"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"การทำงานของข้อความ"</string>
     <string name="email" msgid="4560673117055050403">"อีเมล"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"โทรศัพท์"</string>
     <string name="map" msgid="5441053548030107189">"แผนที่"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"เรียกดู"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"พื้นที่จัดเก็บเหลือน้อย"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"บางฟังก์ชันระบบอาจไม่ทำงาน"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"พื้นที่เก็บข้อมูลไม่เพียงพอสำหรับระบบ โปรดตรวจสอบว่าคุณมีพื้นที่ว่าง 250 MB แล้วรีสตาร์ท"</string>
@@ -1173,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"แตะเพื่อเลือกภาษาและรูปแบบ"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรลวศษสหฬอฮ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรลวศษสหฬอฮ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> แสดงทับแอปอื่น"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"แอป <xliff:g id="NAME">%s</xliff:g> แสดงอยู่ด้านบนสุด"</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"ส่วนต่างๆ ของแอปนี้อาจปรากฏอยู่ตลอดเวลา หากคุณลักษณะนี้ไม่ทำงานอย่างถูกต้อง ให้ปิดแอป"</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ปิด"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"กำลังเตรียม <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"กำลังตรวจหาข้อผิดพลาด"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"ตรวจพบ <xliff:g id="NAME">%s</xliff:g> ใหม่"</string>
@@ -1327,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"แชร์ด้วย <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"ที่จับสำหรับเลื่อน แตะค้างไว้"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"กวาดเพื่อปลดล็อก"</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"เสียบชุดหูฟังเพื่อฟังเสียงเมื่อพิมพ์รหัสผ่าน"</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"เครื่องหมายจุด"</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"นำทางไปหน้าแรก"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"นำทางขึ้น"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"ตัวเลือกเพิ่มเติม"</string>
@@ -1712,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"พิมพ์เวลา"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"สลับไปโหมดป้อนข้อความเพื่อป้อนเวลา"</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"สลับไปโหมดนาฬิกาเพื่อป้อนเวลา"</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"บันทึกไปยัง <xliff:g id="LABEL">%1$s</xliff:g> ใช่ไหม"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"บันทึก <xliff:g id="TYPE">%1$s</xliff:g> ไปยัง <xliff:g id="LABEL">%2$s</xliff:g> ใช่ไหม"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"บันทึก"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"ไม่เป็นไร"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"รหัสผ่าน"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"ที่อยู่"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"บัตรเครดิต"</string>
 </resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index cdb1c5e..2b32267 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Nakatago ang mga content"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Itinago ang mga content alinsunod sa patakaran"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Seguridad"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Mga Alerto"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Lumipat sa Personal"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Pinapayagan ang application na alisin ang mga shortcut ng Homescreen nang walang panghihimasok ng user."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"baguhin ang ruta ng mga papalabas na tawag"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Pinapayagan ang app na makita ang numerong idina-dial sa isang papalabas na tawag na may opsyon na i-redirect ang tawag sa ibang numero o itigil ang tawag nang tuluyan."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"tumanggap ng mga text message (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Pinapayagan ang app na tumanggap at magproseso ng mga mensaheng SMS. Nangangahulugan ito na maaaring sumubaybay o magtanggal ang app ng mga mensaheng ipinapadala sa iyong device nang hindi ipinapakita ang mga ito sa iyo."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"tumanggap ng mga text message (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Pinapayagan ang app na tapusin ang mga proseso sa background ng iba pang apps. Maaari itong maging sanhi ng paghinto sa paggana ng iba pang apps."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Maaaring lumabas ang app na ito sa ibabaw ng iba pang mga app"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Maaaring lumabas ang app na ito sa ibabaw ng iba pang mga app o iba pang mga bahagi ng screen. Maaaring makasagabal ito sa normal na paggamit ng app at mabago nito ang paraan kung paano lumalabas ang iba pang mga app."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"patakbuhin sa background"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Maaaring tumakbo sa background ang app na ito. Maaaring mas mabilis nitong maubos ang baterya."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"gumamit ng data sa background"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Maaaring gumamit ng data sa background ang app na ito. Maaaring mas maraming data ang magamit nito."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"palaging patakbuhin ang app"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Pinapayagan ang app na panatilihin ang ilang bahagi nito sa memory. Maaari nitong limitahan ang memory na available sa iba pang apps na nagpapabagal sa tablet."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Nagbibigay-daan sa app na iimbak sa memory ang mga bahagi nito. Maaari nitong malimitahan ang memory na available sa iba pang mga app na nagpapabagal sa TV."</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"Pamamaraan ng pag-input"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Pagkilos ng teksto"</string>
     <string name="email" msgid="4560673117055050403">"Mag-email"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"Telepono"</string>
     <string name="map" msgid="5441053548030107189">"Mapa"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"Mag-browse"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Nauubusan na ang puwang ng storage"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Maaaring hindi gumana nang tama ang ilang paggana ng system"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Walang sapat na storage para sa system. Tiyaking mayroon kang 250MB na libreng espasyo at i-restart."</string>
@@ -1173,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"I-tap upang pumili ng wika at layout"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"I-draw over ang <xliff:g id="NAME">%s</xliff:g> sa iba pang app"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"Ipinapakita ang <xliff:g id="NAME">%s</xliff:g> app sa itaas."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Maaaring manatiling nakikita ang mga bahagi ng app na ito sa lahat ng oras. Kung hindi gumagana nang tama ang feature na ito, i-off ito."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"I-OFF"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Inihahanda ang <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Sinusuri para sa mga error"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Na-detect ang bagong <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1327,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Ibahagi sa <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Hawakan sa pag-slide. Pindutin nang matagal."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Mag-swipe upang i-unlock."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Mag-plug in ng isang headset upang marinig ang mga password key na binabanggit."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Dot."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Magnabiga sa home"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Magnabiga pataas"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Higit pang mga pagpipilian"</string>
@@ -1712,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"I-type ang oras"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Lumipat sa pamamaraan ng pag-input ng text para sa input na oras."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Lumipat sa mode ng orasan para sa input na oras."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"I-save sa <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"I-save ang <xliff:g id="TYPE">%1$s</xliff:g> sa <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"I-save"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Hindi, salamat na lang"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"password"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"address"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"credit card"</string>
 </resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index e2fbfaf..6ca0c3e 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"İçerik gizlendi"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"İçerikler politika nedeniyle gizlendi"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Güvenlik"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Uyarılar"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Güvenli mod"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android Sistemi"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Kişisel Profile Geç"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Uygulamaya, kullanıcının müdahalesi olmadan kısayolları Ana Ekrandan kaldırma izni verir."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"giden çağrıları yeniden yönlendirme"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Uygulamaya, giden bir çağrının numarası çevrilirken çağrıyı farklı bir numaraya yönlendirme ya da tamamen kapatma seçeneğiyle birlikte numarayı görme izni verir."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"kısa mesajları al (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Uygulamaya SMS iletilerini alma ve işleme izni verir. Bu izin, uygulamanın cihazınıza gönderilen iletileri takip edip size göstermeden silebileceği anlamına gelir."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"kısa mesajları (MMS) al"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Uygulamaya diğer uygulamalara ait arka plan işlemleri sonlandırma izni verir. Bu izin, diğer uygulamaların çalışmayı durdurmasına neden olabilir."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Bu uygulama, diğer uygulamaların üzerinde görünebilir"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Bu uygulama, uygulamaların üzerinde veya ekranın diğer kısımlarında görünebilir. Bu durum, normal uygulama kullanımını etkileyebilir ve diğer uygulamaların görünümünü değiştirebilir."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"arka planda çalıştırma"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Bu uygulama arka planda çalıştırılabilir. Bu durum pilinizin daha hızlı boşalmasına neden olabilir."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"arka planda veri kullanma"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Bu uygulama, arka planda verileri kullanabilir. Bu durum veri kullanımını artırabilir."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"uygulamayı her zaman çalıştırma"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Uygulamaya kendisinin bir bölümünü bellekte kalıcı yapma izni verir. Bu izin, diğer uygulamaların kullanabileceği belleği sınırlandırarak tabletin yavaş çalışmasına neden olabilir."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Uygulamaya, kendi parçalarını bellekte kalıcı hale getirme izni verir. Bu, TV\'yi yavaşlatan diğer uygulamaların kullanabileceği bellek alanını sınırlayabilir."</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"Giriş yöntemi"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Metin eylemleri"</string>
     <string name="email" msgid="4560673117055050403">"E-posta"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"Telefon"</string>
     <string name="map" msgid="5441053548030107189">"Harita"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"Göz at"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Depolama alanı bitiyor"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Bazı sistem işlevleri çalışmayabilir"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Sistem için yeterli depolama alanı yok. 250 MB boş alanınızın bulunduğundan emin olun ve yeniden başlatın."</string>
@@ -1173,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dili ve düzeni seçmek için hafifçe dokunun"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> diğer uygulamaların üzerinde görüntüleniyor"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> üstte gösteriliyor."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Bu uygulamanın bazı bölümleri her zaman görünür durumda kalabilir. Bu özellik düzgün çalışmıyorsa kapatın."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"KAPAT"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> hazırlanıyor"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Hatalar denetleniyor"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Yeni <xliff:g id="NAME">%s</xliff:g> algılandı"</string>
@@ -1327,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> ile paylaş"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Kayan tutma yeri. Dokunun ve basılı tutun."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Kilidi açmak için kaydırın."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Şifre tuşlarının sesli okunmasını dinlemek için mikrofonlu kulaklık takın."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Nokta."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Ana sayfaya git"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Yukarı git"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Diğer seçenekler"</string>
@@ -1712,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Zamanı yazın"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Zaman girişi için metin girişi moduna geçin."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Zaman girişi için saat moduna geçin."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> hizmetine kaydedilsin mi?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g>, <xliff:g id="LABEL">%2$s</xliff:g> etkinliğine kaydedilsin mi?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Kaydet"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Hayır, teşekkürler"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"şifre"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"adres"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kredi kartı"</string>
 </resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 5fac070..55f93d4 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -250,6 +250,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Вміст сховано"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Вміст сховано згідно з правилом"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Безпека"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Сповіщення"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Безп. режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Система Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Перейти в особистий профіль"</string>
@@ -298,6 +324,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Дозволяє програмі самостійно вилучати ярлики з головного екрана."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"переадресовувати вихідні виклики"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Дозволяє додатку читати номер вихідного дзвінка, переспрямовувати дзвінок на інший номер або переривати його."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"отримувати текстові повідомлення (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Дозволяє програмі отримувати й обробляти SMS-повідомлення. Це означає, що програма може відстежувати чи видаляти повідомлення, надіслані на ваш пристрій, навіть не показуючи їх вам."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"отримувати текстові повідомлення (MMS)"</string>
@@ -326,14 +356,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Дозволяє програмі припиняти фонові процеси інших програм. Це може зупиняти запущені програми."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Цей додаток може відображатися поверх інших додатків"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Цей додаток може відображатися поверх інших додатків або частин екрана. Це може заважати нормальній взаємодії з додатком або змінити відображення інших додатків."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"працювати у фоновому режимі"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Цей додаток може працювати у фоновому режимі. Можливо, акумулятор розряджатиметься швидше."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"використовувати трафік у фоновому режимі"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Цей додаток може використовувати трафік у фоновому режимі. Можливо, використання трафіку збільшиться."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"заставляти програму постійно функціонувати"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Дозволяє програмі робити свої частини сталими в пам’яті. Це може зменшувати обсяг пам’яті, доступної для інших програм, і сповільнювати роботу планшетного ПК."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Додаток може робити свої частини сталими в пам’яті. Це може зменшувати обсяг пам’яті, доступної для інших додатків, і сповільнювати роботу телевізора."</string>
@@ -1211,6 +1237,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Торкніться, щоб вибрати мову та розкладку"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" АБВГҐДЕЄЖЗИІЇЙКЛМНОПРСТУФХЦЧШЩЬЮЯ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789АБВГҐДЕЄЖЗИІЇЙКЛМНОПРСТУФХЦЧШЩЬЮЯ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> відображається поверх інших додатків"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> відображається поверх."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Частина цього додатка може постійно залишатися видимою. Якщо ця функція працює неправильно, вимкніть її."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ВИМКНУТИ"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Підготовка пристрою пам’яті <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Виявлення помилок"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Виявлено новий пристрій пам’яті (<xliff:g id="NAME">%s</xliff:g>)"</string>
@@ -1367,8 +1397,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Надіслати через <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Вказівник-повзунок. Торкніться й утримуйте."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Гортайте, щоб розблокувати."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Підключіть гарнітуру, щоб прослухати відтворені вголос символи пароля."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Крапка."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Перейти на головну"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Перейти вгору"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Більше"</string>
@@ -1772,4 +1800,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Введіть час"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Перейти в текстовий режим, щоб ввести час."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Перейти в режим годинника, щоб ввести час."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Зберегти в службі <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Зберегти дані (<xliff:g id="TYPE">%1$s</xliff:g>) у службі <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Зберегти"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Ні, дякую"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"пароль"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"адреса"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"кредитна картка"</string>
 </resources>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 2a83289..5b9b483 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"‎999+‎"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"مواد مخفی ہیں"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"مواد پالیسی کے تحت مخفی ہے"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"سیکیورٹی"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"الرٹس"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"حفاظتی وضع"</string>
     <string name="android_system_label" msgid="6577375335728551336">"‏Android سسٹم"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"ذاتی پر سوئچ کریں"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"ایپلیکیشن کو صارف کی مداخلت کے بغیر ہوم اسکرین شارٹ کٹس ہٹانے کی اجازت دیتا ہے۔"</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"باہر جانے والی کالوں کی سمت دوبارہ طے کریں"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"ایپ کو ایک مختلف نمبر پر کال ری ڈائریکٹ کرنے یا مکمل طور پر کال ختم کر دینے کیلئے اختیار کے ساتھ ایک آؤٹ گوئنگ کال کے دوران ڈائل کیا جا رہا نمبر دیکھنے کی اجازت دیتا ہے۔"</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"‏متنی پیغامات (SMS) حاصل کریں"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"‏ایپ کو SMS پیغامات حاصل اور ان پر کارروائی کرنے کی اجازت دیتا ہے۔ اس کا مطلب ہے کہ ایپ آپ کے آلے پر مرسلہ پیغامات آپ کو دکھائے بغیر ان پر نگاہ رکھ یا انہیں حذف کرسکتی ہے۔"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"‏متنی پیغامات (MMS) حاصل کریں"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"ایپ کو دوسرے ایپس کے پس منظر کی کارروائیوں کو ختم کرنے کی اجازت دیتا ہے۔ اس کی وجہ سے دوسرے ایپس کا چلنا بند ہوسکتا ہے۔"</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"یہ ایپ دیگر ایپس کے اوپر ظاہر ہوسکتی ہے"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"یہ ایپ دیگر ایپس کے اوپر یا سکرین کے دیگر حصوں پر ظاہر ہو سکتی ہے۔ یہ عام ایپ کے استعمال کے ساتھ مداخلت کر سکتی ہے اور دیگر ایپس کے ظاہر ہونے کا طریقہ بدل سکتی ہے۔"</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"پس منظر میں چلائيں"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"یہ ایپ پس منظر میں چل سکتی ہے۔ ممکن ہے یہ بیٹری کو زیادہ تیزی سے ختم کر دے۔"</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"پس منظر میں ڈیٹا استعمال کریں"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"یہ ایپ پس منظر میں ڈیٹا استعمال کر سکتی ہے۔ ممکن ہے یہ ڈیٹا کے استتعمال کو بڑھا دے۔"</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"ایپ کو ہمیشہ چلاتے رہیں"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"ایپ کو خود اپنے ہی حصوں کو میموری میں استقلال پذیر بنانے کی اجازت دیتا ہے۔ یہ ٹیبلٹ کو سست بناکر دوسری ایپس کیلئے دستیاب میموری کو محدود کرسکتا ہے۔"</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"‏ایپ کو خود اپنے ہی حصوں کو میموری میں استقلال پذیر بنانے کی اجازت دیتا ہے۔ یہ TV کو سُست بناکر دوسری ایپس کیلئے دستیاب میموری کو محدود کرسکتا ہے۔"</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"اندراج کا طریقہ"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"متن کی کارروائیاں"</string>
     <string name="email" msgid="4560673117055050403">"ای میل"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"فون کریں"</string>
     <string name="map" msgid="5441053548030107189">"نقشہ"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"براؤز کریں"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"اسٹوریج کی جگہ ختم ہو رہی ہے"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"ممکن ہے سسٹم کے کچھ فنکشنز کام نہ کریں"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"‏سسٹم کیلئے کافی اسٹوریج نہیں ہے۔ اس بات کو یقینی بنائیں کہ آپ کے پاس 250MB خالی جگہ ہے اور دوبارہ شروع کریں۔"</string>
@@ -1174,6 +1198,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"زبان اور لے آؤٹ منتخب کرنے کیلئے تھپتھپائیں"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> کو دیگر ایپس پر ڈرا کریں"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> ایپ اوپر ڈسپلے ہورہی ہے۔"</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"ممکن ہے اس ایپ کے حصے ہر وقت مرئی رہیں۔ اگر یہ خصوصیت ٹھیک سے کام نہیں کررہی ہے، تو اسے آف کردیں۔"</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"آف کریں"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> تیار کیا جا رہا ہے"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"خرابیوں کیلئے چیک کیا جا رہا ہے"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"نئے <xliff:g id="NAME">%s</xliff:g> کا پتا چلا"</string>
@@ -1328,8 +1356,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> کے ساتھ اشتراک کریں"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"سلائیڈنگ ہینڈل۔ ٹچ کریں اور پکڑ کر رکھیں۔"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"غیر مقفل کرنے کیلئے سوائپ کریں۔"</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"بولی گئی پاس ورڈ کلیدیں سننے کیلئے ایک ہیڈ سیٹ لگائیں۔"</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"ڈاٹ۔"</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"ہوم پر نیویگیٹ کریں"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"اوپر نیویگیٹ کریں"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"مزید اختیارات"</string>
@@ -1713,4 +1739,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"وقت ٹائپ کریں"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"وقت ان پٹ کے لیے ٹیکسٹ ان پٹ وضع پر سوئچ کریں۔"</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"وقت ان پٹ کے لیے گھڑی و‏ضع پر سوئچ کریں۔"</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> میں محفوظ کریں؟"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> کو <xliff:g id="LABEL">%2$s</xliff:g> میں محفوظ کریں؟"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"محفوظ کریں"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"نہیں، شکریہ"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"پاس ورڈ"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"پتہ"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"کریڈٹ کارڈ"</string>
 </resources>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 4b4a33e..796ce73 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Kontent yashirildi"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Qoidaga muvofiq kontent yashirilgan"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Xavfsizlik"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Ogohlantirishlar"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Xavfsiz usul"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android tizimi"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Shaxsiy profilga o‘tish"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Dasturga foydalanuvchini aralashtirmasdan, uy ekranidagi yorliqlarni o‘chirishga ruxsat beradi."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"chiquvchi qo‘ng‘iroqlarni qayta yo‘naltirish"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Ilova chiquvchi qo‘ng‘iroq vaqtida terilgan raqamni ko‘rishi va zaruratga qarab uni qayta yo‘naltirishi yoki tugatishi mumkin."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"SMS xabarlarni olish"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Ilovaga SMS xabarlarini qabul qilish va va ularni qayta ishlash uchun ruxsat beradi. Bu sizga yuborilgan xabarlarni ilova sizga ko‘rsatmasdan kuzatishi va o‘chirishi mumkinligini bildiradi."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"MMS xabarlarni olish"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Ilovaga boshqa ilovalarning orqa fonda amalga oshirilayotgan jarayonlarini to‘xtatish uchun ruxsat beradi. Bu boshqa ilovalarning to‘xtatilishiga sabab bo‘lishi mumkin."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Bu ilova boshqa oynalar ustidan ko‘rsatilishi mumkin"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Bu ilova ilovalar yoki ekranning boshqa qismlaridan yuqorida ko‘rinishi mumkin. Bu ilovadan odatiy foydalanishga halaqit berishi va boshqa ilovalar ko‘rinishining usullarini o‘zgartirib yuborishi mumkin."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"orqa fonda ishlaydi"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Bu ilova orqa fonda ham ishlaydi. Bunda batareya quvvati ko‘proq sarflanishi mumkin."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"orqa fonda internetdan foydalanadi"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Bu ilova orqa fonda internetdan foydalanadi. Bunda trafik sarflanishi mumkin."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"ilovani doim ishlab turadigan qilish"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Ilovaga o‘zining komponentlarini xotirada doimiy saqlashga ruxsat beradi. Bu mavjud xotirani cheklashi va planshetni sekin ishlashiga sabab bo‘lishi mumkin."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Ilovaga o‘zining muayyan qismlarining xotiraning turg‘un qismiga aylantirish huquqini beradi. Bunda, boshqa ilovalar uchun xotiradan ajratilgan joy cheklanib, televizorning ishlashi sekinlashishi mumkin."</string>
@@ -1172,6 +1198,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Til va sxemani belgilash uchun bosing"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> boshqa ilovalar ustidan ochiladi"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g> eng tepada ochilgan."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Bu ilovaning ba’zi qismlari har doim ko‘rinib qolishi mumkin. Agar bu funksiya to‘g‘ri ishlamasa, uni o‘chirib qo‘ying."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"O‘CHIRIB QO‘YISH"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> tayyorlanmoqda"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Xatolar qidirilmoqda"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Yangi <xliff:g id="NAME">%s</xliff:g> kartasi aniqlandi"</string>
@@ -1326,8 +1356,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> ilovasiga ruxsat berish"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Surish uchun dastak. Bosing va ushlab turing."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Qulfdan chiqarish uchun silang."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Parol kalitlarini eshitish uchun garnitura ulang."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Dot."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Boshiga o‘tish"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Yuqoriga o‘tish"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Ko‘proq sozlamalar"</string>
@@ -1711,4 +1739,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Vaqtni kiriting"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Vaqtni kiritish uchun matn kiritish rejimiga o‘ting."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Vaqtni kiritish uchun soat rejimiga o‘ting."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> xizmatiga saqlansinmi?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> <xliff:g id="LABEL">%2$s</xliff:g> xizmatiga saqlansinmi?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Saqlash"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Yo‘q, kerak emas"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"parol"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"manzil"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kredit karta"</string>
 </resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 149a661..33eafb1 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Nội dung bị ẩn"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Nội dung bị ẩn theo chính sách"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Bảo mật"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Cảnh báo"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Chế độ an toàn"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Hệ thống Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Chuyển sang Cá nhân"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Cho phép ứng dụng xóa lối tắt trên Màn hình chính mà không cần sự can thiệp của người dùng."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"định tuyến lại cuộc gọi đi"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Cho phép ứng dụng xem số được gọi trong một cuộc gọi đi với tùy chọn chuyển hướng cuộc gọi đến một số khác hoặc hủy cuộc gọi đó hoàn toàn."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"nhận tin nhắn văn bản (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Cho phép ứng dụng nhận và xử lý tin nhắn SMS. Điều này có nghĩa là ứng dụng có thể theo dõi hoặc xóa tin nhắn được gửi đến thiết bị của bạn mà không hiển thị chúng cho bạn."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"nhận tin nhắn văn bản (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Cho phép ứng dụng kết thúc các quá trình nền của các ứng dụng khác. Việc này có thể khiến các ứng dụng khác dừng chạy."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Ứng dụng này có thể xuất hiện ở phía trên cùng của các ứng dụng khác"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Ứng dụng này có thể xuất hiện ở phía trên cùng của các ứng dụng khác hoặc các phần khác của màn hình. Điều này có thể cản trở hoạt động sử dụng ứng dụng thông thường và thay đổi cách các ứng dụng khác xuất hiện."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"chạy trong nền"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Ứng dụng này có thể chạy trong nền. Việc này có thể tiêu hao pin nhanh hơn."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"sử dụng dữ liệu trong nền"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Ứng dụng này có thể sử dụng dữ liệu trong nền. Việc này có thể tăng mức sử dụng dữ liệu."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"đặt ứng dụng luôn chạy"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Cho phép ứng dụng tạo sự đồng nhất cho các phần của mình trong bộ nhớ. Việc này có thể hạn chế bộ nhớ đối với các ứng dụng khác đang làm chậm máy tính bảng."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Cho phép ứng dụng làm cho các phần của ứng dụng trở nên ổn định trong bộ nhớ. Việc này có thể hạn chế bộ nhớ đối với các ứng dụng khác đang làm chậm TV."</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"Phương thức nhập"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Tác vụ văn bản"</string>
     <string name="email" msgid="4560673117055050403">"Email"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"Điện thoại"</string>
     <string name="map" msgid="5441053548030107189">"Bản đồ"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"Duyệt qua"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Sắp hết dung lượng lưu trữ"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Một số chức năng hệ thống có thể không hoạt động"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Không đủ bộ nhớ cho hệ thống. Đảm bảo bạn có 250 MB dung lượng trống và khởi động lại."</string>
@@ -1173,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Nhấn để chọn ngôn ngữ và bố cục"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g> vẽ lên các ứng dụng khác"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"Ứng dụng <xliff:g id="NAME">%s</xliff:g> hiển thị ở trên cùng."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Các phần của ứng dụng này có thể vẫn hiển thị mọi lúc. Nếu tính năng này không hoạt động bình thường, hãy tắt tính năng này."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"TẮT"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Đang chuẩn bị <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Đang kiểm tra lỗi"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"Đã phát hiện <xliff:g id="NAME">%s</xliff:g> mới"</string>
@@ -1327,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Chia sẻ với <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Tay trượt. Chạm &amp; giữ."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Trượt để mở khóa."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Cắm tai nghe để nghe các khóa mật khẩu được đọc."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Dấu chấm."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Điều hướng về trang chủ"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Điều hướng lên trên"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Tùy chọn khác"</string>
@@ -1712,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Nhập thời gian"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Chuyển sang chế độ nhập văn bản để nhập thời gian."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Chuyển sang chế độ đồng hồ để nhập thời gian."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Lưu vào <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Lưu <xliff:g id="TYPE">%1$s</xliff:g> vào <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Lưu"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Không, cảm ơn"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"mật khẩu"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"địa chỉ"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"thẻ tín dụng"</string>
 </resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 10c6ca8..4ef2af0 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"内容已隐藏"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"内容已隐藏(根据政策规定)"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"安全性"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"提醒"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android 系统"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"切换到“个人”"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"允许应用自行删除主屏幕快捷方式。"</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"重新设置外拨电话的路径"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"允许应用在拨出电话时查看拨打的电话号码,并选择改为拨打其他号码或完全中止通话。"</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"接收讯息(短信)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"允许该应用接收和处理短信。这就意味着,该应用可能会监视发送到您设备的短信,或删除发送到您设备的短信而不向您显示。"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"接收讯息(彩信)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"允许该应用结束其他应用的后台进程。此权限可导致其他应用停止运行。"</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"此应用可显示在其他应用上方"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"此应用可显示在其他应用上方或屏幕的其他部分。这可能会妨碍您正常地使用应用,且其他应用的显示方式可能会受到影响。"</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"在后台运行"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"此应用可在后台运行,这样可能会加快耗电速度。"</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"在后台使用数据"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"此应用可在后台使用数据,这样可能会增加流量消耗。"</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"让应用始终运行"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"允许该应用在内存中持续保留其自身的某些组件。这会限制其他应用可用的内存,从而减缓平板电脑运行速度。"</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"允许应用在内存中持续保留其自身的部分组件。此权限可能会限制其他应用可用的内存,从而减缓电视运行速度。"</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"输入法"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"文字操作"</string>
     <string name="email" msgid="4560673117055050403">"电子邮件"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"电话"</string>
     <string name="map" msgid="5441053548030107189">"地图"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"浏览"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"存储空间不足"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"某些系统功能可能无法正常使用"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"系统存储空间不足。请确保您有250MB的可用空间,然后重新启动。"</string>
@@ -1173,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"点按即可选择语言和布局"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g>会在其他应用的上层显示内容"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g>应用目前显示在上层。"</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"此应用的某些部分可能会一直保持可见状态。如果此功能未能正常运行,请将其关闭。"</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"关闭"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"正在准备<xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"检查是否有错误"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"检测到新的<xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1327,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"使用<xliff:g id="APPLICATION_NAME">%s</xliff:g>分享"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"滑动手柄。触摸并按住。"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"滑动解锁。"</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"需要插入耳机才能听到密码的按键声。"</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"点。"</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"导航首页"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"向上导航"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"更多选项"</string>
@@ -1712,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"请输入时间"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"切换到文字输入模式来输入时间。"</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"切换到时钟模式来输入时间。"</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"要保存到<xliff:g id="LABEL">%1$s</xliff:g>吗?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"要将<xliff:g id="TYPE">%1$s</xliff:g>保存到<xliff:g id="LABEL">%2$s</xliff:g>吗?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"保存"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"不用了"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"密码"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"地址"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"信用卡"</string>
 </resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index db9fbab..f07f2c6 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"內容已隱藏"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"已根據政策隱藏內容"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"安全性"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"通知"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android 系統"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"切換至個人設定檔"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"允許應用程式繞過使用者授權直接移除主畫面捷徑。"</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"重新設定撥出電話的路徑"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"允許應用程式在撥出電話時查看所撥打的電話號碼,並選擇將電話重新導向至另一個號碼或完全中斷通話。"</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"接收短訊 (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"允許應用程式接收和處理短訊。這表示應用程式可監控傳送至您裝置的訊息,或在您閱讀訊息前擅自刪除訊息。"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"接收短訊 (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"允許應用程式終止其他應用程式的背景處理程序。這樣可能會導致其他應用程式停止運行。"</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"此應用程式可以出現在其他應用程式上"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"此應用程式可以出現在其他應用程式或螢幕的其他部分上。這可能會影響應用程式的正常使用,並變更其他應用程式的顯示方式。"</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"在背景中執行"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"此應用程式可在背景中執行,這可能會加速耗電。"</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"在背景中使用數據"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"此應用程式可在背景中使用數據,這可能會增加數據用量。"</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"一律執行應用程式"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"允許應用程式設定本身的某些部分持續佔用記憶體。這樣可能會限制其他應用程式可用的記憶體,並拖慢平板電腦的運作速度。"</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"允許應用程式長期佔用部分記憶體。這會限制其他應用程式可用的記憶體,減慢電視操作。"</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"輸入法"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"文字操作"</string>
     <string name="email" msgid="4560673117055050403">"電郵"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"撥打電話"</string>
     <string name="map" msgid="5441053548030107189">"地圖"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"瀏覽"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"儲存空間即將用盡"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"部分系統功能可能無法運作"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"系統儲存空間不足。請確認裝置有 250 MB 的可用空間,然後重新啟動。"</string>
@@ -1173,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"輕按即可選取語言和鍵盤配置"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"「<xliff:g id="NAME">%s</xliff:g>」會覆蓋其他應用程式"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"「<xliff:g id="NAME">%s</xliff:g>」應用程式目前在最上層顯示。"</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"畫面上可能會一直保持顯示此應用程式的某些部分。如果此功能無法正常運作,請將其關閉。"</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"關閉"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"正在準備<xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"正在檢查錯誤"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"已偵測到新<xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1327,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"與「<xliff:g id="APPLICATION_NAME">%s</xliff:g>」分享"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"滑動控制。持續輕觸。"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"滑動即可解鎖。"</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"插上耳機即可聽到系統朗讀密碼鍵。"</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"點。"</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"瀏覽首頁"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"向上瀏覽"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"更多選項"</string>
@@ -1712,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"輸入時間"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"切換至文字輸入模式即可輸入時間。"</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"切換至時鐘模式即可輸入時間。"</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"要儲存至 <xliff:g id="LABEL">%1$s</xliff:g> 嗎?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"要將<xliff:g id="TYPE">%1$s</xliff:g>儲存至 <xliff:g id="LABEL">%2$s</xliff:g> 嗎?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"儲存"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"不用了,謝謝"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"密碼"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"地址"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"信用卡"</string>
 </resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 2fd7c29..2fc1cbc 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -127,10 +127,10 @@
     <string name="roamingTextSearching" msgid="8360141885972279963">"正在搜尋服務"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi 通話"</string>
   <string-array name="wfcOperatorErrorAlertMessages">
-    <item msgid="2254967670088539682">"如要透過 Wi-FI 撥打電話及傳送訊息,請先要求您的行動通訊業者開通這項服務,然後再到「設定」啟用 Wi-Fi 通話功能。"</item>
+    <item msgid="2254967670088539682">"如要透過 Wi-FI 撥打電話及傳送訊息,請先要求您的電信業者開通這項服務,然後再到「設定」啟用 Wi-Fi 通話功能。"</item>
   </string-array>
   <string-array name="wfcOperatorErrorNotificationMessages">
-    <item msgid="6177300162212449033">"向您的行動通訊業者註冊"</item>
+    <item msgid="6177300162212449033">"向您的電信業者註冊"</item>
   </string-array>
   <string-array name="wfcSpnFormats">
     <item msgid="6830082633573257149">"%s"</item>
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"超過 999"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"內容已隱藏"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"內容已依據政策隱藏"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"安全性"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"快訊"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android 系統"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"切換至個人設定檔"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"允許應用程式自動移除主螢幕捷徑。"</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"重設撥號路徑"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"允許應用程式在撥打電話期間查看撥出的電話號碼,並可選擇改撥其他號碼或中斷通話。"</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"接收簡訊 (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"允許應用程式接收和處理簡訊。這項設定可讓應用程式監控傳送至您裝置的訊息,或在您閱讀訊息前擅自刪除訊息。"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"接收簡訊 (MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"允許應用程式終止其他應用程式的背景處理程序。這項設定可能會導致其他應用程式停止執行。"</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"這個應用程式可顯示在其他應用程式上方"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"這個應用程式可顯示在其他應用程式上方或畫面中的其他位置。你可能會無法照常使用應用程式,且其他應用程式的顯示方式可能會受到影響。"</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"在背景執行"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"這個應用程式可在背景執行,這樣可能導致耗電速度加快。"</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"在背景使用行動數據連線"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"這個應用程式可在背景使用行動數據連線,這樣可能導致數據用量增加。"</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"一律執行應用程式"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"允許應用程式的部分內容常駐在記憶體中。這項設定可能會限制其他應用程式可用的記憶體,並拖慢平板電腦運作速度。"</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"允許應用程式的部分內容常駐在記憶體中。這項設定可能會限制其他應用程式可用的記憶體,造成電視的運作速度變慢。"</string>
@@ -515,8 +541,8 @@
     <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"允許應用程式繫結至條件提供者服務的頂層介面 (一般應用程式並不需要)。"</string>
     <string name="permlab_bindDreamService" msgid="4153646965978563462">"繫結至 Dream 服務"</string>
     <string name="permdesc_bindDreamService" msgid="7325825272223347863">"允許應用程式繫結至 Dream 服務的頂層介面 (一般應用程式不需使用)。"</string>
-    <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"叫用行動通訊業者提供的設定應用程式"</string>
-    <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"允許應用程式叫用行動通訊業者提供的設定應用程式 (一般應用程式並不需要)。"</string>
+    <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"叫用電信業者提供的設定應用程式"</string>
+    <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"允許應用程式叫用電信業者提供的設定應用程式 (一般應用程式並不需要)。"</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"監聽網路狀況觀察資訊"</string>
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"允許應用程式監聽網路狀況觀察資訊 (一般應用程式並不需要)。"</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"變更輸入裝置校正設定"</string>
@@ -527,10 +553,10 @@
     <string name="permdesc_handoverStatus" msgid="4788144087245714948">"允許應用程式接收 Android Beam 目前傳輸的資訊"</string>
     <string name="permlab_removeDrmCertificates" msgid="7044888287209892751">"移除 DRM 憑證"</string>
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"允許應用程式移除 DRM 憑證 (一般應用程式並不需要)。"</string>
-    <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"與行動通訊業者簡訊服務繫結"</string>
-    <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"允許應用程式與行動通訊業者簡訊服務的頂層介面繫結 (一般應用程式並不需要)。"</string>
-    <string name="permlab_bindCarrierServices" msgid="3233108656245526783">"與行動通訊業者服務繫結"</string>
-    <string name="permdesc_bindCarrierServices" msgid="1391552602551084192">"允許應用程式繫結至行動通訊業者服務 (一般應用程式並不需要)。"</string>
+    <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"與電信業者簡訊服務繫結"</string>
+    <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"允許應用程式與電信業者簡訊服務的頂層介面繫結 (一般應用程式並不需要)。"</string>
+    <string name="permlab_bindCarrierServices" msgid="3233108656245526783">"與電信業者服務繫結"</string>
+    <string name="permdesc_bindCarrierServices" msgid="1391552602551084192">"允許應用程式繫結至電信業者服務 (一般應用程式並不需要)。"</string>
     <string name="permlab_access_notification_policy" msgid="4247510821662059671">"存取「零打擾」模式"</string>
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"允許應用程式讀取及寫入「零打擾」設定。"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"設定密碼規則"</string>
@@ -960,11 +986,9 @@
     <string name="inputMethod" msgid="1653630062304567879">"輸入法"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"文字動作"</string>
     <string name="email" msgid="4560673117055050403">"電子郵件"</string>
-    <!-- no translation found for dial (4204975095406423102) -->
-    <skip />
+    <string name="dial" msgid="4204975095406423102">"電話"</string>
     <string name="map" msgid="5441053548030107189">"地圖"</string>
-    <!-- no translation found for browse (6079864138582486027) -->
-    <skip />
+    <string name="browse" msgid="6079864138582486027">"瀏覽"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"儲存空間即將用盡"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"部分系統功能可能無法運作"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"系統儲存空間不足。請確定您已釋出 250MB 的可用空間,然後重新啟動。"</string>
@@ -1136,7 +1160,7 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM 卡已新增"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"請重新啟動裝置,才能使用行動網路。"</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"重新啟動"</string>
-    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"要讓新的 SIM 卡正常運作,您必須先安裝行動通訊業者提供的應用程式,並開啟該應用程式。"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"要讓新的 SIM 卡正常運作,您必須先安裝電信業者提供的應用程式,並開啟該應用程式。"</string>
     <string name="carrier_app_dialog_button" msgid="7900235513678617329">"取得應用程式"</string>
     <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"暫時不要"</string>
     <string name="carrier_app_notification_title" msgid="8921767385872554621">"已插入新的 SIM 卡"</string>
@@ -1173,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"輕觸即可選取語言和版面配置"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"<xliff:g id="NAME">%s</xliff:g>會在其他應用程式上層繪製內容"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"<xliff:g id="NAME">%s</xliff:g>應用程式目前顯示在最上層。"</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"這個應用程式的某些部分會一直保持顯示。如果這項功能未正常運作,請將它關閉。"</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"關閉"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"正在準備「<xliff:g id="NAME">%s</xliff:g>」"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"正在檢查錯誤"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"偵測到新的「<xliff:g id="NAME">%s</xliff:g>」"</string>
@@ -1327,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"與「<xliff:g id="APPLICATION_NAME">%s</xliff:g>」分享"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"滑動控制。持續輕觸。"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"滑動即可解鎖。"</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"連接耳機即可聽取系統朗讀密碼按鍵。"</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"點。"</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"瀏覽首頁"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"向上瀏覽"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"更多選項"</string>
@@ -1412,7 +1438,7 @@
     <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"輸入 SIM PIN"</string>
     <string name="kg_pin_instructions" msgid="2377242233495111557">"輸入 PIN"</string>
     <string name="kg_password_instructions" msgid="5753646556186936819">"輸入密碼"</string>
-    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM 卡已遭停用,必須輸入 PUK 碼才能繼續使用。詳情請洽您的行動通訊業者。"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM 卡已遭停用,必須輸入 PUK 碼才能繼續使用。詳情請洽您的電信業者。"</string>
     <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"輸入所需的 PIN 碼"</string>
     <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"確認所需的 PIN 碼"</string>
     <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"正在解除 SIM 卡鎖定..."</string>
@@ -1712,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"輸入時間"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"切換至文字輸入模式來輸入時間。"</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"切換至時鐘模式來輸入時間。"</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"要儲存到「<xliff:g id="LABEL">%1$s</xliff:g>」嗎?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"要將<xliff:g id="TYPE">%1$s</xliff:g>儲存到「<xliff:g id="LABEL">%2$s</xliff:g>」嗎?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"儲存"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"不用了,謝謝"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"密碼"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"地址"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"信用卡"</string>
 </resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 387f5ef..692d4f3 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -244,6 +244,32 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Okuqukethwe kufihliwe"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Okuqukethwe kufihlwe inqubomgomo"</string>
+    <!-- no translation found for notification_channel_virtual_keyboard (6969925135507955575) -->
+    <skip />
+    <!-- no translation found for notification_channel_physical_keyboard (7297661826966861459) -->
+    <skip />
+    <string name="notification_channel_security" msgid="7345516133431326347">"Ukuphepha"</string>
+    <!-- no translation found for notification_channel_car_mode (3553380307619874564) -->
+    <skip />
+    <!-- no translation found for notification_channel_account (7577959168463122027) -->
+    <skip />
+    <!-- no translation found for notification_channel_developer (7579606426860206060) -->
+    <skip />
+    <!-- no translation found for notification_channel_updates (4794517569035110397) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_status (5025648583129035447) -->
+    <skip />
+    <!-- no translation found for notification_channel_network_alerts (2895141221414156525) -->
+    <skip />
+    <!-- no translation found for notification_channel_vpn (8330103431055860618) -->
+    <skip />
+    <!-- no translation found for notification_channel_device_admin (1568154104368069249) -->
+    <skip />
+    <string name="notification_channel_alerts" msgid="4496839309318519037">"Izexwayiso"</string>
+    <!-- no translation found for notification_channel_retail_mode (6088920674914038779) -->
+    <skip />
+    <!-- no translation found for notification_channel_usb (9006850475328924681) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Imodi ephephile"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Uhlelo lwe-Android"</string>
     <string name="user_owner_label" msgid="1119010402169916617">"Shintshela komuntu siqu"</string>
@@ -292,6 +318,10 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Ivumela uhlelo lokusebenza ukususa izinqamuleli zesikrini sasekhaya ngaphandle kokungenela komsebenzisi."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"thumela amakholi aphumayo kabusha"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Ivumela uhlelo lokusebenza ukubona inombolo eshayelwayo ngesikhathi sekholi ephumayo ngenketho yokuqondisa kabusha ikholi kwinombolo ehlukile noma ukuyekisa ikholi yonke."</string>
+    <!-- no translation found for permlab_answerPhoneCalls (4077162841226223337) -->
+    <skip />
+    <!-- no translation found for permdesc_answerPhoneCalls (2901889867993572266) -->
+    <skip />
     <string name="permlab_receiveSms" msgid="8673471768947895082">"thola imiyalezo ebhaliwe (i-SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Ivumela uhlelo lokusebenza ukuthola nokucubungula imilayezo ye-SMS. Loku kuchaza ukuthi uhlelo lokusebenza lungangamela noma lesuse imilayezo ethunyelwe kudivayisi yakho ngaphandle kokukubonisa yona."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"thola imiyalezo ebhaliwe (i-MMS)"</string>
@@ -320,14 +350,10 @@
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Ivumela uhelo lokusebenza ukuqeda izinqubo zangokwasemuva zezinhlelo zokusebenza. Lokhu kungababangela ezinye izinhlelo zokusebenza ukuyeka ukusebenza."</string>
     <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Lolu hlelo lokusebenza lungabonakala phezu kwezinhlelo zokusebenza"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Lolu hlelo lokusebenza lungabonakala phezu kwezinye izinhlelo zokusebenza noma ezinye izingxenye zesikrini. Lokhu kungaphazamisana nokusebenza okuvamile kohlelo lokusebenza futhi kushintshe indlela ezinye izinhlelo zokusebenza zibonakala ngakhona."</string>
-    <!-- no translation found for permlab_runInBackground (7365290743781858803) -->
-    <skip />
-    <!-- no translation found for permdesc_runInBackground (7370142232209999824) -->
-    <skip />
-    <!-- no translation found for permlab_useDataInBackground (8694951340794341809) -->
-    <skip />
-    <!-- no translation found for permdesc_useDataInBackground (6049514223791806027) -->
-    <skip />
+    <string name="permlab_runInBackground" msgid="7365290743781858803">"isebenza ngasemuva"</string>
+    <string name="permdesc_runInBackground" msgid="7370142232209999824">"Lolu hlelo lokusebenza lungaqalisa ngasemuva. Lokhu kungaqeda ibhethri lakho ngokushesha."</string>
+    <string name="permlab_useDataInBackground" msgid="8694951340794341809">"sebenzisa idatha ngasemuva"</string>
+    <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Lolu hlelo lokusebenza lingasebenzisa idatha ngasemuva. Lokhu kungabangela ukusetshenziswa kwedatha okwengeziwe."</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"yenza uhlelo lokusebenza ukuthi ihlale isebenza"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Ivumela uhlelo kusebenza ukwenza izingxenye yazo ezicindezelayo kumemori. Lokhu kungakhawulela imemori ekhona kwezinye izinhlelo zokusebenza ukwenza ukuthi ithebhulethi ingasheshi."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Ivumela uhlelo lokusebenza ukwenza izingxenye zalo ziqhubeke kumemori. Lokhu kungakhawulela imemori etholakala kwezinye izinhlelo zokusebenza ezenza i-TV ihambe kancane."</string>
@@ -1171,6 +1197,10 @@
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Thepha ukuze ukhethe ulimi nesakhiwo"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="alert_windows_notification_channel_name" msgid="7443890103456396837">"I-<xliff:g id="NAME">%s</xliff:g> yokudweba ngaphezu kwezinye izinhlelo zokusebenza"</string>
+    <string name="alert_windows_notification_title" msgid="5399998516035621282">"Uhlelo lokusebenza lwe-<xliff:g id="NAME">%s</xliff:g> liboniswa ngaphezulu."</string>
+    <string name="alert_windows_notification_message" msgid="2456738662997073459">"Izingxenye zalolu hlelo lokusebenza zingahlala zibonakala ngazo zonke izikhathi. Uma lesi sici singasebenzi ngokufanelekile, sivale."</string>
+    <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"VALA"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Ilungiselela i-<xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Ihlolela amaphutha"</string>
     <string name="ext_media_new_notification_message" msgid="7589986898808506239">"I-<xliff:g id="NAME">%s</xliff:g> entsha itholiwe"</string>
@@ -1325,8 +1355,6 @@
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Yabelana no <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Ihaambis isibambo. Thinta &amp; ubambe."</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Swayipha ukuze uvule."</string>
-    <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Plaka ku-headset ukuze uzwe okhiye bephasiwedi ezindlebeni zakho bezwakala kakhulu."</string>
-    <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Icashazi."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Zulazulela ekhaya"</string>
     <string name="action_bar_up_description" msgid="2237496562952152589">"Zulazulela phezulu"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Izinketho ezingaphezulu"</string>
@@ -1710,4 +1738,11 @@
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Thayipha isikhathi"</string>
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Shintshela kumodi yokufaka umbhalo ngokufaka isikhathi."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Shintshela kumodi yewashi ngokufakwa kwesikhathi."</string>
+    <string name="autofill_save_title" msgid="7081244500504163245">"Londoloza ku-<xliff:g id="LABEL">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Londoloza i-<xliff:g id="TYPE">%1$s</xliff:g> ku-<xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_yes" msgid="6398026094049005921">"Londoloza"</string>
+    <string name="autofill_save_no" msgid="2625132258725581787">"Cha ngiyabonga"</string>
+    <string name="autofill_save_type_password" msgid="5288448918465971568">"iphasiwedi"</string>
+    <string name="autofill_save_type_address" msgid="4936707762193009542">"ikheli"</string>
+    <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"ikhadi lesikweletu"</string>
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 958cacf..b3cb2c7 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -66,6 +66,9 @@
         <attr name="primaryContentAlpha" format="float" />
         <!-- The alpha applied to the foreground color to create the secondary text color. -->
         <attr name="secondaryContentAlpha" format="float" />
+        <!-- Color used for error states and things that need to be drawn to
+             the users attention.. -->
+        <attr name="colorError" format="reference|color" />
         <!-- Default background dim amount when a menu, dialog, or something similar pops up. -->
         <attr name="backgroundDimAmount" format="float" />
         <!-- Control whether dimming behind the window is enabled.  The default
@@ -135,9 +138,6 @@
         <!-- Color of list item text in alert dialogs. -->
         <attr name="textColorAlertDialogListItem" format="reference|color" />
 
-        <!-- Text color for errors. -->
-        <attr name="textColorError" format="reference|color" />
-
         <!-- Search widget more corpus result item background. -->
         <attr name="searchWidgetCorpusItemBackground" format="reference|color" />
 
@@ -804,16 +804,20 @@
         <!-- Action bar styles   -->
         <!-- =================== -->
         <eat-comment />
-        <!-- Default style for tabs within an action bar -->
+        <!-- Default style for tabs within an action bar. -->
         <attr name="actionBarTabStyle" format="reference" />
+        <!-- Reference to a style for the Action Bar Tab Bar. -->
         <attr name="actionBarTabBarStyle" format="reference" />
+        <!-- Reference to a style for the Action Bar Tab text. -->
         <attr name="actionBarTabTextStyle" format="reference" />
+        <!-- Reference to a style for Action Bar overflow buttons. -->
         <attr name="actionOverflowButtonStyle" format="reference" />
+        <!-- Reference to a style for the Action Bar menu. -->
         <attr name="actionOverflowMenuStyle" format="reference" />
         <!-- Reference to a theme that should be used to inflate popups
              shown by widgets in the action bar. -->
         <attr name="actionBarPopupTheme" format="reference" />
-        <!-- Reference to a style for the Action Bar -->
+        <!-- Reference to a style for the Action Bar. -->
         <attr name="actionBarStyle" format="reference" />
         <!-- Reference to a style for the split Action Bar. This style
              controls the split component that holds the menu/action
@@ -851,28 +855,30 @@
         <!-- Action mode styles  -->
         <!-- =================== -->
         <eat-comment />
+        <!-- Reference to a style for the Action Mode. -->
         <attr name="actionModeStyle" format="reference" />
+        <!-- Reference to a style for the Action Mode close button. -->
         <attr name="actionModeCloseButtonStyle" format="reference" />
-        <!-- Background drawable to use for action mode UI -->
+        <!-- Background drawable to use for action mode UI. -->
         <attr name="actionModeBackground" format="reference" />
-        <!-- Background drawable to use for action mode UI in the lower split bar -->
+        <!-- Background drawable to use for action mode UI in the lower split bar. -->
         <attr name="actionModeSplitBackground" format="reference" />
-        <!-- Drawable to use for the close action mode button -->
+        <!-- Drawable to use for the close action mode button. -->
         <attr name="actionModeCloseDrawable" format="reference" />
 
-        <!-- Drawable to use for the Cut action button in Contextual Action Bar -->
+        <!-- Drawable to use for the Cut action button in Contextual Action Bar. -->
         <attr name="actionModeCutDrawable" format="reference" />
-        <!-- Drawable to use for the Copy action button in Contextual Action Bar -->
+        <!-- Drawable to use for the Copy action button in Contextual Action Bar. -->
         <attr name="actionModeCopyDrawable" format="reference" />
-        <!-- Drawable to use for the Paste action button in Contextual Action Bar -->
+        <!-- Drawable to use for the Paste action button in Contextual Action Bar. -->
         <attr name="actionModePasteDrawable" format="reference" />
-        <!-- Drawable to use for the Select all action button in Contextual Action Bar -->
+        <!-- Drawable to use for the Select all action button in Contextual Action Bar. -->
         <attr name="actionModeSelectAllDrawable" format="reference" />
-        <!-- Drawable to use for the Share action button in WebView selection action modes -->
+        <!-- Drawable to use for the Share action button in WebView selection action modes. -->
         <attr name="actionModeShareDrawable" format="reference" />
-        <!-- Drawable to use for the Find action button in WebView selection action modes -->
+        <!-- Drawable to use for the Find action button in WebView selection action modes. -->
         <attr name="actionModeFindDrawable" format="reference" />
-        <!-- Drawable to use for the Web Search action button in WebView selection action modes -->
+        <!-- Drawable to use for the Web Search action button in WebView selection action modes. -->
         <attr name="actionModeWebSearchDrawable" format="reference" />
 
         <!-- PopupWindow style to use for action modes when showing as a window overlay. -->
@@ -969,7 +975,7 @@
 
         <!-- Theme to use for alert dialogs spawned from this theme. -->
         <attr name="alertDialogTheme" format="reference" />
-        <!-- Icon drawable to use for alerts -->
+        <!-- Icon drawable to use for alerts. -->
         <attr name="alertDialogIcon" format="reference" />
 
         <!-- Theme to use for presentations spawned from this theme. -->
@@ -981,19 +987,19 @@
         <!-- Drawable to use for generic horizontal dividers. -->
         <attr name="dividerHorizontal" format="reference" />
 
-        <!-- Style for button bars -->
+        <!-- Style for button bars. -->
         <attr name="buttonBarStyle" format="reference" />
 
-        <!-- Style for buttons within button bars -->
+        <!-- Style for buttons within button bars. -->
         <attr name="buttonBarButtonStyle" format="reference" />
 
-        <!-- Style for the "positive" buttons within button bars -->
+        <!-- Style for the "positive" buttons within button bars. -->
         <attr name="buttonBarPositiveButtonStyle" format="reference" />
 
-        <!-- Style for the "negative" buttons within button bars -->
+        <!-- Style for the "negative" buttons within button bars. -->
         <attr name="buttonBarNegativeButtonStyle" format="reference" />
 
-        <!-- Style for the "neutral" buttons within button bars -->
+        <!-- Style for the "neutral" buttons within button bars. -->
         <attr name="buttonBarNeutralButtonStyle" format="reference" />
 
         <!-- Style for the search query widget. -->
@@ -1012,19 +1018,19 @@
         <!-- Style for buttons without an explicit border, often used in groups. -->
         <attr name="borderlessButtonStyle" format="reference" />
 
-        <!-- Background to use for toasts -->
+        <!-- Background to use for toasts. -->
         <attr name="toastFrameBackground" format="reference" />
 
-        <!-- Background to use for tooltip popups -->
+        <!-- Background to use for tooltip popups. -->
         <attr name="tooltipFrameBackground" format="reference" />
 
-        <!-- Foreground color to use for tooltip popups -->
+        <!-- Foreground color to use for tooltip popups. -->
         <attr name="tooltipForegroundColor" format="reference|color" />
 
-        <!-- Background color to use for tooltip popups -->
+        <!-- Background color to use for tooltip popups. -->
         <attr name="tooltipBackgroundColor" format="reference|color" />
 
-        <!-- Theme to use for Search Dialogs -->
+        <!-- Theme to use for Search Dialogs. -->
         <attr name="searchDialogTheme" format="reference" />
 
         <!-- Specifies a drawable to use for the 'home as up' indicator. -->
@@ -2287,17 +2293,63 @@
             <enum name="auto" value="0x00000010" />
         </attr>
 
-        <!-- Controls the auto-fill behavior for this view -->
+        <!-- Controls the auto-fill behavior for this view. -->
         <attr name="autoFillMode">
-            <!-- Inherit the behavior from the parent. If there is no parent it is auto. -->
+            <!-- Inherit the behavior from the parent. If there is no parent it is auto. This is the
+                 default value for this attribute.-->
             <enum name="inherit" value="0" />
             <!-- Allows this view to automatically trigger an auto-fill request when it get focus.
                  -->
             <enum name="auto" value="1" />
-            <!-- The user has to manually force an auto-fill request for this view. -->
+            <!-- Do not trigger an auto-fill request when this view is focused. The user can still
+                 manually force an auto-fill request for this view. -->
             <enum name="manual" value="2" />
         </attr>
 
+        <!-- Describes the content of a view so that a auto-fill service can fill in the appropriate
+             data. Multiple flags can be combined to mean e.g. emailAddress or postalAddress. -->
+        <attr name="autoFillHint">
+            <!-- No hint. -->
+            <flag name="none" value="0" />
+            <!-- The view contains an email address. -->
+            <flag name="emailAddress" value="0x1" />
+            <!-- The view contains a real name. -->
+            <flag name="name" value="0x2" />
+            <!-- The view contains a user name. -->
+            <flag name="username" value="0x4" />
+            <!-- The view contains a password. -->
+            <flag name="password" value="0x8" />
+            <!-- The view contains a phone number. -->
+            <flag name="phone" value="0x10" />
+            <!-- The view contains a postal address. -->
+            <flag name="postalAddress" value="0x20" />
+            <!-- The view contains a postal code. -->
+            <flag name="postalCode" value="0x40" />
+            <!-- The view contains a credit card number. -->
+            <flag name="creditCardNumber" value="0x80" />
+            <!-- The view contains a credit card security code -->
+            <flag name="creditCardSecurityCode" value="0x100" />
+            <!-- The view contains a credit card expiration date -->
+            <flag name="creditCardExpirationDate" value="0x200" />
+            <!-- The view contains the month a credit card expires -->
+            <flag name="creditCardExpirationMonth" value="0x400" />
+            <!-- The view contains the year a credit card expires -->
+            <flag name="creditCardExpirationYear" value="0x800" />
+            <!-- The view contains the day a credit card expires -->
+            <flag name="creditCardExpirationDay" value="0x1000" />
+        </attr>
+
+        <!-- Hints the Android System whether the view node associated with this View should be
+             included in a view structure used for autofill purposes. -->
+        <attr name="importantForAutofill">
+            <!-- Let the Android System use its heuristics to determine if the view is important for autofill. -->
+            <flag name="auto" value="0" />
+            <!-- Hint the Android System that this view is important for autofill. -->
+            <flag name="yes" value="0x1" />
+            <!-- Hint the Android System that this view is *not* important for autofill. -->
+            <flag name="no" value="0x2" />
+        </attr>
+
         <!-- Boolean that controls whether a view can take focus while in touch mode.
              If this is true for a view, that view can gain focus when clicked on, and can keep
              focus if another view is clicked on that doesn't have this attribute set to true. -->
@@ -2338,13 +2390,13 @@
              to appear at the edge of the view, ignoring the padding, then you can
              use outsideOverlay or outsideInset.-->
         <attr name="scrollbarStyle">
-            <!-- Inside the padding and overlaid -->
+            <!-- Inside the padding and overlaid. -->
             <enum name="insideOverlay" value="0x0" />
-            <!-- Inside the padding and inset -->
+            <!-- Inside the padding and inset. -->
             <enum name="insideInset" value="0x01000000" />
-            <!-- Edge of the view and overlaid -->
+            <!-- Edge of the view and overlaid. -->
             <enum name="outsideOverlay" value="0x02000000" />
-            <!-- Edge of the view and inset -->
+            <!-- Edge of the view and inset. -->
             <enum name="outsideInset" value="0x03000000" />
         </attr>
 
@@ -2548,7 +2600,7 @@
              (completely opaque). -->
         <attr name="alpha" format="float" />
 
-        <!-- base z depth of the view -->
+        <!-- base z depth of the view. -->
         <attr name="elevation" format="dimension" />
 
         <!-- translation in x of the view. This value is added post-layout to the left
@@ -2617,19 +2669,19 @@
              to inherit, "locale" is used. "locale" falls back to "en-US". "ltr" is the direction
              used in "en-US". The default for this attribute is "inherit". -->
         <attr name="layoutDirection">
-            <!-- Left-to-Right -->
+            <!-- Left-to-Right. -->
             <enum name="ltr" value="0" />
-            <!-- Right-to-Left -->
+            <!-- Right-to-Left. -->
             <enum name="rtl" value="1" />
-            <!-- Inherit from parent -->
+            <!-- Inherit from parent. -->
             <enum name="inherit" value="2" />
-            <!-- Locale -->
+            <!-- Locale. -->
             <enum name="locale" value="3" />
         </attr>
 
         <!-- Defines the direction of the text. -->
          <attr name="textDirection" format="integer">
-            <!-- Default -->
+            <!-- Default. -->
             <enum name="inherit" value="0" />
             <!-- Default for the root view. The first strong directional character determines the
                  paragraph direction.  If there is no strong directional character, the paragraph
@@ -2655,23 +2707,23 @@
 
         <!-- Defines the alignment of the text. -->
         <attr name="textAlignment" format="integer">
-            <!-- Default -->
+            <!-- Default. -->
             <enum name="inherit" value="0" />
             <!-- Default for the root view. The gravity determines the alignment, ALIGN_NORMAL,
                 ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s
-                text direction -->
+                text direction. -->
             <enum name="gravity" value="1" />
-            <!-- Align to the start of the paragraph, e.g. ALIGN_NORMAL. -->
+            <!-- Align to the start of the paragraph, for example: ALIGN_NORMAL. -->
             <enum name="textStart" value="2" />
-            <!-- Align to the end of the paragraph, e.g. ALIGN_OPPOSITE. -->
+            <!-- Align to the end of the paragraph, for example: ALIGN_OPPOSITE. -->
             <enum name="textEnd" value="3" />
-            <!-- Center the paragraph, e.g. ALIGN_CENTER. -->
+            <!-- Center the paragraph, for example: ALIGN_CENTER. -->
             <enum name="center" value="4" />
             <!-- Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
                 layoutDirection is LTR, and ALIGN_RIGHT otherwise. -->
             <enum name="viewStart" value="5" />
             <!-- Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
-                layoutDirection is LTR, and ALIGN_LEFT otherwise -->
+                layoutDirection is LTR, and ALIGN_LEFT otherwise. -->
             <enum name="viewEnd" value="6" />
         </attr>
 
@@ -3148,19 +3200,19 @@
               If both layout_marginHorizontal and any of layout_marginLeft,
               layout_marginRight, layout_marginStart, and layout_marginEnd are
               also specified, the layout_marginHorizontal value will take precedence over the
-              edge-specific values. Also, layout_margin will always take precendent over
+              edge-specific values. Also, layout_margin will always take precedence over
               any of these values, including layout_marginHorizontal.
               This space is outside this view's bounds.
               Margin values should be positive.-->
         <attr name="layout_marginHorizontal" format="dimension"  />
-        <!--  Specifies extra space on the tyop and bottom sides of this view.
+        <!--  Specifies extra space on the top and bottom sides of this view.
               Specifying layout_marginVertical is equivalent to specifying
               layout_marginTop and layout_marginBottom with that same value.
               If both layout_marginVertical and either/both layout_marginTop and
               layout_marginBottom are also specified, the layout_marginVertical value
               will take precedence over the edge-specific values.
-              Also, layout_margin will always take precendent over
-              any of these values, including layout_marginHorizontal.
+              Also, layout_margin will always take precedence over
+              any of these values, including layout_marginVertical.
               This space is outside this view's bounds.
               Margin values should be positive.-->
         <attr name="layout_marginVertical" format="dimension"  />
@@ -3181,7 +3233,7 @@
              method should be considered an option as the default. -->
         <attr name="isDefault" format="boolean" />
         <!-- Set to true if this input method supports ways to switch to
-             a next input method (e.g. a globe key.). When this is true and
+             a next input method (for example, a globe key.). When this is true and
              InputMethodManager#shouldOfferSwitchingToNextInputMethod() returns true,
              the IME has to offer ways to invoke InputMethodManager#switchToNextInputMethod()
              accordingly.
@@ -3190,7 +3242,7 @@
              between IMEs and subtypes. -->
         <attr name="supportsSwitchingToNextInputMethod" format="boolean" />
         <!-- Set to true if this input method supports ways to dismiss the windows assigned to
-             the input method (e.g. a dismiss button rendered by the input method itself).  The
+             the input method (for example, a dismiss button rendered by the input method itself).  The
              System UI may optimize the UI by not showing system-level dismiss button if this
              value is true.
              <p> Must be a boolean value, either "true" or "false". The default value is "false".
@@ -3203,21 +3255,21 @@
         <attr name="supportsDismissingWindow" format="boolean" />
     </declare-styleable>
 
-    <!-- This is the subtype of InputMethod. Subtype can describe locales (e.g. en_US, fr_FR...)
-         and modes (e.g. voice, keyboard...), and is used for IME switch. This subtype allows
-         the system to call the specified subtype of the IME directly. -->
+    <!-- This is the subtype of InputMethod. Subtype can describe locales (for example, en_US and
+         fr_FR) and modes (for example, voice and keyboard), and is used for IME switch. This
+         subtype allows the system to call the specified subtype of the IME directly. -->
     <declare-styleable name="InputMethod_Subtype">
         <!-- The name of the subtype. -->
         <attr name="label" />
         <!-- The icon of the subtype. -->
         <attr name="icon" />
-        <!-- The locale of the subtype. This string should be a locale (e.g. en_US, fr_FR...)
+        <!-- The locale of the subtype. This string should be a locale (for example en_US and fr_FR)
              and will be passed to the IME when the framework calls the IME
              with the subtype. This is also used by the framework to know the supported locales
              of the IME.  -->
         <attr name="imeSubtypeLocale" format="string" />
-        <!-- The mode of the subtype. This string can be a mode (e.g. voice, keyboard...) and this
-             string will be passed to the IME when the framework calls the IME with the
+        <!-- The mode of the subtype. This string can be a mode (for example, voice and keyboard)
+             and this string will be passed to the IME when the framework calls the IME with the
              subtype.  {@link android.view.inputmethod.InputMethodSubtype#getLocale()} returns the
              value specified in this attribute.  -->
         <attr name="imeSubtypeMode" format="string" />
@@ -3264,12 +3316,13 @@
         <attr name="settingsActivity"/>
     </declare-styleable>
 
-    <!-- This is the subtype of the spell checker. Subtype can describe locales (e.g. en_US, fr_FR...) -->
+    <!-- This is the subtype of the spell checker. Subtype can describe locales (for example,
+             en_US and fr_FR). -->
     <declare-styleable name="SpellChecker_Subtype">
         <!-- The name of the subtype. -->
         <attr name="label" />
-        <!-- The locale of the subtype. This string should be a locale (e.g. en_US, fr_FR...)
-             This is also used by the framework to know the supported locales
+        <!-- The locale of the subtype. This string should be a locale (for example, en_US and
+             fr_FR). This is also used by the framework to know the supported locales
              of the spell checker. {@link android.view.textservice.SpellCheckerSubtype#getLocale()}
              returns the value specified in this attribute.  -->
         <attr name="subtypeLocale" format="string" />
@@ -3294,7 +3347,7 @@
          {@link android.accessibilityservice.AccessibilityService#SERVICE_META_DATA}
          meta-data entry. -->
     <declare-styleable name="AccessibilityService">
-        <!-- The event types this serivce would like to receive as specified in
+        <!-- The event types this service would like to receive as specified in
              {@link android.view.accessibility.AccessibilityEvent}. This setting
              can be changed at runtime by calling
              {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)
@@ -3353,11 +3406,11 @@
             <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPES_ALL_MASK} i.e. all events. -->
             <flag name="typeAllMask" value="0xffffffff" />
         </attr>
-        <!-- Comma separated package names from which this serivce would like to receive events (leave out for all packages).
+        <!-- Comma separated package names from which this service would like to receive events (leave out for all packages).
              {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)
              android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
         <attr name="packageNames" format="string" />
-        <!-- The feedback types this serivce provides as specified in
+        <!-- The feedback types this service provides as specified in
              {@link android.accessibilityservice.AccessibilityServiceInfo}. This setting
              can be changed at runtime by calling
              {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)
@@ -3377,7 +3430,7 @@
             <flag name="feedbackAllMask" value="0xffffffff" />
         </attr>
         <!-- The minimal period in milliseconds between two accessibility events of the same type
-             are sent to this serivce. This setting can be changed at runtime by calling
+             are sent to this service. This setting can be changed at runtime by calling
              {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)
              android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
         <attr name="notificationTimeout" format="integer" />
@@ -3387,25 +3440,25 @@
              {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)
              android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
         <attr name="accessibilityFlags">
-            <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#DEFAULT} -->
+            <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#DEFAULT}. -->
             <flag name="flagDefault" value="0x00000001" />
-            <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} -->
+            <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS}. -->
             <flag name="flagIncludeNotImportantViews" value="0x00000002" />
-            <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} -->
+            <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE}. -->
             <flag name="flagRequestTouchExplorationMode" value="0x00000004" />
-            <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY} -->
+            <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY}. -->
             <flag name="flagRequestEnhancedWebAccessibility" value="0x00000008" />
-            <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS} -->
+            <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS}. -->
             <flag name="flagReportViewIds" value="0x00000010" />
-            <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_REQUEST_FILTER_KEY_EVENTS} -->
+            <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_REQUEST_FILTER_KEY_EVENTS}. -->
             <flag name="flagRequestFilterKeyEvents" value="0x00000020" />
-            <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_RETRIEVE_INTERACTIVE_WINDOWS} -->
+            <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_RETRIEVE_INTERACTIVE_WINDOWS}. -->
             <flag name="flagRetrieveInteractiveWindows" value="0x00000040" />
-            <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_ENABLE_ACCESSIBILITY_VOLUME} -->
+            <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_ENABLE_ACCESSIBILITY_VOLUME}. -->
             <flag name="flagEnableAccessibilityVolume" value="0x00000080" />
-            <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_REQUEST_ACCESSIBILITY_BUTTON} -->
+            <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_REQUEST_ACCESSIBILITY_BUTTON}. -->
             <flag name="flagRequestAccessibilityButton" value="0x00000100" />
-            <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_CAPTURE_FINGERPRINT_GESTURES} -->
+            <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_CAPTURE_FINGERPRINT_GESTURES}. -->
             <flag name="flagCaptureFingerprintGestures" value="0x00000200" />
         </attr>
         <!-- Component name of an activity that allows the user to modify
@@ -3456,6 +3509,8 @@
         <attr name="canCaptureFingerprintGestures" format="boolean" />
         <!-- Short description of the accessibility service purpose or behavior.-->
         <attr name="description" />
+        <!-- Brief summary of the accessibility service purpose or behavior. -->
+        <attr name="summary" />
     </declare-styleable>
 
     <!-- Use <code>print-service</code> as the root tag of the XML resource that
@@ -3682,7 +3737,7 @@
     <declare-styleable name="CompoundButton">
         <!-- Indicates the initial checked state of this button. -->
         <attr name="checked" format="boolean" />
-        <!-- Drawable used for the button graphic (e.g. checkbox, radio button, etc). -->
+        <!-- Drawable used for the button graphic (for example, checkbox and radio button). -->
         <attr name="button" format="reference" />
         <!-- Tint to apply to the button graphic. -->
         <attr name="buttonTint" format="color" />
@@ -4105,11 +4160,11 @@
         <attr name="minHeight" format="dimension" />
         <attr name="maxHeight" />
         <attr name="interpolator" format="reference" />
-        <!-- Timeout between frames of animation in milliseconds
-             {@deprecated Not used by the framework.} -->
+        <!-- Timeout between frames of animation in milliseconds.
+             {@deprecated Not used by the framework}. -->
         <attr name="animationResolution" format="integer" />
         <!-- Defines if the associated drawables need to be mirrored when in RTL mode.
-             Default is false -->
+             Default is false. -->
         <attr name="mirrorForRtl" format="boolean" />
         <!-- Tint to apply to the progress indicator. -->
         <attr name="progressTint" format="color" />
@@ -4720,24 +4775,25 @@
             <enum name="full" value="2" />
         </attr>
         <!-- Specify the type of auto-size. Note that this feature is not supported by EditText,
-        works only for TextView -->
-        <attr name="autoSizeText" format="enum">
+        works only for TextView. -->
+        <attr name="autoSizeTextType" format="enum">
             <!-- No auto-sizing (default). -->
             <enum name="none" value="0" />
-            <!-- Uniform horizontal and vertical scaling. -->
+            <!-- Uniform horizontal and vertical text size scaling to fit within the
+            container. -->
             <enum name="uniform" value="1" />
         </attr>
-        <!-- Specify the auto-size step size if <code>autoSizeText</code> is set to
-        <code>xy</code>. The default is 1px. Overwrites
+        <!-- Specify the auto-size step size if <code>autoSizeTextType</code> is set to
+        <code>uniform</code>. The default is 1px. Overwrites
         <code>autoSizePresetSizes</code> if set. -->
         <attr name="autoSizeStepGranularity" format="dimension" />
-        <!-- Array of dimensions to be used in conjunction with
-        <code>autoSizeText</code> set to <code>xy</code>. Overwrites
+        <!-- Resource array of dimensions to be used in conjunction with
+        <code>autoSizeTextType</code> set to <code>uniform</code>. Overrides
         <code>autoSizeStepGranularity</code> if set. -->
         <attr name="autoSizePresetSizes"/>
-        <!-- The minimum text size constraint to be used when auto-sizing text -->
+        <!-- The minimum text size constraint to be used when auto-sizing text. -->
         <attr name="autoSizeMinTextSize" format="dimension" />
-        <!-- The maximum text size constraint to be used when auto-sizing text -->
+        <!-- The maximum text size constraint to be used when auto-sizing text. -->
         <attr name="autoSizeMaxTextSize" format="dimension" />
     </declare-styleable>
     <declare-styleable name="TextViewAppearance">
@@ -4839,7 +4895,7 @@
     </declare-styleable>
     <declare-styleable name="ViewFlipper">
         <attr name="flipInterval" format="integer" min="0" />
-        <!-- When true, automatically start animating -->
+        <!-- When true, automatically start animating. -->
         <attr name="autoStart" format="boolean" />
     </declare-styleable>
     <declare-styleable name="AdapterViewAnimator">
@@ -4856,7 +4912,7 @@
     </declare-styleable>
     <declare-styleable name="AdapterViewFlipper">
         <attr name="flipInterval" />
-        <!-- When true, automatically start animating -->
+        <!-- When true, automatically start animating. -->
         <attr name="autoStart" />
     </declare-styleable>
     <declare-styleable name="ViewSwitcher">
@@ -5623,7 +5679,7 @@
             <!-- Indicates that the layer is opaque and contains no transparent
                  nor translucent pixels. -->
             <enum name="opaque" value="-1" />
-            <!-- The layer is completely transparent (no pixel will be drawn.) -->
+            <!-- The layer is completely transparent (no pixel will be drawn). -->
             <enum name="transparent" value="-2" />
             <!-- The layer has translucent pixels. -->
             <enum name="translucent" value="-3" />
@@ -5648,10 +5704,10 @@
         <!-- Explicit right padding. Overrides child padding. -->
         <attr name="paddingRight" />
         <!-- Explicit start padding. Overrides child padding. Takes precedence
-             over absolute padding (e.g. left when layout direction is LTR). -->
+             over absolute padding (for example, left when layout direction is LTR). -->
         <attr name="paddingStart" />
         <!-- Explicit end padding. Overrides child padding. Takes precedence
-             over absolute padding (e.g. right when layout direction is LTR). -->
+             over absolute padding (for example, right when layout direction is LTR). -->
         <attr name="paddingEnd" />
     </declare-styleable>
 
@@ -5673,7 +5729,7 @@
         <attr name="end" format="dimension" />
         <!-- Width of the layer. Defaults to the layer's intrinsic width. -->
         <attr name="width" />
-        <!-- Height of the layer. Defaults to the layer's intrinsic height -->
+        <!-- Height of the layer. Defaults to the layer's intrinsic height. -->
         <attr name="height" />
         <!-- Gravity used to align the layer within its container. If no value
              is specified, the default behavior depends on whether an explicit
@@ -5855,8 +5911,8 @@
         <attr name="color" />
     </declare-styleable>
 
-    <!-- Drawable used to draw masked icons with foreground and background layers. -->
-    <declare-styleable name="MaskableIconDrawableLayer">
+    <!-- Drawable used to draw adaptive icons with foreground and background layers. -->
+    <declare-styleable name="AdaptiveIconDrawableLayer">
         <!-- The drawable to use for the layer. -->
         <attr name="drawable" />
      </declare-styleable>
@@ -5994,7 +6050,7 @@
         <attr name="viewportWidth" format="float"/>
         <!-- The height of the canvas the drawing is on. -->
         <attr name="viewportHeight" format="float"/>
-        <!-- The name of this vector drawable -->
+        <!-- The name of this vector drawable. -->
         <attr name="name" />
         <!-- The opacity of the whole vector drawable, as a value between 0
              (completely transparent) and 1 (completely opaque). -->
@@ -6015,64 +6071,64 @@
 
     <!-- Defines the group used in VectorDrawables. -->
     <declare-styleable name="VectorDrawableGroup">
-        <!-- The name of this group -->
+        <!-- The name of this group. -->
         <attr name="name" />
-        <!-- The amount to rotate the group -->
+        <!-- The amount to rotate the group. -->
         <attr name="rotation" />
-        <!-- The X coordinate of the center of rotation of a group -->
+        <!-- The X coordinate of the center of rotation of a group. -->
         <attr name="pivotX" />
-        <!-- The Y coordinate of the center of rotation of a group -->
+        <!-- The Y coordinate of the center of rotation of a group. -->
         <attr name="pivotY" />
-        <!-- The amount to translate the group on X coordinate -->
+        <!-- The amount to translate the group on X coordinate. -->
         <attr name="translateX" format="float"/>
-        <!-- The amount to translate the group on Y coordinate -->
+        <!-- The amount to translate the group on Y coordinate. -->
         <attr name="translateY" format="float"/>
-        <!-- The amount to scale the group on X coordinate -->
+        <!-- The amount to scale the group on X coordinate. -->
         <attr name="scaleX" />
-        <!-- The amount to scale the group on X coordinate -->
+        <!-- The amount to scale the group on X coordinate. -->
         <attr name="scaleY" />
     </declare-styleable>
 
     <!-- Defines the path used in VectorDrawables. -->
     <declare-styleable name="VectorDrawablePath">
-        <!-- The name of this path -->
+        <!-- The name of this path. -->
         <attr name="name" />
-        <!-- The width a path stroke -->
+        <!-- The width a path stroke. -->
         <attr name="strokeWidth" format="float" />
-        <!-- The color to stroke the path if not defined implies no stroke-->
+        <!-- The color to stroke the path if not defined implies no stroke. -->
         <attr name="strokeColor" format="color" />
         <!-- The opacity of a path stroke, as a value between 0 (completely transparent)
-             and 1 (completely opaque) -->
+             and 1 (completely opaque). -->
         <attr name="strokeAlpha" format="float" />
-        <!-- The color to fill the path if not defined implies no fill-->
+        <!-- The color to fill the path if not defined implies no fill. -->
         <attr name="fillColor" format="color" />
         <!-- The alpha of the path fill, as a value between 0 (completely transparent)
-             and 1 (completely opaque)-->
+             and 1 (completely opaque). -->
         <attr name="fillAlpha" format="float" />
-        <!-- The specification of the operations that define the path  -->
+        <!-- The specification of the operations that define the path. -->
         <attr name="pathData" format="string" />
-        <!-- The fraction of the path to trim from the start from 0 to 1 -->
+        <!-- The fraction of the path to trim from the start from 0 to 1. -->
         <attr name="trimPathStart" format="float" />
-        <!-- The fraction of the path to trim from the end from 0 to 1  -->
+        <!-- The fraction of the path to trim from the end from 0 to 1 . -->
         <attr name="trimPathEnd" format="float" />
-        <!-- Shift trim region (allows visible region to include the start and end) from 0 to 1  -->
+        <!-- Shift trim region (allows visible region to include the start and end) from 0 to 1. -->
         <attr name="trimPathOffset" format="float" />
-        <!-- sets the linecap for a stroked path -->
+        <!-- sets the linecap for a stroked path. -->
         <attr name="strokeLineCap" format="enum">
             <enum name="butt" value="0"/>
             <enum name="round" value="1"/>
             <enum name="square" value="2"/>
         </attr>
-        <!-- sets the lineJoin for a stroked path -->
+        <!-- sets the lineJoin for a stroked path. -->
         <attr name="strokeLineJoin" format="enum">
             <enum name="miter" value="0"/>
             <enum name="round" value="1"/>
             <enum name="bevel" value="2"/>
         </attr>
-        <!-- sets the Miter limit for a stroked path -->
+        <!-- sets the Miter limit for a stroked path. -->
         <attr name="strokeMiterLimit" format="float"/>
         <!-- sets the fillType for a path. It is the same as SVG's "fill-rule" properties.
-             For more details, see https://www.w3.org/TR/SVG/painting.html#FillRuleProperty -->
+             For more details, see https://www.w3.org/TR/SVG/painting.html#FillRuleProperty. -->
         <attr name="fillType" format="enum">
             <enum name="nonZero" value="0"/>
             <enum name="evenOdd" value="1"/>
@@ -6081,9 +6137,9 @@
 
     <!-- Defines the clip path used in VectorDrawables. -->
     <declare-styleable name="VectorDrawableClipPath">
-        <!-- The Name of this path -->
+        <!-- The Name of this path. -->
         <attr name="name" />
-        <!-- The specification of the operations that define the path  -->
+        <!-- The specification of the operations that define the path. -->
         <attr name="pathData"/>
     </declare-styleable>
 
@@ -6100,9 +6156,9 @@
 
     <!-- Defines the target used in the AnimatedVectorDrawable. -->
     <declare-styleable name="AnimatedVectorDrawableTarget">
-        <!-- The name of the target path, group or vector drawable -->
+        <!-- The name of the target path, group or vector drawable. -->
         <attr name="name" />
-        <!-- The animation for the target path, group or vector drawable -->
+        <!-- The animation for the target path, group or vector drawable. -->
         <attr name="animation" />
     </declare-styleable>
 
@@ -6281,13 +6337,13 @@
     </declare-styleable>
 
     <declare-styleable name="PathInterpolator">
-        <!-- The x coordinate of the first control point of the cubic Bezier -->
+        <!-- The x coordinate of the first control point of the cubic Bezier. -->
         <attr name="controlX1" format="float" />
-        <!-- The y coordinate of the first control point of the cubic Bezier -->
+        <!-- The y coordinate of the first control point of the cubic Bezier. -->
         <attr name="controlY1" format="float" />
-        <!-- The x coordinate of the second control point of the cubic Bezier -->
+        <!-- The x coordinate of the second control point of the cubic Bezier. -->
         <attr name="controlX2" format="float" />
-        <!-- The y coordinate of the second control point of the cubic Bezier -->
+        <!-- The y coordinate of the second control point of the cubic Bezier. -->
         <attr name="controlY2" format="float" />
         <!-- The control points defined as a path.
              When pathData is defined, then both of the control points of the
@@ -6525,7 +6581,7 @@
         <attr name="value" />
         <attr name="fraction" format="float" />
         <!-- Defines a per-interval interpolator for this keyframe. This interpolator will be used
-             to interpolate between this keyframe and the previous keyframe.-->
+             to interpolate between this keyframe and the previous keyframe. -->
         <attr name="interpolator" />
     </declare-styleable>
 
@@ -6541,7 +6597,7 @@
         <attr name="propertyXName" format="string"/>
         <!-- Name of the property being animated as the Y coordinate of the pathData. -->
         <attr name="propertyYName" format="string"/>
-        <!-- The path used to animate the properties in the ObjectAnimator -->
+        <!-- The path used to animate the properties in the ObjectAnimator. -->
         <attr name="pathData"/>
     </declare-styleable>
 
@@ -6786,8 +6842,8 @@
 
         <!-- If provided, this is the trigger indicating that the searchable activity
             provides suggestions as well.  The value must be a fully-qualified content provider
-            authority (e.g. "com.example.android.apis.SuggestionProvider") and should match the
-            "android:authorities" tag in your content provider's manifest entry.  <i>Optional
+            authority (for example, "com.example.android.apis.SuggestionProvider") and should match
+            the "android:authorities" tag in your content provider's manifest entry.  <i>Optional
             attribute.</i> -->
         <attr name="searchSuggestAuthority" format="string" />
         <!-- If provided, this will be inserted in the suggestions query Uri, after the authority
@@ -6995,12 +7051,12 @@
             <flag name="FUNCTION" value="0x8" />
         </attr>
 
-        <!-- The numeric shortcut key.  This is the shortcut when using a numeric (e.g., 12-key)
-             keyboard. -->
+        <!-- The numeric shortcut key.  This is the shortcut when using a numeric (for example,
+             12-key) keyboard. -->
         <attr name="numericShortcut" format="string" />
 
-        <!-- The numeric modifier key. This is the modifier when using a numeric (e.g., 12-key)
-             keyboard. The values should be kept in sync with KeyEvent -->
+        <!-- The numeric modifier key. This is the modifier when using a numeric (for example,
+             12-key) keyboard. The values should be kept in sync with KeyEvent -->
         <attr name="numericModifiers">
             <flag name="META" value="0x10000" />
             <flag name="CTRL" value="0x1000" />
@@ -7120,13 +7176,13 @@
     </declare-styleable>
 
     <!-- WARNING:  If adding attributes to Preference, make sure it does not conflict
-                   with a View's attributes.  Some subclasses (e.g., EditTextPreference)
+                   with a View's attributes.  Some subclasses (for example, EditTextPreference)
                    proxy all attributes to its EditText widget. -->
     <eat-comment />
 
     <!-- Base attributes available to Preference. -->
     <declare-styleable name="Preference">
-        <!-- The optional icon for the preference -->
+        <!-- The optional icon for the preference. -->
         <attr name="icon" />
         <!-- The key to store the Preference value. -->
         <attr name="key" format="string" />
@@ -7548,16 +7604,19 @@
         <!-- Reference to the wallpaper's thumbnail bitmap. -->
         <attr name="thumbnail" format="reference" />
 
-        <!-- Name of the author and/or source/collection of this component, e.g. Art Collection, Picasso. -->
+        <!-- Name of the author and/or source/collection of this component, for example,
+             Art Collection, Picasso. -->
         <attr name="author" format="reference" />
 
         <!-- Short description of the component's purpose or behavior. -->
         <attr name="description" />
 
-        <!-- Uri that specifies a link for further context of this wallpaper, e.g. http://www.picasso.org. -->
+        <!-- Uri that specifies a link for further context of this wallpaper, for example,
+             http://www.picasso.org. -->
         <attr name="contextUri" format="reference" />
 
-        <!-- Title of the uri that specifies a link for further context of this wallpaper, e.g. Explore collection. -->
+        <!-- Title of the uri that specifies a link for further context of this wallpaper,
+             for example, Explore collection. -->
         <attr name="contextDescription" format="reference" />
 
         <!-- Whether to show any metadata when previewing the wallpaper. If this value is
@@ -7702,7 +7761,7 @@
         <attr name="detailColumn" format="string" />
         <!-- Flag indicating that detail should be built from SocialProvider. -->
         <attr name="detailSocialSummary" format="boolean" />
-        <!-- Resource representing the term "All Contacts" (e.g. "All Friends" or
+        <!-- Resource representing the term "All Contacts" (for example, "All Friends" or
         "All connections"). Optional (Default is "All Contacts"). -->
         <attr name="allContactsName" format="string" />
     </declare-styleable>
@@ -7727,7 +7786,7 @@
         <attr name="targetDescriptions" format="reference" />
 
         <!-- Reference to an array resource that be used to announce the directions with targets around the circle.
-             {@deprecated Removed.}-->
+             {@deprecated Removed.} -->
         <attr name="directionDescriptions" format="reference" />
     </declare-styleable>
 
@@ -7827,7 +7886,7 @@
     <declare-styleable name="ActionBar">
         <!-- The type of navigation to use. -->
         <attr name="navigationMode">
-            <!-- Normal static title text -->
+            <!-- Normal static title text. -->
             <enum name="normal" value="0" />
             <!-- The action bar will use a selection list for navigation. -->
             <enum name="listMode" value="1" />
@@ -7844,9 +7903,9 @@
             <flag name="showCustom" value="0x10" />
             <flag name="disableHome" value="0x20" />
         </attr>
-        <!-- Specifies title text used for navigationMode="normal" -->
+        <!-- Specifies title text used for navigationMode="normal". -->
         <attr name="title" />
-        <!-- Specifies subtitle text used for navigationMode="normal" -->
+        <!-- Specifies subtitle text used for navigationMode="normal". -->
         <attr name="subtitle" format="string" />
         <!-- Specifies a style to use for title text. -->
         <attr name="titleTextStyle" format="reference" />
@@ -7876,7 +7935,7 @@
         <attr name="indeterminateProgressStyle" format="reference" />
         <!-- Specifies the horizontal padding on either end for an embedded progress bar. -->
         <attr name="progressBarPadding" format="dimension" />
-        <!-- Up navigation glyph -->
+        <!-- Up navigation glyph. -->
         <attr name="homeAsUpIndicator" />
         <!-- Specifies padding that should be applied to the left and right sides of
              system-provided items in the bar. -->
@@ -7901,7 +7960,7 @@
         <!-- Minimum inset for content views within a bar when actions from a menu
              are present. Only valid for some themes and configurations. -->
         <attr name="contentInsetEndWithActions" format="dimension" />
-        <!-- Elevation for the action bar itself -->
+        <!-- Elevation for the action bar itself. -->
         <attr name="elevation" />
         <!-- Reference to a theme that should be used to inflate popups
              shown by widgets in the action bar. -->
@@ -7941,23 +8000,23 @@
         <attr name="imeOptions" />
         <!-- The input type to set on the query text field. -->
         <attr name="inputType" />
-        <!-- Close button icon -->
+        <!-- Close button icon. -->
         <attr name="closeIcon" format="reference" />
-        <!-- Go button icon -->
+        <!-- Go button icon. -->
         <attr name="goIcon" format="reference" />
-        <!-- Search icon -->
+        <!-- Search icon. -->
         <attr name="searchIcon" format="reference" />
-        <!-- Search icon displayed as a text field hint -->
+        <!-- Search icon displayed as a text field hint. -->
         <attr name="searchHintIcon" format="reference" />
-        <!-- Voice button icon -->
+        <!-- Voice button icon. -->
         <attr name="voiceIcon" format="reference" />
-        <!-- Commit icon shown in the query suggestion row -->
+        <!-- Commit icon shown in the query suggestion row. -->
         <attr name="commitIcon" format="reference" />
-        <!-- Layout for query suggestion rows -->
+        <!-- Layout for query suggestion rows. -->
         <attr name="suggestionRowLayout" format="reference" />
-        <!-- Background for the section containing the search query -->
+        <!-- Background for the section containing the search query. -->
         <attr name="queryBackground" format="reference" />
-        <!-- Background for the section containing the action (e.g. voice search) -->
+        <!-- Background for the section containing the action (for example, voice search). -->
         <attr name="submitBackground" format="reference" />
     </declare-styleable>
 
@@ -8000,9 +8059,9 @@
         <attr name="thumbTextPadding" format="dimension" />
         <!-- TextAppearance style for text displayed on the switch thumb. -->
         <attr name="switchTextAppearance" format="reference" />
-        <!-- Minimum width for the switch component -->
+        <!-- Minimum width for the switch component. -->
         <attr name="switchMinWidth" format="dimension" />
-        <!-- Minimum space between the switch and caption text -->
+        <!-- Minimum space between the switch and caption text. -->
         <attr name="switchPadding" format="dimension" />
         <!-- Whether to split the track and leave a gap for the thumb drawable. -->
         <attr name="splitTrack" />
@@ -8011,53 +8070,53 @@
     </declare-styleable>
 
     <declare-styleable name="Pointer">
-        <!-- Reference to a pointer icon drawable with STYLE_ARROW -->
+        <!-- Reference to a pointer icon drawable with STYLE_ARROW. -->
         <attr name="pointerIconArrow" format="reference" />
-        <!-- Reference to a pointer icon drawable with STYLE_SPOT_HOVER -->
+        <!-- Reference to a pointer icon drawable with STYLE_SPOT_HOVER. -->
         <attr name="pointerIconSpotHover" format="reference" />
-        <!-- Reference to a pointer icon drawable with STYLE_SPOT_TOUCH -->
+        <!-- Reference to a pointer icon drawable with STYLE_SPOT_TOUCH. -->
         <attr name="pointerIconSpotTouch" format="reference" />
-        <!-- Reference to a pointer icon drawable with STYLE_SPOT_ANCHOR -->
+        <!-- Reference to a pointer icon drawable with STYLE_SPOT_ANCHOR. -->
         <attr name="pointerIconSpotAnchor" format="reference" />
-        <!-- Reference to a pointer drawable with STYLE_CONTEXT_MENU -->
+        <!-- Reference to a pointer drawable with STYLE_CONTEXT_MENU. -->
         <attr name="pointerIconContextMenu" format="reference"/>
-        <!-- Reference to a pointer drawable with STYLE_HAND -->
+        <!-- Reference to a pointer drawable with STYLE_HAND. -->
         <attr name="pointerIconHand" format="reference"/>
-        <!-- Reference to a pointer drawable with STYLE_HELP -->
+        <!-- Reference to a pointer drawable with STYLE_HELP. -->
         <attr name="pointerIconHelp" format="reference"/>
-        <!-- Reference to a pointer drawable with STYLE_WAIT -->
+        <!-- Reference to a pointer drawable with STYLE_WAIT. -->
         <attr name="pointerIconWait" format="reference"/>
-        <!-- Reference to a pointer drawable with STYLE_CELL -->
+        <!-- Reference to a pointer drawable with STYLE_CELL. -->
         <attr name="pointerIconCell" format="reference"/>
-        <!-- Reference to a pointer drawable with STYLE_CROSSHAIR -->
+        <!-- Reference to a pointer drawable with STYLE_CROSSHAIR. -->
         <attr name="pointerIconCrosshair" format="reference"/>
-        <!-- Reference to a pointer drawable with STYLE_TEXT -->
+        <!-- Reference to a pointer drawable with STYLE_TEXT. -->
         <attr name="pointerIconText" format="reference"/>
-        <!-- Reference to a pointer drawable with STYLE_VERTICAL_TEXT -->
+        <!-- Reference to a pointer drawable with STYLE_VERTICAL_TEXT. -->
         <attr name="pointerIconVerticalText" format="reference"/>
-        <!-- Reference to a pointer drawable with STYLE_ALIAS -->
+        <!-- Reference to a pointer drawable with STYLE_ALIAS. -->
         <attr name="pointerIconAlias" format="reference"/>
-        <!-- Reference to a pointer drawable with STYLE_COPY -->
+        <!-- Reference to a pointer drawable with STYLE_COPY. -->
         <attr name="pointerIconCopy" format="reference"/>
-        <!-- Reference to a pointer drawable with STYLE_NODROP -->
+        <!-- Reference to a pointer drawable with STYLE_NODROP. -->
         <attr name="pointerIconNodrop" format="reference"/>
-        <!-- Reference to a pointer drawable with STYLE_ALL_SCROLL -->
+        <!-- Reference to a pointer drawable with STYLE_ALL_SCROLL. -->
         <attr name="pointerIconAllScroll" format="reference"/>
-        <!-- Reference to a pointer drawable with STYLE_HORIZONTAL_DOUBLE_ARROW -->
+        <!-- Reference to a pointer drawable with STYLE_HORIZONTAL_DOUBLE_ARROW. -->
         <attr name="pointerIconHorizontalDoubleArrow" format="reference"/>
-        <!-- Reference to a pointer drawable with STYLE_VERTICAL_DOUBLE_ARROW -->
+        <!-- Reference to a pointer drawable with STYLE_VERTICAL_DOUBLE_ARROW. -->
         <attr name="pointerIconVerticalDoubleArrow" format="reference"/>
-        <!-- Reference to a pointer drawable with STYLE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW -->
+        <!-- Reference to a pointer drawable with STYLE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW. -->
         <attr name="pointerIconTopRightDiagonalDoubleArrow" format="reference"/>
-        <!-- Reference to a pointer drawable with STYLE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW -->
+        <!-- Reference to a pointer drawable with STYLE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW. -->
         <attr name="pointerIconTopLeftDiagonalDoubleArrow" format="reference"/>
-        <!-- Reference to a pointer drawable with STYLE_ZOOM_IN -->
+        <!-- Reference to a pointer drawable with STYLE_ZOOM_IN. -->
         <attr name="pointerIconZoomIn" format="reference"/>
-        <!-- Reference to a pointer drawable with STYLE_ZOOM_OUT -->
+        <!-- Reference to a pointer drawable with STYLE_ZOOM_OUT. -->
         <attr name="pointerIconZoomOut" format="reference"/>
-        <!-- Reference to a pointer drawable with STYLE_GRAB -->
+        <!-- Reference to a pointer drawable with STYLE_GRAB. -->
         <attr name="pointerIconGrab" format="reference"/>
-        <!-- Reference to a pointer drawable with STYLE_GRABBING -->
+        <!-- Reference to a pointer drawable with STYLE_GRABBING. -->
         <attr name="pointerIconGrabbing" format="reference"/>
     </declare-styleable>
 
@@ -8071,22 +8130,22 @@
     </declare-styleable>
 
     <declare-styleable name="Storage">
-        <!-- path to mount point for the storage -->
+        <!-- path to mount point for the storage. -->
         <attr name="mountPoint" format="string" />
-        <!-- user visible description of the storage -->
+        <!-- user visible description of the storage. -->
         <attr name="storageDescription" format="string" />
-        <!-- true if the storage is the primary external storage -->
+        <!-- true if the storage is the primary external storage. -->
         <attr name="primary" format="boolean" />
-        <!-- true if the storage is removable -->
+        <!-- true if the storage is removable. -->
         <attr name="removable" format="boolean" />
-        <!-- true if the storage is emulated via the FUSE sdcard daemon -->
+        <!-- true if the storage is emulated via the FUSE sdcard daemon. -->
         <attr name="emulated" format="boolean" />
         <!-- number of megabytes of storage MTP should reserve for free storage
-             (used for emulated storage that is shared with system's data partition) -->
+             (used for emulated storage that is shared with system's data partition). -->
         <attr name="mtpReserve" format="integer" />
-        <!-- true if the storage can be shared via USB mass storage -->
+        <!-- true if the storage can be shared via USB mass storage. -->
         <attr name="allowMassStorage" format="boolean" />
-        <!-- maximum file size for the volume in megabytes, zero or unspecified if it is unbounded -->
+        <!-- maximum file size for the volume in megabytes, zero or unspecified if it is unbounded. -->
         <attr name="maxFileSize" format="integer" />
     </declare-styleable>
 
@@ -8113,9 +8172,9 @@
     <declare-styleable name="SeekBarPreference">
         <attr name="layout" />
         <!-- Attribute indicating whether the slider within this preference can be adjusted, that is
-        pressing left/right keys when this preference is focused will move the slider accordingly (e.g.
-        inline adjustable preferences). False, if the slider within the preference is read-only and
-        cannot be adjusted. By default, the seekbar is adjustable. -->
+        pressing left/right keys when this preference is focused will move the slider accordingly
+        (for example, inline adjustable preferences). False, if the slider within the preference is
+        read-only and cannot be adjusted. By default, the seekbar is adjustable. -->
         <attr name="adjustable" format="boolean" />
         <!-- Flag indicating whether the TextView next to the seekbar that shows the current seekbar value will be
         displayed. If true, the view is VISIBLE; if false, the view will be GONE. By default, this view is VISIBLE. -->
@@ -8207,7 +8266,7 @@
     <declare-styleable name="PagedView">
         <!-- The space between adjacent pages of the PagedView. -->
         <attr name="pageSpacing" format="dimension" />
-        <!-- The padding for the scroll indicator area -->
+        <!-- The padding for the scroll indicator area. -->
         <attr name="scrollIndicatorPaddingLeft" format="dimension" />
         <attr name="scrollIndicatorPaddingRight" format="dimension" />
     </declare-styleable>
@@ -8472,7 +8531,7 @@
 
     <!-- Describes an item of a GradientColor. Minimally need 2 items to define the gradient
          Colors defined in <item> override the simple color attributes such as
-         "startColor / centerColor / endColor" are ignored -->
+         "startColor / centerColor / endColor" are ignored. -->
     <declare-styleable name="GradientColorItem">
         <!-- The offset (or ratio) of this current color item inside the gradient.
              The value is only meaningful when it is between 0 and 1. -->
@@ -8516,9 +8575,10 @@
         <attr name="fontWeight" format="integer" />
     </declare-styleable>
 
-    <!-- Attributes that are read when parsing a <fontfamily> tag, -->
+    <!-- Attributes that are read when parsing a <fontfamily> tag. -->
     <declare-styleable name="FontFamily">
         <attr name="fontProviderAuthority" format="string" />
+        <attr name="fontProviderPackage" format="string" />
         <attr name="fontProviderQuery" format="string" />
     </declare-styleable>
 
@@ -8531,4 +8591,6 @@
         <attr name="reverseLayout" format="boolean" />
         <attr name="stackFromEnd" format="boolean" />
     </declare-styleable>
+
+    <attr name="lockPatternStyle" format="reference" />
 </resources>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 76f4a76..bfe666e 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1534,6 +1534,14 @@
              of Android higher than the number given here, the permission will not
              be requested.  -->
         <attr name="maxSdkVersion" format="integer" />
+        <!-- Optional: the system must support this feature for the permission to be
+        requested.  If it doesn't support the feature, it will be as if the manifest didn't
+        request it at all. -->
+        <attr name="requiredFeature" format="string" />
+        <!-- Optional: the system must NOT support this feature for the permission to be
+        requested.  If it does support the feature, it will be as if the manifest didn't
+        request it at all. -->
+        <attr name="requiredNotFeature" format="string" />
     </declare-styleable>
 
     <!-- The <code>uses-configuration</code> tag specifies
@@ -1883,6 +1891,7 @@
         <attr name="path" />
         <attr name="pathPrefix" />
         <attr name="pathPattern" />
+        <attr name="pathAdvancedPattern" />
         <attr name="permission" />
         <attr name="readPermission" />
         <attr name="writePermission" />
@@ -2272,6 +2281,17 @@
              "\\\\".  This is basically the same as what you would need to
              write if constructing the string in Java code. -->
         <attr name="pathPattern" />
+        <!-- Specify a URI path that matches an advanced pattern, as per
+             {@link android.content.IntentFilter#addDataPath
+             IntentFilter.addDataPath()} with
+             {@link android.os.PatternMatcher#PATTERN_ADVANCED_GLOB}.
+             Note that because '\' is used as an escape character when
+             reading the string from XML (before it is parsed as a pattern),
+             you will need to double-escape: for example a literal "*" would
+             be written as "\\*" and a literal "\" would be written as
+             "\\\\".  This is basically the same as what you would need to
+             write if constructing the string in Java code. -->
+        <attr name="pathAdvancedPattern" />
     </declare-styleable>
 
     <!-- Attributes that can be supplied in an AndroidManifest.xml
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index b28c6f2..6015ed5 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -75,8 +75,6 @@
     <drawable name="input_method_fullscreen_background">#fff9f9f9</drawable>
     <color name="input_method_navigation_guard">#ff000000</color>
 
-    <color name="system_error">#fff4511e</color> <!-- deep orange 600 -->
-
     <!-- For date picker widget -->
     <drawable name="selected_day_background">#ff0092f4</drawable>
 
@@ -88,7 +86,6 @@
     <color name="perms_dangerous_grp_color">#33b5e5</color>
     <color name="perms_dangerous_perm_color">#33b5e5</color>
     <color name="shadow">#cc222222</color>
-    <color name="perms_costs_money">#fff4511e</color>
 
     <!-- For search-related UIs -->
     <color name="search_url_text_normal">#7fa87f</color>
@@ -121,7 +118,6 @@
     <!-- LockPatternView -->
     <color name="lock_pattern_view_regular_color">#ffffffff</color>
     <color name="lock_pattern_view_success_color">#ffffffff</color>
-    <color name="lock_pattern_view_error_color">@color/system_error</color>
 
     <!-- FaceLock -->
     <color name="facelock_spotlight_mask">#CC000000</color>
@@ -156,7 +152,6 @@
     <color name="accessibility_focus_highlight">#bf39b500</color>
 
     <color name="system_notification_accent_color">#ff607D8B</color>
-    <color name="battery_saver_mode_color">#fff4511e</color><!-- deep orange 600 -->
 
     <!-- Default user icon colors -->
     <color name="user_icon_1">#ff00bcd4</color><!-- cyan 500 -->
diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml
index 0a24565..e0cc5b5 100644
--- a/core/res/res/values/colors_material.xml
+++ b/core/res/res/values/colors_material.xml
@@ -46,6 +46,7 @@
 
     <color name="button_material_dark">#ff5a595b</color>
     <color name="button_material_light">#ffd6d7d7</color>
+    <color name="error_color_material">#F4511E</color>
 
     <color name="switch_thumb_normal_material_dark">#ffbdbdbd</color>
     <color name="switch_thumb_normal_material_light">#fff1f1f1</color>
@@ -65,9 +66,6 @@
     <!-- 70% white -->
     <color name="secondary_text_default_material_dark">#b3ffffff</color>
 
-    <color name="error_text_material_light">@color/material_red_A700</color>
-    <color name="error_text_material_dark">@color/material_red_A100</color>
-
     <item name="hint_alpha_material_dark" format="float" type="dimen">0.50</item>
     <item name="hint_alpha_material_light" format="float" type="dimen">0.38</item>
 
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index fcb0e08..a3a0c83 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -239,6 +239,7 @@
         <item>"mobile,0,0,0,-1,true"</item>
         <item>"mobile_mms,2,0,2,60000,true"</item>
         <item>"mobile_supl,3,0,2,60000,true"</item>
+        <item>"mobile_dun,4,0,2,60000,true"</item>
         <item>"mobile_hipri,5,0,3,60000,true"</item>
         <item>"mobile_fota,10,0,2,60000,true"</item>
         <item>"mobile_ims,11,0,2,60000,true"</item>
@@ -1273,19 +1274,6 @@
          config_enableFusedLocationOverlay is false. -->
     <string name="config_fusedLocationProviderPackageName" translatable="false">com.android.location.fused</string>
 
-    <!-- A list of potential packages, in priority order, that may contain a
-         network recommendation provider. A network recommendation provider must:
-             * Be granted the SCORE_NETWORKS permission.
-             * Include a Service for the android.net.scoring.RECOMMEND_NETWORKS action
-               protected by the BIND_NETWORK_RECOMMENDATION_SERVICE permission.
-
-         This may be empty if network scoring and recommending isn't supported.
-         -->
-    <string-array name="config_networkRecommendationPackageNames" translatable="false">
-        <!-- The standard AOSP network recommendation provider -->
-        <item>com.android.networkrecommendation</item>
-    </string-array>
-
     <!-- The package name of the default network recommendation app.
          A network recommendation provider must:
              * Be granted the SCORE_NETWORKS permission.
@@ -1873,6 +1861,10 @@
     <!-- Amount of time in ms the user needs to press the relevant key to bring up the global actions dialog -->
     <integer name="config_globalActionsKeyTimeout">500</integer>
 
+    <!-- Default width of a vertical scrollbar and height of a horizontal scrollbar.
+         Takes effect only if the scrollbar drawables have no intrinsic size. -->
+    <dimen name="config_scrollbarSize">4dp</dimen>
+
     <!-- Distance that should be scrolled in response to a {@link MotionEvent#ACTION_SCROLL event}
          with an axis value of 1. -->
     <dimen name="config_scrollFactor">64dp</dimen>
@@ -2553,9 +2545,17 @@
          These values are in DPs and will be converted to pixel sizes internally. -->
     <string translatable="false" name="config_defaultPictureInPictureScreenEdgeInsets">16x16</string>
 
-    <!-- Max default size [WIDTHxHEIGHT] on screen for picture-in-picture windows to fit inside.
-         These values are in DPs and will be converted to pixel sizes internally. -->
-    <string translatable="false" name="config_defaultPictureInPictureSize">192x120</string>
+    <!-- The percentage of the screen width to use for the default width or height of
+         picture-in-picture windows. Regardless of the percent set here, calculated size will never
+         be smaller than @dimen/default_minimal_size_pip_resizable_task. -->
+    <item name="config_pictureInPictureDefaultSizePercent" format="float" type="dimen">0.23</item>
+
+    <!-- The default aspect ratio for picture-in-picture windows. -->
+    <item name="config_pictureInPictureDefaultAspectRatio" format="float" type="dimen">1.777778</item>
+
+    <!-- This is the limit for the max and min aspect ratio (1 / this value) at which the min size
+         will be used instead of an adaptive size based loosely on area. -->
+    <item name="config_pictureInPictureAspectRatioLimitForMinSize" format="float" type="dimen">1.777778</item>
 
     <!-- The default gravity for the picture-in-picture window.
          Currently, this maps to Gravity.BOTTOM | Gravity.RIGHT -->
@@ -2608,6 +2608,10 @@
     <!-- True if the device supports split screen as a form of multi-window. -->
     <bool name="config_supportsSplitScreenMultiWindow">true</bool>
 
+    <!-- True if the device has no home screen. That is a launcher activity
+         where the user can launch other applications from.  -->
+    <bool name="config_noHomeScreen">false</bool>
+
     <!-- True if the device requires AppWidgetService even if it does not have
          the PackageManager.FEATURE_APP_WIDGETS feature -->
     <bool name="config_enableAppWidgetService">false</bool>
@@ -2740,10 +2744,10 @@
     <!-- Flag indicates that whether non-system apps can be installed on internal storage. -->
     <bool name="config_allow3rdPartyAppOnInternal">true</bool>
 
-    <!-- Component name of the default cell broadcast receiver -->
-    <string name="config_defaultCellBroadcastReceiverComponent" translatable="false">com.android.cellbroadcastreceiver/.PrivilegedCellBroadcastReceiver</string>
+    <!-- Package name of the default cell broadcast receiver -->
+    <string name="config_defaultCellBroadcastReceiverPkg" translatable="false">com.android.cellbroadcastreceiver</string>
 
-    <!-- Specifies the path that is used by MaskableIconDrawable class to crop launcher icons. -->
+    <!-- Specifies the path that is used by AdaptiveIconDrawable class to crop launcher icons. -->
     <string name="config_icon_mask" translatable="false">"M50,0L100,0 100,100 0,100 0,0z"</string>
 
     <!-- The component name, flattened to a string, for the default accessibility service to be
@@ -2751,4 +2755,16 @@
          without explicit consent of the user. If no accessibility service with the specified name
          exists on the device, the accessibility shortcut will be disabled by default. -->
     <string name="config_defaultAccessibilityService" translatable="false"></string>
+
+    <!-- Flag indicates that whether escrow token API is enabled for TrustAgent -->
+    <!-- Warning: This API can be dangerous when not implemented properly. In particular,
+         escrow token must NOT be retrievable from device storage. In other words, either
+         escrow token is not stored on device or its ciphertext is stored on device while
+         the decryption key is not. Before enabling this feature, please ensure you've read
+         and followed the pertinent sections of the escrow tokens section of the CDD <link>-->
+    <!-- TODO(b/35230407) complete the link field -->
+    <bool name="config_allowEscrowTokenForTrustAgent">false</bool>
+
+    <!-- Colon separated list of package names that should be granted Notification Listener access -->
+    <string name="config_defaultListenerAccessPackages" translatable="false"></string>
 </resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 640e74d..d0127a3 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -459,6 +459,7 @@
 
     <!-- Floating toolbar dimensions -->
     <dimen name="floating_toolbar_height">48dp</dimen>
+    <dimen name="floating_toolbar_menu_image_width">24dp</dimen>
     <dimen name="floating_toolbar_menu_image_button_width">56dp</dimen>
     <dimen name="floating_toolbar_menu_image_button_vertical_padding">12dp</dimen>
     <dimen name="floating_toolbar_menu_button_side_padding">11dp</dimen>
@@ -485,6 +486,9 @@
     <!-- The default minimal size of a resizable task, in both dimensions. -->
     <dimen name="default_minimal_size_resizable_task">220dp</dimen>
 
+    <!-- The default minimal size of a PiP task, in both dimensions. -->
+    <dimen name="default_minimal_size_pip_resizable_task">108dp</dimen>
+
     <!-- Height of a task when in minimized mode from the top when launcher is resizable. -->
     <dimen name="task_height_of_minimized_mode">80dp</dimen>
 
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 78549b5..b664448 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2760,12 +2760,13 @@
        =============================================================== -->
     <eat-comment />
 
-    <public-group type="attr" first-id="0x01010531">
-        <public name="fontStyle" />
+    <public type="attr" name="visibleToInstantApps" id="0x01010531" />
+
+    <public-group type="attr" first-id="0x01010532">
         <public name="font" />
         <public name="fontWeight" />
         <public name="tooltipText" />
-        <public name="autoSizeText" />
+        <public name="autoSizeTextType" />
         <public name="autoSizeStepGranularity" />
         <public name="autoSizePresetSizes" />
         <public name="autoSizeMinTextSize" />
@@ -2775,12 +2776,12 @@
         <public name="layout_marginVertical" />
         <public name="paddingHorizontal" />
         <public name="paddingVertical" />
-        <public name="visibleToInstantApps" />
+        <public name="fontStyle" />
         <public name="keyboardNavigationCluster" />
         <public name="targetProcess" />
         <public name="nextClusterForward" />
         <public name="__removed1" />
-        <public name="textColorError" />
+        <public name="colorError" />
         <public name="focusedByDefault" />
         <public name="appCategory" />
         <public name="autoSizeMaxTextSize" />
@@ -2797,6 +2798,13 @@
         <public name="fontProviderAuthority" />
         <public name="fontProviderQuery" />
         <public name="autoFillMode" />
+        <public name="primaryContentAlpha" />
+        <public name="secondaryContentAlpha" />
+        <public name="requiredFeature" />
+        <public name="requiredNotFeature" />
+        <public name="autoFillHint" />
+        <public name="fontProviderPackage" />
+        <public name="importantForAutofill" />
     </public-group>
 
     <public-group type="style" first-id="0x010302e0">
@@ -2806,9 +2814,6 @@
         <public name="textAssist" />
     </public-group>
 
-    <public type="attr" name="primaryContentAlpha" />
-    <public type="attr" name="secondaryContentAlpha" />
-
 
   <!-- ===============================================================
        DO NOT ADD UN-GROUPED ITEMS HERE
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 8faa76c..bd8d572 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -587,6 +587,48 @@
     <!-- Text shown in place of notification contents when the notification is hidden by policy on a secure lockscreen -->
     <string name="notification_hidden_by_policy_text">Contents hidden by policy</string>
 
+    <!-- Text shown when viewing channel settings for notifications related to the virtual keyboard -->
+    <string name="notification_channel_virtual_keyboard">Virtual keyboard</string>
+
+    <!-- Text shown when viewing channel settings for notifications related to the hardware keyboard -->
+    <string name="notification_channel_physical_keyboard">Physical keyboard</string>
+
+    <!-- Text shown when viewing channel settings for notifications related to security -->
+    <string name="notification_channel_security">Security</string>
+
+    <!-- Text shown when viewing channel settings for notifications related to car mode -->
+    <string name="notification_channel_car_mode">Car mode</string>
+
+    <!-- Text shown when viewing channel settings for notifications related to account status -->
+    <string name="notification_channel_account">Account status</string>
+
+    <!-- Text shown when viewing channel settings for notifications related to developers -->
+    <string name="notification_channel_developer">Developer messages</string>
+
+    <!-- Text shown when viewing channel settings for notifications related to system updates -->
+    <string name="notification_channel_updates">Updates</string>
+
+    <!-- Text shown when viewing channel settings for notifications related to network status -->
+    <string name="notification_channel_network_status">Network status</string>
+
+    <!-- Text shown when viewing channel settings for notifications related to network alerts -->
+    <string name="notification_channel_network_alerts">Network alerts</string>
+
+    <!-- Text shown when viewing channel settings for notifications related to vpn status -->
+    <string name="notification_channel_vpn">VPN status</string>
+
+    <!-- Text shown when viewing channel settings for notifications related to remote device administration -->
+    <string name="notification_channel_device_admin">Device administration</string>
+
+    <!-- Text shown when viewing channel settings for notifications related to important alerts -->
+    <string name="notification_channel_alerts">Alerts</string>
+
+    <!-- Text shown when viewing channel settings for notifications related to being in retail mode -->
+    <string name="notification_channel_retail_mode">Retail demo</string>
+
+    <!-- Text shown when viewing channel settings for notifications related to a usb connection -->
+    <string name="notification_channel_usb">USB connection</string>
+
     <!-- Displayed to the user to tell them that they have started up the phone in "safe mode" -->
     <string name="safeMode">Safe mode</string>
 
@@ -728,6 +770,11 @@
         the call to a different number or abort the call altogether.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_answerPhoneCalls">answer phone calls</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_answerPhoneCalls">Allows the app to answer an incoming phone call.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_receiveSms">receive text messages (SMS)</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_receiveSms">Allows the app to receive and process SMS
@@ -3116,6 +3163,21 @@
     <string name="fast_scroll_alphabet">\u0020ABCDEFGHIJKLMNOPQRSTUVWXYZ</string>
     <string name="fast_scroll_numeric_alphabet">\u00200123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ</string>
 
+    <!-- Alert windows notification strings -->
+    <skip />
+    <!-- Name of notification channel the system post notification to inform the use about apps
+         that are drawing ui on-top of other apps (alert-windows) [CHAR LIMIT=NONE] -->
+    <string name="alert_windows_notification_channel_name"><xliff:g id="name" example="Google Maps">%s</xliff:g> draw over other apps</string>
+    <!-- Notification title when an application is displaying ui on-top of other apps
+         [CHAR LIMIT=30] -->
+    <string name="alert_windows_notification_title"><xliff:g id="name" example="Google Maps">%s</xliff:g> app displaying on top.</string>
+    <!-- Notification body when an application is displaying ui on-top of other apps
+         [CHAR LIMIT=NONE] -->
+    <string name="alert_windows_notification_message">Parts of this app may remain visible at all times. If this feature isn\'t working correctly, turn it off.</string>
+    <!-- Notification action to turn-off app displaying on-top of other apps. [CHAR LIMIT=20] -->
+    <string name="alert_windows_notification_turn_off_action">TURN OFF</string>
+
+
     <!-- External media notification strings -->
     <skip />
 
@@ -3512,11 +3574,6 @@
     <!-- Description of the unlock handle in the Slide unlock screen for tablets. [CHAR LIMIT=NONE] -->
     <string name="description_target_unlock_tablet">Swipe to unlock.</string>
 
-    <!-- Announce that a headset is required to hear keyboard keys while typing a password. [CHAR LIMIT=NONE] -->
-    <string name="keyboard_headset_required_to_hear_password">Plug in a headset to hear password keys spoken.</string>
-    <!-- The value of a keyboard key announced when accessibility is enabled and no headsed is used. [CHAR LIMIT=NONE] -->
-    <string name="keyboard_password_character_no_headset">Dot.</string>
-
     <!-- Content description for the action bar "home" affordance. [CHAR LIMIT=NONE] -->
     <string name="action_bar_home_description">Navigate home</string>
     <!-- Content description for the action bar "up" affordance. [CHAR LIMIT=NONE] -->
@@ -4325,8 +4382,11 @@
     <!-- Content description of the work profile icon in the notification. -->
     <string name="notification_work_profile_content_description">Work profile</string>
 
-    <!-- Content description of the expand button icon in the notification.-->
-    <string name="expand_button_content_description">Expand button</string>
+    <!-- Content description of the expand button icon in the notification when collaped.-->
+    <string name="expand_button_content_description_collapsed">Expand</string>
+
+    <!-- Content description of the expand button icon in the notification when expanded.-->
+    <string name="expand_button_content_description_expanded">Collapse</string>
 
     <!-- Accessibility action description on the expand button. -->
     <string name="expand_action_accessibility">toggle expansion</string>
@@ -4500,4 +4560,22 @@
     <!-- Accessibility string used for describing the button in time picker that changes the dialog to circular clock mode. [CHAR LIMIT=NONE] -->
     <string name="time_picker_radial_mode_description">Switch to clock mode for the time input.</string>
 
+    <!-- Title for the auto-fill save dialog shown when the the contents of the activity can be saved
+         by an auto-fill service, but the service does not know what the activity represents [CHAR LIMIT=NONE] -->
+    <string name="autofill_save_title">Save to <xliff:g id="label" example="MyPass">%1$s</xliff:g>?</string>
+    <!-- Title for the auto-fill save dialog shown when the the contents of the activity can be saved
+         by an auto-fill service, and the service does knows what the activity represents (for example, credit card info) [CHAR LIMIT=NONE] -->
+    <string name="autofill_save_title_with_type">Save <xliff:g id="type" example="Credit Card">%1$s</xliff:g> to <xliff:g id="label" example="MyPass">%2$s</xliff:g>?</string>
+    <!-- Label for the auto-fill save button [CHAR LIMIT=NONE] -->
+    <string name="autofill_save_yes">Save</string>
+    <!-- Label for the auto-fill cancel button [CHAR LIMIT=NONE] -->
+    <string name="autofill_save_no">No thanks</string>
+
+    <!-- Label for the type of data being saved for auto-fill when it represent user credentials with a password [CHAR LIMIT=NONE] -->
+    <string name="autofill_save_type_password">password</string>
+    <!-- Label for the type of data being saved for auto-fill when it represent an address (street, city, etc.) [CHAR LIMIT=NONE] -->
+    <string name="autofill_save_type_address">address</string>
+    <!-- Label for the type of data being saved for auto-fill when it represents a credit card [CHAR LIMIT=NONE] -->
+    <string name="autofill_save_type_credit_card">credit card</string>
+
 </resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index faf451b..25873d2 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1475,4 +1475,10 @@
         <item name="padding">16dp</item>
     </style>
 
+    <style name="Widget.LockPatternView">
+        <item name="regularColor">@color/lock_pattern_view_regular_color</item>
+        <item name="errorColor">?attr/colorError</item>
+        <item name="successColor">@color/lock_pattern_view_success_color</item>
+    </style>
+
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 0d63a1e..32babab 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -312,12 +312,15 @@
   <java-symbol type="bool" name="config_freeformWindowManagement" />
   <java-symbol type="bool" name="config_supportsMultiWindow" />
   <java-symbol type="bool" name="config_supportsSplitScreenMultiWindow" />
+  <java-symbol type="bool" name="config_noHomeScreen" />
   <java-symbol type="bool" name="config_guestUserEphemeral" />
   <java-symbol type="bool" name="config_localDisplaysMirrorContent" />
   <java-symbol type="integer" name="config_defaultDisplayDefaultColorMode" />
   <java-symbol type="bool" name="config_enableAppWidgetService" />
   <java-symbol type="string" name="config_defaultPictureInPictureScreenEdgeInsets" />
-  <java-symbol type="string" name="config_defaultPictureInPictureSize" />
+  <java-symbol type="dimen" name="config_pictureInPictureDefaultSizePercent" />
+  <java-symbol type="dimen" name="config_pictureInPictureDefaultAspectRatio" />
+  <java-symbol type="dimen" name="config_pictureInPictureAspectRatioLimitForMinSize" />
   <java-symbol type="integer" name="config_defaultPictureInPictureGravity" />
   <java-symbol type="dimen" name="config_pictureInPictureMinAspectRatio" />
   <java-symbol type="dimen" name="config_pictureInPictureMaxAspectRatio" />
@@ -428,6 +431,7 @@
   <java-symbol type="dimen" name="config_viewConfigurationTouchSlop" />
   <java-symbol type="dimen" name="config_viewMinFlingVelocity" />
   <java-symbol type="dimen" name="config_viewMaxFlingVelocity" />
+  <java-symbol type="dimen" name="config_scrollbarSize" />
   <java-symbol type="dimen" name="config_scrollFactor" />
   <java-symbol type="dimen" name="default_app_widget_padding_bottom" />
   <java-symbol type="dimen" name="default_app_widget_padding_left" />
@@ -707,8 +711,6 @@
   <java-symbol type="string" name="js_dialog_before_unload" />
   <java-symbol type="string" name="js_dialog_title" />
   <java-symbol type="string" name="js_dialog_title_default" />
-  <java-symbol type="string" name="keyboard_headset_required_to_hear_password" />
-  <java-symbol type="string" name="keyboard_password_character_no_headset" />
   <java-symbol type="string" name="keyboardview_keycode_alt" />
   <java-symbol type="string" name="keyboardview_keycode_cancel" />
   <java-symbol type="string" name="keyboardview_keycode_delete" />
@@ -1195,7 +1197,6 @@
   <java-symbol type="drawable" name="btn_check_off" />
   <java-symbol type="color" name="lock_pattern_view_regular_color" />
   <java-symbol type="color" name="lock_pattern_view_success_color" />
-  <java-symbol type="color" name="lock_pattern_view_error_color" />
   <java-symbol type="dimen" name="lock_pattern_dot_line_width" />
   <java-symbol type="dimen" name="lock_pattern_dot_size" />
   <java-symbol type="dimen" name="lock_pattern_dot_size_activated" />
@@ -1778,6 +1779,7 @@
   <java-symbol type="id" name="replace_message" />
   <java-symbol type="fraction" name="config_dimBehindFadeDuration" />
   <java-symbol type="dimen" name="default_minimal_size_resizable_task" />
+  <java-symbol type="dimen" name="default_minimal_size_pip_resizable_task" />
   <java-symbol type="dimen" name="task_height_of_minimized_mode" />
   <java-symbol type="fraction" name="config_screenAutoBrightnessDozeScaleFactor" />
   <java-symbol type="fraction" name="config_autoBrightnessAdjustmentMaxGamma" />
@@ -2310,7 +2312,6 @@
   <java-symbol type="layout" name="select_dialog_singlechoice_material" />
   <java-symbol type="layout" name="select_dialog_multichoice_material" />
   <java-symbol type="array" name="no_ems_support_sim_operators" />
-  <java-symbol type="color" name="battery_saver_mode_color" />
   <java-symbol type="color" name="system_notification_accent_color" />
   <java-symbol type="dimen" name="text_handle_min_size" />
   <java-symbol type="id" name="transitionTransform" />
@@ -2398,15 +2399,13 @@
   <java-symbol type="drawable" name="ic_usb_48dp" />
 
   <!-- Floating toolbar -->
-  <java-symbol type="id" name="floating_toolbar_menu_item_image_button" />
+  <java-symbol type="id" name="floating_toolbar_menu_item_image" />
+  <java-symbol type="id" name="floating_toolbar_menu_item_text" />
   <java-symbol type="id" name="overflow" />
   <java-symbol type="layout" name="floating_popup_container" />
   <java-symbol type="layout" name="floating_popup_menu_button" />
   <java-symbol type="layout" name="floating_popup_open_overflow_button" />
   <java-symbol type="layout" name="floating_popup_close_overflow_button" />
-  <java-symbol type="layout" name="floating_popup_menu_image_button" />
-  <java-symbol type="layout" name="floating_popup_overflow_list_item" />
-  <java-symbol type="layout" name="floating_popup_overflow_image_list_item" />
   <java-symbol type="layout" name="floating_popup_overflow_button" />
   <java-symbol type="string" name="floating_toolbar_open_overflow_description" />
   <java-symbol type="string" name="floating_toolbar_close_overflow_description" />
@@ -2789,7 +2788,6 @@
   <java-symbol type="layout" name="notification_template_material_ambient" />
 
   <!-- Network Recommendation -->
-  <java-symbol type="array" name="config_networkRecommendationPackageNames" />
   <java-symbol type="string" name="config_defaultNetworkRecommendationProviderPackage" />
 
   <!-- Whether allow 3rd party apps on internal storage. -->
@@ -2800,7 +2798,7 @@
   <java-symbol type="drawable" name="lockscreen_selected" />
 
   <java-symbol type="string" name="notification_header_divider_symbol_with_spaces" />
-  <java-symbol type="string" name="config_defaultCellBroadcastReceiverComponent" />
+  <java-symbol type="string" name="config_defaultCellBroadcastReceiverPkg" />
 
   <java-symbol type="color" name="notification_primary_text_color_light" />
   <java-symbol type="color" name="notification_primary_text_color_dark" />
@@ -2840,14 +2838,27 @@
   <java-symbol type="dimen" name="autofill_fill_item_height" />
   <java-symbol type="dimen" name="autofill_fill_min_margin" />
   <java-symbol type="layout" name="autofill_save"/>
+  <java-symbol type="layout" name="autofill_dataset_picker"/>
   <java-symbol type="id" name="autofill_save_title" />
+  <java-symbol type="id" name="autofill_save_subtitle" />
   <java-symbol type="id" name="autofill_save_no" />
   <java-symbol type="id" name="autofill_save_yes" />
+  <java-symbol type="id" name="autofill_save_close" />
+  <java-symbol type="string" name="autofill_save_title" />
+  <java-symbol type="string" name="autofill_save_title_with_type" />
+  <java-symbol type="string" name="autofill_save_yes" />
+  <java-symbol type="string" name="autofill_save_no" />
+  <java-symbol type="string" name="autofill_save_type_password" />
+  <java-symbol type="string" name="autofill_save_type_address" />
+  <java-symbol type="string" name="autofill_save_type_credit_card" />
 
   <!-- Accessibility fingerprint gestures -->
   <java-symbol type="string" name="capability_title_canCaptureFingerprintGestures" />
   <java-symbol type="string" name="capability_desc_canCaptureFingerprintGestures" />
 
+  <!-- android.service.trust -->
+  <java-symbol type="bool" name="config_allowEscrowTokenForTrustAgent"/>
+
   <!-- Time picker -->
   <java-symbol type="id" name="toggle_mode"/>
   <java-symbol type="id" name="input_mode"/>
@@ -2867,4 +2878,36 @@
 
   <!-- resolver activity -->
   <java-symbol type="drawable" name="resolver_icon_placeholder" />
+
+  <!-- Alert windows notification -->
+  <java-symbol type="string" name="alert_windows_notification_channel_name" />
+  <java-symbol type="string" name="alert_windows_notification_title" />
+  <java-symbol type="string" name="alert_windows_notification_message" />
+  <java-symbol type="string" name="alert_windows_notification_turn_off_action" />
+  <java-symbol type="drawable" name="alert_window_layer" />
+  <java-symbol type="style" name="Widget.LockPatternView" />
+  <java-symbol type="attr" name="lockPatternStyle" />
+
+  <java-symbol type="string" name="expand_button_content_description_collapsed" />
+  <java-symbol type="string" name="expand_button_content_description_expanded" />
+
+  <!-- Colon separated list of package names that should be granted Notification Listener access -->
+  <java-symbol type="string" name="config_defaultListenerAccessPackages" />
+
+  <!-- system notification channels -->
+  <java-symbol type="string" name="notification_channel_virtual_keyboard" />
+  <java-symbol type="string" name="notification_channel_physical_keyboard" />
+  <java-symbol type="string" name="notification_channel_security" />
+  <java-symbol type="string" name="notification_channel_car_mode" />
+  <java-symbol type="string" name="notification_channel_account" />
+  <java-symbol type="string" name="notification_channel_developer" />
+  <java-symbol type="string" name="notification_channel_updates" />
+  <java-symbol type="string" name="notification_channel_network_status" />
+  <java-symbol type="string" name="notification_channel_network_alerts" />
+  <java-symbol type="string" name="notification_channel_vpn" />
+  <java-symbol type="string" name="notification_channel_device_admin" />
+  <java-symbol type="string" name="notification_channel_alerts" />
+  <java-symbol type="string" name="notification_channel_retail_mode" />
+  <java-symbol type="string" name="notification_channel_usb" />
+
 </resources>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index e357678..d100c63 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -63,6 +63,7 @@
         <item name="colorControlHighlight">@color/legacy_button_pressed</item>
         <item name="colorButtonNormal">@color/legacy_button_normal</item>
         <item name="colorEdgeEffect">?attr/colorPrimary</item>
+        <item name="colorError">@color/red</item>
 
         <item name="disabledAlpha">0.5</item>
         <item name="backgroundDimAmount">0.6</item>
@@ -93,7 +94,6 @@
         <item name="textColorLink">@color/link_text_dark</item>
         <item name="textColorLinkInverse">@color/link_text_light</item>
         <item name="textColorAlertDialogListItem">@color/primary_text_light_disable_only</item>
-        <item name="textColorError">@color/red</item>
 
         <item name="textAppearanceLarge">@style/TextAppearance.Large</item>
         <item name="textAppearanceMedium">@style/TextAppearance.Medium</item>
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index 5961cb0..7deff06 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -735,6 +735,10 @@
 
     <!-- DeviceDefault theme for a window that should look like the Settings app.  -->
     <style name="Theme.DeviceDefault.Settings" parent="Theme.Material.Settings">
+        <!-- action bar -->
+        <item name="actionBarTheme">@style/ThemeOverlay.DeviceDefault.ActionBar.Accent</item>
+        <item name="popupTheme">@style/ThemeOverlay.DeviceDefault.Popup.Light</item>
+
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_settings_light</item>
         <item name="colorPrimaryDark">@color/primary_dark_device_default_settings_light</item>
@@ -809,6 +813,15 @@
 
     <style name="ThemeOverlay.DeviceDefault" />
 
+    <!-- @hide Theme overlay that inherits from material actionbar,  and use accent color for
+             primary text -->
+    <style name="ThemeOverlay.DeviceDefault.ActionBar.Accent" parent="ThemeOverlay.Material.ActionBar">
+        <item name="textColorPrimary">@color/btn_colored_borderless_text_material</item>
+    </style>
+
+    <!-- @hide Theme overlay for a light popup in action bar -->
+    <style name="ThemeOverlay.DeviceDefault.Popup.Light" parent="@style/ThemeOverlay.Material.Light" />
+
     <style name="ThemeOverlay.DeviceDefault.Accent">
         <item name="colorAccent">@color/accent_device_default_dark</item>
     </style>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index b063baf..008c817 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -51,6 +51,7 @@
         <item name="primaryContentAlpha">@dimen/primary_content_alpha_material_dark</item>
         <item name="secondaryContentAlpha">@dimen/secondary_content_alpha_material_dark</item>
         <item name="backgroundDimAmount">0.6</item>
+        <item name="colorError">@color/error_color_material</item>
 
         <!-- Text styles -->
         <item name="textAppearance">@style/TextAppearance.Material</item>
@@ -73,7 +74,6 @@
         <item name="textColorLinkInverse">?attr/colorAccent</item>
         <item name="textColorSearchUrl">@color/search_url_text_material_dark</item>
         <item name="textColorAlertDialogListItem">@color/primary_text_material_dark</item>
-        <item name="textColorError">@color/error_text_material_dark</item>
 
         <item name="textAppearanceLarge">@style/TextAppearance.Material.Large</item>
         <item name="textAppearanceLargeInverse">@style/TextAppearance.Material.Large.Inverse</item>
@@ -214,7 +214,7 @@
         <!-- Scrollbar attributes -->
         <item name="scrollbarFadeDuration">250</item>
         <item name="scrollbarDefaultDelayBeforeFade">400</item>
-        <item name="scrollbarSize">10dp</item>
+        <item name="scrollbarSize">@dimen/config_scrollbarSize</item>
         <item name="scrollbarThumbHorizontal">@drawable/scrollbar_handle_material</item>
         <item name="scrollbarThumbVertical">@drawable/config_scrollbarThumbVertical</item>
         <item name="scrollbarTrackHorizontal">@null</item>
@@ -441,7 +441,6 @@
         <item name="textColorLinkInverse">?attr/colorAccent</item>
         <item name="textColorSearchUrl">@color/search_url_text_material_light</item>
         <item name="textColorAlertDialogListItem">@color/primary_text_material_light</item>
-        <item name="textColorError">@color/error_text_material_light</item>
 
         <item name="textAppearanceLarge">@style/TextAppearance.Material.Large</item>
         <item name="textAppearanceLargeInverse">@style/TextAppearance.Material.Large.Inverse</item>
@@ -583,7 +582,7 @@
         <!-- Scrollbar attributes -->
         <item name="scrollbarFadeDuration">250</item>
         <item name="scrollbarDefaultDelayBeforeFade">400</item>
-        <item name="scrollbarSize">10dp</item>
+        <item name="scrollbarSize">@dimen/config_scrollbarSize</item>
         <item name="scrollbarThumbHorizontal">@drawable/scrollbar_handle_material</item>
         <item name="scrollbarThumbVertical">@drawable/config_scrollbarThumbVertical</item>
         <item name="scrollbarTrackHorizontal">@null</item>
@@ -823,7 +822,6 @@
         <item name="textColorHighlightInverse">@color/highlighted_text_material</item>
         <item name="textColorSearchUrl">@color/search_url_text_material_light</item>
         <item name="textColorAlertDialogListItem">@color/primary_text_material_light</item>
-        <item name="textColorError">@color/error_text_material_light</item>
 
         <item name="textCheckMark">@drawable/indicator_check_mark_light</item>
         <item name="textCheckMarkInverse">@drawable/indicator_check_mark_dark</item>
@@ -856,7 +854,6 @@
         <item name="textColorHighlightInverse">@color/highlighted_text_material</item>
         <item name="textColorSearchUrl">@color/search_url_text_material_dark</item>
         <item name="textColorAlertDialogListItem">@color/primary_text_material_dark</item>
-        <item name="textColorError">@color/error_text_material_dark</item>
 
         <item name="textCheckMark">@drawable/indicator_check_mark_dark</item>
         <item name="textCheckMarkInverse">@drawable/indicator_check_mark_light</item>
diff --git a/core/tests/coretests/Android.mk b/core/tests/coretests/Android.mk
index 48b78d4..1a16b3b 100644
--- a/core/tests/coretests/Android.mk
+++ b/core/tests/coretests/Android.mk
@@ -21,6 +21,7 @@
 	$(call all-java-files-under, DisabledTestApp/src) \
 	$(call all-java-files-under, EnabledTestApp/src)
 
+LOCAL_DX_FLAGS := --core-library
 LOCAL_AAPT_FLAGS = -0 dat -0 gld -c fa
 LOCAL_STATIC_JAVA_LIBRARIES := \
     core-tests-support \
@@ -28,7 +29,6 @@
     frameworks-core-util-lib \
     mockwebserver \
     guava \
-    littlemock \
     android-support-test \
     mockito-target-minus-junit4 \
     espresso-core \
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index 91ce7a4..7b8c229 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -1357,6 +1357,9 @@
             </intent-filter>
         </service>
 
+        <service android:name="android.content.CrossUserContentService"
+                android:exported="true" />
+
     </application>
 
     <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/graphics/tests/graphicstests/res/color/color1.xml b/core/tests/coretests/res/color/color1.xml
similarity index 100%
rename from graphics/tests/graphicstests/res/color/color1.xml
rename to core/tests/coretests/res/color/color1.xml
diff --git a/graphics/tests/graphicstests/res/color/color_no_default.xml b/core/tests/coretests/res/color/color_no_default.xml
similarity index 100%
rename from graphics/tests/graphicstests/res/color/color_no_default.xml
rename to core/tests/coretests/res/color/color_no_default.xml
diff --git a/graphics/tests/graphicstests/res/drawable-nodpi/landscape.png b/core/tests/coretests/res/drawable-nodpi/landscape.png
similarity index 100%
rename from graphics/tests/graphicstests/res/drawable-nodpi/landscape.png
rename to core/tests/coretests/res/drawable-nodpi/landscape.png
Binary files differ
diff --git a/graphics/tests/graphicstests/res/drawable/test128x96.png b/core/tests/coretests/res/drawable/test128x96.png
similarity index 100%
rename from graphics/tests/graphicstests/res/drawable/test128x96.png
rename to core/tests/coretests/res/drawable/test128x96.png
Binary files differ
diff --git a/graphics/tests/graphicstests/res/drawable/test16x12.png b/core/tests/coretests/res/drawable/test16x12.png
similarity index 100%
rename from graphics/tests/graphicstests/res/drawable/test16x12.png
rename to core/tests/coretests/res/drawable/test16x12.png
Binary files differ
diff --git a/graphics/tests/graphicstests/res/drawable/test256x192.png b/core/tests/coretests/res/drawable/test256x192.png
similarity index 100%
rename from graphics/tests/graphicstests/res/drawable/test256x192.png
rename to core/tests/coretests/res/drawable/test256x192.png
Binary files differ
diff --git a/graphics/tests/graphicstests/res/drawable/test320x240.png b/core/tests/coretests/res/drawable/test320x240.png
similarity index 100%
rename from graphics/tests/graphicstests/res/drawable/test320x240.png
rename to core/tests/coretests/res/drawable/test320x240.png
Binary files differ
diff --git a/graphics/tests/graphicstests/res/drawable/test32x24.png b/core/tests/coretests/res/drawable/test32x24.png
similarity index 100%
rename from graphics/tests/graphicstests/res/drawable/test32x24.png
rename to core/tests/coretests/res/drawable/test32x24.png
Binary files differ
diff --git a/graphics/tests/graphicstests/res/drawable/test64x48.png b/core/tests/coretests/res/drawable/test64x48.png
similarity index 100%
rename from graphics/tests/graphicstests/res/drawable/test64x48.png
rename to core/tests/coretests/res/drawable/test64x48.png
Binary files differ
diff --git a/core/tests/coretests/res/font/samplexmldownloadedfont.xml b/core/tests/coretests/res/font/samplexmldownloadedfont.xml
index 35391bd..f1bdc47 100644
--- a/core/tests/coretests/res/font/samplexmldownloadedfont.xml
+++ b/core/tests/coretests/res/font/samplexmldownloadedfont.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <font-family xmlns:android="http://schemas.android.com/apk/res/android"
-        android:fontProviderAuthority="com.example.test.fontprovider"
+        android:fontProviderAuthority="com.example.test.fontprovider.authority"
+        android:fontProviderPackage="com.example.test.fontprovider.package"
         android:fontProviderQuery="MyRequestedFont">
 </font-family>
\ No newline at end of file
diff --git a/core/tests/coretests/res/values/colors.xml b/core/tests/coretests/res/values/colors.xml
index f881660..f01af84 100644
--- a/core/tests/coretests/res/values/colors.xml
+++ b/core/tests/coretests/res/values/colors.xml
@@ -23,4 +23,7 @@
     <drawable name="blue">#ff0000ff</drawable>
     <drawable name="green">#ff00ff00</drawable>
     <drawable name="yellow">#ffffff00</drawable>
+    <color name="testcolor1">#ff00ff00</color>
+    <color name="testcolor2">#ffff0000</color>
+    <color name="failColor">#ff0000ff</color>
 </resources>
diff --git a/core/tests/coretests/src/android/app/activity/LocalProvider.java b/core/tests/coretests/src/android/app/activity/LocalProvider.java
index d6a10c2..b7a63ce 100644
--- a/core/tests/coretests/src/android/app/activity/LocalProvider.java
+++ b/core/tests/coretests/src/android/app/activity/LocalProvider.java
@@ -29,6 +29,19 @@
 public class LocalProvider extends ContentProvider {
     private static final String TAG = "LocalProvider";
 
+    private static final String AUTHORITY = "com.android.frameworks.coretests.LocalProvider";
+    private static final String TABLE_DATA_NAME = "data";
+    public static final Uri TABLE_DATA_URI =
+            Uri.parse("content://" + AUTHORITY + "/" + TABLE_DATA_NAME);
+
+    public static final String COLUMN_TEXT_NAME = "text";
+    public static final String COLUMN_INTEGER_NAME = "integer";
+
+    public static final String TEXT1 = "first data";
+    public static final String TEXT2 = "second data";
+    public static final int INTEGER1 = 100;
+    public static final int INTEGER2 = 101;
+
     private SQLiteOpenHelper mOpenHelper;
 
     private static final int DATA = 1;
@@ -51,13 +64,20 @@
 
         @Override
         public void onCreate(SQLiteDatabase db) {
-            db.execSQL("CREATE TABLE data (" +
+            db.execSQL("CREATE TABLE " + TABLE_DATA_NAME + " (" +
                        "_id INTEGER PRIMARY KEY," +
-                       "text TEXT, " +
-                       "integer INTEGER);");
+                       COLUMN_TEXT_NAME + " TEXT, " +
+                       COLUMN_INTEGER_NAME + " INTEGER);");
 
             // insert alarms
-            db.execSQL("INSERT INTO data (text, integer) VALUES ('first data', 100);");
+            db.execSQL(getInsertCommand(TEXT1, INTEGER1));
+            db.execSQL(getInsertCommand(TEXT2, INTEGER2));
+        }
+
+        private String getInsertCommand(String textValue, int integerValue) {
+            return "INSERT INTO " + TABLE_DATA_NAME
+                    + " (" + COLUMN_TEXT_NAME + ", " + COLUMN_INTEGER_NAME + ") "
+                    + "VALUES ('" + textValue + "', " + integerValue + ");";
         }
 
         @Override
@@ -74,6 +94,10 @@
     public LocalProvider() {
     }
 
+    static public Uri getTableDataUriForRow(int rowId) {
+        return Uri.parse("content://" + AUTHORITY + "/" + TABLE_DATA_NAME + "/" + rowId);
+    }
+
     @Override
     public boolean onCreate() {
         mOpenHelper = new DatabaseHelper(getContext());
diff --git a/core/tests/coretests/src/android/content/AbstractCrossUserContentResolverTest.java b/core/tests/coretests/src/android/content/AbstractCrossUserContentResolverTest.java
new file mode 100644
index 0000000..5f6f62a
--- /dev/null
+++ b/core/tests/coretests/src/android/content/AbstractCrossUserContentResolverTest.java
@@ -0,0 +1,178 @@
+/*
+ * 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 android.content;
+
+
+import static org.junit.Assert.fail;
+
+import android.app.ActivityManager;
+import android.app.activity.LocalProvider;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.UserInfo;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+abstract class AbstractCrossUserContentResolverTest {
+    private final static int TIMEOUT_SERVICE_CONNECTION_SEC = 4;
+    private final static int TIMEOUT_CONTENT_CHANGE_SEC = 4;
+
+    private Context mContext;
+    protected UserManager mUm;
+    private int mCrossUserId = -1;
+    private CrossUserContentServiceConnection mServiceConnection;
+
+    @Before
+    public void setUp() throws Exception {
+        mContext = InstrumentationRegistry.getContext();
+        mUm = UserManager.get(mContext);
+        final UserInfo userInfo = createUser();
+        mCrossUserId = userInfo.id;
+        final PackageManager pm = mContext.getPackageManager();
+        pm.installExistingPackageAsUser(mContext.getPackageName(), mCrossUserId);
+        ActivityManager.getService().startUserInBackground(mCrossUserId);
+
+        final CountDownLatch connectionLatch = new CountDownLatch(1);
+        mServiceConnection = new CrossUserContentServiceConnection(connectionLatch);
+        mContext.bindServiceAsUser(
+                new Intent(mContext, CrossUserContentService.class),
+                mServiceConnection,
+                Context.BIND_AUTO_CREATE,
+                UserHandle.of(mCrossUserId));
+        if (!connectionLatch.await(TIMEOUT_SERVICE_CONNECTION_SEC, TimeUnit.SECONDS)) {
+            fail("Timed out waiting for service connection to establish");
+        }
+    }
+
+    protected abstract UserInfo createUser() throws RemoteException ;
+
+    @After
+    public void tearDown() throws Exception {
+        if (mCrossUserId != -1) {
+            mUm.removeUser(mCrossUserId);
+        }
+        if (mServiceConnection != null) {
+            mContext.unbindService(mServiceConnection);
+        }
+    }
+
+    /**
+     * Register an observer for an URI in another user and verify that it receives
+     * onChange callback when data at the URI changes.
+     */
+    @Test
+    public void testRegisterContentObserver() throws Exception {
+        Context crossUserContext = null;
+        String packageName = null;
+        try {
+            packageName = InstrumentationRegistry.getContext().getPackageName();
+            crossUserContext =
+                    InstrumentationRegistry.getContext().createPackageContextAsUser(
+                            packageName, 0 /* flags */, UserHandle.of(mCrossUserId));
+        } catch (NameNotFoundException e) {
+            fail("Couldn't find package " + packageName + " in u" + mCrossUserId);
+        }
+
+        final CountDownLatch updateLatch = new CountDownLatch(1);
+        final Uri uriToUpdate = LocalProvider.getTableDataUriForRow(2);
+        final TestContentObserver observer = new TestContentObserver(updateLatch,
+                uriToUpdate, mCrossUserId);
+        crossUserContext.getContentResolver().registerContentObserver(
+                LocalProvider.TABLE_DATA_URI, true, observer, mCrossUserId);
+        mServiceConnection.getService().updateContent(uriToUpdate, "New Text", 42);
+        if (!updateLatch.await(TIMEOUT_CONTENT_CHANGE_SEC, TimeUnit.SECONDS)) {
+            fail("Timed out waiting for the content change callback");
+        }
+    }
+
+    /**
+     * Register an observer for an URI in the current user and verify that another user can
+     * notify changes for this URI.
+     */
+    @Test
+    public void testNotifyChange() throws Exception {
+        final CountDownLatch notifyLatch = new CountDownLatch(1);
+        final Uri notifyUri = LocalProvider.TABLE_DATA_URI;
+        final TestContentObserver observer = new TestContentObserver(notifyLatch,
+                notifyUri, UserHandle.myUserId());
+        mContext.getContentResolver().registerContentObserver(notifyUri, true, observer);
+        mServiceConnection.getService().notifyForUriAsUser(notifyUri, UserHandle.myUserId());
+        if (!notifyLatch.await(TIMEOUT_CONTENT_CHANGE_SEC, TimeUnit.SECONDS)) {
+            fail("Timed out waiting for the notify callback");
+        }
+    }
+
+    private static final class CrossUserContentServiceConnection implements ServiceConnection {
+        private ICrossUserContentService mService;
+        private final CountDownLatch mLatch;
+
+        public CrossUserContentServiceConnection(CountDownLatch latch) {
+            mLatch = latch;
+        }
+
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            mService = ICrossUserContentService.Stub.asInterface(service);
+            mLatch.countDown();
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+        }
+
+        public ICrossUserContentService getService() {
+            return mService;
+        }
+    }
+
+    private static final class TestContentObserver extends ContentObserver {
+        private final CountDownLatch mLatch;
+        private final Uri mExpectedUri;
+        private final int mExpectedUserId;
+
+        public TestContentObserver(CountDownLatch latch, Uri exptectedUri, int expectedUserId) {
+            super(null);
+            mLatch = latch;
+            mExpectedUri = exptectedUri;
+            mExpectedUserId = expectedUserId;
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri, int userId) {
+            if (mExpectedUri.equals(uri) && mExpectedUserId == userId) {
+                mLatch.countDown();
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/tests/coretests/src/android/content/CrossUserContentService.java b/core/tests/coretests/src/android/content/CrossUserContentService.java
new file mode 100644
index 0000000..9cbe549
--- /dev/null
+++ b/core/tests/coretests/src/android/content/CrossUserContentService.java
@@ -0,0 +1,45 @@
+/*
+ * 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 android.content;
+
+import android.app.Service;
+import android.app.activity.LocalProvider;
+import android.net.Uri;
+import android.os.IBinder;
+
+public class CrossUserContentService extends Service {
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return mLocalService.asBinder();
+    }
+
+    private ICrossUserContentService mLocalService = new ICrossUserContentService.Stub() {
+        @Override
+        public void updateContent(Uri uri, String key, int value) {
+            final ContentValues values = new ContentValues();
+            values.put(LocalProvider.COLUMN_TEXT_NAME, key);
+            values.put(LocalProvider.COLUMN_INTEGER_NAME, value);
+            getContentResolver().update(uri, values, null, null);
+        }
+
+        @Override
+        public void notifyForUriAsUser(Uri uri, int userId) {
+            getContentResolver().notifyChange(uri, null, false, userId);
+        }
+    };
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/logging/legacy/Util.java b/core/tests/coretests/src/android/content/ICrossUserContentService.aidl
similarity index 70%
copy from core/java/com/android/internal/logging/legacy/Util.java
copy to core/tests/coretests/src/android/content/ICrossUserContentService.aidl
index 99f71ca..2c5cde4 100644
--- a/core/java/com/android/internal/logging/legacy/Util.java
+++ b/core/tests/coretests/src/android/content/ICrossUserContentService.aidl
@@ -11,15 +11,14 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
- * limitations under the License.
+ * limitations under the License
  */
-package com.android.internal.logging.legacy;
 
-/**
- * Created by cwren on 11/21/16.
- */
-public class Util {
-    public static boolean debug() {
-        return false;
-    }
-}
+package android.content;
+
+import android.net.Uri;
+
+interface ICrossUserContentService {
+    void updateContent(in Uri uri, String key, int value);
+    void notifyForUriAsUser(in Uri uri, int userId);
+}
\ No newline at end of file
diff --git a/core/tests/coretests/src/android/content/ManagedUserContentResolverTest.java b/core/tests/coretests/src/android/content/ManagedUserContentResolverTest.java
new file mode 100644
index 0000000..4362ec3
--- /dev/null
+++ b/core/tests/coretests/src/android/content/ManagedUserContentResolverTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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 android.content;
+
+import android.content.pm.UserInfo;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.support.test.filters.LargeTest;
+
+/**
+ * To run the tests, use
+ *
+ * runtest -c android.content.ManagedUserContentResolverTest frameworks-core
+ *
+ * or the following steps:
+ *
+ * Build: m FrameworksCoreTests
+ * Install: adb install -r \
+ *     ${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreTests/FrameworksCoreTests.apk
+ * Run: adb shell am instrument -e class android.content.ManagedUserContentResolverTest -w \
+ *     com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner
+ */
+@LargeTest
+public class ManagedUserContentResolverTest extends AbstractCrossUserContentResolverTest {
+    @Override
+    protected UserInfo createUser() throws RemoteException {
+        return mUm.createProfileForUser("Managed user",
+                UserInfo.FLAG_MANAGED_PROFILE, UserHandle.myUserId());
+    }
+}
diff --git a/core/tests/coretests/src/android/content/SecondaryUserContentResolverTest.java b/core/tests/coretests/src/android/content/SecondaryUserContentResolverTest.java
new file mode 100644
index 0000000..f8b13f0
--- /dev/null
+++ b/core/tests/coretests/src/android/content/SecondaryUserContentResolverTest.java
@@ -0,0 +1,42 @@
+/*
+ * 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 android.content;
+
+import android.content.pm.UserInfo;
+import android.os.RemoteException;
+import android.support.test.filters.LargeTest;
+
+/**
+ * To run the tests, use
+ *
+ * runtest -c android.content.SecondaryUserContentResolverTest frameworks-core
+ *
+ * or the following steps:
+ *
+ * Build: m FrameworksCoreTests
+ * Install: adb install -r \
+ *     ${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreTests/FrameworksCoreTests.apk
+ * Run: adb shell am instrument -e class android.content.SecondaryUserContentResolverTest -w \
+ *     com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner
+ */
+@LargeTest
+public class SecondaryUserContentResolverTest extends AbstractCrossUserContentResolverTest {
+    @Override
+    protected UserInfo createUser() throws RemoteException {
+        return mUm.createUser("Secondary user", 0);
+    }
+}
diff --git a/core/tests/coretests/src/android/content/pm/ParceledListSliceTest.java b/core/tests/coretests/src/android/content/pm/ParceledListSliceTest.java
index e5a92bf..5dd3c2c 100644
--- a/core/tests/coretests/src/android/content/pm/ParceledListSliceTest.java
+++ b/core/tests/coretests/src/android/content/pm/ParceledListSliceTest.java
@@ -91,6 +91,28 @@
         }
     }
 
+    public void testStringList() throws Exception {
+        final int objectCount = 400;
+        List<String> list = new ArrayList<String>();
+        for (long i = 0; i < objectCount; i++) {
+            list.add(Long.toString(i * (6 - i)));
+        }
+
+        StringParceledListSlice slice;
+        Parcel parcel = Parcel.obtain();
+        try {
+            parcel.writeParcelable(new StringParceledListSlice(list), 0);
+            parcel.setDataPosition(0);
+            slice = parcel.readParcelable(getClass().getClassLoader());
+        } finally {
+            parcel.recycle();
+        }
+
+        assertNotNull(slice);
+        assertNotNull(slice.getList());
+        assertEquals(list, slice.getList());
+    }
+
     /**
      * Test that only homogeneous elements may be unparceled.
      */
diff --git a/core/tests/coretests/src/android/content/res/FontResourcesParserTest.java b/core/tests/coretests/src/android/content/res/FontResourcesParserTest.java
index 8b536a7..23d3aa5 100644
--- a/core/tests/coretests/src/android/content/res/FontResourcesParserTest.java
+++ b/core/tests/coretests/src/android/content/res/FontResourcesParserTest.java
@@ -91,7 +91,8 @@
         List<FontConfig.Family> families = result.getFamilies();
         assertEquals(1, families.size());
         FontConfig.Family family = families.get(0);
-        assertEquals("com.example.test.fontprovider", family.getProviderAuthority());
+        assertEquals("com.example.test.fontprovider.authority", family.getProviderAuthority());
+        assertEquals("com.example.test.fontprovider.package", family.getProviderPackage());
         assertEquals("MyRequestedFont", family.getQuery());
         assertNull(family.getFonts());
     }
diff --git a/graphics/tests/graphicstests/src/android/graphics/BitmapFactoryTest.java b/core/tests/coretests/src/android/graphics/BitmapFactoryTest.java
similarity index 99%
rename from graphics/tests/graphicstests/src/android/graphics/BitmapFactoryTest.java
rename to core/tests/coretests/src/android/graphics/BitmapFactoryTest.java
index 09820ef..e9e2a4d 100644
--- a/graphics/tests/graphicstests/src/android/graphics/BitmapFactoryTest.java
+++ b/core/tests/coretests/src/android/graphics/BitmapFactoryTest.java
@@ -19,11 +19,11 @@
 import android.os.ParcelFileDescriptor;
 import android.test.suitebuilder.annotation.SmallTest;
 
+import junit.framework.TestCase;
+
 import java.io.ByteArrayOutputStream;
 import java.io.FileDescriptor;
 
-import junit.framework.TestCase;
-
 
 public class BitmapFactoryTest extends TestCase {
 
diff --git a/graphics/tests/graphicstests/src/android/graphics/BitmapTest.java b/core/tests/coretests/src/android/graphics/BitmapTest.java
similarity index 91%
rename from graphics/tests/graphicstests/src/android/graphics/BitmapTest.java
rename to core/tests/coretests/src/android/graphics/BitmapTest.java
index 685a998..3666ddd 100644
--- a/graphics/tests/graphicstests/src/android/graphics/BitmapTest.java
+++ b/core/tests/coretests/src/android/graphics/BitmapTest.java
@@ -17,6 +17,7 @@
 package android.graphics;
 
 import android.test.suitebuilder.annotation.SmallTest;
+
 import junit.framework.TestCase;
 
 
@@ -38,11 +39,11 @@
 
         assertEquals("rowbytes", 400, bm1.getRowBytes());
         assertEquals("rowbytes", 200, bm2.getRowBytes());
-        assertEquals("rowbytes", 200, bm3.getRowBytes());
-        
+        assertEquals("rowbytes", 400, bm3.getRowBytes());
+
         assertEquals("byteCount", 80000, bm1.getByteCount());
         assertEquals("byteCount", 40000, bm2.getByteCount());
-        assertEquals("byteCount", 40000, bm3.getByteCount());
+        assertEquals("byteCount", 80000, bm3.getByteCount());
 
         assertEquals("height", 200, bm1.getHeight());
         assertEquals("height", 200, bm2.getHeight());
@@ -51,10 +52,10 @@
         assertTrue("hasAlpha", bm1.hasAlpha());
         assertFalse("hasAlpha", bm2.hasAlpha());
         assertTrue("hasAlpha", bm3.hasAlpha());
-        
+
         assertTrue("getConfig", bm1.getConfig() == Bitmap.Config.ARGB_8888);
         assertTrue("getConfig", bm2.getConfig() == Bitmap.Config.RGB_565);
-        assertTrue("getConfig", bm3.getConfig() == Bitmap.Config.ARGB_4444);
+        assertTrue("getConfig", bm3.getConfig() == Bitmap.Config.ARGB_8888);
     }
 
     @SmallTest
@@ -181,12 +182,12 @@
         for (int i = 0; i < 256; i++) {
             colors[i] = (i << 24) | (0xFF << 16) | (0x80 << 8) | 0;
         }
-        
+
         Bitmap.Config config = Bitmap.Config.ARGB_8888;
 
         // create a bitmap with the color array specified
         Bitmap bm1 = Bitmap.createBitmap(colors, 16, 16, config);
-        
+
         // create a bitmap with no colors, but then call setPixels
         Bitmap bm2 = Bitmap.createBitmap(16, 16, config);
         bm2.setPixels(colors, 0, 16, 0, 0, 16, 16);
@@ -197,32 +198,32 @@
             int c0 = colors[i];
             int c1 = bm1.getPixel(i % 16, i / 16);
             int c2 = bm2.getPixel(i % 16, i / 16);
-            
+
             // these two should always be identical
             assertEquals("getPixel", c1, c2);
-            
+
             // comparing the original (c0) with the returned color is tricky,
             // since it gets premultiplied during the set(), and unpremultiplied
             // by the get().
             int a0 = Color.alpha(c0);
             int a1 = Color.alpha(c1);
             assertEquals("alpha", a0, a1);
-            
+
             int r0 = Color.red(c0);
             int r1 = Color.red(c1);
             int rr = computePrePostMul(a0, r0);
             assertTrue("red", Math.abs(rr - r1) <= tolerance);
-            
+
             int g0 = Color.green(c0);
             int g1 = Color.green(c1);
             int gg = computePrePostMul(a0, g0);
             assertTrue("green", Math.abs(gg - g1) <= tolerance);
-            
+
             int b0 = Color.blue(c0);
             int b1 = Color.blue(c1);
             int bb = computePrePostMul(a0, b0);
             assertTrue("blue", Math.abs(bb - b1) <= tolerance);
-            
+
             if (false) {
                 int cc = Color.argb(a0, rr, gg, bb);
                 android.util.Log.d("skia", "original " + Integer.toHexString(c0) +
@@ -231,4 +232,16 @@
             }
         }
     }
+
+    @SmallTest
+    public void testCreateHardwareBitmapFromGraphicBuffer() {
+        GraphicBuffer buffer = GraphicBuffer.create(10, 10, PixelFormat.RGBA_8888,
+                GraphicBuffer.USAGE_HW_TEXTURE | GraphicBuffer.USAGE_SOFTWARE_MASK);
+        Canvas canvas = buffer.lockCanvas();
+        canvas.drawColor(Color.YELLOW);
+        buffer.unlockCanvasAndPost(canvas);
+        Bitmap hardwareBitmap = Bitmap.createHardwareBitmap(buffer);
+        assertTrue(hardwareBitmap.isPremultiplied());
+        assertFalse(hardwareBitmap.isMutable());
+    }
 }
diff --git a/graphics/tests/graphicstests/src/android/graphics/ColorStateListTest.java b/core/tests/coretests/src/android/graphics/ColorStateListTest.java
similarity index 97%
rename from graphics/tests/graphicstests/src/android/graphics/ColorStateListTest.java
rename to core/tests/coretests/src/android/graphics/ColorStateListTest.java
index eb1025c..374d142 100644
--- a/graphics/tests/graphicstests/src/android/graphics/ColorStateListTest.java
+++ b/core/tests/coretests/src/android/graphics/ColorStateListTest.java
@@ -16,13 +16,13 @@
 
 package android.graphics;
 
-import com.android.frameworks.graphicstests.R;
-
-import android.content.res.Resources;
 import android.content.res.ColorStateList;
+import android.content.res.Resources;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 
+import com.android.frameworks.coretests.R;
+
 /**
  * Tests of {@link android.graphics.ColorStateList}
  */
diff --git a/graphics/tests/graphicstests/src/android/graphics/GraphicsPerformanceTests.java b/core/tests/coretests/src/android/graphics/GraphicsPerformanceTests.java
similarity index 98%
rename from graphics/tests/graphicstests/src/android/graphics/GraphicsPerformanceTests.java
rename to core/tests/coretests/src/android/graphics/GraphicsPerformanceTests.java
index f60ac7b..164c1aa 100644
--- a/graphics/tests/graphicstests/src/android/graphics/GraphicsPerformanceTests.java
+++ b/core/tests/coretests/src/android/graphics/GraphicsPerformanceTests.java
@@ -16,19 +16,15 @@
 
 package android.graphics;
 
-import junit.framework.Assert;
 import android.content.Context;
 import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.Paint;
 import android.test.AndroidTestCase;
 import android.test.PerformanceTestCase;
 import android.test.suitebuilder.annotation.Suppress;
-import android.util.Log;
 
-import com.android.frameworks.graphicstests.R;
+import com.android.frameworks.coretests.R;
+
+import junit.framework.Assert;
 
 /**
  * Graphics Performance Tests
diff --git a/graphics/tests/graphicstests/src/android/graphics/GraphicsTests.java b/core/tests/coretests/src/android/graphics/GraphicsTests.java
similarity index 100%
rename from graphics/tests/graphicstests/src/android/graphics/GraphicsTests.java
rename to core/tests/coretests/src/android/graphics/GraphicsTests.java
diff --git a/core/tests/coretests/src/android/graphics/PaintTest.java b/core/tests/coretests/src/android/graphics/PaintTest.java
index 2a3d463..5811ca0 100644
--- a/core/tests/coretests/src/android/graphics/PaintTest.java
+++ b/core/tests/coretests/src/android/graphics/PaintTest.java
@@ -156,4 +156,213 @@
             }
         }
     }
+
+    public void testGetTextRunAdvances() {
+        {
+            // LTR
+            String text = "abcdef";
+            assertGetTextRunAdvances(text, 0, text.length(), 0, text.length(), false, true);
+            assertGetTextRunAdvances(text, 1, text.length() - 1, 0, text.length(), false, false);
+        }
+        {
+            // RTL
+            final String text =
+                    "\u0645\u0627\u0020\u0647\u064A\u0020\u0627\u0644\u0634" +
+                            "\u0641\u0631\u0629\u0020\u0627\u0644\u0645\u0648\u062D" +
+                            "\u062F\u0629\u0020\u064A\u0648\u0646\u064A\u0643\u0648" +
+                            "\u062F\u061F";
+            assertGetTextRunAdvances(text, 0, text.length(), 0, text.length(), true, true);
+            assertGetTextRunAdvances(text, 1, text.length() - 1, 0, text.length(), true, false);
+        }
+    }
+
+    private void assertGetTextRunAdvances(String str, int start, int end,
+            int contextStart, int contextEnd, boolean isRtl, boolean compareWithOtherMethods) {
+        Paint p = new Paint();
+
+        final int count = end - start;
+        final float[][] advanceArrays = new float[4][count];
+
+        final float advance = p.getTextRunAdvances(str, start, end, contextStart, contextEnd,
+                isRtl, advanceArrays[0], 0);
+
+        char chars[] = str.toCharArray();
+        final float advance_c = p.getTextRunAdvances(chars, start, count, contextStart,
+                contextEnd - contextStart, isRtl, advanceArrays[1], 0);
+        assertEquals(advance, advance_c, 1.0f);
+
+        for (int c = 1; c < count; ++c) {
+            final float firstPartAdvance = p.getTextRunAdvances(str, start, start + c,
+                    contextStart, contextEnd, isRtl, advanceArrays[2], 0);
+            final float secondPartAdvance = p.getTextRunAdvances(str, start + c, end,
+                    contextStart, contextEnd, isRtl, advanceArrays[2], c);
+            assertEquals(advance, firstPartAdvance + secondPartAdvance, 1.0f);
+
+
+            final float firstPartAdvance_c = p.getTextRunAdvances(chars, start, c,
+                    contextStart, contextEnd - contextStart, isRtl, advanceArrays[3], 0);
+            final float secondPartAdvance_c = p.getTextRunAdvances(chars, start + c,
+                    count - c, contextStart, contextEnd - contextStart, isRtl,
+                    advanceArrays[3], c);
+            assertEquals(advance, firstPartAdvance_c + secondPartAdvance_c, 1.0f);
+            assertEquals(firstPartAdvance, firstPartAdvance_c, 1.0f);
+            assertEquals(secondPartAdvance, secondPartAdvance_c, 1.0f);
+
+            for (int i = 1; i < advanceArrays.length; i++) {
+                for (int j = 0; j < count; j++) {
+                    assertEquals(advanceArrays[0][j], advanceArrays[i][j], 1.0f);
+                }
+            }
+
+            // Compare results with measureText, getRunAdvance, and getTextWidths.
+            if (compareWithOtherMethods && start == contextStart && end == contextEnd) {
+                assertEquals(advance, p.measureText(str, start, end), 1.0f);
+                assertEquals(advance, p.getRunAdvance(
+                        str, start, end, contextStart, contextEnd, isRtl, end), 1.0f);
+
+                final float[] widths = new float[count];
+                p.getTextWidths(str, start, end, widths);
+                for (int i = 0; i < count; i++) {
+                    assertEquals(advanceArrays[0][i], widths[i], 1.0f);
+                }
+            }
+        }
+    }
+
+    public void testGetTextRunAdvances_invalid() {
+        Paint p = new Paint();
+        String text = "test";
+
+        try {
+            p.getTextRunAdvances((String)null, 0, 0, 0, 0, false, null, 0);
+            fail("Should throw an IllegalArgumentException.");
+        } catch (IllegalArgumentException e) {
+        }
+
+        try {
+            p.getTextRunAdvances((CharSequence)null, 0, 0, 0, 0, false, null, 0);
+            fail("Should throw an IllegalArgumentException.");
+        } catch (IllegalArgumentException e) {
+        }
+
+        try {
+            p.getTextRunAdvances((char[])null, 0, 0, 0, 0, false, null, 0);
+            fail("Should throw an IllegalArgumentException.");
+        } catch (IllegalArgumentException e) {
+        }
+
+        try {
+            p.getTextRunAdvances(text, 0, text.length(), 0, text.length(), false,
+                    new float[text.length() - 1], 0);
+            fail("Should throw an IndexOutOfBoundsException.");
+        } catch (IndexOutOfBoundsException e) {
+        }
+
+        try {
+            p.getTextRunAdvances(text, 0, text.length(), 0, text.length(), false,
+                    new float[text.length()], 1);
+            fail("Should throw an IndexOutOfBoundsException.");
+        } catch (IndexOutOfBoundsException e) {
+        }
+
+        // 0 > contextStart
+        try {
+            p.getTextRunAdvances(text, 0, text.length(), -1, text.length(), false, null, 0);
+            fail("Should throw an IndexOutOfBoundsException.");
+        } catch (IndexOutOfBoundsException e) {
+        }
+
+        // contextStart > start
+        try {
+            p.getTextRunAdvances(text, 0, text.length(), 1, text.length(), false, null, 0);
+            fail("Should throw an IndexOutOfBoundsException.");
+        } catch (IndexOutOfBoundsException e) {
+        }
+
+        // start > end
+        try {
+            p.getTextRunAdvances(text, 1, 0, 0, text.length(), false, null, 0);
+            fail("Should throw an IndexOutOfBoundsException.");
+        } catch (IndexOutOfBoundsException e) {
+        }
+
+        // end > contextEnd
+        try {
+            p.getTextRunAdvances(text, 0, text.length(), 0, text.length() - 1, false, null, 0);
+            fail("Should throw an IndexOutOfBoundsException.");
+        } catch (IndexOutOfBoundsException e) {
+        }
+
+        // contextEnd > text.length
+        try {
+            p.getTextRunAdvances(text, 0, text.length(), 0, text.length() + 1, false, null, 0);
+            fail("Should throw an IndexOutOfBoundsException.");
+        } catch (IndexOutOfBoundsException e) {
+        }
+    }
+
+    public void testMeasureTextBidi() {
+        Paint p = new Paint();
+        {
+            String bidiText = "abc \u0644\u063A\u0629 def";
+            p.setBidiFlags(Paint.BIDI_LTR);
+            float width = p.measureText(bidiText, 0, 4);
+            p.setBidiFlags(Paint.BIDI_RTL);
+            width += p.measureText(bidiText, 4, 7);
+            p.setBidiFlags(Paint.BIDI_LTR);
+            width += p.measureText(bidiText, 7, bidiText.length());
+            assertEquals(width, p.measureText(bidiText), 1.0f);
+        }
+        {
+            String bidiText = "abc \u0644\u063A\u0629 def";
+            p.setBidiFlags(Paint.BIDI_DEFAULT_LTR);
+            float width = p.measureText(bidiText, 0, 4);
+            width += p.measureText(bidiText, 4, 7);
+            width += p.measureText(bidiText, 7, bidiText.length());
+            assertEquals(width, p.measureText(bidiText), 1.0f);
+        }
+        {
+            String bidiText = "abc \u0644\u063A\u0629 def";
+            p.setBidiFlags(Paint.BIDI_FORCE_LTR);
+            float width = p.measureText(bidiText, 0, 4);
+            width += p.measureText(bidiText, 4, 7);
+            width += p.measureText(bidiText, 7, bidiText.length());
+            assertEquals(width, p.measureText(bidiText), 1.0f);
+        }
+        {
+            String bidiText = "\u0644\u063A\u0629 abc \u0644\u063A\u0629";
+            p.setBidiFlags(Paint.BIDI_RTL);
+            float width = p.measureText(bidiText, 0, 4);
+            p.setBidiFlags(Paint.BIDI_LTR);
+            width += p.measureText(bidiText, 4, 7);
+            p.setBidiFlags(Paint.BIDI_RTL);
+            width += p.measureText(bidiText, 7, bidiText.length());
+            assertEquals(width, p.measureText(bidiText), 1.0f);
+        }
+        {
+            String bidiText = "\u0644\u063A\u0629 abc \u0644\u063A\u0629";
+            p.setBidiFlags(Paint.BIDI_DEFAULT_RTL);
+            float width = p.measureText(bidiText, 0, 4);
+            width += p.measureText(bidiText, 4, 7);
+            width += p.measureText(bidiText, 7, bidiText.length());
+            assertEquals(width, p.measureText(bidiText), 1.0f);
+        }
+        {
+            String bidiText = "\u0644\u063A\u0629 abc \u0644\u063A\u0629";
+            p.setBidiFlags(Paint.BIDI_FORCE_RTL);
+            float width = p.measureText(bidiText, 0, 4);
+            width += p.measureText(bidiText, 4, 7);
+            width += p.measureText(bidiText, 7, bidiText.length());
+            assertEquals(width, p.measureText(bidiText), 1.0f);
+        }
+    }
+
+    public void testSetGetWordSpacing() {
+        Paint p = new Paint();
+        assertEquals(0.0f, p.getWordSpacing());  // The default value should be 0.
+        p.setWordSpacing(1.0f);
+        assertEquals(1.0f, p.getWordSpacing());
+        p.setWordSpacing(-2.0f);
+        assertEquals(-2.0f, p.getWordSpacing());
+    }
 }
diff --git a/graphics/tests/graphicstests/src/android/graphics/PathTest.java b/core/tests/coretests/src/android/graphics/PathTest.java
similarity index 99%
rename from graphics/tests/graphicstests/src/android/graphics/PathTest.java
rename to core/tests/coretests/src/android/graphics/PathTest.java
index 96200bc..78e4959 100644
--- a/graphics/tests/graphicstests/src/android/graphics/PathTest.java
+++ b/core/tests/coretests/src/android/graphics/PathTest.java
@@ -17,6 +17,7 @@
 package android.graphics;
 
 import android.test.suitebuilder.annotation.SmallTest;
+
 import junit.framework.TestCase;
 
 
diff --git a/graphics/tests/graphicstests/src/android/graphics/ThreadBitmapTest.java b/core/tests/coretests/src/android/graphics/ThreadBitmapTest.java
similarity index 97%
rename from graphics/tests/graphicstests/src/android/graphics/ThreadBitmapTest.java
rename to core/tests/coretests/src/android/graphics/ThreadBitmapTest.java
index 84bdc56..909a8d9 100644
--- a/graphics/tests/graphicstests/src/android/graphics/ThreadBitmapTest.java
+++ b/core/tests/coretests/src/android/graphics/ThreadBitmapTest.java
@@ -16,10 +16,10 @@
 
 package android.graphics;
 
-import junit.framework.TestCase;
-import android.graphics.Bitmap;
 import android.test.suitebuilder.annotation.LargeTest;
 
+import junit.framework.TestCase;
+
 public class ThreadBitmapTest extends TestCase {
 
     @Override
diff --git a/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java b/core/tests/coretests/src/android/graphics/VariationParserTest.java
similarity index 99%
rename from graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java
rename to core/tests/coretests/src/android/graphics/VariationParserTest.java
index c7a46a3..a2ead40 100644
--- a/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java
+++ b/core/tests/coretests/src/android/graphics/VariationParserTest.java
@@ -18,9 +18,11 @@
 
 import android.test.suitebuilder.annotation.SmallTest;
 import android.text.FontConfig;
-import java.util.List;
+
 import junit.framework.TestCase;
 
+import java.util.List;
+
 
 public class VariationParserTest extends TestCase {
 
diff --git a/core/tests/coretests/src/android/graphics/drawable/AdaptiveIconDrawableTest.java b/core/tests/coretests/src/android/graphics/drawable/AdaptiveIconDrawableTest.java
new file mode 100644
index 0000000..5ade66e
--- /dev/null
+++ b/core/tests/coretests/src/android/graphics/drawable/AdaptiveIconDrawableTest.java
@@ -0,0 +1,193 @@
+package android.graphics.drawable;
+
+import static org.junit.Assert.assertTrue;
+
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.Path.Direction;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.test.AndroidTestCase;
+import android.util.Log;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.util.Arrays;
+import org.junit.Test;
+
+public class AdaptiveIconDrawableTest extends AndroidTestCase {
+
+    public static final String TAG = AdaptiveIconDrawableTest.class.getSimpleName();
+    public static void L(String s, Object... parts) {
+        Log.d(TAG, (parts.length == 0) ? s : String.format(s, parts));
+    }
+    private Drawable mBackgroundDrawable;
+    private Drawable mForegroundDrawable;
+    private AdaptiveIconDrawable mIconDrawable;
+    private File mDir;
+
+    /**
+     * When setBound isn't called before draw method is called.
+     * Nothing is drawn.
+     */
+    @Test
+    public void testDrawWithoutSetBounds() throws Exception {
+        mBackgroundDrawable = new ColorDrawable(Color.BLUE);
+        mForegroundDrawable = new ColorDrawable(Color.RED);
+        mIconDrawable = new AdaptiveIconDrawable(mBackgroundDrawable, mForegroundDrawable);
+        mDir = getContext().getExternalFilesDir(null);
+        L("writing temp bitmaps to %s...", mDir);
+
+        final Bitmap bm_test = Bitmap.createBitmap(150, 150, Bitmap.Config.ARGB_8888);
+        final Bitmap bm_org = bm_test.copy(Config.ARGB_8888, false);
+        final Canvas can1 = new Canvas(bm_test);
+
+        // Even when setBounds is not called, should not crash
+        mIconDrawable.draw(can1);
+        // Draws nothing! Hence same as original.
+        if (!equalBitmaps(bm_test, bm_org)) {
+            findBitmapDifferences(bm_test, bm_org);
+            fail("bm differs, check " + mDir);
+        }
+    }
+
+    /**
+     * When setBound is called, translate accordingly.
+     */
+    @Test
+    public void testDrawSetBounds() throws Exception {
+        int dpi = 4 ;
+        int top = 18 * dpi;
+        int left = 18 * dpi;
+        int right = 90 * dpi;
+        int bottom = 90 * dpi;
+        int width = right - left;
+        int height = bottom - top;
+
+        mIconDrawable = (AdaptiveIconDrawable) getContext().getResources().getDrawable(android.R.drawable.sym_def_app_icon);
+        mDir = getContext().getExternalFilesDir(null);
+        L("writing temp bitmaps to %s...", mDir);
+        final Bitmap bm_org = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+        final Canvas can_org = new Canvas(bm_org);
+        mIconDrawable.setBounds(0, 0, width, height);
+        mIconDrawable.draw(can_org);
+
+        // Tested bitmap is drawn from the adaptive icon drawable.
+        final Bitmap bm_test = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+        final Canvas can_test = new Canvas(bm_test);
+
+        mIconDrawable.setBounds(left, top, right, bottom);
+        can_test.translate(-left, -top);
+        mIconDrawable.draw(can_test);
+        can_test.translate(left, top);
+
+
+        bm_org.compress(Bitmap.CompressFormat.PNG, 100,
+            new FileOutputStream(new File(mDir, "adaptive-bm-original.png")));
+        bm_test.compress(Bitmap.CompressFormat.PNG, 100,
+            new FileOutputStream(new File(mDir, "adaptive-bm-test.png")));
+        Region region = new Region(new Rect(0, 0, width, height));
+
+        Path circle = new Path();
+        circle.addCircle(width / 2, height / 2,  (right - left)/2 -10 /* room for anti-alias */, Direction.CW);
+
+        region.setPath(circle, region);
+        if (!equalBitmaps(bm_test, bm_org, region)) {
+            findBitmapDifferences(bm_test, bm_org);
+            fail("bm differs, check " + mDir);
+        }
+    }
+
+    //
+    // Utils
+    //
+
+    boolean equalBitmaps(Bitmap a, Bitmap b) {
+      return equalBitmaps(a, b, null);
+    }
+
+    boolean equalBitmaps(Bitmap a, Bitmap b, Region region) {
+        if (a.getWidth() != b.getWidth() || a.getHeight() != b.getHeight()) return false;
+
+        final int w = a.getWidth();
+        final int h = a.getHeight();
+        int[] aPix = new int[w * h];
+        int[] bPix = new int[w * h];
+
+        if (region != null) {
+            for (int i = 0; i < w; i++) {
+                for (int j = 0; j < h; j++) {
+                    int ra = (a.getPixel(i, j) >> 16) & 0xff;
+                    int ga = (a.getPixel(i, j) >> 8) & 0xff;
+                    int ba = a.getPixel(i, j) & 0xff;
+                    int rb = (b.getPixel(i, j) >> 16) & 0xff;
+                    int gb = (b.getPixel(i, j) >> 8) & 0xff;
+                    int bb = b.getPixel(i, j) & 0xff;
+                    if (region.contains(i, j) && a.getPixel(i, j) != b.getPixel(i, j) ) {
+                        return false;
+                    }
+                }
+            }
+            return true;
+        } else {
+            a.getPixels(aPix, 0, w, 0, 0, w, h);
+            b.getPixels(bPix, 0, w, 0, 0, w, h);
+            return Arrays.equals(aPix, bPix);
+        }
+    }
+
+    void findBitmapDifferences(Bitmap a, Bitmap b) {
+        if (a.getWidth() != b.getWidth() || a.getHeight() != b.getHeight()) {
+            L("different sizes: %dx%d vs %dx%d",
+                a.getWidth(), a.getHeight(), b.getWidth(), b.getHeight());
+            return;
+        }
+
+        final int w = a.getWidth();
+        final int h = a.getHeight();
+        int[] aPix = new int[w * h];
+        int[] bPix = new int[w * h];
+
+        a.getPixels(aPix, 0, w, 0, 0, w, h);
+        b.getPixels(bPix, 0, w, 0, 0, w, h);
+
+        L("bitmap a (%dx%d)", w, h);
+        printBits(aPix, w, h);
+        L("bitmap b (%dx%d)", w, h);
+        printBits(bPix, w, h);
+
+        StringBuffer sb = new StringBuffer("Different pixels: ");
+        for (int i=0; i<w; i++) {
+            for (int j=0; j<h; j++) {
+                if (aPix[i+w*j] != bPix[i+w*j]) {
+                    sb.append(" ").append(i).append(",").append(j).append("<")
+                        .append(aPix[i+w*j]).append(",").append(bPix[i+w*j]).append(">");
+                }
+            }
+        }
+        L(sb.toString());
+    }
+
+    static void printBits(int[] a, int w, int h) {
+        final StringBuilder sb = new StringBuilder();
+        for (int i=0; i<w; i++) {
+            for (int j=0; j<h; j++) {
+                sb.append(colorToChar(a[i+w*j]));
+            }
+            sb.append('\n');
+        }
+        L(sb.toString());
+    }
+
+    static char colorToChar(int color) {
+        int sum = ((color >> 16) & 0xff)
+            + ((color >> 8)  & 0xff)
+            + ((color)       & 0xff);
+        return GRADIENT[sum * (GRADIENT.length-1) / (3*0xff)];
+    }
+    static final char[] GRADIENT = " .:;+=xX$#".toCharArray();
+}
diff --git a/graphics/tests/graphicstests/src/android/graphics/drawable/IconTest.java b/core/tests/coretests/src/android/graphics/drawable/IconTest.java
similarity index 95%
rename from graphics/tests/graphicstests/src/android/graphics/drawable/IconTest.java
rename to core/tests/coretests/src/android/graphics/drawable/IconTest.java
index 50c498b..b50955b 100644
--- a/graphics/tests/graphicstests/src/android/graphics/drawable/IconTest.java
+++ b/core/tests/coretests/src/android/graphics/drawable/IconTest.java
@@ -26,14 +26,13 @@
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Log;
 
+import com.android.frameworks.coretests.R;
+
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
-import java.lang.Override;
-import java.util.Arrays;
 import java.util.ArrayList;
-
-import com.android.frameworks.graphicstests.R;
+import java.util.Arrays;
 
 public class IconTest extends AndroidTestCase {
     public static final String TAG = IconTest.class.getSimpleName();
@@ -109,36 +108,36 @@
     }
 
     @SmallTest
-    public void testWithMaskableBitmap() throws Exception {
+    public void testWithAdaptiveBitmap() throws Exception {
         final Bitmap bm1 = Bitmap.createBitmap(150, 150, Bitmap.Config.ARGB_8888);
 
         final Canvas can1 = new Canvas(bm1);
         can1.drawColor(0xFFFF0000);
 
-        final Icon im1 = Icon.createWithMaskableBitmap(bm1);
+        final Icon im1 = Icon.createWithAdaptiveBitmap(bm1);
 
-        final MaskableIconDrawable draw1 = (MaskableIconDrawable) im1.loadDrawable(mContext);
+        final AdaptiveIconDrawable draw1 = (AdaptiveIconDrawable) im1.loadDrawable(mContext);
 
         final Bitmap test1 = Bitmap.createBitmap(
-            (int)(draw1.getIntrinsicWidth() * (1 + 2 * MaskableIconDrawable.getExtraInsetPercentage())),
-            (int)(draw1.getIntrinsicHeight() * (1 + 2 * MaskableIconDrawable.getExtraInsetPercentage())),
+            (int)(draw1.getIntrinsicWidth() * (1 + 2 * AdaptiveIconDrawable.getExtraInsetPercentage())),
+            (int)(draw1.getIntrinsicHeight() * (1 + 2 * AdaptiveIconDrawable.getExtraInsetPercentage())),
             Bitmap.Config.ARGB_8888);
 
         draw1.setBounds(0, 0,
-            (int) (draw1.getIntrinsicWidth() * (1 + 2 * MaskableIconDrawable.getExtraInsetPercentage())),
-            (int) (draw1.getIntrinsicHeight() * (1 + 2 * MaskableIconDrawable.getExtraInsetPercentage())));
+            (int) (draw1.getIntrinsicWidth() * (1 + 2 * AdaptiveIconDrawable.getExtraInsetPercentage())),
+            (int) (draw1.getIntrinsicHeight() * (1 + 2 * AdaptiveIconDrawable.getExtraInsetPercentage())));
         draw1.draw(new Canvas(test1));
 
         final File dir = getContext().getExternalFilesDir(null);
         L("writing temp bitmaps to %s...", dir);
 
         bm1.compress(Bitmap.CompressFormat.PNG, 100,
-            new FileOutputStream(new File(dir, "maskable-bitmap1-original.png")));
+            new FileOutputStream(new File(dir, "adaptive-bitmap1-original.png")));
         test1.compress(Bitmap.CompressFormat.PNG, 100,
-            new FileOutputStream(new File(dir, "maskable-bitmap1-test.png")));
+            new FileOutputStream(new File(dir, "adaptive-bitmap1-test.png")));
         if (!equalBitmaps(bm1, test1, draw1.getSafeZone())) {
             findBitmapDifferences(bm1, test1);
-            fail("maskable bitmap1 differs, check " + dir);
+            fail("adaptive bitmap1 differs, check " + dir);
         }
     }
 
diff --git a/graphics/tests/graphicstests/src/android/graphics/drawable/StateListDrawableTest.java b/core/tests/coretests/src/android/graphics/drawable/StateListDrawableTest.java
similarity index 99%
rename from graphics/tests/graphicstests/src/android/graphics/drawable/StateListDrawableTest.java
rename to core/tests/coretests/src/android/graphics/drawable/StateListDrawableTest.java
index 0d9f72e..03a9c25 100644
--- a/graphics/tests/graphicstests/src/android/graphics/drawable/StateListDrawableTest.java
+++ b/core/tests/coretests/src/android/graphics/drawable/StateListDrawableTest.java
@@ -16,14 +16,14 @@
 
 package android.graphics.drawable;
 
-import junit.framework.TestCase;
-
 import android.R;
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
 import android.util.StateSet;
 import android.view.MockView;
 
+import junit.framework.TestCase;
+
 /**
  * Tests for StateListDrawable
  *
diff --git a/core/tests/coretests/src/android/metrics/LogMakerTest.java b/core/tests/coretests/src/android/metrics/LogMakerTest.java
index b9c973f..ece44be 100644
--- a/core/tests/coretests/src/android/metrics/LogMakerTest.java
+++ b/core/tests/coretests/src/android/metrics/LogMakerTest.java
@@ -122,6 +122,55 @@
         assertEquals(null, builder.getTaggedData(1));
     }
 
+    public void testClearFieldLeavesOtherFieldsIntact() {
+        LogMaker builder = new LogMaker(0);
+        builder.setPackageName("package.name");
+        builder.setSubtype(10);
+        builder.clearPackageName();
+        assertEquals(null, builder.getPackageName());
+        assertEquals(10, builder.getSubtype());
+    }
+
+    public void testSetAndClearCategory() {
+        LogMaker builder = new LogMaker(0);
+        builder.setCategory(MetricsEvent.MAIN_SETTINGS);
+        assertEquals(MetricsEvent.MAIN_SETTINGS, builder.getCategory());
+        builder.clearCategory();
+        assertEquals(MetricsEvent.VIEW_UNKNOWN, builder.getCategory());
+    }
+
+    public void testSetAndClearType() {
+        LogMaker builder = new LogMaker(0);
+        builder.setType(MetricsEvent.TYPE_OPEN);
+        assertEquals(MetricsEvent.TYPE_OPEN, builder.getType());
+        builder.clearType();
+        assertEquals(MetricsEvent.TYPE_UNKNOWN, builder.getType());
+    }
+
+    public void testSetAndClearSubtype() {
+        LogMaker builder = new LogMaker(0);
+        builder.setSubtype(1);
+        assertEquals(1, builder.getSubtype());
+        builder.clearSubtype();
+        assertEquals(0, builder.getSubtype());
+    }
+
+    public void testSetAndClearTimestamp() {
+        LogMaker builder = new LogMaker(0);
+        builder.setTimestamp(1);
+        assertEquals(1, builder.getTimestamp());
+        builder.clearTimestamp();
+        assertEquals(0, builder.getTimestamp());
+    }
+
+    public void testSetAndClearPackageName() {
+        LogMaker builder = new LogMaker(0);
+        builder.setPackageName("package.name");
+        assertEquals("package.name", builder.getPackageName());
+        builder.clearPackageName();
+        assertEquals(null, builder.getPackageName());
+    }
+
     public void testGiantLogOmitted() {
         LogMaker badBuilder = new LogMaker(0);
         StringBuilder b = new StringBuilder();
diff --git a/core/tests/coretests/src/android/net/NetworkRecommendationProviderTest.java b/core/tests/coretests/src/android/net/NetworkRecommendationProviderTest.java
index bdc0200..497bc5c 100644
--- a/core/tests/coretests/src/android/net/NetworkRecommendationProviderTest.java
+++ b/core/tests/coretests/src/android/net/NetworkRecommendationProviderTest.java
@@ -3,61 +3,62 @@
 import static android.net.NetworkRecommendationProvider.EXTRA_RECOMMENDATION_RESULT;
 import static android.net.NetworkRecommendationProvider.EXTRA_SEQUENCE;
 
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertSame;
+import static junit.framework.Assert.fail;
+import static junit.framework.TestCase.assertEquals;
+
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+
+import android.Manifest.permission;
 import android.content.Context;
 import android.os.Bundle;
-import android.os.Handler;
-import android.os.HandlerThread;
 import android.os.IRemoteCallback;
-import android.test.InstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
 
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
 
 /**
  * Unit test for the {@link NetworkRecommendationProvider}.
  */
-public class NetworkRecommendationProviderTest extends InstrumentationTestCase {
+@RunWith(AndroidJUnit4.class)
+public class NetworkRecommendationProviderTest {
     @Mock private IRemoteCallback mMockRemoteCallback;
+    @Mock private Context mContext;
     private NetworkRecProvider mRecProvider;
-    private Handler mHandler;
     private INetworkRecommendationProvider mStub;
     private CountDownLatch mRecRequestLatch;
     private CountDownLatch mScoreRequestLatch;
     private NetworkKey[] mTestNetworkKeys;
 
-    @Override
+    @Before
     public void setUp() throws Exception {
-        super.setUp();
-
-        // Configuration needed to make mockito/dexcache work.
-        final Context context = getInstrumentation().getTargetContext();
-        System.setProperty("dexmaker.dexcache",
-                context.getCacheDir().getPath());
-        ClassLoader newClassLoader = getInstrumentation().getClass().getClassLoader();
-        Thread.currentThread().setContextClassLoader(newClassLoader);
-
         MockitoAnnotations.initMocks(this);
 
-        HandlerThread thread = new HandlerThread("NetworkRecommendationProviderTest");
-        thread.start();
+        Executor executor = Executors.newSingleThreadExecutor();
         mRecRequestLatch = new CountDownLatch(1);
         mScoreRequestLatch = new CountDownLatch(1);
-        mHandler = new Handler(thread.getLooper());
-        mRecProvider = new NetworkRecProvider(mHandler, mRecRequestLatch, mScoreRequestLatch);
+        mRecProvider = new NetworkRecProvider(mContext, executor, mRecRequestLatch,
+                mScoreRequestLatch);
         mStub = INetworkRecommendationProvider.Stub.asInterface(mRecProvider.getBinder());
         mTestNetworkKeys = new NetworkKey[2];
         mTestNetworkKeys[0] = new NetworkKey(new WifiKey("\"ssid_01\"", "00:00:00:00:00:11"));
         mTestNetworkKeys[1] = new NetworkKey(new WifiKey("\"ssid_02\"", "00:00:00:00:00:22"));
     }
 
-    @MediumTest
+    @Test
     public void testRecommendationRequestReceived() throws Exception {
         final RecommendationRequest request = new RecommendationRequest.Builder().build();
         final int sequence = 100;
@@ -71,7 +72,23 @@
         assertEquals(expectedResultCallback, mRecProvider.mCapturedCallback);
     }
 
-    @SmallTest
+    @Test
+    public void testRecommendationRequest_permissionsEnforced() throws Exception {
+        final RecommendationRequest request = new RecommendationRequest.Builder().build();
+        final int sequence = 100;
+        Mockito.doThrow(new SecurityException())
+                .when(mContext)
+                .enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES), anyString());
+
+        try {
+            mStub.requestRecommendation(request, mMockRemoteCallback, sequence);
+            fail("SecurityException expected.");
+        } catch (SecurityException e) {
+            // expected
+        }
+    }
+
+    @Test
     public void testResultCallbackOnResult() throws Exception {
         final int sequence = 100;
         final NetworkRecommendationProvider.ResultCallback callback =
@@ -87,7 +104,7 @@
         assertSame(result, capturedBundle.getParcelable(EXTRA_RECOMMENDATION_RESULT));
     }
 
-    @SmallTest
+    @Test
     public void testResultCallbackOnResult_runTwice_throwsException() throws Exception {
         final int sequence = 100;
         final NetworkRecommendationProvider.ResultCallback callback =
@@ -104,7 +121,7 @@
         }
     }
 
-    @MediumTest
+    @Test
     public void testScoreRequestReceived() throws Exception {
         mStub.requestScores(mTestNetworkKeys);
 
@@ -114,7 +131,7 @@
         assertSame(mTestNetworkKeys, mRecProvider.mCapturedNetworks);
     }
 
-    @MediumTest
+    @Test
     public void testScoreRequest_nullInput() throws Exception {
         mStub.requestScores(null);
 
@@ -122,7 +139,7 @@
         assertFalse(mScoreRequestLatch.await(200, TimeUnit.MILLISECONDS));
     }
 
-    @MediumTest
+    @Test
     public void testScoreRequest_emptyInput() throws Exception {
         mStub.requestScores(new NetworkKey[0]);
 
@@ -130,6 +147,20 @@
         assertFalse(mScoreRequestLatch.await(200, TimeUnit.MILLISECONDS));
     }
 
+    @Test
+    public void testScoreRequest_permissionsEnforced() throws Exception {
+        Mockito.doThrow(new SecurityException())
+                .when(mContext)
+                .enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES), anyString());
+
+        try {
+            mStub.requestScores(mTestNetworkKeys);
+            fail("SecurityException expected.");
+        } catch (SecurityException e) {
+            // expected
+        }
+    }
+
     private static class NetworkRecProvider extends NetworkRecommendationProvider {
         private final CountDownLatch mRecRequestLatch;
         private final CountDownLatch mScoreRequestLatch;
@@ -137,9 +168,9 @@
         ResultCallback mCapturedCallback;
         NetworkKey[] mCapturedNetworks;
 
-        NetworkRecProvider(Handler handler, CountDownLatch recRequestLatch,
+        NetworkRecProvider(Context context, Executor executor, CountDownLatch recRequestLatch,
             CountDownLatch networkRequestLatch) {
-            super(handler);
+            super(context, executor);
             mRecRequestLatch = recRequestLatch;
             mScoreRequestLatch = networkRequestLatch;
         }
diff --git a/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java b/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
deleted file mode 100644
index ce5d3ef..0000000
--- a/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package android.net;
-
-import static org.mockito.Mockito.when;
-
-import android.Manifest.permission;
-import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.ServiceInfo;
-import android.content.res.Resources;
-import android.net.NetworkScorerAppManager.NetworkScorerAppData;
-import android.provider.Settings;
-import android.test.InstrumentationTestCase;
-
-import com.android.internal.R;
-
-import org.mockito.ArgumentMatcher;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-
-import java.util.List;
-
-public class NetworkScorerAppManagerTest extends InstrumentationTestCase {
-    @Mock private Context mMockContext;
-    @Mock private PackageManager mMockPm;
-    @Mock private Resources mResources;
-    @Mock private ContentResolver mContentResolver;
-    private Context mTargetContext;
-    private NetworkScorerAppManager mNetworkScorerAppManager;
-
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-
-        // Configuration needed to make mockito/dexcache work.
-        mTargetContext = getInstrumentation().getTargetContext();
-        System.setProperty("dexmaker.dexcache", mTargetContext.getCacheDir().getPath());
-        ClassLoader newClassLoader = getInstrumentation().getClass().getClassLoader();
-        Thread.currentThread().setContextClassLoader(newClassLoader);
-
-        MockitoAnnotations.initMocks(this);
-        when(mMockContext.getPackageManager()).thenReturn(mMockPm);
-        when(mMockContext.getResources()).thenReturn(mResources);
-        when(mMockContext.getContentResolver()).thenReturn(mTargetContext.getContentResolver());
-        mNetworkScorerAppManager = new NetworkScorerAppManager(mMockContext);
-    }
-
-    public void testGetPotentialRecommendationProviderPackages_emptyConfig() throws Exception {
-        setNetworkRecommendationPackageNames(/*no configured packages*/);
-        assertTrue(mNetworkScorerAppManager.getPotentialRecommendationProviderPackages().isEmpty());
-    }
-
-    public void testGetPotentialRecommendationProviderPackages_permissionNotGranted()
-            throws Exception {
-        setNetworkRecommendationPackageNames("package1");
-        mockScoreNetworksDenied("package1");
-
-        assertTrue(mNetworkScorerAppManager.getPotentialRecommendationProviderPackages().isEmpty());
-    }
-
-    public void testGetPotentialRecommendationProviderPackages_permissionGranted()
-            throws Exception {
-        setNetworkRecommendationPackageNames("package1");
-        mockScoreNetworksGranted("package1");
-
-        List<String> potentialProviderPackages =
-                mNetworkScorerAppManager.getPotentialRecommendationProviderPackages();
-
-        assertFalse(potentialProviderPackages.isEmpty());
-        assertEquals("package1", potentialProviderPackages.get(0));
-    }
-
-    public void testGetPotentialRecommendationProviderPackages_multipleConfigured()
-            throws Exception {
-        setNetworkRecommendationPackageNames("package1", "package2");
-        mockScoreNetworksDenied("package1");
-        mockScoreNetworksGranted("package2");
-
-        List<String> potentialProviderPackages =
-                mNetworkScorerAppManager.getPotentialRecommendationProviderPackages();
-
-        assertEquals(1, potentialProviderPackages.size());
-        assertEquals("package2", potentialProviderPackages.get(0));
-    }
-
-    public void testGetNetworkRecommendationProviderData_noPotentialPackages() throws Exception {
-        setNetworkRecommendationPackageNames(/*no configured packages*/);
-        assertNull(mNetworkScorerAppManager.getNetworkRecommendationProviderData());
-    }
-
-    public void testGetNetworkRecommendationProviderData_serviceMissing() throws Exception {
-        setNetworkRecommendationPackageNames("package1");
-        mockScoreNetworksGranted("package1");
-
-        assertNull(mNetworkScorerAppManager.getNetworkRecommendationProviderData());
-    }
-
-    public void testGetNetworkRecommendationProviderData_scoreNetworksNotGranted()
-            throws Exception {
-        final ComponentName recoComponent = new ComponentName("package1", "class1");
-        setNetworkRecommendationPackageNames(recoComponent.getPackageName());
-        mockScoreNetworksDenied(recoComponent.getPackageName());
-        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */);
-
-        assertNull(mNetworkScorerAppManager.getNetworkRecommendationProviderData());
-    }
-
-    public void testGetNetworkRecommendationProviderData_available() throws Exception {
-        final ComponentName recoComponent = new ComponentName("package1", "class1");
-        setNetworkRecommendationPackageNames(recoComponent.getPackageName());
-        mockScoreNetworksGranted(recoComponent.getPackageName());
-        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */);
-
-        NetworkScorerAppData appData =
-                mNetworkScorerAppManager.getNetworkRecommendationProviderData();
-        assertNotNull(appData);
-        assertEquals(recoComponent, appData.getRecommendationServiceComponent());
-        assertEquals(924, appData.packageUid);
-    }
-
-    public void testGetActiveScorer_providerAvailable() throws Exception {
-        final ComponentName recoComponent = new ComponentName("package1", "class1");
-        setNetworkRecommendationPackageNames(recoComponent.getPackageName());
-        mockScoreNetworksGranted(recoComponent.getPackageName());
-        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */);
-
-        ContentResolver cr = mTargetContext.getContentResolver();
-        Settings.Global.putInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 1);
-
-        final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
-        assertNotNull(activeScorer);
-        assertEquals(recoComponent, activeScorer.getRecommendationServiceComponent());
-        assertEquals(924, activeScorer.packageUid);
-    }
-
-    public void testGetActiveScorer_providerNotAvailable()
-            throws Exception {
-        ContentResolver cr = mTargetContext.getContentResolver();
-        Settings.Global.putInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 1);
-
-        final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
-        assertNull(activeScorer);
-    }
-
-    public void testGetActiveScorer_recommendationsDisabled() throws Exception {
-        final ComponentName recoComponent = new ComponentName("package1", "class1");
-        setNetworkRecommendationPackageNames(recoComponent.getPackageName());
-        mockScoreNetworksGranted(recoComponent.getPackageName());
-        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */);
-        ContentResolver cr = mTargetContext.getContentResolver();
-        Settings.Global.putInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0);
-
-        final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
-        assertNull(activeScorer);
-    }
-
-    private void setNetworkRecommendationPackageNames(String... names) {
-        if (names == null) {
-            names = new String[0];
-        }
-        when(mResources.getStringArray(R.array.config_networkRecommendationPackageNames))
-                .thenReturn(names);
-    }
-
-    private void mockScoreNetworksGranted(String packageName) {
-        when(mMockPm.checkPermission(permission.SCORE_NETWORKS, packageName))
-                .thenReturn(PackageManager.PERMISSION_GRANTED);
-    }
-
-    private void mockScoreNetworksDenied(String packageName) {
-        when(mMockPm.checkPermission(permission.SCORE_NETWORKS, packageName))
-                .thenReturn(PackageManager.PERMISSION_DENIED);
-    }
-
-    private void mockRecommendationServiceAvailable(final ComponentName compName, int packageUid) {
-        final ResolveInfo serviceInfo = new ResolveInfo();
-        serviceInfo.serviceInfo = new ServiceInfo();
-        serviceInfo.serviceInfo.name = compName.getClassName();
-        serviceInfo.serviceInfo.packageName = compName.getPackageName();
-        serviceInfo.serviceInfo.applicationInfo = new ApplicationInfo();
-        serviceInfo.serviceInfo.applicationInfo.uid = packageUid;
-
-        final int flags = 0;
-        when(mMockPm.resolveService(
-                Mockito.argThat(new ArgumentMatcher<Intent>() {
-                    @Override
-                    public boolean matches(Object object) {
-                        Intent intent = (Intent) object;
-                        return NetworkScoreManager.ACTION_RECOMMEND_NETWORKS
-                                .equals(intent.getAction())
-                                && compName.getPackageName().equals(intent.getPackage());
-                    }
-                }), Mockito.eq(flags))).thenReturn(serviceInfo);
-    }
-}
diff --git a/core/tests/coretests/src/android/net/SSLSessionCacheTest.java b/core/tests/coretests/src/android/net/SSLSessionCacheTest.java
index be19303..ec130e0 100644
--- a/core/tests/coretests/src/android/net/SSLSessionCacheTest.java
+++ b/core/tests/coretests/src/android/net/SSLSessionCacheTest.java
@@ -19,7 +19,7 @@
 import com.android.org.conscrypt.ClientSessionContext;
 import com.android.org.conscrypt.SSLClientSessionCache;
 
-import com.google.testing.littlemock.LittleMock;
+import org.mockito.Mockito;
 
 import junit.framework.TestCase;
 
@@ -39,25 +39,25 @@
 
     public void testInstall_compatibleContext() throws Exception {
         final SSLContext ctx = SSLContext.getDefault();
-        final SSLClientSessionCache mock = LittleMock.mock(SSLClientSessionCache.class);
+        final SSLClientSessionCache mock = Mockito.mock(SSLClientSessionCache.class);
         final ClientSessionContext clientCtx = (ClientSessionContext) ctx.getClientSessionContext();
 
         try {
             SSLSessionCache.install(new SSLSessionCache(mock), ctx);
             clientCtx.getSession("www.foogle.com", 443);
-            LittleMock.verify(mock).getSessionData(LittleMock.anyString(), LittleMock.anyInt());
+            Mockito.verify(mock).getSessionData(Mockito.anyString(), Mockito.anyInt());
         } finally {
             // Restore cacheless behaviour.
             SSLSessionCache.install(null, ctx);
             clientCtx.getSession("www.foogle.com", 443);
-            LittleMock.verifyNoMoreInteractions(mock);
+            Mockito.verifyNoMoreInteractions(mock);
         }
     }
 
     public void testInstall_incompatibleContext() {
         try {
             SSLSessionCache.install(
-                    new SSLSessionCache(LittleMock.mock(SSLClientSessionCache.class)),
+                    new SSLSessionCache(Mockito.mock(SSLClientSessionCache.class)),
                     new FakeSSLContext());
             fail();
         } catch (IllegalArgumentException expected) {}
@@ -102,7 +102,7 @@
 
         @Override
         protected SSLSessionContext engineGetClientSessionContext() {
-            return LittleMock.mock(SSLSessionContext.class);
+            return Mockito.mock(SSLSessionContext.class);
         }
     }
 }
diff --git a/core/tests/coretests/src/android/net/ScoredNetworkTest.java b/core/tests/coretests/src/android/net/ScoredNetworkTest.java
index e818c56..dc17da2 100644
--- a/core/tests/coretests/src/android/net/ScoredNetworkTest.java
+++ b/core/tests/coretests/src/android/net/ScoredNetworkTest.java
@@ -18,13 +18,10 @@
 
 import static org.junit.Assert.*;
 
-import android.os.Build;
 import android.os.Bundle;
 import android.os.Parcel;
-import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
-import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -170,41 +167,41 @@
     @Test
     public void calculateBadgeShouldReturnNoBadgeWhenNoAttributesBundle() {
         ScoredNetwork network = new ScoredNetwork(KEY, CURVE);
-        assertEquals(ScoredNetwork.BADGING_NONE, network.calculateBadge(TEST_RSSI));
+        assertEquals(NetworkBadging.BADGING_NONE, network.calculateBadge(TEST_RSSI));
     }
 
     @Test
     public void calculateBadgeShouldReturnNoBadgeWhenNoBadgingCurveInBundle() {
         ScoredNetwork network = new ScoredNetwork(KEY, CURVE, false /* meteredHint */, ATTRIBUTES);
-        assertEquals(ScoredNetwork.BADGING_NONE, network.calculateBadge(TEST_RSSI));
+        assertEquals(NetworkBadging.BADGING_NONE, network.calculateBadge(TEST_RSSI));
     }
 
     @Test
     public void calculateBadgeShouldReturn4kBadge() {
         ScoredNetwork network =
-            buildScoredNetworkWithGivenBadgeForTestRssi(ScoredNetwork.BADGING_4K);
-        assertEquals(ScoredNetwork.BADGING_4K, network.calculateBadge(TEST_RSSI));
+            buildScoredNetworkWithGivenBadgeForTestRssi(NetworkBadging.BADGING_4K);
+        assertEquals(NetworkBadging.BADGING_4K, network.calculateBadge(TEST_RSSI));
     }
 
     @Test
     public void calculateBadgeShouldReturnHdBadge() {
         ScoredNetwork network =
-            buildScoredNetworkWithGivenBadgeForTestRssi(ScoredNetwork.BADGING_HD);
-        assertEquals(ScoredNetwork.BADGING_HD, network.calculateBadge(TEST_RSSI));
+            buildScoredNetworkWithGivenBadgeForTestRssi(NetworkBadging.BADGING_HD);
+        assertEquals(NetworkBadging.BADGING_HD, network.calculateBadge(TEST_RSSI));
     }
 
     @Test
     public void calculateBadgeShouldReturnSdBadge() {
         ScoredNetwork network =
-            buildScoredNetworkWithGivenBadgeForTestRssi(ScoredNetwork.BADGING_SD);
-        assertEquals(ScoredNetwork.BADGING_SD, network.calculateBadge(TEST_RSSI));
+            buildScoredNetworkWithGivenBadgeForTestRssi(NetworkBadging.BADGING_SD);
+        assertEquals(NetworkBadging.BADGING_SD, network.calculateBadge(TEST_RSSI));
     }
 
     @Test
     public void calculateBadgeShouldReturnNoBadge() {
         ScoredNetwork network =
-            buildScoredNetworkWithGivenBadgeForTestRssi(ScoredNetwork.BADGING_NONE);
-        assertEquals(ScoredNetwork.BADGING_NONE, network.calculateBadge(TEST_RSSI));
+            buildScoredNetworkWithGivenBadgeForTestRssi(NetworkBadging.BADGING_NONE);
+        assertEquals(NetworkBadging.BADGING_NONE, network.calculateBadge(TEST_RSSI));
     }
 
     private ScoredNetwork buildScoredNetworkWithGivenBadgeForTestRssi(int badge) {
diff --git a/core/tests/coretests/src/android/os/FileUtilsTest.java b/core/tests/coretests/src/android/os/FileUtilsTest.java
index bd90079..3a751af 100644
--- a/core/tests/coretests/src/android/os/FileUtilsTest.java
+++ b/core/tests/coretests/src/android/os/FileUtilsTest.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import static android.os.FileUtils.roundStorageSize;
 import static android.text.format.DateUtils.DAY_IN_MILLIS;
 import static android.text.format.DateUtils.HOUR_IN_MILLIS;
 import static android.text.format.DateUtils.WEEK_IN_MILLIS;
@@ -25,10 +26,10 @@
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.MediumTest;
 
-import com.google.android.collect.Sets;
-
 import libcore.io.IoUtils;
 
+import com.google.android.collect.Sets;
+
 import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FileOutputStream;
@@ -311,6 +312,34 @@
         assertNameEquals("test.foo (1).bar", FileUtils.buildUniqueFile(mTarget, "test.foo.bar"));
     }
 
+    public void testRoundStorageSize() throws Exception {
+        final long M128 = 128000000L;
+        final long M256 = 256000000L;
+        final long M512 = 512000000L;
+        final long G1 = 1000000000L;
+        final long G2 = 2000000000L;
+        final long G16 = 16000000000L;
+        final long G32 = 32000000000L;
+        final long G64 = 64000000000L;
+
+        assertEquals(M128, roundStorageSize(M128));
+        assertEquals(M256, roundStorageSize(M128 + 1));
+        assertEquals(M256, roundStorageSize(M256 - 1));
+        assertEquals(M256, roundStorageSize(M256));
+        assertEquals(M512, roundStorageSize(M256 + 1));
+        assertEquals(M512, roundStorageSize(M512 - 1));
+        assertEquals(M512, roundStorageSize(M512));
+        assertEquals(G1, roundStorageSize(M512 + 1));
+        assertEquals(G1, roundStorageSize(G1));
+        assertEquals(G2, roundStorageSize(G1 + 1));
+
+        assertEquals(G16, roundStorageSize(G16));
+        assertEquals(G32, roundStorageSize(G16 + 1));
+        assertEquals(G32, roundStorageSize(G32 - 1));
+        assertEquals(G32, roundStorageSize(G32));
+        assertEquals(G64, roundStorageSize(G32 + 1));
+    }
+
     private static void assertNameEquals(String expected, File actual) {
         assertEquals(expected, actual.getName());
     }
diff --git a/core/tests/coretests/src/android/provider/FontsContractTest.java b/core/tests/coretests/src/android/provider/FontsContractTest.java
new file mode 100644
index 0000000..db623a4
--- /dev/null
+++ b/core/tests/coretests/src/android/provider/FontsContractTest.java
@@ -0,0 +1,235 @@
+/*
+ * 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 android.provider;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ProviderInfo;
+import android.content.pm.Signature;
+import android.graphics.Typeface;
+import android.graphics.fonts.FontRequest;
+import android.graphics.fonts.FontResult;
+import android.os.Bundle;
+import android.os.ResultReceiver;
+import android.support.test.filters.SmallTest;
+import android.test.ProviderTestCase2;
+import android.util.Base64;
+
+import org.mockito.ArgumentCaptor;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Unit tests for {@link FontsContract}.
+ */
+@SmallTest
+public class FontsContractTest extends ProviderTestCase2<TestFontsProvider> {
+    private static final byte[] BYTE_ARRAY =
+            Base64.decode("e04fd020ea3a6910a2d808002b30", Base64.DEFAULT);
+    private static final String PACKAGE_NAME = "com.my.font.provider.package";
+
+    private final FontRequest request = new FontRequest(
+            TestFontsProvider.AUTHORITY, PACKAGE_NAME, "query");
+    private TestFontsProvider mProvider;
+    private FontsContract mContract;
+    private ResultReceiver mResultReceiver;
+    private PackageManager mPackageManager;
+
+    public FontsContractTest() {
+        super(TestFontsProvider.class, TestFontsProvider.AUTHORITY);
+    }
+
+    public void setUp() throws Exception {
+        super.setUp();
+
+        mProvider = getProvider();
+        mPackageManager = mock(PackageManager.class);
+        mContract = new FontsContract(getMockContext(), mPackageManager);
+        mResultReceiver = mock(ResultReceiver.class);
+    }
+
+    public void testGetFontFromProvider() {
+        mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
+
+        final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+        verify(mResultReceiver).send(eq(FontsContract.RESULT_CODE_OK), bundleCaptor.capture());
+
+        Bundle bundle = bundleCaptor.getValue();
+        assertNotNull(bundle);
+        List<FontResult> resultList =
+                bundle.getParcelableArrayList(FontsContract.PARCEL_FONT_RESULTS);
+        assertNotNull(resultList);
+        assertEquals(1, resultList.size());
+        FontResult fontResult = resultList.get(0);
+        assertEquals(TestFontsProvider.TTC_INDEX, fontResult.getTtcIndex());
+        assertEquals(TestFontsProvider.VARIATION_SETTINGS, fontResult.getFontVariationSettings());
+        assertEquals(TestFontsProvider.STYLE, fontResult.getStyle());
+        assertNotNull(fontResult.getFileDescriptor());
+    }
+
+    public void testGetFontFromProvider_providerDoesntReturnAllFields() {
+        mProvider.setReturnAllFields(false);
+
+        final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+        mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
+        verify(mResultReceiver).send(eq(FontsContract.RESULT_CODE_OK), bundleCaptor.capture());
+
+        Bundle bundle = bundleCaptor.getValue();
+        assertNotNull(bundle);
+        List<FontResult> resultList =
+                bundle.getParcelableArrayList(FontsContract.PARCEL_FONT_RESULTS);
+        assertNotNull(resultList);
+        assertEquals(1, resultList.size());
+        FontResult fontResult = resultList.get(0);
+        assertEquals(0, fontResult.getTtcIndex());
+        assertNull(fontResult.getFontVariationSettings());
+        assertEquals(Typeface.NORMAL, fontResult.getStyle());
+        assertNotNull(fontResult.getFileDescriptor());
+    }
+
+    public void testGetProvider_providerNotFound() {
+        when(mPackageManager.resolveContentProvider(anyString(), anyInt())).thenReturn(null);
+
+        ProviderInfo result = mContract.getProvider(request);
+
+        assertNull(result);
+    }
+
+    public void testGetProvider_providerIsSystemApp() throws PackageManager.NameNotFoundException {
+        ProviderInfo info = setupPackageManager();
+        info.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
+        when(mPackageManager.resolveContentProvider(anyString(), anyInt())).thenReturn(info);
+
+        ProviderInfo result = mContract.getProvider(request);
+
+        assertEquals(info, result);
+    }
+
+    public void testGetProvider_providerIsSystemAppWrongPackage()
+            throws PackageManager.NameNotFoundException {
+        ProviderInfo info = setupPackageManager();
+        info.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
+        when(mPackageManager.resolveContentProvider(anyString(), anyInt())).thenReturn(info);
+
+        ProviderInfo result = mContract.getProvider(
+                new FontRequest(TestFontsProvider.AUTHORITY, "com.wrong.package", "query"));
+
+        assertNull(result);
+    }
+
+    public void testGetProvider_providerIsNonSystemAppNoCerts()
+            throws PackageManager.NameNotFoundException {
+        setupPackageManager();
+
+        // The default request is missing the certificates info.
+        ProviderInfo result = mContract.getProvider(request);
+
+        assertNull(result);
+    }
+
+    public void testGetProvider_providerIsNonSystemAppWrongCerts()
+            throws PackageManager.NameNotFoundException {
+        setupPackageManager();
+
+        byte[] wrongCert = Base64.decode("this is a wrong cert", Base64.DEFAULT);
+        List<byte[]> certList = Arrays.asList(wrongCert);
+        FontRequest requestWrongCerts = new FontRequest(
+                TestFontsProvider.AUTHORITY, PACKAGE_NAME, "query", Arrays.asList(certList));
+        ProviderInfo result = mContract.getProvider(requestWrongCerts);
+
+        assertNull(result);
+    }
+
+    public void testGetProvider_providerIsNonSystemAppCorrectCerts()
+            throws PackageManager.NameNotFoundException {
+        ProviderInfo info = setupPackageManager();
+
+        List<byte[]> certList = Arrays.asList(BYTE_ARRAY);
+        FontRequest requestRightCerts = new FontRequest(
+                TestFontsProvider.AUTHORITY, PACKAGE_NAME, "query", Arrays.asList(certList));
+        ProviderInfo result = mContract.getProvider(requestRightCerts);
+
+        assertEquals(info, result);
+    }
+
+    public void testGetProvider_providerIsNonSystemAppMoreCerts()
+            throws PackageManager.NameNotFoundException {
+        setupPackageManager();
+
+        byte[] wrongCert = Base64.decode("this is a wrong cert", Base64.DEFAULT);
+        List<byte[]> certList = Arrays.asList(wrongCert, BYTE_ARRAY);
+        FontRequest requestRightCerts = new FontRequest(
+                TestFontsProvider.AUTHORITY, PACKAGE_NAME, "query", Arrays.asList(certList));
+        ProviderInfo result = mContract.getProvider(requestRightCerts);
+
+        // There is one too many certs, should fail as the set doesn't match.
+        assertNull(result);
+    }
+
+    public void testGetProvider_providerIsNonSystemAppCorrectCertsSeveralSets()
+            throws PackageManager.NameNotFoundException {
+        ProviderInfo info = setupPackageManager();
+
+        List<List<byte[]>> certList = new ArrayList<>();
+        byte[] wrongCert = Base64.decode("this is a wrong cert", Base64.DEFAULT);
+        certList.add(Arrays.asList(wrongCert));
+        certList.add(Arrays.asList(BYTE_ARRAY));
+        FontRequest requestRightCerts = new FontRequest(
+                TestFontsProvider.AUTHORITY, PACKAGE_NAME, "query", certList);
+        ProviderInfo result = mContract.getProvider(requestRightCerts);
+
+        assertEquals(info, result);
+    }
+
+    public void testGetProvider_providerIsNonSystemAppWrongPackage()
+            throws PackageManager.NameNotFoundException {
+        setupPackageManager();
+
+        List<List<byte[]>> certList = new ArrayList<>();
+        certList.add(Arrays.asList(BYTE_ARRAY));
+        FontRequest requestRightCerts = new FontRequest(
+                TestFontsProvider.AUTHORITY, "com.wrong.package.name", "query", certList);
+        ProviderInfo result = mContract.getProvider(requestRightCerts);
+
+        assertNull(result);
+    }
+
+    private ProviderInfo setupPackageManager()
+            throws PackageManager.NameNotFoundException {
+        ProviderInfo info = new ProviderInfo();
+        info.packageName = PACKAGE_NAME;
+        info.applicationInfo = new ApplicationInfo();
+        when(mPackageManager.resolveContentProvider(anyString(), anyInt())).thenReturn(info);
+        PackageInfo packageInfo = new PackageInfo();
+        Signature signature = mock(Signature.class);
+        when(signature.toByteArray()).thenReturn(BYTE_ARRAY);
+        packageInfo.packageName = PACKAGE_NAME;
+        packageInfo.signatures = new Signature[] { signature };
+        when(mPackageManager.getPackageInfo(anyString(), anyInt())).thenReturn(packageInfo);
+        return info;
+    }
+}
diff --git a/core/tests/coretests/src/android/provider/SettingsTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
similarity index 97%
rename from core/tests/coretests/src/android/provider/SettingsTest.java
rename to core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 019f837..696d498 100644
--- a/core/tests/coretests/src/android/provider/SettingsTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -24,8 +24,7 @@
 import static java.lang.reflect.Modifier.isPublic;
 import static java.lang.reflect.Modifier.isStatic;
 
-import android.annotation.TargetApi;
-
+import android.platform.test.annotations.Presubmit;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
@@ -36,11 +35,11 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-/** Unit test for Settings. */
-@TargetApi(25)
+/** Tests that ensure appropriate settings are backed up. */
 @RunWith(AndroidJUnit4.class)
+@Presubmit
 @SmallTest
-public class SettingsTest {
+public class SettingsBackupTest {
 
     /**
      * The following blacklists contain settings that should *not* be backed up and restored to
@@ -64,7 +63,6 @@
                     Settings.System.NOTIFICATION_SOUND_CACHE, // internal cache
                     Settings.System.POINTER_LOCATION, // backup candidate?
                     Settings.System.RINGTONE_CACHE, // internal cache
-                    Settings.System.SCREEN_BRIGHTNESS_FOR_VR, // bug?
                     Settings.System.SETUP_WIZARD_HAS_RUN, // Only used by SuW
                     Settings.System.SHOW_GTALK_SERVICE_STATUS, // candidate for backup?
                     Settings.System.SHOW_TOUCHES, // bug?
@@ -160,6 +158,7 @@
                     Settings.Global.DEVICE_DEMO_MODE,
                     Settings.Global.DEVICE_IDLE_CONSTANTS,
                     Settings.Global.DEVICE_IDLE_CONSTANTS_WATCH,
+                    Settings.Global.BATTERY_SAVER_CONSTANTS,
                     Settings.Global.DEVICE_NAME,
                     Settings.Global.DEVICE_PROVISIONED,
                     Settings.Global.DEVICE_PROVISIONING_MOBILE_DATA_ENABLED,
@@ -181,6 +180,7 @@
                     Settings.Global.DROPBOX_TAG_PREFIX,
                     Settings.Global.EMERGENCY_AFFORDANCE_NEEDED,
                     Settings.Global.ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED,
+                    Settings.Global.ENABLE_CACHE_QUOTA_CALCULATION,
                     Settings.Global.ENABLE_CELLULAR_ON_BOOT,
                     Settings.Global.ENABLE_DISKSTATS_LOGGING,
                     Settings.Global.ENABLE_EPHEMERAL_FEATURE,
@@ -246,6 +246,7 @@
                     Settings.Global.NETWORK_AVOID_BAD_WIFI,
                     Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE,
                     Settings.Global.NETWORK_PREFERENCE,
+                    Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE,
                     Settings.Global.NETWORK_RECOMMENDATION_REQUEST_TIMEOUT_MS,
                     Settings.Global.NETWORK_SCORER_APP,
                     Settings.Global.NETWORK_SCORING_PROVISIONED,
@@ -281,6 +282,7 @@
                     Settings.Global.RADIO_NFC,
                     Settings.Global.RADIO_WIFI,
                     Settings.Global.RADIO_WIMAX,
+                    Settings.Global.RECOMMENDED_NETWORK_EVALUATOR_CACHE_EXPIRY_MS,
                     Settings.Global.READ_EXTERNAL_STORAGE_ENFORCED_DEFAULT,
                     Settings.Global.REQUIRE_PASSWORD_TO_DECRYPT,
                     Settings.Global.RETAIL_DEMO_MODE_CONSTANTS,
@@ -306,6 +308,8 @@
                     Settings.Global.STORAGE_BENCHMARK_INTERVAL,
                     Settings.Global.SYNC_MAX_RETRY_DELAY_IN_SECONDS,
                     Settings.Global.SYS_FREE_STORAGE_LOG_INTERVAL,
+                    Settings.Global.SYS_STORAGE_CACHE_MAX_BYTES,
+                    Settings.Global.SYS_STORAGE_CACHE_PERCENTAGE,
                     Settings.Global.SYS_STORAGE_FULL_THRESHOLD_BYTES,
                     Settings.Global.SYS_STORAGE_THRESHOLD_MAX_BYTES,
                     Settings.Global.SYS_STORAGE_THRESHOLD_PERCENTAGE,
@@ -383,7 +387,6 @@
                  Settings.Secure.ASSIST_STRUCTURE_ENABLED,
                  Settings.Secure.AUTO_FILL_SERVICE,
                  Settings.Secure.AUTOMATIC_STORAGE_MANAGER_BYTES_CLEARED,
-                 Settings.Secure.AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
                  Settings.Secure.AUTOMATIC_STORAGE_MANAGER_ENABLED,
                  Settings.Secure.AUTOMATIC_STORAGE_MANAGER_LAST_RUN,
                  Settings.Secure.BACKUP_AUTO_RESTORE,
@@ -392,6 +395,7 @@
                  Settings.Secure.BACKUP_TRANSPORT,
                  Settings.Secure.BLUETOOTH_HCI_LOG,
                  Settings.Secure.CARRIER_APPS_HANDLED,
+                 Settings.Secure.CMAS_ADDITIONAL_BROADCAST_PKG,
                  Settings.Secure.COMPLETED_CATEGORY_PREFIX,
                  Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS,
                  Settings.Secure.DEFAULT_INPUT_METHOD,
@@ -422,6 +426,7 @@
                  Settings.Secure.MANAGED_PROFILE_CONTACT_REMOTE_SEARCH,
                  Settings.Secure.MULTI_PRESS_TIMEOUT,
                  Settings.Secure.NFC_PAYMENT_FOREGROUND,
+                 Settings.Secure.OVERVIEW_LAST_STACK_ACTIVE_TIME,
                  Settings.Secure.PACKAGE_VERIFIER_STATE,
                  Settings.Secure.PACKAGE_VERIFIER_USER_CONSENT,
                  Settings.Secure.PARENTAL_CONTROL_LAST_UPDATE,
@@ -460,12 +465,12 @@
                  Settings.Secure.TV_INPUT_CUSTOM_LABELS,
                  Settings.Secure.TV_INPUT_HIDDEN_INPUTS,
                  Settings.Secure.UI_NIGHT_MODE, // candidate?
+                 Settings.Secure.UNKNOWN_SOURCES_DEFAULT_REVERSED,
                  Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS,
                  Settings.Secure.USB_AUDIO_AUTOMATIC_ROUTING_DISABLED,
                  Settings.Secure.USER_SETUP_COMPLETE,
                  Settings.Secure.VOICE_INTERACTION_SERVICE,
                  Settings.Secure.VOICE_RECOGNITION_SERVICE,
-                 Settings.Secure.VR_DISPLAY_MODE, // Candidate?
                  Settings.Secure.WEB_ACTION_ENABLED);
 
     @Test
diff --git a/core/tests/coretests/src/android/provider/TestFontsProvider.java b/core/tests/coretests/src/android/provider/TestFontsProvider.java
new file mode 100644
index 0000000..6d40f37
--- /dev/null
+++ b/core/tests/coretests/src/android/provider/TestFontsProvider.java
@@ -0,0 +1,117 @@
+/*
+ * 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 android.provider;
+
+import static android.os.ParcelFileDescriptor.MODE_READ_ONLY;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.graphics.Typeface;
+import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Provides a test Content Provider implementing {@link FontsContract}.
+ */
+public class TestFontsProvider extends ContentProvider {
+    static final String AUTHORITY = "android.provider.TestFontsProvider";
+    static final int TTC_INDEX = 2;
+    static final String VARIATION_SETTINGS = "'wdth' 1";
+    static final int STYLE = Typeface.BOLD;
+
+    private ParcelFileDescriptor mPfd;
+    private boolean mReturnAllFields = true;
+
+    /**
+     * Used by tests to switch whether all fields should be returned or not.
+     */
+    void setReturnAllFields(boolean returnAllFields) {
+        mReturnAllFields = returnAllFields;
+    }
+
+    @Override
+    public boolean onCreate() {
+        mPfd = createFontFile();
+        return true;
+    }
+
+    @Override
+    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,
+            @Nullable String[] selectionArgs, @Nullable String sortOrder) {
+        MatrixCursor cursor;
+        if (mReturnAllFields) {
+            cursor = new MatrixCursor(new String[] { FontsContract.Columns._ID,
+                    FontsContract.Columns.TTC_INDEX, FontsContract.Columns.VARIATION_SETTINGS,
+                    FontsContract.Columns.STYLE });
+            cursor.addRow(new Object[] { 1, TTC_INDEX, VARIATION_SETTINGS, STYLE });
+        } else {
+            cursor = new MatrixCursor(new String[] { FontsContract.Columns._ID });
+            cursor.addRow(new Object[] { 1 });
+        }
+        return cursor;
+    }
+
+    @Override
+    public ParcelFileDescriptor openFile(Uri uri, String mode) {
+        try {
+            return mPfd.dup();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    @Override
+    public String getType(@NonNull Uri uri) {
+        return "application/x-font-ttf";
+    }
+
+    @Override
+    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
+        return null;
+    }
+
+    @Override
+    public int delete(@NonNull Uri uri, @Nullable String selection,
+            @Nullable String[] selectionArgs) {
+        return 0;
+    }
+
+    @Override
+    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection,
+            @Nullable String[] selectionArgs) {
+        return 0;
+    }
+
+    private ParcelFileDescriptor createFontFile() {
+        try {
+            final File file = new File(getContext().getCacheDir(), "font.ttf");
+            file.getParentFile().mkdirs();
+            file.createNewFile();
+            return ParcelFileDescriptor.open(file, MODE_READ_ONLY);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+}
diff --git a/graphics/tests/graphicstests/src/android/view/MockView.java b/core/tests/coretests/src/android/view/MockView.java
similarity index 100%
rename from graphics/tests/graphicstests/src/android/view/MockView.java
rename to core/tests/coretests/src/android/view/MockView.java
diff --git a/core/tests/coretests/src/android/view/PopupWindowVisibility.java b/core/tests/coretests/src/android/view/PopupWindowVisibility.java
index 7eb0468..6e11ede 100644
--- a/core/tests/coretests/src/android/view/PopupWindowVisibility.java
+++ b/core/tests/coretests/src/android/view/PopupWindowVisibility.java
@@ -82,7 +82,7 @@
         "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
         "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
         "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
-        "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
+        "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czechia",
         "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
         "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
         "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
diff --git a/core/tests/coretests/src/android/widget/focus/RequestFocusTest.java b/core/tests/coretests/src/android/widget/focus/RequestFocusTest.java
index f2eba23..cdfa217 100644
--- a/core/tests/coretests/src/android/widget/focus/RequestFocusTest.java
+++ b/core/tests/coretests/src/android/widget/focus/RequestFocusTest.java
@@ -16,8 +16,8 @@
 
 package android.widget.focus;
 
-import static com.google.testing.littlemock.LittleMock.inOrder;
-import static com.google.testing.littlemock.LittleMock.mock;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
 
 import android.os.Handler;
 import android.test.ActivityInstrumentationTestCase2;
@@ -31,7 +31,7 @@
 import android.widget.Button;
 
 import com.android.frameworks.coretests.R;
-import com.google.testing.littlemock.LittleMock.InOrder;
+import org.mockito.InOrder;
 
 /**
  * {@link RequestFocusTest} is set up to exercise cases where the views that
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index 1080a9f..3dfecc6 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -16,6 +16,17 @@
 
 package com.android.internal.app;
 
+import android.app.Instrumentation;
+import android.content.ComponentName;
+import android.content.IntentFilter;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.LauncherApps;
+import android.content.pm.PackageManager;
+import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutManager;
+import android.graphics.drawable.Icon;
+import android.os.SystemClock;
 import com.android.internal.R;
 import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
 
@@ -48,25 +59,31 @@
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.mockito.Mockito.when;
-import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.isA;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 /**
  * Chooser activity instrumentation tests
  */
 @RunWith(AndroidJUnit4.class)
 public class ChooserActivityTest {
+    private Instrumentation instrumentation;
+
+    @Before
+    public void setUp() {
+        instrumentation = InstrumentationRegistry.getInstrumentation();
+        sOverrides.reset();
+    }
+
     @Rule
     public ActivityTestRule<ChooserWrapperActivity> mActivityRule =
             new ActivityTestRule<>(ChooserWrapperActivity.class, false,
                     false);
 
-    @Before
-    public void cleanOverrideData() {
-        sOverrides.reset();
-    }
-
     @Test
     public void customTitle() throws InterruptedException {
         Intent sendIntent = createSendImageIntent();
@@ -235,7 +252,6 @@
             chosen[0] = targetInfo.getResolveInfo();
             return true;
         };
-
         // Make a stable copy of the components as the original list may be modified
         List<ResolvedComponentInfo> stableCopy =
                 createResolvedComponentsForTestWithOtherProfile(2);
@@ -324,6 +340,32 @@
         assertThat(chosen[0], is(toChoose));
     }
 
+    public void pushedChooserTarget() {
+        ResolveInfo[] chosen = new ResolveInfo[1];
+        sOverrides.onSafelyStartCallback = targetInfo -> {
+            chosen[0] = targetInfo.getResolveInfo();
+            return true;
+        };
+
+        setChooserShortcuts(1);
+        List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
+        when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
+
+        Intent sendIntent = createSendImageIntent();
+        final ChooserWrapperActivity activity = mActivityRule
+                .launchActivity(Intent.createChooser(sendIntent, null));
+
+        waitForIdle();
+
+        onView(withText("short chooser label 0"))
+                .perform(click());
+        waitForIdle();
+        assertThat(chosen[0].resolvePackageName,
+                is(ResolverDataProvider.createActivityInfo(0).packageName));
+    }
+
     private Intent createSendImageIntent() {
         Intent sendIntent = new Intent();
         sendIntent.setAction(Intent.ACTION_SEND);
@@ -371,4 +413,48 @@
         }
         return packageStats.mChooserCounts.get(action).getOrDefault(annotation, 0);
     }
+
+    private void setChooserShortcuts(int numShortcuts) {
+        ArrayList<ShortcutInfo> shortcuts = new ArrayList<>();
+        for (int i = 0; i < numShortcuts; i++) {
+           shortcuts.add(makeShortcut(i));
+        }
+        when(sOverrides.launcherApps.getShortcuts(
+                Mockito.isA(LauncherApps.ShortcutQuery.class),
+                Mockito.eq(UserHandle.SYSTEM)))
+                .thenReturn(shortcuts);
+    }
+
+    private ShortcutInfo makeShortcut(int i) {
+        try {
+            IntentFilter filter = new IntentFilter(Intent.ACTION_SEND, "image/jpeg");
+
+            ComponentName component = new ComponentName("foo.bar", "foo.bar" + ".MainActivity");
+            ShortcutInfo.Builder b = new ShortcutInfo.Builder(instrumentation.getContext(), "" + i)
+                    .setActivity(component)
+                    .setShortLabel("short chooser label " + i)
+                    .setLongLabel("long chooser label" + i)
+                    .setRank(i)
+                    .setIntent(createSendImageIntent())
+                    .setIcon(Icon.createWithResource(instrumentation.getContext(),
+                            android.R.drawable.ic_menu_add))
+                    .addChooserIntentFilter(
+                            filter,
+                            component);
+
+            sOverrides.createPackageManager = pm -> {
+                final PackageManager spied = spy(pm);
+                try {
+                    doAnswer(invocation -> ResolverDataProvider.createActivityInfo(i))
+                            .when(spied).getActivityInfo(
+                            Mockito.isA(ComponentName.class), Mockito.anyInt());
+                } catch (Exception e) {
+                    // this is ok, just not found
+                    e.printStackTrace();
+                }
+                return spied;
+            };
+            return b.build();
+        } catch (Exception e) {return null;}
+    }
 }
\ No newline at end of file
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
index c446f3c..0dac260 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
@@ -18,6 +18,7 @@
 
 import android.app.usage.UsageStatsManager;
 import android.content.Context;
+import android.content.pm.LauncherApps;
 import android.content.pm.PackageManager;
 
 import java.util.function.Function;
@@ -74,6 +75,11 @@
         return super.getPackageManager();
     }
 
+    @Override
+    public LauncherApps getLauncherApps() {
+        return sOverrides.launcherApps;
+    }
+
     /**
      * We cannot directly mock the activity created since instrumentation creates it.
      * <p>
@@ -82,6 +88,7 @@
     static class OverrideData {
         @SuppressWarnings("Since15")
         public Function<PackageManager, PackageManager> createPackageManager;
+        public LauncherApps launcherApps;
         public Function<TargetInfo, Boolean> onSafelyStartCallback;
         public ResolverListController resolverListController;
         public Boolean isVoiceInteraction;
@@ -90,6 +97,7 @@
             onSafelyStartCallback = null;
             isVoiceInteraction = null;
             createPackageManager = null;
+            launcherApps = mock(LauncherApps.class);
             resolverListController = mock(ResolverListController.class);
         }
     }
diff --git a/core/tests/coretests/src/com/android/internal/logging/legacy/ParserTest.java b/core/tests/coretests/src/com/android/internal/logging/legacy/ParserTest.java
deleted file mode 100644
index 4adf629..0000000
--- a/core/tests/coretests/src/com/android/internal/logging/legacy/ParserTest.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * 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.internal.logging.legacy;
-
-import android.metrics.LogMaker;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.when;
-
-import junit.framework.TestCase;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.mockito.stubbing.OngoingStubbing;
-
-/**
- * Common functions and temporaries for parser tests.
- */
-public class ParserTest extends TestCase {
-    @Mock
-    protected TronLogger mLogger;
-
-    protected TagParser mParser;
-
-    protected LogMaker[] mProto;
-    protected ArgumentCaptor<LogMaker> mProtoCaptor;
-    protected ArgumentCaptor<String> mNameCaptor;
-    protected ArgumentCaptor<Integer> mCountCaptor;
-    protected String mKey = "0|com.android.example.notificationshowcase|31338|null|10090";
-    protected String mTaggedKey = "0|com.android.example.notificationshowcase|31338|badger|10090";
-    protected String mKeyPackage = "com.android.example.notificationshowcase";
-    protected String mTag = "badger";
-    protected int mId = 31338;
-    protected int mSinceCreationMillis = 5000;
-    protected int mSinceUpdateMillis = 1012;
-    protected int mSinceVisibleMillis = 323;
-
-
-    public ParserTest() {
-        mProto = new LogMaker[5];
-        for (int i = 0; i < mProto.length; i++) {
-            mProto[i] = new LogMaker(MetricsEvent.VIEW_UNKNOWN);
-        }
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        MockitoAnnotations.initMocks(this);
-
-        mProtoCaptor = ArgumentCaptor.forClass(LogMaker.class);
-        mNameCaptor = ArgumentCaptor.forClass(String.class);
-        mCountCaptor = ArgumentCaptor.forClass(Integer.class);
-
-        OngoingStubbing<LogMaker> stub = when(mLogger.obtain()).thenReturn(mProto[0]);
-        for (int i = 1; i < mProto.length; i++) {
-            stub.thenReturn(mProto[i]);
-        }
-        doNothing().when(mLogger).addEvent(any(LogMaker.class));
-        doNothing().when(mLogger).incrementBy(anyString(), anyInt());
-    }
-
-    protected void validateNotificationTimes(LogMaker proto, int life, int freshness,
-            int exposure) {
-        validateNotificationTimes(proto, life, freshness);
-        if (exposure != 0) {
-            assertEquals(exposure,
-                proto.getTaggedData(MetricsEvent.NOTIFICATION_SINCE_VISIBLE_MILLIS));
-        } else {
-            assertNull(proto.getTaggedData(MetricsEvent.NOTIFICATION_SINCE_VISIBLE_MILLIS));
-        }
-    }
-
-    protected void validateNotificationTimes(LogMaker proto, int life, int freshness) {
-        if (life != 0) {
-            assertEquals(life,
-                proto.getTaggedData(MetricsEvent.NOTIFICATION_SINCE_CREATE_MILLIS));
-        } else {
-            assertNull(proto.getTaggedData(MetricsEvent.NOTIFICATION_SINCE_CREATE_MILLIS));
-        }
-        if (freshness != 0) {
-            assertEquals(freshness,
-                proto.getTaggedData(MetricsEvent.NOTIFICATION_SINCE_UPDATE_MILLIS));
-        } else {
-            assertNull(proto.getTaggedData(MetricsEvent.NOTIFICATION_SINCE_UPDATE_MILLIS));
-        }
-    }
-
-    protected void validateNotificationIdAndTag(LogMaker proto, int id, String tag) {
-        assertEquals(tag, proto.getTaggedData(MetricsEvent.NOTIFICATION_TAG));
-        assertEquals(id, proto.getTaggedData(MetricsEvent.NOTIFICATION_ID));
-    }
-}
diff --git a/core/tests/coretests/src/com/android/internal/logging/legacy/PowerScreenStateParserTest.java b/core/tests/coretests/src/com/android/internal/logging/legacy/PowerScreenStateParserTest.java
deleted file mode 100644
index b480e61..0000000
--- a/core/tests/coretests/src/com/android/internal/logging/legacy/PowerScreenStateParserTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.internal.logging.legacy;
-
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-
-import android.metrics.LogMaker;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
-public class PowerScreenStateParserTest extends ParserTest {
-
-    public PowerScreenStateParserTest() {
-        mParser = new PowerScreenStateParser();
-    }
-
-    public void testScreenOn() throws Throwable {
-        validate(MetricsEvent.TYPE_OPEN, 0, "1,0,0,0");
-    }
-
-    public void testTimeout() throws Throwable {
-        validate(MetricsEvent.TYPE_CLOSE, 3, "0,3,0,0");
-    }
-
-    public void testUser() throws Throwable {
-        validate(MetricsEvent.TYPE_CLOSE, 2, "0,2,0,0");
-    }
-
-    public void testAdmin() throws Throwable {
-        validate(MetricsEvent.TYPE_CLOSE, 1, "0,1,0,0");
-    }
-
-    public void testIgnoreUnexpectedData() throws Throwable {
-        validate(MetricsEvent.TYPE_OPEN, 0, "1,0,0,0,5");
-    }
-
-    private void validate(int type, int subType, String log) {
-        String[] parts = log.split(",");
-        int t = 1000;
-        Object[] objects = new Object[parts.length];
-        for (int i = 0; i < parts.length; i++) {
-            objects[i] = Integer.valueOf(parts[i]);
-        }
-
-        mParser.parseEvent(mLogger, t, objects);
-
-        verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
-
-        LogMaker proto = mProtoCaptor.getValue();
-        assertEquals(t, proto.getTimestamp());
-        assertEquals(type, proto.getType());
-        assertEquals(MetricsEvent.SCREEN, proto.getCategory());
-        assertEquals(subType, proto.getSubtype());
-    }
-}
diff --git a/core/tests/coretests/src/com/android/internal/logging/legacy/SysuiMultiActionParserTest.java b/core/tests/coretests/src/com/android/internal/logging/legacy/SysuiMultiActionParserTest.java
deleted file mode 100644
index e7a05d8..0000000
--- a/core/tests/coretests/src/com/android/internal/logging/legacy/SysuiMultiActionParserTest.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.internal.logging.legacy;
-
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-
-import android.metrics.LogMaker;
-
-public class SysuiMultiActionParserTest extends ParserTest {
-
-    public SysuiMultiActionParserTest() {
-        mParser = new SysuiMultiActionParser();
-    }
-
-    public void testParseAllFields() {
-        int category = 10;
-        int type = 11;
-        int subtype = 12;
-        long timestamp = 1484669007890L;
-        String packageName = "com.foo.bar";
-        String counterName = "sheep";
-        int bucket = 13;
-        int value = 14;
-        LogMaker builder = new LogMaker(category);
-        builder.setType(type);
-        builder.setSubtype(subtype);
-        builder.setPackageName(packageName);
-        builder.setCounterName(counterName);
-        builder.setCounterBucket(bucket);
-        builder.setCounterValue(value);
-        builder.addTaggedData(1, "one");
-        builder.addTaggedData(2, "two");
-        Object[] out = builder.serialize();
-        int t = 1000;
-
-        mParser.parseEvent(mLogger, timestamp, out);
-
-        verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
-
-        LogMaker proto = mProtoCaptor.getValue();
-        assertEquals(category, proto.getCategory());
-        assertEquals(type, proto.getType());
-        assertEquals(subtype, proto.getSubtype());
-        assertEquals(timestamp, proto.getTimestamp());
-        assertEquals(packageName, proto.getPackageName());
-        assertEquals(counterName, proto.getCounterName());
-        assertEquals(bucket, proto.getCounterBucket());
-        assertEquals(value, proto.getCounterValue());
-        assertEquals("one", proto.getTaggedData(1));
-        assertEquals("two", proto.getTaggedData(2));
-    }
-}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java
index 0bdf7ca..e152163 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java
@@ -48,9 +48,11 @@
 
         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_RECEIVER);
         bi.noteStartSensorLocked(UID, SENSOR_ID);
+        bi.noteStartSensorLocked(UID, SENSOR_ID);
         clocks.realtime = 400;
         clocks.uptime = 400;
         bi.noteStopSensorLocked(UID, SENSOR_ID);
+        bi.noteStopSensorLocked(UID, SENSOR_ID);
 
         BatteryStats.Timer sensorTimer = bi.getUidStats().get(UID).getSensorStats()
                 .get(SENSOR_ID).getSensorTime();
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk
index 836ede6..14b032e 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk
@@ -31,9 +31,28 @@
 
 LOCAL_JAVACFLAGS := -nowarn
 
+mainDexList:= \
+    $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
+
+LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
 LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.preprocessor=true\
     -D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true
 
+#################################
+include $(BUILD_SYSTEM)/configure_local_jack.mk
+#################################
+
+ifdef LOCAL_JACK_ENABLED
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp
+endif
 
 include $(BUILD_PACKAGE)
+
+ifndef LOCAL_JACK_ENABLED
+$(mainDexList): $(full_classes_proguard_jar) | $(MAINDEXCLASSES)
+	$(hide) mkdir -p $(dir $@)
+	$(MAINDEXCLASSES) $< 1>$@
+	echo "com/android/multidexlegacyandexception/Test.class" >> $@
+
+$(built_dex_intermediate): $(mainDexList)
+endif
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk
index 2915914..208eceb 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk
@@ -29,13 +29,32 @@
 
 LOCAL_DEX_PREOPT := false
 
+mainDexList:= \
+	$(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
+
+LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
 LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.preprocessor=true\
     -D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true
 
+#################################
+include $(BUILD_SYSTEM)/configure_local_jack.mk
+#################################
+
+ifdef LOCAL_JACK_ENABLED
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp
+endif
 
 include $(BUILD_PACKAGE)
 
+ifndef LOCAL_JACK_ENABLED
+$(mainDexList): $(full_classes_proguard_jar) | $(MAINDEXCLASSES)
+	$(hide) mkdir -p $(dir $@)
+	$(MAINDEXCLASSES) $< 1>$@
+	echo "com/android/multidexlegacytestapp/Test.class" >> $@
+
+$(built_dex_intermediate): $(mainDexList)
+endif
+
 ## The application with a full main dex
 include $(CLEAR_VARS)
 
@@ -51,9 +70,28 @@
 
 LOCAL_DEX_PREOPT := false
 
+mainDexList2:= \
+	$(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
+
+LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList2)
 LOCAL_JACK_FLAGS := -D jack.dex.output.policy=multidex -D jack.preprocessor=true\
     -D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true
 
+#################################
+include $(BUILD_SYSTEM)/configure_local_jack.mk
+#################################
+
+ifdef LOCAL_JACK_ENABLED
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp
+endif
 
 include $(BUILD_PACKAGE)
+
+ifndef LOCAL_JACK_ENABLED
+$(mainDexList2): $(full_classes_proguard_jar) | $(MAINDEXCLASSES)
+	$(hide) mkdir -p $(dir $@)
+	$(MAINDEXCLASSES) $< 1>$@
+	echo "com/android/multidexlegacytestapp/Test.class" >> $@
+
+$(built_dex_intermediate): $(mainDexList2)
+endif
\ No newline at end of file
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk
index 2732372..99bcd6c 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk
@@ -26,8 +26,20 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := android-support-multidex
 
+mainDexList:= \
+	$(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
+
+LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
 LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.dex.output.multidex.legacy=true
 
 LOCAL_DEX_PREOPT := false
 
 include $(BUILD_PACKAGE)
+
+ifndef LOCAL_JACK_ENABLED
+$(mainDexList): $(full_classes_proguard_jar) | $(MAINDEXCLASSES)
+	$(hide) mkdir -p $(dir $@)
+	$(MAINDEXCLASSES) $< 1>$@
+
+$(built_dex_intermediate): $(mainDexList)
+endif
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk
index b4a666f..1c7d807 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk
@@ -28,9 +28,28 @@
 
 LOCAL_DEX_PREOPT := false
 
+mainDexList:= \
+	$(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
+
+LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
 LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.preprocessor=true\
     -D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true
 
+#################################
+include $(BUILD_SYSTEM)/configure_local_jack.mk
+#################################
+
+ifdef LOCAL_JACK_ENABLED
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp
+endif
 
 include $(BUILD_PACKAGE)
+
+ifndef LOCAL_JACK_ENABLED
+$(mainDexList): $(full_classes_proguard_jar) | $(MAINDEXCLASSES)
+	$(hide) mkdir -p $(dir $@)
+	$(MAINDEXCLASSES) $< 1>$@
+	echo "com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.class" >> $@
+
+$(built_dex_intermediate): $(mainDexList)
+endif
\ No newline at end of file
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk
index f38bd4f..b77cf31 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk
@@ -28,9 +28,28 @@
 
 LOCAL_DEX_PREOPT := false
 
+mainDexList:= \
+	$(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
+
+LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
 LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.preprocessor=true\
     -D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true
 
+#################################
+include $(BUILD_SYSTEM)/configure_local_jack.mk
+#################################
+
+ifdef LOCAL_JACK_ENABLED
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp
+endif
 
 include $(BUILD_PACKAGE)
+
+ifndef LOCAL_JACK_ENABLED
+$(mainDexList): $(full_classes_proguard_jar) | $(MAINDEXCLASSES)
+	$(hide) mkdir -p $(dir $@)
+	$(MAINDEXCLASSES) $< 1>$@
+	echo "com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.class" >> $@
+
+$(built_dex_intermediate): $(mainDexList)
+endif
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk
index 5bc2c95..3631626 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk
@@ -26,11 +26,31 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := android-support-multidex
 
+mainDexList:= \
+	$(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
+
 LOCAL_DEX_PREOPT := false
 
+LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
 LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.preprocessor=true\
     -D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true
 
+#################################
+include $(BUILD_SYSTEM)/configure_local_jack.mk
+#################################
+
+ifdef LOCAL_JACK_ENABLED
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp
+endif
 
 include $(BUILD_PACKAGE)
+
+ifndef LOCAL_JACK_ENABLED
+$(mainDexList): $(full_classes_proguard_jar) | $(MAINDEXCLASSES)
+	$(hide) mkdir -p $(dir $@)
+	$(MAINDEXCLASSES) $< 1>$@
+	echo "com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.class" >> $@
+
+$(built_dex_intermediate): $(mainDexList)
+endif
+
diff --git a/core/tests/systemproperties/Android.mk b/core/tests/systemproperties/Android.mk
index e16c367..4c2e224 100644
--- a/core/tests/systemproperties/Android.mk
+++ b/core/tests/systemproperties/Android.mk
@@ -8,6 +8,7 @@
 LOCAL_SRC_FILES := \
 	$(call all-java-files-under, src)
 
+LOCAL_DX_FLAGS := --core-library
 LOCAL_STATIC_JAVA_LIBRARIES := android-common frameworks-core-util-lib
 LOCAL_JAVA_LIBRARIES := android.test.runner
 LOCAL_PACKAGE_NAME := FrameworksCoreSystemPropertiesTests
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 5226fe5..77a1035 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -139,6 +139,7 @@
         <permission name="android.permission.CHANGE_CONFIGURATION"/>
         <permission name="android.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST"/>
         <permission name="android.permission.CONNECTIVITY_INTERNAL"/>
+        <permission name="android.permission.CONTROL_INCALL_EXPERIENCE"/>
         <permission name="android.permission.DUMP"/>
         <permission name="android.permission.INTERACT_ACROSS_USERS"/>
         <permission name="android.permission.LOCAL_MAC_ADDRESS"/>
@@ -253,6 +254,7 @@
         <permission name="android.permission.BIND_APPWIDGET"/>
         <permission name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"/>
         <permission name="android.permission.CHANGE_CONFIGURATION"/>
+        <permission name="android.permission.CHANGE_OVERLAY_PACKAGES"/>
         <permission name="android.permission.CONNECTIVITY_INTERNAL"/>
         <permission name="android.permission.DELETE_CACHE_FILES"/>
         <permission name="android.permission.DELETE_PACKAGES"/>
@@ -262,6 +264,7 @@
         <permission name="android.permission.INSTALL_LOCATION_PROVIDER"/>
         <permission name="android.permission.INSTALL_PACKAGES"/>
         <permission name="android.permission.INTERACT_ACROSS_USERS"/>
+        <permission name="android.permission.LOCAL_MAC_ADDRESS"/>
         <permission name="android.permission.MANAGE_ACTIVITY_STACKS"/>
         <permission name="android.permission.MANAGE_DEVICE_ADMINS"/>
         <permission name="android.permission.MANAGE_USB"/>
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index d8e6db7..76598a0 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -1,8 +1,22 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-    All fonts without names are added to the default list. Fonts are chosen
-    based on a match: full BCP-47 language tag including script, then just
-    language, and finally order (the first font containing the glyph).
+    WARNING: Parsing of this file by third-party apps is not supported. The
+    file, and the font files it refers to, will be renamed and/or moved out
+    from their respective location in the next Android release, and/or the
+    format or syntax of the file may change significantly. You must not
+    parse this file for information about system fonts. Instead, you must
+    call android.text.FontManager#getSystemFonts(). For example, it can be
+    called as context.getSystemService(FontManager.class).getSystemFonts().
+    Note that the returned FontConfig includes data on all the defined font
+    families and all the details about weight, style, etc. It also provides
+    an open file descriptor to each font file. Note that callers of the API
+    should ensure they close the given file descriptors once they are done
+    using them.
+
+    In this file, all fonts without names are added to the default list.
+    Fonts are chosen based on a match: full BCP-47 language tag including
+    script, then just language, and finally order (the first font containing
+    the glyph).
 
     Order of appearance is also the tiebreaker for weight matching. This is
     the reason why the 900 weights of Roboto precede the 700 weights - we
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index ba7f05d..3d5ba79 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -19,12 +19,12 @@
 import android.annotation.CheckResult;
 import android.annotation.ColorInt;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.Trace;
 import android.util.DisplayMetrics;
 import android.util.Log;
-
 import libcore.util.NativeAllocationRegistry;
 
 import java.io.OutputStream;
@@ -73,6 +73,8 @@
     private int mHeight;
     private boolean mRecycled;
 
+    private ColorSpace mColorSpace;
+
     /** @hide */
     public int mDensity = getDefaultDensity();
 
@@ -145,6 +147,7 @@
         mWidth = width;
         mHeight = height;
         mRequestPremultiplied = requestPremultiplied;
+        mColorSpace = null;
     }
 
     /**
@@ -252,6 +255,7 @@
         nativeReconfigure(mNativePtr, width, height, config.nativeInt, mRequestPremultiplied);
         mWidth = width;
         mHeight = height;
+        mColorSpace = null;
     }
 
     /**
@@ -518,7 +522,7 @@
      * <p>The content of the bitmap is copied into the buffer as-is. This means
      * that if this bitmap stores its pixels pre-multiplied
      * (see {@link #isPremultiplied()}, the values in the buffer will also be
-     * pre-multiplied.</p>
+     * pre-multiplied. The pixels remain in the color space of the bitmap.</p>
      * <p>After this method returns, the current position of the buffer is
      * updated: the position is incremented by the number of elements written
      * in the buffer.</p>
@@ -558,7 +562,8 @@
      * <p>Copy the pixels from the buffer, beginning at the current position,
      * overwriting the bitmap's pixels. The data in the buffer is not changed
      * in any way (unlike setPixels(), which converts from unpremultipled 32bit
-     * to whatever the bitmap's native format is.</p>
+     * to whatever the bitmap's native format is. The pixels in the source
+     * buffer are assumed to be in the bitmap's color space.</p>
      * <p>After this method returns, the current position of the buffer is
      * updated: the position is incremented by the number of elements read from
      * the buffer. If you need to read the bitmap from the buffer again you must
@@ -1435,6 +1440,47 @@
     }
 
     /**
+     * Returns the color space associated with this bitmap. If the color
+     * space is unknown, this method returns null.
+     */
+    @Nullable
+    public final ColorSpace getColorSpace() {
+        // A reconfigure can change the configuration and rgba16f is
+        // always linear scRGB at this time
+        if (getConfig() == Config.RGBA_F16) {
+            // Reset the color space for potential future reconfigurations
+            mColorSpace = null;
+            return ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB);
+        }
+
+        // Cache the color space retrieval since it can be fairly expensive
+        if (mColorSpace == null) {
+            if (nativeIsSRGB(mNativePtr)) {
+                mColorSpace = ColorSpace.get(ColorSpace.Named.SRGB);
+            } else {
+                float[] xyz = new float[9];
+                float[] params = new float[7];
+
+                boolean hasColorSpace = nativeGetColorSpace(mNativePtr, xyz, params);
+                if (hasColorSpace) {
+                    ColorSpace.Rgb.TransferParameters parameters =
+                            new ColorSpace.Rgb.TransferParameters(
+                                    params[0], params[1], params[2],
+                                    params[3], params[4], params[5], params[6]);
+                    ColorSpace cs = ColorSpace.match(xyz, parameters);
+                    if (cs != null) {
+                        mColorSpace = cs;
+                    } else {
+                        mColorSpace = new ColorSpace.Rgb("Unknown", xyz, parameters);
+                    }
+                }
+            }
+        }
+
+        return mColorSpace;
+    }
+
+    /**
      * Fills the bitmap's pixels with the specified {@link Color}.
      *
      * @throws IllegalStateException if the bitmap is not mutable.
@@ -1450,7 +1496,8 @@
     /**
      * Returns the {@link Color} at the specified location. Throws an exception
      * if x or y are out of bounds (negative or >= to the width or height
-     * respectively). The returned color is a non-premultiplied ARGB value.
+     * respectively). The returned color is a non-premultiplied ARGB value in
+     * the {@link ColorSpace.Named#SRGB sRGB} color space.
      *
      * @param x    The x coordinate (0...width-1) of the pixel to return
      * @param y    The y coordinate (0...height-1) of the pixel to return
@@ -1472,7 +1519,8 @@
      * a packed int representing a {@link Color}. The stride parameter allows
      * the caller to allow for gaps in the returned pixels array between
      * rows. For normal packed results, just pass width for the stride value.
-     * The returned colors are non-premultiplied ARGB values.
+     * The returned colors are non-premultiplied ARGB values in the
+     * {@link ColorSpace.Named#SRGB sRGB} color space.
      *
      * @param pixels   The array to receive the bitmap's colors
      * @param offset   The first index to write into pixels[]
@@ -1565,7 +1613,8 @@
     /**
      * <p>Write the specified {@link Color} into the bitmap (assuming it is
      * mutable) at the x,y coordinate. The color must be a
-     * non-premultiplied ARGB value.</p>
+     * non-premultiplied ARGB value in the {@link ColorSpace.Named#SRGB sRGB}
+     * color space.</p>
      *
      * @param x     The x coordinate of the pixel to replace (0...width-1)
      * @param y     The y coordinate of the pixel to replace (0...height-1)
@@ -1587,7 +1636,7 @@
     /**
      * <p>Replace pixels in the bitmap with the colors in the array. Each element
      * in the array is a packed int representing a non-premultiplied ARGB
-     * {@link Color}.</p>
+     * {@link Color} in the {@link ColorSpace.Named#SRGB sRGB} color space.</p>
      *
      * @param pixels   The colors to write to the bitmap
      * @param offset   The index of the first color to read from pixels[]
@@ -1816,4 +1865,6 @@
     private static native Bitmap nativeCopyPreserveInternalConfig(long nativeBitmap);
     private static native Bitmap nativeCreateHardwareBitmap(GraphicBuffer buffer);
     private static native GraphicBuffer nativeCreateGraphicBufferHandle(long nativeBitmap);
+    private static native boolean nativeGetColorSpace(long nativePtr, float[] xyz, float[] params);
+    private static native boolean nativeIsSRGB(long nativePtr);
 }
diff --git a/graphics/java/android/graphics/Color.java b/graphics/java/android/graphics/Color.java
index ff21cac..33d19d4 100644
--- a/graphics/java/android/graphics/Color.java
+++ b/graphics/java/android/graphics/Color.java
@@ -1023,9 +1023,9 @@
                     "The color space must use a color model with at most 3 components");
         }
 
-        @HalfFloat short r = Half.valueOf(red);
-        @HalfFloat short g = Half.valueOf(green);
-        @HalfFloat short b = Half.valueOf(blue);
+        @HalfFloat short r = Half.toHalf(red);
+        @HalfFloat short g = Half.toHalf(green);
+        @HalfFloat short b = Half.toHalf(blue);
 
         int a = (int) (Math.max(0.0f, Math.min(alpha, 1.0f)) * 1023.0f + 0.5f);
 
diff --git a/graphics/java/android/graphics/ColorSpace.java b/graphics/java/android/graphics/ColorSpace.java
index ec00c45..908ec50 100644
--- a/graphics/java/android/graphics/ColorSpace.java
+++ b/graphics/java/android/graphics/ColorSpace.java
@@ -20,8 +20,8 @@
 import android.annotation.ColorInt;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
-import android.annotation.Size;
 import android.annotation.Nullable;
+import android.annotation.Size;
 import android.util.Pair;
 
 import java.util.ArrayList;
@@ -263,18 +263,18 @@
          *     <tr><td>Name</td><td colspan="4">sRGB IEC61966-2.1</td></tr>
          *     <tr><td>CIE standard illuminant</td><td colspan="4">D65</td></tr>
          *     <tr>
-         *         <td>Opto-electronic transfer function</td>
+         *         <td>Opto-electronic transfer function (OETF)</td>
          *         <td colspan="4">\(\begin{equation}
-         *             C_{sRGB} = \begin{cases} 12.92 \times C_{linear} & C_{linear} \le 0.0031308 \\
-         *             1.055 \times C_{linear}^{\frac{1}{2.4}} - 0.055 & C_{linear} \gt 0.0031308 \end{cases}
+         *             C_{sRGB} = \begin{cases} 12.92 \times C_{linear} & C_{linear} \lt 0.0031308 \\
+         *             1.055 \times C_{linear}^{\frac{1}{2.4}} - 0.055 & C_{linear} \ge 0.0031308 \end{cases}
          *             \end{equation}\)
          *         </td>
          *     </tr>
          *     <tr>
-         *         <td>Electro-optical transfer function</td>
+         *         <td>Electro-optical transfer function (EOTF)</td>
          *         <td colspan="4">\(\begin{equation}
-         *             C_{linear} = \begin{cases}\frac{C_{sRGB}}{12.92} & C_{sRGB} \le 0.04045 \\
-         *             \left( \frac{C_{sRGB} + 0.055}{1.055} \right) ^{2.4} & C_{sRGB} \gt 0.04045 \end{cases}
+         *             C_{linear} = \begin{cases}\frac{C_{sRGB}}{12.92} & C_{sRGB} \lt 0.04045 \\
+         *             \left( \frac{C_{sRGB} + 0.055}{1.055} \right) ^{2.4} & C_{sRGB} \ge 0.04045 \end{cases}
          *             \end{equation}\)
          *         </td>
          *     </tr>
@@ -298,11 +298,11 @@
          *     <tr><td>Name</td><td colspan="4">sRGB IEC61966-2.1 (Linear)</td></tr>
          *     <tr><td>CIE standard illuminant</td><td colspan="4">D65</td></tr>
          *     <tr>
-         *         <td>Opto-electronic transfer function</td>
+         *         <td>Opto-electronic transfer function (OETF)</td>
          *         <td colspan="4">\(C_{sRGB} = C_{linear}\)</td>
          *     </tr>
          *     <tr>
-         *         <td>Electro-optical transfer function</td>
+         *         <td>Electro-optical transfer function (EOTF)</td>
          *         <td colspan="4">\(C_{linear} = C_{sRGB}\)</td>
          *     </tr>
          *     <tr><td>Range</td><td colspan="4">\([0..1]\)</td></tr>
@@ -325,22 +325,22 @@
          *     <tr><td>Name</td><td colspan="4">scRGB-nl IEC 61966-2-2:2003</td></tr>
          *     <tr><td>CIE standard illuminant</td><td colspan="4">D65</td></tr>
          *     <tr>
-         *         <td>Opto-electronic transfer function</td>
+         *         <td>Opto-electronic transfer function (OETF)</td>
          *         <td colspan="4">\(\begin{equation}
          *             C_{scRGB} = \begin{cases} sign(C_{linear}) 12.92 \times \left| C_{linear} \right| &
-         *                      \left| C_{linear} \right| \le 0.0031308 \\
+         *                      \left| C_{linear} \right| \lt 0.0031308 \\
          *             sign(C_{linear}) 1.055 \times \left| C_{linear} \right| ^{\frac{1}{2.4}} - 0.055 &
-         *                      \left| C_{linear} \right| \gt 0.0031308 \end{cases}
+         *                      \left| C_{linear} \right| \ge 0.0031308 \end{cases}
          *             \end{equation}\)
          *         </td>
          *     </tr>
          *     <tr>
-         *         <td>Electro-optical transfer function</td>
+         *         <td>Electro-optical transfer function (EOTF)</td>
          *         <td colspan="4">\(\begin{equation}
          *             C_{linear} = \begin{cases}sign(C_{scRGB}) \frac{\left| C_{scRGB} \right|}{12.92} &
-         *                  \left| C_{scRGB} \right| \le 0.04045 \\
+         *                  \left| C_{scRGB} \right| \lt 0.04045 \\
          *             sign(C_{scRGB}) \left( \frac{\left| C_{scRGB} \right| + 0.055}{1.055} \right) ^{2.4} &
-         *                  \left| C_{scRGB} \right| \gt 0.04045 \end{cases}
+         *                  \left| C_{scRGB} \right| \ge 0.04045 \end{cases}
          *             \end{equation}\)
          *         </td>
          *     </tr>
@@ -364,11 +364,11 @@
          *     <tr><td>Name</td><td colspan="4">scRGB IEC 61966-2-2:2003</td></tr>
          *     <tr><td>CIE standard illuminant</td><td colspan="4">D65</td></tr>
          *     <tr>
-         *         <td>Opto-electronic transfer function</td>
+         *         <td>Opto-electronic transfer function (OETF)</td>
          *         <td colspan="4">\(C_{scRGB} = C_{linear}\)</td>
          *     </tr>
          *     <tr>
-         *         <td>Electro-optical transfer function</td>
+         *         <td>Electro-optical transfer function (EOTF)</td>
          *         <td colspan="4">\(C_{linear} = C_{scRGB}\)</td>
          *     </tr>
          *     <tr><td>Range</td><td colspan="4">\([-0.5..7.499[\)</td></tr>
@@ -391,7 +391,7 @@
          *     <tr><td>Name</td><td colspan="4">Rec. ITU-R BT.709-5</td></tr>
          *     <tr><td>CIE standard illuminant</td><td colspan="4">D65</td></tr>
          *     <tr>
-         *         <td>Opto-electronic transfer function</td>
+         *         <td>Opto-electronic transfer function (OETF)</td>
          *         <td colspan="4">\(\begin{equation}
          *             C_{BT709} = \begin{cases} 4.5 \times C_{linear} & C_{linear} \lt 0.018 \\
          *             1.099 \times C_{linear}^{\frac{1}{2.2}} - 0.099 & C_{linear} \ge 0.018 \end{cases}
@@ -399,7 +399,7 @@
          *         </td>
          *     </tr>
          *     <tr>
-         *         <td>Electro-optical transfer function</td>
+         *         <td>Electro-optical transfer function (EOTF)</td>
          *         <td colspan="4">\(\begin{equation}
          *             C_{linear} = \begin{cases}\frac{C_{BT709}}{4.5} & C_{BT709} \lt 0.081 \\
          *             \left( \frac{C_{BT709} + 0.099}{1.099} \right) ^{2.2} & C_{BT709} \ge 0.081 \end{cases}
@@ -426,7 +426,7 @@
          *     <tr><td>Name</td><td colspan="4">Rec. ITU-R BT.2020-1</td></tr>
          *     <tr><td>CIE standard illuminant</td><td colspan="4">D65</td></tr>
          *     <tr>
-         *         <td>Opto-electronic transfer function</td>
+         *         <td>Opto-electronic transfer function (OETF)</td>
          *         <td colspan="4">\(\begin{equation}
          *             C_{BT2020} = \begin{cases} 4.5 \times C_{linear} & C_{linear} \lt 0.0181 \\
          *             1.0993 \times C_{linear}^{\frac{1}{2.2}} - 0.0993 & C_{linear} \ge 0.0181 \end{cases}
@@ -434,7 +434,7 @@
          *         </td>
          *     </tr>
          *     <tr>
-         *         <td>Electro-optical transfer function</td>
+         *         <td>Electro-optical transfer function (EOTF)</td>
          *         <td colspan="4">\(\begin{equation}
          *             C_{linear} = \begin{cases}\frac{C_{BT2020}}{4.5} & C_{BT2020} \lt 0.08145 \\
          *             \left( \frac{C_{BT2020} + 0.0993}{1.0993} \right) ^{2.2} & C_{BT2020} \ge 0.08145 \end{cases}
@@ -461,11 +461,11 @@
          *     <tr><td>Name</td><td colspan="4">SMPTE RP 431-2-2007 DCI (P3)</td></tr>
          *     <tr><td>CIE standard illuminant</td><td colspan="4">N/A</td></tr>
          *     <tr>
-         *         <td>Opto-electronic transfer function</td>
+         *         <td>Opto-electronic transfer function (OETF)</td>
          *         <td colspan="4">\(C_{P3} = C_{linear}^{\frac{1}{2.6}}\)</td>
          *     </tr>
          *     <tr>
-         *         <td>Electro-optical transfer function</td>
+         *         <td>Electro-optical transfer function (EOTF)</td>
          *         <td colspan="4">\(C_{linear} = C_{P3}^{2.6}\)</td>
          *     </tr>
          *     <tr><td>Range</td><td colspan="4">\([0..1]\)</td></tr>
@@ -488,18 +488,18 @@
          *     <tr><td>Name</td><td colspan="4">Display P3</td></tr>
          *     <tr><td>CIE standard illuminant</td><td colspan="4">D65</td></tr>
          *     <tr>
-         *         <td>Opto-electronic transfer function</td>
+         *         <td>Opto-electronic transfer function (OETF)</td>
          *         <td colspan="4">\(\begin{equation}
-         *             C_{sRGB} = \begin{cases} 12.92 \times C_{linear} & C_{linear} \le 0.0031308 \\
-         *             1.055 \times C_{linear}^{\frac{1}{2.4}} - 0.055 & C_{linear} \gt 0.0031308 \end{cases}
+         *             C_{sRGB} = \begin{cases} 12.92 \times C_{linear} & C_{linear} \lt 0.0031308 \\
+         *             1.055 \times C_{linear}^{\frac{1}{2.4}} - 0.055 & C_{linear} \ge 0.0031308 \end{cases}
          *             \end{equation}\)
          *         </td>
          *     </tr>
          *     <tr>
-         *         <td>Electro-optical transfer function</td>
+         *         <td>Electro-optical transfer function (EOTF)</td>
          *         <td colspan="4">\(\begin{equation}
-         *             C_{linear} = \begin{cases}\frac{C_{sRGB}}{12.92} & C_{sRGB} \le 0.04045 \\
-         *             \left( \frac{C_{sRGB} + 0.055}{1.055} \right) ^{2.4} & C_{sRGB} \gt 0.04045 \end{cases}
+         *             C_{linear} = \begin{cases}\frac{C_{sRGB}}{12.92} & C_{sRGB} \lt 0.04045 \\
+         *             \left( \frac{C_{sRGB} + 0.055}{1.055} \right) ^{2.4} & C_{sRGB} \ge 0.04045 \end{cases}
          *             \end{equation}\)
          *         </td>
          *     </tr>
@@ -523,7 +523,7 @@
          *     <tr><td>Name</td><td colspan="4">NTSC (1953)</td></tr>
          *     <tr><td>CIE standard illuminant</td><td colspan="4">C</td></tr>
          *     <tr>
-         *         <td>Opto-electronic transfer function</td>
+         *         <td>Opto-electronic transfer function (OETF)</td>
          *         <td colspan="4">\(\begin{equation}
          *             C_{BT709} = \begin{cases} 4.5 \times C_{linear} & C_{linear} \lt 0.018 \\
          *             1.099 \times C_{linear}^{\frac{1}{2.2}} - 0.099 & C_{linear} \ge 0.018 \end{cases}
@@ -531,7 +531,7 @@
          *         </td>
          *     </tr>
          *     <tr>
-         *         <td>Electro-optical transfer function</td>
+         *         <td>Electro-optical transfer function (EOTF)</td>
          *         <td colspan="4">\(\begin{equation}
          *             C_{linear} = \begin{cases}\frac{C_{BT709}}{4.5} & C_{BT709} \lt 0.081 \\
          *             \left( \frac{C_{BT709} + 0.099}{1.099} \right) ^{2.2} & C_{BT709} \ge 0.081 \end{cases}
@@ -558,7 +558,7 @@
          *     <tr><td>Name</td><td colspan="4">SMPTE-C RGB</td></tr>
          *     <tr><td>CIE standard illuminant</td><td colspan="4">D65</td></tr>
          *     <tr>
-         *         <td>Opto-electronic transfer function</td>
+         *         <td>Opto-electronic transfer function (OETF)</td>
          *         <td colspan="4">\(\begin{equation}
          *             C_{BT709} = \begin{cases} 4.5 \times C_{linear} & C_{linear} \lt 0.018 \\
          *             1.099 \times C_{linear}^{\frac{1}{2.2}} - 0.099 & C_{linear} \ge 0.018 \end{cases}
@@ -566,7 +566,7 @@
          *         </td>
          *     </tr>
          *     <tr>
-         *         <td>Electro-optical transfer function</td>
+         *         <td>Electro-optical transfer function (EOTF)</td>
          *         <td colspan="4">\(\begin{equation}
          *             C_{linear} = \begin{cases}\frac{C_{BT709}}{4.5} & C_{BT709} \lt 0.081 \\
          *             \left( \frac{C_{BT709} + 0.099}{1.099} \right) ^{2.2} & C_{BT709} \ge 0.081 \end{cases}
@@ -593,11 +593,11 @@
          *     <tr><td>Name</td><td colspan="4">Adobe RGB (1998)</td></tr>
          *     <tr><td>CIE standard illuminant</td><td colspan="4">D65</td></tr>
          *     <tr>
-         *         <td>Opto-electronic transfer function</td>
+         *         <td>Opto-electronic transfer function (OETF)</td>
          *         <td colspan="4">\(C_{RGB} = C_{linear}^{\frac{1}{2.2}}\)</td>
          *     </tr>
          *     <tr>
-         *         <td>Electro-optical transfer function</td>
+         *         <td>Electro-optical transfer function (EOTF)</td>
          *         <td colspan="4">\(C_{linear} = C_{RGB}^{2.2}\)</td>
          *     </tr>
          *     <tr><td>Range</td><td colspan="4">\([0..1]\)</td></tr>
@@ -620,7 +620,7 @@
          *     <tr><td>Name</td><td colspan="4">ROMM RGB ISO 22028-2:2013</td></tr>
          *     <tr><td>CIE standard illuminant</td><td colspan="4">D50</td></tr>
          *     <tr>
-         *         <td>Opto-electronic transfer function</td>
+         *         <td>Opto-electronic transfer function (OETF)</td>
          *         <td colspan="4">\(\begin{equation}
          *             C_{ROMM} = \begin{cases} 16 \times C_{linear} & C_{linear} \lt 0.001953 \\
          *             C_{linear}^{\frac{1}{1.8}} & C_{linear} \ge 0.001953 \end{cases}
@@ -628,7 +628,7 @@
          *         </td>
          *     </tr>
          *     <tr>
-         *         <td>Electro-optical transfer function</td>
+         *         <td>Electro-optical transfer function (EOTF)</td>
          *         <td colspan="4">\(\begin{equation}
          *             C_{linear} = \begin{cases}\frac{C_{ROMM}}{16} & C_{ROMM} \lt 0.031248 \\
          *             C_{ROMM}^{1.8} & C_{ROMM} \ge 0.031248 \end{cases}
@@ -655,11 +655,11 @@
          *     <tr><td>Name</td><td colspan="4">SMPTE ST 2065-1:2012 ACES</td></tr>
          *     <tr><td>CIE standard illuminant</td><td colspan="4">D60</td></tr>
          *     <tr>
-         *         <td>Opto-electronic transfer function</td>
+         *         <td>Opto-electronic transfer function (OETF)</td>
          *         <td colspan="4">\(C_{ACES} = C_{linear}\)</td>
          *     </tr>
          *     <tr>
-         *         <td>Electro-optical transfer function</td>
+         *         <td>Electro-optical transfer function (EOTF)</td>
          *         <td colspan="4">\(C_{linear} = C_{ACES}\)</td>
          *     </tr>
          *     <tr><td>Range</td><td colspan="4">\([-65504.0, 65504.0]\)</td></tr>
@@ -682,11 +682,11 @@
          *     <tr><td>Name</td><td colspan="4">Academy S-2014-004 ACEScg</td></tr>
          *     <tr><td>CIE standard illuminant</td><td colspan="4">D60</td></tr>
          *     <tr>
-         *         <td>Opto-electronic transfer function</td>
+         *         <td>Opto-electronic transfer function (OETF)</td>
          *         <td colspan="4">\(C_{ACEScg} = C_{linear}\)</td>
          *     </tr>
          *     <tr>
-         *         <td>Electro-optical transfer function</td>
+         *         <td>Electro-optical transfer function (EOTF)</td>
          *         <td colspan="4">\(C_{linear} = C_{ACEScg}\)</td>
          *     </tr>
          *     <tr><td>Range</td><td colspan="4">\([-65504.0, 65504.0]\)</td></tr>
@@ -805,7 +805,8 @@
      */
     public enum Adaptation {
         /**
-         * Bradford matrix for the von Kries chromatic adaptation transform.
+         * Bradford chromatic adaptation transform, as defined in the
+         * CIECAM97s color appearance model.
          */
         BRADFORD(new float[] {
                  0.8951f, -0.7502f,  0.0389f,
@@ -813,12 +814,21 @@
                 -0.1614f,  0.0367f,  1.0296f
         }),
         /**
-         * von Kries matrix for the von Kries chromatic adaptation transform.
+         * von Kries chromatic adaptation transform.
          */
         VON_KRIES(new float[] {
                  0.40024f, -0.22630f, 0.00000f,
                  0.70760f,  1.16532f, 0.00000f,
                 -0.08081f,  0.04570f, 0.91822f
+        }),
+        /**
+         * CIECAT02 chromatic adaption transform, as defined in the
+         * CIECAM02 color appearance model.
+         */
+        CIECAT02(new float[] {
+                 0.7328f, -0.7036f,  0.0030f,
+                 0.4296f,  1.6975f,  0.0136f,
+                -0.1624f,  0.0061f,  0.9834f
         });
 
         final float[] mTransform;
@@ -1369,6 +1379,37 @@
     }
 
     /**
+     * <p>Returns a {@link Named} instance of {@link ColorSpace} that matches
+     * the specified RGB to CIE XYZ transform and transfer functions. If no
+     * instance can be found, this method returns null.</p>
+     *
+     * <p>The color transform matrix is assumed to target the CIE XYZ space
+     * a {@link #ILLUMINANT_D50 D50} standard illuminant.</p>
+     *
+     * @param toXYZD50 3x3 column-major transform matrix from RGB to the profile
+     *                 connection space CIE XYZ as an array of 9 floats, cannot be null
+     * @param function Parameters for the transfer functions
+     * @return A non-null {@link ColorSpace} if a match is found, null otherwise
+     */
+    @Nullable
+    public static ColorSpace match(
+            @NonNull @Size(9) float[] toXYZD50,
+            @NonNull Rgb.TransferParameters function) {
+
+        for (ColorSpace colorSpace : sNamedColorSpaces) {
+            if (colorSpace.getModel() == Model.RGB) {
+                ColorSpace.Rgb rgb = (ColorSpace.Rgb) adapt(colorSpace, ILLUMINANT_D50_XYZ);
+                if (compare(toXYZD50, rgb.mTransform) &&
+                        compare(function, rgb.mTransferParameters)) {
+                    return colorSpace;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    /**
      * <p>Creates a new {@link Renderer} that can be used to visualize and
      * debug color spaces. See the documentation of {@link Renderer} for
      * more information.</p>
@@ -1387,17 +1428,14 @@
                 "sRGB IEC61966-2.1",
                 SRGB_PRIMARIES,
                 ILLUMINANT_D65,
-                x -> rcpResponse(x, 2.4, 1 / 1.055, 0.055 / 1.055, 1 / 12.92, 0.04045),
-                x -> response(x, 2.4, 1 / 1.055, 0.055 / 1.055, 1 / 12.92, 0.04045),
-                0.0f, 1.0f,
+                new Rgb.TransferParameters(1 / 1.055, 0.055 / 1.055, 1 / 12.92, 0.04045, 2.4),
                 Named.SRGB.ordinal()
         );
         sNamedColorSpaces[Named.LINEAR_SRGB.ordinal()] = new ColorSpace.Rgb(
                 "sRGB IEC61966-2.1 (Linear)",
                 SRGB_PRIMARIES,
                 ILLUMINANT_D65,
-                DoubleUnaryOperator.identity(),
-                DoubleUnaryOperator.identity(),
+                1.0,
                 0.0f, 1.0f,
                 Named.LINEAR_SRGB.ordinal()
         );
@@ -1405,17 +1443,16 @@
                 "scRGB-nl IEC 61966-2-2:2003",
                 SRGB_PRIMARIES,
                 ILLUMINANT_D65,
-                x -> absRcpResponse(x, 2.4, 1 / 1.055, 0.055 / 1.055, 1 / 12.92, 0.04045),
-                x -> absResponse(x, 2.4, 1 / 1.055, 0.055 / 1.055, 1 / 12.92, 0.04045),
+                x -> absRcpResponse(x, 1 / 1.055, 0.055 / 1.055, 1 / 12.92, 0.04045, 2.4),
+                x -> absResponse(x, 1 / 1.055, 0.055 / 1.055, 1 / 12.92, 0.04045, 2.4),
                 -0.799f, 2.399f,
                 Named.EXTENDED_SRGB.ordinal()
         );
         sNamedColorSpaces[Named.LINEAR_EXTENDED_SRGB.ordinal()] = new ColorSpace.Rgb(
-                "scRGB- IEC 61966-2-2:2003",
+                "scRGB IEC 61966-2-2:2003",
                 SRGB_PRIMARIES,
                 ILLUMINANT_D65,
-                DoubleUnaryOperator.identity(),
-                DoubleUnaryOperator.identity(),
+                1.0,
                 -0.5f, 7.499f,
                 Named.LINEAR_EXTENDED_SRGB.ordinal()
         );
@@ -1423,26 +1460,21 @@
                 "Rec. ITU-R BT.709-5",
                 new float[] { 0.640f, 0.330f, 0.300f, 0.600f, 0.150f, 0.060f },
                 ILLUMINANT_D65,
-                x -> rcpResponse(x, 1 / 0.45, 1 / 1.099, 0.099 / 1.099, 1 / 4.5, 0.081),
-                x -> response(x, 1 / 0.45, 1 / 1.099, 0.099 / 1.099, 1 / 4.5, 0.081),
-                0.0f, 1.0f,
+                new Rgb.TransferParameters(1 / 1.099, 0.099 / 1.099, 1 / 4.5, 0.081, 1 / 0.45),
                 Named.BT709.ordinal()
         );
         sNamedColorSpaces[Named.BT2020.ordinal()] = new ColorSpace.Rgb(
                 "Rec. ITU-R BT.2020-1",
                 new float[] { 0.708f, 0.292f, 0.170f, 0.797f, 0.131f, 0.046f },
                 ILLUMINANT_D65,
-                x -> rcpResponse(x, 1 / 0.45, 1 / 1.0993, 0.0993 / 1.0993, 1 / 4.5, 0.08145),
-                x -> response(x, 1 / 0.45, 1 / 1.0993, 0.099 / 1.0993, 1 / 4.5, 0.08145),
-                0.0f, 1.0f,
+                new Rgb.TransferParameters(1 / 1.0993, 0.0993 / 1.0993, 1 / 4.5, 0.08145, 1 / 0.45),
                 Named.BT2020.ordinal()
         );
         sNamedColorSpaces[Named.DCI_P3.ordinal()] = new ColorSpace.Rgb(
                 "SMPTE RP 431-2-2007 DCI (P3)",
                 new float[] { 0.680f, 0.320f, 0.265f, 0.690f, 0.150f, 0.060f },
                 new float[] { 0.314f, 0.351f },
-                x -> Math.pow(x < 0.0f ? 0.0f : x, 1 / 2.6),
-                x -> Math.pow(x < 0.0f ? 0.0f : x, 2.6),
+                2.6,
                 0.0f, 1.0f,
                 Named.DCI_P3.ordinal()
         );
@@ -1450,35 +1482,28 @@
                 "Display P3",
                 new float[] { 0.680f, 0.320f, 0.265f, 0.690f, 0.150f, 0.060f },
                 ILLUMINANT_D65,
-                x -> rcpResponse(x, 2.4, 1 / 1.055, 0.055 / 1.055, 1 / 12.92, 0.04045),
-                x -> response(x, 2.4, 1 / 1.055, 0.055 / 1.055, 1 / 12.92, 0.04045),
-                0.0f, 1.0f,
+                new Rgb.TransferParameters(1 / 1.055, 0.055 / 1.055, 1 / 12.92, 0.04045, 2.4),
                 Named.DISPLAY_P3.ordinal()
         );
         sNamedColorSpaces[Named.NTSC_1953.ordinal()] = new ColorSpace.Rgb(
                 "NTSC (1953)",
                 NTSC_1953_PRIMARIES,
                 ILLUMINANT_C,
-                x -> rcpResponse(x, 1 / 0.45, 1 / 1.099, 0.099 / 1.099, 1 / 4.5, 0.081),
-                x -> response(x, 1 / 0.45, 1 / 1.099, 0.099 / 1.099, 1 / 4.5, 0.081),
-                0.0f, 1.0f,
+                new Rgb.TransferParameters(1 / 1.099, 0.099 / 1.099, 1 / 4.5, 0.081, 1 / 0.45),
                 Named.NTSC_1953.ordinal()
         );
         sNamedColorSpaces[Named.SMPTE_C.ordinal()] = new ColorSpace.Rgb(
                 "SMPTE-C RGB",
                 new float[] { 0.630f, 0.340f, 0.310f, 0.595f, 0.155f, 0.070f },
                 ILLUMINANT_D65,
-                x -> rcpResponse(x, 1 / 0.45, 1 / 1.099, 0.099 / 1.099, 1 / 4.5, 0.081),
-                x -> response(x, 1 / 0.45, 1 / 1.099, 0.099 / 1.099, 1 / 4.5, 0.081),
-                0.0f, 1.0f,
+                new Rgb.TransferParameters(1 / 1.099, 0.099 / 1.099, 1 / 4.5, 0.081, 1 / 0.45),
                 Named.SMPTE_C.ordinal()
         );
         sNamedColorSpaces[Named.ADOBE_RGB.ordinal()] = new ColorSpace.Rgb(
                 "Adobe RGB (1998)",
                 new float[] { 0.64f, 0.33f, 0.21f, 0.71f, 0.15f, 0.06f },
                 ILLUMINANT_D65,
-                x -> Math.pow(x < 0.0f ? 0.0f : x, 1 / 2.2),
-                x -> Math.pow(x < 0.0f ? 0.0f : x, 2.2),
+                2.2,
                 0.0f, 1.0f,
                 Named.ADOBE_RGB.ordinal()
         );
@@ -1486,17 +1511,14 @@
                 "ROMM RGB ISO 22028-2:2013",
                 new float[] { 0.7347f, 0.2653f, 0.1596f, 0.8404f, 0.0366f, 0.0001f },
                 ILLUMINANT_D50,
-                x -> rcpResponse(x, 1.8, 1.0, 0.0, 1 / 16.0, 0.031248),
-                x -> response(x, 1.8, 1.0, 0.0, 1 / 16.0, 0.031248),
-                0.0f, 1.0f,
+                new Rgb.TransferParameters(1.0, 0.0, 1 / 16.0, 0.031248, 1.8),
                 Named.PRO_PHOTO_RGB.ordinal()
         );
         sNamedColorSpaces[Named.ACES.ordinal()] = new ColorSpace.Rgb(
                 "SMPTE ST 2065-1:2012 ACES",
                 new float[] { 0.73470f, 0.26530f, 0.0f, 1.0f, 0.00010f, -0.0770f },
                 ILLUMINANT_D60,
-                DoubleUnaryOperator.identity(),
-                DoubleUnaryOperator.identity(),
+                1.0,
                 -65504.0f, 65504.0f,
                 Named.ACES.ordinal()
         );
@@ -1504,8 +1526,7 @@
                 "Academy S-2014-004 ACEScg",
                 new float[] { 0.713f, 0.293f, 0.165f, 0.830f, 0.128f, 0.044f },
                 ILLUMINANT_D60,
-                DoubleUnaryOperator.identity(),
-                DoubleUnaryOperator.identity(),
+                1.0,
                 -65504.0f, 65504.0f,
                 Named.ACESCG.ordinal()
         );
@@ -1520,27 +1541,61 @@
     }
 
     // Reciprocal piecewise gamma response
-    private static double rcpResponse(double x, double g,double a, double b, double c, double d) {
+    private static double rcpResponse(double x, double a, double b, double c, double d, double g) {
         return x >= d * c ? (Math.pow(x, 1.0 / g) - b) / a : x / c;
     }
 
     // Piecewise gamma response
-    private static double response(double x, double g, double a, double b, double c, double d) {
+    private static double response(double x, double a, double b, double c, double d, double g) {
         return x >= d ? Math.pow(a * x + b, g) : c * x;
     }
 
+    // Reciprocal piecewise gamma response
+    private static double rcpResponse(double x, double a, double b, double c, double d,
+            double e, double f, double g) {
+        return x >= d * c ? (Math.pow(x - e, 1.0 / g) - b) / a : (x - f) / c;
+    }
+
+    // Piecewise gamma response
+    private static double response(double x, double a, double b, double c, double d,
+            double e, double f, double g) {
+        return x >= d ? Math.pow(a * x + b, g) + e : c * x + f;
+    }
+
     // Reciprocal piecewise gamma response, encoded as sign(x).f(abs(x)) for color
     // spaces that allow negative values
     @SuppressWarnings("SameParameterValue")
-    private static double absRcpResponse(double x, double g, double a, double b, double c, double d) {
-        return Math.copySign(rcpResponse(x < 0.0 ? -x : x, g, a, b, c, d), x);
+    private static double absRcpResponse(double x, double a, double b, double c, double d, double g) {
+        return Math.copySign(rcpResponse(x < 0.0 ? -x : x, a, b, c, d, g), x);
     }
 
     // Piecewise gamma response, encoded as sign(x).f(abs(x)) for color spaces that
     // allow negative values
     @SuppressWarnings("SameParameterValue")
-    private static double absResponse(double x, double g, double a, double b, double c, double d) {
-        return Math.copySign(response(x < 0.0 ? -x : x, g, a, b, c, d), x);
+    private static double absResponse(double x, double a, double b, double c, double d, double g) {
+        return Math.copySign(response(x < 0.0 ? -x : x, a, b, c, d, g), x);
+    }
+
+    /**
+     * Compares two sets of parametric transfer functions parameters with a precision of 1e-3.
+     *
+     * @param a The first set of parameters to compare
+     * @param b The second set of parameters to compare
+     * @return True if the two sets are equal, false otherwise
+     */
+    private static boolean compare(
+            @Nullable Rgb.TransferParameters a,
+            @Nullable Rgb.TransferParameters b) {
+        //noinspection SimplifiableIfStatement
+        if (a == null && b == null) return true;
+        return a != null && b != null &&
+                Math.abs(a.a - b.a) < 1e-3 &&
+                Math.abs(a.b - b.b) < 1e-3 &&
+                Math.abs(a.c - b.c) < 1e-3 &&
+                Math.abs(a.d - b.d) < 1e-3 &&
+                Math.abs(a.e - b.e) < 1e-3 &&
+                Math.abs(a.f - b.f) < 1e-3 &&
+                Math.abs(a.g - b.g) < 1e-3;
     }
 
     /**
@@ -1700,7 +1755,7 @@
      * <p>Computes the chromatic adaptation transform from the specified
      * source white point to the specified destination white point.</p>
      *
-     * <p>The transform is computed using the von Kris method, described
+     * <p>The transform is computed using the von Kries method, described
      * in more details in the documentation of {@link Adaptation}. The
      * {@link Adaptation} enum provides different matrices that can be
      * used to perform the adaptation.</p>
@@ -1915,6 +1970,11 @@
      *
      * $$RGB_{out} = OETF(f(EOTF(RGB_{in})))$$
      *
+     * <p>If the transfer functions of the color space can be expressed as an
+     * ICC parametric curve as defined in ICC.1:2004-10, the numeric parameters
+     * can be retrieved by calling {@link #getTransferParameters()}. This can
+     * be useful to match color spaces for instance.</p>
+     *
      * <p class="note">Some RGB color spaces, such as {@link Named#ACES} and
      * {@link Named#LINEAR_EXTENDED_SRGB scRGB}, are said to be linear because
      * their transfer functions are the identity function: \(f(x) = x\).
@@ -1957,14 +2017,175 @@
      */
     @AnyThread
     public static class Rgb extends ColorSpace {
+        /**
+         * {@usesMathJax}
+         *
+         * <p>Defines the parameters for the ICC parametric curve type 4, as
+         * defined in ICC.1:2004-10, section 10.15.</p>
+         *
+         * <p>The EOTF is of the form:</p>
+         *
+         * \(\begin{equation}
+         * Y = \begin{cases}c X + f & X \lt d \\
+         * \left( a X + b \right) ^{g} + e & X \ge d \end{cases}
+         * \end{equation}\)
+         *
+         * <p>The corresponding OETF is simply the inverse function.</p>
+         *
+         * <p>The parameters defined by this class form a valid transfer
+         * function only if all the following conditions are met:</p>
+         * <ul>
+         *     <li>No parameter is a {@link Double#isNaN(double) Not-a-Number}</li>
+         *     <li>\(d\) is in the range \([0..1]\)</li>
+         *     <li>The function is not constant</li>
+         *     <li>The function is positive and increasing</li>
+         * </ul>
+         */
+        public static class TransferParameters {
+            /** Variable \(a\) in the equation of the EOTF described above. */
+            public final double a;
+            /** Variable \(b\) in the equation of the EOTF described above. */
+            public final double b;
+            /** Variable \(c\) in the equation of the EOTF described above. */
+            public final double c;
+            /** Variable \(d\) in the equation of the EOTF described above. */
+            public final double d;
+            /** Variable \(e\) in the equation of the EOTF described above. */
+            public final double e;
+            /** Variable \(f\) in the equation of the EOTF described above. */
+            public final double f;
+            /** Variable \(g\) in the equation of the EOTF described above. */
+            public final double g;
+
+            /**
+             * <p>Defines the parameters for the ICC parametric curve type 3, as
+             * defined in ICC.1:2004-10, section 10.15.</p>
+             *
+             * <p>The EOTF is of the form:</p>
+             *
+             * \(\begin{equation}
+             * Y = \begin{cases}c X & X \lt d \\
+             * \left( a X + b \right) ^{g} & X \ge d \end{cases}
+             * \end{equation}\)
+             *
+             * <p>This constructor is equivalent to setting  \(e\) and \(f\) to 0.</p>
+             *
+             * @param a The value of \(a\) in the equation of the EOTF described above
+             * @param b The value of \(b\) in the equation of the EOTF described above
+             * @param c The value of \(c\) in the equation of the EOTF described above
+             * @param d The value of \(d\) in the equation of the EOTF described above
+             * @param g The value of \(g\) in the equation of the EOTF described above
+             *
+             * @throws IllegalArgumentException If the parameters form an invalid transfer function
+             */
+            public TransferParameters(double a, double b, double c, double d, double g) {
+                this(a, b, c, d, 0.0, 0.0, g);
+            }
+
+            /**
+             * <p>Defines the parameters for the ICC parametric curve type 4, as
+             * defined in ICC.1:2004-10, section 10.15.</p>
+             *
+             * @param a The value of \(a\) in the equation of the EOTF described above
+             * @param b The value of \(b\) in the equation of the EOTF described above
+             * @param c The value of \(c\) in the equation of the EOTF described above
+             * @param d The value of \(d\) in the equation of the EOTF described above
+             * @param e The value of \(e\) in the equation of the EOTF described above
+             * @param f The value of \(f\) in the equation of the EOTF described above
+             * @param g The value of \(g\) in the equation of the EOTF described above
+             *
+             * @throws IllegalArgumentException If the parameters form an invalid transfer function
+             */
+            public TransferParameters(double a, double b, double c, double d, double e,
+                    double f, double g) {
+
+                if (Double.isNaN(a) || Double.isNaN(b) || Double.isNaN(c) ||
+                        Double.isNaN(d) || Double.isNaN(e) || Double.isNaN(f) ||
+                        Double.isNaN(g)) {
+                    throw new IllegalArgumentException("Parameters cannot be NaN");
+                }
+
+                if (!(d >= 0.0 && d <= 1.0 + Math.ulp(1.0))) {
+                    throw new IllegalArgumentException("Parameter d must be in the range [0..1]");
+                }
+
+                if (d == 0.0 && (a == 0.0 || g == 0.0)) {
+                    throw new IllegalArgumentException(
+                            "Parameter a or g is zero, the transfer function is constant");
+                }
+
+                if (d >= 1.0 && c == 0.0) {
+                    throw new IllegalArgumentException(
+                            "Parameter c is zero, the transfer function is constant");
+                }
+
+                if ((a == 0.0 || g == 0.0) && c == 0.0) {
+                    throw new IllegalArgumentException("Parameter a or g is zero," +
+                            " and c is zero, the transfer function is constant");
+                }
+
+                if (c < 0.0) {
+                    throw new IllegalArgumentException("The transfer function must be increasing");
+                }
+
+                if (a < 0.0 || g < 0.0) {
+                    throw new IllegalArgumentException("The transfer function must be " +
+                            "positive or increasing");
+                }
+
+                this.a = a;
+                this.b = b;
+                this.c = c;
+                this.d = d;
+                this.e = e;
+                this.f = f;
+                this.g = g;
+            }
+
+            @SuppressWarnings("SimplifiableIfStatement")
+            @Override
+            public boolean equals(Object o) {
+                if (this == o) return true;
+                if (o == null || getClass() != o.getClass()) return false;
+
+                TransferParameters that = (TransferParameters) o;
+
+                if (Double.compare(that.a, a) != 0) return false;
+                if (Double.compare(that.b, b) != 0) return false;
+                if (Double.compare(that.c, c) != 0) return false;
+                if (Double.compare(that.d, d) != 0) return false;
+                if (Double.compare(that.e, e) != 0) return false;
+                if (Double.compare(that.f, f) != 0) return false;
+                return Double.compare(that.g, g) == 0;
+            }
+
+            @Override
+            public int hashCode() {
+                int result;
+                long temp;
+                temp = Double.doubleToLongBits(a);
+                result = (int) (temp ^ (temp >>> 32));
+                temp = Double.doubleToLongBits(b);
+                result = 31 * result + (int) (temp ^ (temp >>> 32));
+                temp = Double.doubleToLongBits(c);
+                result = 31 * result + (int) (temp ^ (temp >>> 32));
+                temp = Double.doubleToLongBits(d);
+                result = 31 * result + (int) (temp ^ (temp >>> 32));
+                temp = Double.doubleToLongBits(e);
+                result = 31 * result + (int) (temp ^ (temp >>> 32));
+                temp = Double.doubleToLongBits(f);
+                result = 31 * result + (int) (temp ^ (temp >>> 32));
+                temp = Double.doubleToLongBits(g);
+                result = 31 * result + (int) (temp ^ (temp >>> 32));
+                return result;
+            }
+        }
+
         @NonNull private final float[] mWhitePoint;
         @NonNull private final float[] mPrimaries;
         @NonNull private final float[] mTransform;
         @NonNull private final float[] mInverseTransform;
 
-        @NonNull private final boolean mIsWideGamut;
-        @NonNull private final boolean mIsSrgb;
-
         @NonNull private final DoubleUnaryOperator mOetf;
         @NonNull private final DoubleUnaryOperator mEotf;
         @NonNull private final DoubleUnaryOperator mClampedOetf;
@@ -1973,6 +2194,11 @@
         private final float mMin;
         private final float mMax;
 
+        private final boolean mIsWideGamut;
+        private final boolean mIsSrgb;
+
+        @Nullable private TransferParameters mTransferParameters;
+
         /**
          * <p>Creates a new RGB color space using a 3x3 column-major transform matrix.
          * The transform matrix must convert from the RGB space to the profile connection
@@ -2000,7 +2226,7 @@
                 @NonNull @Size(9) float[] toXYZ,
                 @NonNull DoubleUnaryOperator oetf,
                 @NonNull DoubleUnaryOperator eotf) {
-            this(name, computePrimaries(toXYZ, eotf), computeWhitePoint(toXYZ, eotf),
+            this(name, computePrimaries(toXYZ), computeWhitePoint(toXYZ),
                     oetf, eotf, 0.0f, 1.0f, MIN_ID);
         }
 
@@ -2055,6 +2281,251 @@
         }
 
         /**
+         * <p>Creates a new RGB color space using a 3x3 column-major transform matrix.
+         * The transform matrix must convert from the RGB space to the profile connection
+         * space CIE XYZ.</p>
+         *
+         * <p class="note">The range of the color space is imposed to be \([0..1]\).</p>
+         *
+         * @param name Name of the color space, cannot be null, its length must be >= 1
+         * @param toXYZ 3x3 column-major transform matrix from RGB to the profile
+         *              connection space CIE XYZ as an array of 9 floats, cannot be null
+         * @param function Parameters for the transfer functions
+         *
+         * @throws IllegalArgumentException If any of the following conditions is met:
+         * <ul>
+         *     <li>The name is null or has a length of 0.</li>
+         *     <li>Gamma is negative.</li>
+         * </ul>
+         *
+         * @see #get(Named)
+         */
+        public Rgb(
+                @NonNull @Size(min = 1) String name,
+                @NonNull @Size(9) float[] toXYZ,
+                @NonNull TransferParameters function) {
+            this(name, computePrimaries(toXYZ), computeWhitePoint(toXYZ), function, MIN_ID);
+        }
+
+        /**
+         * <p>Creates a new RGB color space using a specified set of primaries
+         * and a specified white point.</p>
+         *
+         * <p>The primaries and white point can be specified in the CIE xyY space
+         * or in CIE XYZ. The length of the arrays depends on the chosen space:</p>
+         *
+         * <table summary="Parameters length">
+         *     <tr><th>Space</th><th>Primaries length</th><th>White point length</th></tr>
+         *     <tr><td>xyY</td><td>6</td><td>2</td></tr>
+         *     <tr><td>XYZ</td><td>9</td><td>3</td></tr>
+         * </table>
+         *
+         * <p>When the primaries and/or white point are specified in xyY, the Y component
+         * does not need to be specified and is assumed to be 1.0. Only the xy components
+         * are required.</p>
+         *
+         * @param name Name of the color space, cannot be null, its length must be >= 1
+         * @param primaries RGB primaries as an array of 6 (xy) or 9 (XYZ) floats
+         * @param whitePoint Reference white as an array of 2 (xy) or 3 (XYZ) floats
+         * @param function Parameters for the transfer functions
+         *
+         * @throws IllegalArgumentException If any of the following conditions is met:
+         * <ul>
+         *     <li>The name is null or has a length of 0.</li>
+         *     <li>The primaries array is null or has a length that is neither 6 or 9.</li>
+         *     <li>The white point array is null or has a length that is neither 2 or 3.</li>
+         *     <li>The transfer parameters are invalid.</li>
+         * </ul>
+         *
+         * @see #get(Named)
+         */
+        public Rgb(
+                @NonNull @Size(min = 1) String name,
+                @NonNull @Size(min = 6, max = 9) float[] primaries,
+                @NonNull @Size(min = 2, max = 3) float[] whitePoint,
+                @NonNull TransferParameters function) {
+            this(name, primaries, whitePoint, function, MIN_ID);
+        }
+
+        /**
+         * <p>Creates a new RGB color space using a specified set of primaries
+         * and a specified white point.</p>
+         *
+         * <p>The primaries and white point can be specified in the CIE xyY space
+         * or in CIE XYZ. The length of the arrays depends on the chosen space:</p>
+         *
+         * <table summary="Parameters length">
+         *     <tr><th>Space</th><th>Primaries length</th><th>White point length</th></tr>
+         *     <tr><td>xyY</td><td>6</td><td>2</td></tr>
+         *     <tr><td>XYZ</td><td>9</td><td>3</td></tr>
+         * </table>
+         *
+         * <p>When the primaries and/or white point are specified in xyY, the Y component
+         * does not need to be specified and is assumed to be 1.0. Only the xy components
+         * are required.</p>
+         *
+         * @param name Name of the color space, cannot be null, its length must be >= 1
+         * @param primaries RGB primaries as an array of 6 (xy) or 9 (XYZ) floats
+         * @param whitePoint Reference white as an array of 2 (xy) or 3 (XYZ) floats
+         * @param function Parameters for the transfer functions
+         * @param id ID of this color space as an integer between {@link #MIN_ID} and {@link #MAX_ID}
+         *
+         * @throws IllegalArgumentException If any of the following conditions is met:
+         * <ul>
+         *     <li>The name is null or has a length of 0.</li>
+         *     <li>The primaries array is null or has a length that is neither 6 or 9.</li>
+         *     <li>The white point array is null or has a length that is neither 2 or 3.</li>
+         *     <li>The ID is not between {@link #MIN_ID} and {@link #MAX_ID}.</li>
+         *     <li>The transfer parameters are invalid.</li>
+         * </ul>
+         *
+         * @see #get(Named)
+         */
+        private Rgb(
+                @NonNull @Size(min = 1) String name,
+                @NonNull @Size(min = 6, max = 9) float[] primaries,
+                @NonNull @Size(min = 2, max = 3) float[] whitePoint,
+                @NonNull TransferParameters function,
+                @IntRange(from = MIN_ID, to = MAX_ID) int id) {
+            this(name, primaries, whitePoint,
+                    function.e == 0.0 && function.f == 0.0 ?
+                            x -> rcpResponse(x, function.a, function.b,
+                                    function.c, function.d, function.g) :
+                            x -> rcpResponse(x, function.a, function.b, function.c,
+                                    function.d, function.e, function.f, function.g),
+                    function.e == 0.0 && function.f == 0.0 ?
+                            x -> response(x, function.a, function.b,
+                                    function.c, function.d, function.g) :
+                            x -> response(x, function.a, function.b, function.c,
+                                    function.d, function.e, function.f, function.g),
+                    0.0f, 1.0f, id);
+            mTransferParameters = function;
+        }
+
+        /**
+         * <p>Creates a new RGB color space using a 3x3 column-major transform matrix.
+         * The transform matrix must convert from the RGB space to the profile connection
+         * space CIE XYZ.</p>
+         *
+         * <p class="note">The range of the color space is imposed to be \([0..1]\).</p>
+         *
+         * @param name Name of the color space, cannot be null, its length must be >= 1
+         * @param toXYZ 3x3 column-major transform matrix from RGB to the profile
+         *              connection space CIE XYZ as an array of 9 floats, cannot be null
+         * @param gamma Gamma to use as the transfer function
+         *
+         * @throws IllegalArgumentException If any of the following conditions is met:
+         * <ul>
+         *     <li>The name is null or has a length of 0.</li>
+         *     <li>Gamma is negative.</li>
+         * </ul>
+         *
+         * @see #get(Named)
+         */
+        public Rgb(
+                @NonNull @Size(min = 1) String name,
+                @NonNull @Size(9) float[] toXYZ,
+                double gamma) {
+            this(name, computePrimaries(toXYZ), computeWhitePoint(toXYZ), gamma, 0.0f, 1.0f, MIN_ID);
+        }
+
+        /**
+         * <p>Creates a new RGB color space using a specified set of primaries
+         * and a specified white point.</p>
+         *
+         * <p>The primaries and white point can be specified in the CIE xyY space
+         * or in CIE XYZ. The length of the arrays depends on the chosen space:</p>
+         *
+         * <table summary="Parameters length">
+         *     <tr><th>Space</th><th>Primaries length</th><th>White point length</th></tr>
+         *     <tr><td>xyY</td><td>6</td><td>2</td></tr>
+         *     <tr><td>XYZ</td><td>9</td><td>3</td></tr>
+         * </table>
+         *
+         * <p>When the primaries and/or white point are specified in xyY, the Y component
+         * does not need to be specified and is assumed to be 1.0. Only the xy components
+         * are required.</p>
+         *
+         * @param name Name of the color space, cannot be null, its length must be >= 1
+         * @param primaries RGB primaries as an array of 6 (xy) or 9 (XYZ) floats
+         * @param whitePoint Reference white as an array of 2 (xy) or 3 (XYZ) floats
+         * @param gamma Gamma to use as the transfer function
+         *
+         * @throws IllegalArgumentException If any of the following conditions is met:
+         * <ul>
+         *     <li>The name is null or has a length of 0.</li>
+         *     <li>The primaries array is null or has a length that is neither 6 or 9.</li>
+         *     <li>The white point array is null or has a length that is neither 2 or 3.</li>
+         *     <li>Gamma is negative.</li>
+         * </ul>
+         *
+         * @see #get(Named)
+         */
+        public Rgb(
+                @NonNull @Size(min = 1) String name,
+                @NonNull @Size(min = 6, max = 9) float[] primaries,
+                @NonNull @Size(min = 2, max = 3) float[] whitePoint,
+                double gamma) {
+            this(name, primaries, whitePoint, gamma, 0.0f, 1.0f, MIN_ID);
+        }
+
+        /**
+         * <p>Creates a new RGB color space using a specified set of primaries
+         * and a specified white point.</p>
+         *
+         * <p>The primaries and white point can be specified in the CIE xyY space
+         * or in CIE XYZ. The length of the arrays depends on the chosen space:</p>
+         *
+         * <table summary="Parameters length">
+         *     <tr><th>Space</th><th>Primaries length</th><th>White point length</th></tr>
+         *     <tr><td>xyY</td><td>6</td><td>2</td></tr>
+         *     <tr><td>XYZ</td><td>9</td><td>3</td></tr>
+         * </table>
+         *
+         * <p>When the primaries and/or white point are specified in xyY, the Y component
+         * does not need to be specified and is assumed to be 1.0. Only the xy components
+         * are required.</p>
+         *
+         * @param name Name of the color space, cannot be null, its length must be >= 1
+         * @param primaries RGB primaries as an array of 6 (xy) or 9 (XYZ) floats
+         * @param whitePoint Reference white as an array of 2 (xy) or 3 (XYZ) floats
+         * @param gamma Gamma to use as the transfer function
+         * @param min The minimum valid value in this color space's RGB range
+         * @param max The maximum valid value in this color space's RGB range
+         * @param id ID of this color space as an integer between {@link #MIN_ID} and {@link #MAX_ID}
+         *
+         * @throws IllegalArgumentException If any of the following conditions is met:
+         * <ul>
+         *     <li>The name is null or has a length of 0.</li>
+         *     <li>The primaries array is null or has a length that is neither 6 or 9.</li>
+         *     <li>The white point array is null or has a length that is neither 2 or 3.</li>
+         *     <li>The minimum valid value is >= the maximum valid value.</li>
+         *     <li>The ID is not between {@link #MIN_ID} and {@link #MAX_ID}.</li>
+         *     <li>Gamma is negative.</li>
+         * </ul>
+         *
+         * @see #get(Named)
+         */
+        private Rgb(
+                @NonNull @Size(min = 1) String name,
+                @NonNull @Size(min = 6, max = 9) float[] primaries,
+                @NonNull @Size(min = 2, max = 3) float[] whitePoint,
+                double gamma,
+                float min,
+                float max,
+                @IntRange(from = MIN_ID, to = MAX_ID) int id) {
+            this(name, primaries, whitePoint,
+                    gamma == 1.0 ? DoubleUnaryOperator.identity() :
+                            x -> Math.pow(x < 0.0 ? 0.0 : x, 1 / gamma),
+                    gamma == 1.0 ? DoubleUnaryOperator.identity() :
+                            x -> Math.pow(x < 0.0 ? 0.0 : x, gamma),
+                    min, max, id);
+            mTransferParameters = gamma == 1.0 ?
+                    new TransferParameters(0.0, 0.0, 1.0, 1.0 + Math.ulp(1.0), gamma) :
+                    new TransferParameters(1.0, 0.0, 0.0, 0.0, gamma);
+        }
+
+        /**
          * <p>Creates a new RGB color space using a specified set of primaries
          * and a specified white point.</p>
          *
@@ -2173,6 +2644,8 @@
 
             mIsWideGamut = colorSpace.mIsWideGamut;
             mIsSrgb = colorSpace.mIsSrgb;
+
+            mTransferParameters = colorSpace.mTransferParameters;
         }
 
         /**
@@ -2350,6 +2823,7 @@
          * @return A transfer function that converts from linear space to "gamma space"
          *
          * @see #getEotf()
+         * @see #getTransferParameters()
          */
         @NonNull
         public DoubleUnaryOperator getOetf() {
@@ -2373,12 +2847,31 @@
          * @return A transfer function that converts from "gamma space" to linear space
          *
          * @see #getOetf()
+         * @see #getTransferParameters()
          */
         @NonNull
         public DoubleUnaryOperator getEotf() {
             return mClampedEotf;
         }
 
+        /**
+         * <p>Returns the parameters used by the {@link #getEotf() electro-optical}
+         * and {@link #getOetf() opto-electronic} transfer functions. If the transfer
+         * functions do not match the ICC parametric curves defined in ICC.1:2004-10
+         * (section 10.15), this method returns null.</p>
+         *
+         * <p>See {@link TransferParameters} for a full description of the transfer
+         * functions.</p>
+         *
+         * @return An instance of {@link TransferParameters} or null if this color
+         *         space's transfer functions do not match the equation defined in
+         *         {@link TransferParameters}
+         */
+        @Nullable
+        public TransferParameters getTransferParameters() {
+            return mTransferParameters;
+        }
+
         @Override
         public boolean isSrgb() {
             return mIsSrgb;
@@ -2534,6 +3027,11 @@
             if (Float.compare(rgb.mMax, mMax) != 0) return false;
             if (!Arrays.equals(mWhitePoint, rgb.mWhitePoint)) return false;
             if (!Arrays.equals(mPrimaries, rgb.mPrimaries)) return false;
+            if (mTransferParameters != null) {
+                return mTransferParameters.equals(rgb.mTransferParameters);
+            } else if (rgb.mTransferParameters == null) {
+                return true;
+            }
             //noinspection SimplifiableIfStatement
             if (!mOetf.equals(rgb.mOetf)) return false;
             return mEotf.equals(rgb.mEotf);
@@ -2544,10 +3042,14 @@
             int result = super.hashCode();
             result = 31 * result + Arrays.hashCode(mWhitePoint);
             result = 31 * result + Arrays.hashCode(mPrimaries);
-            result = 31 * result + mOetf.hashCode();
-            result = 31 * result + mEotf.hashCode();
             result = 31 * result + (mMin != +0.0f ? Float.floatToIntBits(mMin) : 0);
             result = 31 * result + (mMax != +0.0f ? Float.floatToIntBits(mMax) : 0);
+            result = 31 * result +
+                    (mTransferParameters != null ? mTransferParameters.hashCode() : 0);
+            if (mTransferParameters == null) {
+                result = 31 * result + mOetf.hashCode();
+                result = 31 * result + mEotf.hashCode();
+            }
             return result;
         }
 
@@ -2736,18 +3238,15 @@
          * range of the color space is [0..1].
          *
          * @param toXYZ The color space's 3x3 transform matrix to XYZ
-         * @param EOTF The color space's electro-optical transfer function
          * @return A new array of 6 floats containing the color space's
          *         primaries in CIE xyY
          */
         @NonNull
         @Size(6)
-        private static float[] computePrimaries(@NonNull @Size(9) float[] toXYZ,
-                DoubleUnaryOperator EOTF) {
-            float one = (float) EOTF.applyAsDouble(1.0);
-            float[] r = mul3x3Float3(toXYZ, new float[] { one, 0.0f, 0.0f });
-            float[] g = mul3x3Float3(toXYZ, new float[] { 0.0f, one, 0.0f });
-            float[] b = mul3x3Float3(toXYZ, new float[] { 0.0f, 0.0f, one });
+        private static float[] computePrimaries(@NonNull @Size(9) float[] toXYZ) {
+            float[] r = mul3x3Float3(toXYZ, new float[] { 1.0f, 0.0f, 0.0f });
+            float[] g = mul3x3Float3(toXYZ, new float[] { 0.0f, 1.0f, 0.0f });
+            float[] b = mul3x3Float3(toXYZ, new float[] { 0.0f, 0.0f, 1.0f });
 
             float rSum = r[0] + r[1] + r[2];
             float gSum = g[0] + g[1] + g[2];
@@ -2766,16 +3265,13 @@
          * range of the color space is [0..1].
          *
          * @param toXYZ The color space's 3x3 transform matrix to XYZ
-         * @param EOTF The color space's electro-optical transfer function
          * @return A new array of 2 floats containing the color space's
          *         white point in CIE xyY
          */
         @NonNull
         @Size(2)
-        private static float[] computeWhitePoint(@NonNull @Size(9) float[] toXYZ,
-                @NonNull DoubleUnaryOperator EOTF) {
-            float one = (float) EOTF.applyAsDouble(1.0);
-            float[] w = mul3x3Float3(toXYZ, new float[] { one, one, one });
+        private static float[] computeWhitePoint(@NonNull @Size(9) float[] toXYZ) {
+            float[] w = mul3x3Float3(toXYZ, new float[] { 1.0f, 1.0f, 1.0f });
             float sum = w[0] + w[1] + w[2];
             return new float[] { w[0] / sum, w[1] / sum };
         }
@@ -2978,6 +3474,7 @@
          * Computes an extra transform to apply in XYZ space depending on the
          * selected rendering intent.
          */
+        @Nullable
         private static float[] computeTransform(@NonNull ColorSpace source,
                 @NonNull ColorSpace destination, @NonNull RenderIntent intent) {
             if (intent != RenderIntent.ABSOLUTE) return null;
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 4ee0c34..b1d51ec 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -340,6 +340,20 @@
     private static final int CURSOR_OPT_MAX_VALUE = CURSOR_AT;
 
     /**
+     * Mask for hyphen edits that happen at the end of a line. Keep in sync with the definition in
+     * Minikin's Hyphenator.h.
+     * @hide
+     */
+    public static final int HYPHENEDIT_MASK_END_OF_LINE = 0x07;
+
+    /**
+     * Mask for hyphen edits that happen at the start of a line. Keep in sync with the definition in
+     * Minikin's Hyphenator.h.
+     * @hide
+     */
+    public static final int HYPHENEDIT_MASK_START_OF_LINE = 0x03 << 3;
+
+    /**
      * The Style specifies if the primitive being drawn is filled, stroked, or
      * both (in the same color). The default is FILL.
      */
@@ -1540,7 +1554,8 @@
      * Set a hyphen edit on the paint (causes a hyphen to be added to text when
      * measured or drawn).
      *
-     * @param hyphen 0 for no edit, 1 for adding a hyphen (other values in future)
+     * @param hyphen 0 for no edit, 1 for adding a hyphen at the end, etc.
+     *        Definition of various values are in the HyphenEdit class in Minikin's Hyphenator.h.
      *
      * @hide
      */
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index efb46b90..90bdd81 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -403,11 +403,4 @@
     private native int nativeGetQueuedCount();
     private native void nativeRelease();
     private native boolean nativeIsReleased();
-
-    /*
-     * We use a class initializer to allow the native code to cache some
-     * field offsets.
-     */
-    private static native void nativeClassInit();
-    static { nativeClassInit(); }
 }
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 52e18a9..8b30903 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -186,8 +186,8 @@
                 }
                 // Downloaded font and it wasn't cached, request it again and return a
                 // default font instead (nothing we can do now).
-                create(new FontRequest(family.getProviderAuthority(), family.getQuery()),
-                        NO_OP_REQUEST_CALLBACK);
+                create(new FontRequest(family.getProviderAuthority(), family.getProviderPackage(),
+                        family.getQuery()), NO_OP_REQUEST_CALLBACK);
                 return DEFAULT;
             }
 
diff --git a/graphics/java/android/graphics/drawable/MaskableIconDrawable.java b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
similarity index 95%
rename from graphics/java/android/graphics/drawable/MaskableIconDrawable.java
rename to graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
index 472b229..0722c18 100644
--- a/graphics/java/android/graphics/drawable/MaskableIconDrawable.java
+++ b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
@@ -29,7 +29,6 @@
 import android.graphics.Bitmap;
 import android.graphics.BitmapShader;
 import android.graphics.Canvas;
-import android.graphics.Color;
 import android.graphics.ColorFilter;
 import android.graphics.Matrix;
 import android.graphics.Outline;
@@ -56,10 +55,10 @@
  *
  * <p>The layers are clipped when rendering using the mask path defined in the device configuration.
  *
- * <p>This class can also be created via XML inflation using <code>&lt;maskable-icon></code> tag
+ * <p>This class can also be created via XML inflation using <code>&lt;adaptive-icon></code> tag
  * in addition to dynamic creation.
  */
-public class MaskableIconDrawable extends Drawable implements Drawable.Callback {
+public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback {
 
     /**
      * Mask path is defined inside device configuration in following dimension: [100 x 100]
@@ -122,7 +121,7 @@
     /**
      * Constructor used for xml inflation.
      */
-    MaskableIconDrawable() {
+    AdaptiveIconDrawable() {
         this((LayerState) null, null);
     }
 
@@ -130,7 +129,7 @@
      * The one constructor to rule them all. This is called by all public
      * constructors to set the state and initialize local properties.
      */
-    MaskableIconDrawable(@Nullable LayerState state, @Nullable Resources res) {
+    AdaptiveIconDrawable(@Nullable LayerState state, @Nullable Resources res) {
         mLayerState = createConstantState(state, res);
 
         if (sMask == null) {
@@ -163,7 +162,7 @@
      * @param foregroundDrawable drawable that should be rendered in the foreground
      * @hide
      */
-    public MaskableIconDrawable(Drawable backgroundDrawable,
+    public AdaptiveIconDrawable(Drawable backgroundDrawable,
             Drawable foregroundDrawable) {
         this((LayerState)null, null);
         if (backgroundDrawable != null) {
@@ -257,9 +256,12 @@
         }
     }
 
+    /**
+     * Set the child layer bounds bigger than the view port size by {@link #DEFAULT_VIEW_PORT_SCALE}
+     */
     private void updateLayerBoundsInternal(Rect bounds) {
-        int cX = bounds.centerX();
-        int cY = bounds.centerY();
+        int cX = bounds.width() / 2;
+        int cY = bounds.height() / 2;
 
         for (int i = 0, count = mLayerState.N_CHILDREN; i < count; i++) {
             final ChildDrawable r = mLayerState.mChildren[i];
@@ -284,7 +286,11 @@
         mMaskMatrix.setScale(b.width() / MASK_SIZE, b.height() / MASK_SIZE);
         sMask.transform(mMaskMatrix, mMask);
 
-        mMaskBitmap = Bitmap.createBitmap(b.width(), b.height(), Bitmap.Config.ALPHA_8);
+        if (mMaskBitmap == null || mMaskBitmap.getWidth() != b.width() ||
+            mMaskBitmap.getHeight() != b.height()) {
+            mMaskBitmap = Bitmap.createBitmap(b.width(), b.height(), Bitmap.Config.ALPHA_8);
+            mLayersBitmap = Bitmap.createBitmap(b.width(), b.height(), Bitmap.Config.ARGB_8888);
+        }
         mCanvas.setBitmap(mMaskBitmap);
         mPaint.setShader(null);
         mCanvas.drawPath(mMask, mPaint);
@@ -292,7 +298,6 @@
         // reset everything that depends on the view bounds
         mTransparentRegion.setEmpty();
         mLayersShader = null;
-        mLayersBitmap = Bitmap.createBitmap(b.width(), b.height(), Bitmap.Config.ARGB_8888);
     }
 
     @Override
@@ -311,7 +316,10 @@
             mLayersShader = new BitmapShader(mLayersBitmap, TileMode.CLAMP, TileMode.CLAMP);
             mPaint.setShader(mLayersShader);
         }
-        canvas.drawBitmap(mMaskBitmap, 0.0f, 0.0f, mPaint);
+        if (mMaskBitmap != null) {
+            Rect bounds = getBounds();
+            canvas.drawBitmap(mMaskBitmap, bounds.left, bounds.top, mPaint);
+        }
     }
 
     @Override
@@ -367,7 +375,7 @@
 
             if (layer.mThemeAttrs != null) {
                 final TypedArray a = t.resolveAttributes(
-                    layer.mThemeAttrs, R.styleable.MaskableIconDrawableLayer);
+                    layer.mThemeAttrs, R.styleable.AdaptiveIconDrawableLayer);
                 updateLayerFromTypedArray(layer, a);
                 a.recycle();
             }
@@ -414,7 +422,7 @@
 
             final ChildDrawable layer = new ChildDrawable(state.mDensity);
             final TypedArray a = obtainAttributes(r, theme, attrs,
-                R.styleable.MaskableIconDrawableLayer);
+                R.styleable.AdaptiveIconDrawableLayer);
             updateLayerFromTypedArray(layer, a);
             a.recycle();
 
@@ -450,7 +458,7 @@
         // Extract the theme attributes, if any.
         layer.mThemeAttrs = a.extractThemeAttrs();
 
-        Drawable dr = a.getDrawable(R.styleable.MaskableIconDrawableLayer_drawable);
+        Drawable dr = a.getDrawable(R.styleable.AdaptiveIconDrawableLayer_drawable);
         if (dr != null) {
             if (layer.mDrawable != null) {
                 // It's possible that a drawable was already set, in which case
@@ -841,7 +849,7 @@
             mDensity = density;
         }
 
-        ChildDrawable(@NonNull ChildDrawable orig, @NonNull MaskableIconDrawable owner,
+        ChildDrawable(@NonNull ChildDrawable orig, @NonNull AdaptiveIconDrawable owner,
                 @Nullable Resources res) {
 
             final Drawable dr = orig.mDrawable;
@@ -899,7 +907,7 @@
         private boolean mIsStateful;
         private boolean mAutoMirrored = false;
 
-        LayerState(@Nullable LayerState orig, @NonNull MaskableIconDrawable owner,
+        LayerState(@Nullable LayerState orig, @NonNull AdaptiveIconDrawable owner,
                 @Nullable Resources res) {
             mDensity = Drawable.resolveDensity(res, orig != null ? orig.mDensity : 0);
             mChildren = new ChildDrawable[N_CHILDREN];
@@ -952,12 +960,12 @@
 
         @Override
         public Drawable newDrawable() {
-            return new MaskableIconDrawable(this, null);
+            return new AdaptiveIconDrawable(this, null);
         }
 
         @Override
         public Drawable newDrawable(@Nullable Resources res) {
-            return new MaskableIconDrawable(this, res);
+            return new AdaptiveIconDrawable(this, res);
         }
 
         @Override
diff --git a/graphics/java/android/graphics/drawable/DrawableInflater.java b/graphics/java/android/graphics/drawable/DrawableInflater.java
index 6d0bbdf..3404d8c 100644
--- a/graphics/java/android/graphics/drawable/DrawableInflater.java
+++ b/graphics/java/android/graphics/drawable/DrawableInflater.java
@@ -147,8 +147,8 @@
                 return new TransitionDrawable();
             case "ripple":
                 return new RippleDrawable();
-            case "maskable-icon":
-                return new MaskableIconDrawable();
+            case "adaptive-icon":
+                return new AdaptiveIconDrawable();
             case "color":
                 return new ColorDrawable();
             case "shape":
diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java
index 60c3b1c..8ce7ed0 100644
--- a/graphics/java/android/graphics/drawable/Icon.java
+++ b/graphics/java/android/graphics/drawable/Icon.java
@@ -68,7 +68,7 @@
     /** @hide */
     public static final int TYPE_URI      = 4;
     /** @hide */
-    public static final int TYPE_BITMAP_MASKABLE      = 5;
+    public static final int TYPE_ADAPTIVE_BITMAP = 5;
 
     private static final int VERSION_STREAM_SERIALIZER = 1;
 
@@ -103,7 +103,7 @@
      * {@link #TYPE_RESOURCE},
      * {@link #TYPE_DATA}, or
      * {@link #TYPE_URI}.
-     * {@link #TYPE_BITMAP_MASKABLE}
+     * {@link #TYPE_ADAPTIVE_BITMAP}
      * @hide
      */
     public int getType() {
@@ -115,7 +115,7 @@
      * @hide
      */
     public Bitmap getBitmap() {
-        if (mType != TYPE_BITMAP && mType != TYPE_BITMAP_MASKABLE) {
+        if (mType != TYPE_BITMAP && mType != TYPE_ADAPTIVE_BITMAP) {
             throw new IllegalStateException("called getBitmap() on " + this);
         }
         return (Bitmap) mObj1;
@@ -221,7 +221,7 @@
     private static final String typeToString(int x) {
         switch (x) {
             case TYPE_BITMAP: return "BITMAP";
-            case TYPE_BITMAP_MASKABLE: return "BITMAP_MASKABLE";
+            case TYPE_ADAPTIVE_BITMAP: return "BITMAP_MASKABLE";
             case TYPE_DATA: return "DATA";
             case TYPE_RESOURCE: return "RESOURCE";
             case TYPE_URI: return "URI";
@@ -289,8 +289,8 @@
         switch (mType) {
             case TYPE_BITMAP:
                 return new BitmapDrawable(context.getResources(), getBitmap());
-            case TYPE_BITMAP_MASKABLE:
-                return new MaskableIconDrawable(null,
+            case TYPE_ADAPTIVE_BITMAP:
+                return new AdaptiveIconDrawable(null,
                     new BitmapDrawable(context.getResources(), getBitmap()));
             case TYPE_RESOURCE:
                 if (getResources() == null) {
@@ -395,7 +395,7 @@
      * @hide
      */
     public void convertToAshmem() {
-        if ((mType == TYPE_BITMAP || mType == TYPE_BITMAP_MASKABLE) &&
+        if ((mType == TYPE_BITMAP || mType == TYPE_ADAPTIVE_BITMAP) &&
             getBitmap().isMutable() &&
             getBitmap().getAllocationByteCount() >= MIN_ASHMEM_ICON_SIZE) {
             setBitmap(getBitmap().createAshmemBitmap());
@@ -416,7 +416,7 @@
 
         switch (mType) {
             case TYPE_BITMAP:
-            case TYPE_BITMAP_MASKABLE:
+            case TYPE_ADAPTIVE_BITMAP:
                 getBitmap().compress(Bitmap.CompressFormat.PNG, 100, dataStream);
                 break;
             case TYPE_DATA:
@@ -452,8 +452,8 @@
             switch (type) {
                 case TYPE_BITMAP:
                     return createWithBitmap(BitmapFactory.decodeStream(inputStream));
-                case TYPE_BITMAP_MASKABLE:
-                    return createWithMaskableBitmap(BitmapFactory.decodeStream(inputStream));
+                case TYPE_ADAPTIVE_BITMAP:
+                    return createWithAdaptiveBitmap(BitmapFactory.decodeStream(inputStream));
                 case TYPE_DATA:
                     final int length = inputStream.readInt();
                     final byte[] data = new byte[length];
@@ -488,7 +488,7 @@
         }
         switch (mType) {
             case TYPE_BITMAP:
-            case TYPE_BITMAP_MASKABLE:
+            case TYPE_ADAPTIVE_BITMAP:
                 return getBitmap() == otherIcon.getBitmap();
             case TYPE_DATA:
                 return getDataLength() == otherIcon.getDataLength()
@@ -563,14 +563,14 @@
 
     /**
      * Create an Icon pointing to a bitmap in memory that follows the icon design guideline defined
-     * by {@link MaskableIconDrawable}.
+     * by {@link AdaptiveIconDrawable}.
      * @param bits A valid {@link android.graphics.Bitmap} object
      */
-    public static Icon createWithMaskableBitmap(Bitmap bits) {
+    public static Icon createWithAdaptiveBitmap(Bitmap bits) {
         if (bits == null) {
             throw new IllegalArgumentException("Bitmap must not be null.");
         }
-        final Icon rep = new Icon(TYPE_BITMAP_MASKABLE);
+        final Icon rep = new Icon(TYPE_ADAPTIVE_BITMAP);
         rep.setBitmap(bits);
         return rep;
     }
@@ -679,7 +679,7 @@
         final StringBuilder sb = new StringBuilder("Icon(typ=").append(typeToString(mType));
         switch (mType) {
             case TYPE_BITMAP:
-            case TYPE_BITMAP_MASKABLE:
+            case TYPE_ADAPTIVE_BITMAP:
                 sb.append(" size=")
                         .append(getBitmap().getWidth())
                         .append("x")
@@ -718,7 +718,7 @@
      * Parcelable interface
      */
     public int describeContents() {
-        return (mType == TYPE_BITMAP || mType == TYPE_BITMAP_MASKABLE || mType == TYPE_DATA)
+        return (mType == TYPE_BITMAP || mType == TYPE_ADAPTIVE_BITMAP || mType == TYPE_DATA)
                 ? Parcelable.CONTENTS_FILE_DESCRIPTOR : 0;
     }
 
@@ -728,7 +728,7 @@
         this(in.readInt());
         switch (mType) {
             case TYPE_BITMAP:
-            case TYPE_BITMAP_MASKABLE:
+            case TYPE_ADAPTIVE_BITMAP:
                 final Bitmap bits = Bitmap.CREATOR.createFromParcel(in);
                 mObj1 = bits;
                 break;
@@ -767,7 +767,7 @@
         dest.writeInt(mType);
         switch (mType) {
             case TYPE_BITMAP:
-            case TYPE_BITMAP_MASKABLE:
+            case TYPE_ADAPTIVE_BITMAP:
                 final Bitmap bits = getBitmap();
                 getBitmap().writeToParcel(dest, flags);
                 break;
diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java
index fe82a93..a24b970 100644
--- a/graphics/java/android/graphics/drawable/ShapeDrawable.java
+++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java
@@ -16,9 +16,11 @@
 
 package android.graphics.drawable;
 
+import android.annotation.NonNull;
 import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
+import android.content.res.Resources.Theme;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
@@ -31,10 +33,10 @@
 import android.graphics.Rect;
 import android.graphics.Shader;
 import android.graphics.drawable.shapes.Shape;
-import android.content.res.Resources.Theme;
 import android.util.AttributeSet;
 
 import com.android.internal.R;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -69,7 +71,7 @@
  * @attr ref android.R.styleable#ShapeDrawable_height
  */
 public class ShapeDrawable extends Drawable {
-    private ShapeState mShapeState;
+    private @NonNull ShapeState mShapeState;
     private PorterDuffColorFilter mTintFilter;
     private boolean mMutated;
 
@@ -77,7 +79,7 @@
      * ShapeDrawable constructor.
      */
     public ShapeDrawable() {
-        this(new ShapeState(null), null);
+        this(new ShapeState(), null);
     }
 
     /**
@@ -86,7 +88,7 @@
      * @param s the Shape that this ShapeDrawable should be
      */
     public ShapeDrawable(Shape s) {
-        this(new ShapeState(null), null);
+        this(new ShapeState(), null);
 
         mShapeState.mShape = s;
     }
@@ -402,7 +404,7 @@
         }
 
         // Update local properties.
-        updateLocalState(r);
+        updateLocalState();
     }
 
     @Override
@@ -426,7 +428,7 @@
         }
 
         // Update local properties.
-        updateLocalState(t.getResources());
+        updateLocalState();
     }
 
     private void updateStateFromTypedArray(TypedArray a) {
@@ -447,10 +449,10 @@
         dither = a.getBoolean(R.styleable.ShapeDrawable_dither, dither);
         paint.setDither(dither);
 
-        setIntrinsicWidth((int) a.getDimension(
-                R.styleable.ShapeDrawable_width, state.mIntrinsicWidth));
-        setIntrinsicHeight((int) a.getDimension(
-                R.styleable.ShapeDrawable_height, state.mIntrinsicHeight));
+        state.mIntrinsicWidth = (int) a.getDimension(
+                R.styleable.ShapeDrawable_width, state.mIntrinsicWidth);
+        state.mIntrinsicHeight = (int) a.getDimension(
+                R.styleable.ShapeDrawable_height, state.mIntrinsicHeight);
 
         final int tintMode = a.getInt(R.styleable.ShapeDrawable_tintMode, -1);
         if (tintMode != -1) {
@@ -494,21 +496,8 @@
     @Override
     public Drawable mutate() {
         if (!mMutated && super.mutate() == this) {
-            if (mShapeState.mPaint != null) {
-                mShapeState.mPaint = new Paint(mShapeState.mPaint);
-            } else {
-                mShapeState.mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
-            }
-            if (mShapeState.mPadding != null) {
-                mShapeState.mPadding = new Rect(mShapeState.mPadding);
-            } else {
-                mShapeState.mPadding = new Rect();
-            }
-            try {
-                mShapeState.mShape = mShapeState.mShape.clone();
-            } catch (CloneNotSupportedException e) {
-                return null;
-            }
+            mShapeState = new ShapeState(mShapeState);
+            updateLocalState();
             mMutated = true;
         }
         return this;
@@ -525,12 +514,13 @@
     /**
      * Defines the intrinsic properties of this ShapeDrawable's Shape.
      */
-    final static class ShapeState extends ConstantState {
-        int[] mThemeAttrs;
+    static final class ShapeState extends ConstantState {
+        final @NonNull Paint mPaint;
+
         @Config int mChangingConfigurations;
-        Paint mPaint;
+        int[] mThemeAttrs;
         Shape mShape;
-        ColorStateList mTint = null;
+        ColorStateList mTint;
         Mode mTintMode = DEFAULT_TINT_MODE;
         Rect mPadding;
         int mIntrinsicWidth;
@@ -538,21 +528,43 @@
         int mAlpha = 255;
         ShaderFactory mShaderFactory;
 
-        ShapeState(ShapeState orig) {
-            if (orig != null) {
-                mThemeAttrs = orig.mThemeAttrs;
-                mPaint = orig.mPaint;
-                mShape = orig.mShape;
-                mTint = orig.mTint;
-                mTintMode = orig.mTintMode;
-                mPadding = orig.mPadding;
-                mIntrinsicWidth = orig.mIntrinsicWidth;
-                mIntrinsicHeight = orig.mIntrinsicHeight;
-                mAlpha = orig.mAlpha;
-                mShaderFactory = orig.mShaderFactory;
-            } else {
-                mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        /**
+         * Constructs a new ShapeState.
+         */
+        ShapeState() {
+            mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        }
+
+        /**
+         * Constructs a new ShapeState that contains a deep copy of the
+         * specified ShapeState.
+         *
+         * @param orig the state to create a deep copy of
+         */
+        ShapeState(@NonNull ShapeState orig) {
+            mChangingConfigurations = orig.mChangingConfigurations;
+            mPaint = new Paint(orig.mPaint);
+            mThemeAttrs = orig.mThemeAttrs;
+            if (mShape != null) {
+                try {
+                    mShape = orig.mShape.clone();
+                } catch (CloneNotSupportedException e) {
+                    // Well, at least we tried.
+                    mShape = orig.mShape;
+                }
             }
+            mTint = orig.mTint;
+            mTintMode = orig.mTintMode;
+            if (orig.mPadding != null) {
+                mPadding = new Rect(orig.mPadding);
+            }
+            mIntrinsicWidth = orig.mIntrinsicWidth;
+            mIntrinsicHeight = orig.mIntrinsicHeight;
+            mAlpha = orig.mAlpha;
+
+            // We don't have any way to clone a shader factory, so hopefully
+            // this class doesn't contain any local state.
+            mShaderFactory = orig.mShaderFactory;
         }
 
         @Override
@@ -585,7 +597,7 @@
     private ShapeDrawable(ShapeState state, Resources res) {
         mShapeState = state;
 
-        updateLocalState(res);
+        updateLocalState();
     }
 
     /**
@@ -593,7 +605,7 @@
      * after significant state changes, e.g. from the One True Constructor and
      * after inflating or applying a theme.
      */
-    private void updateLocalState(Resources res) {
+    private void updateLocalState() {
         mTintFilter = updateTintFilter(mTintFilter, mShapeState.mTint, mShapeState.mTintMode);
     }
 
@@ -617,8 +629,4 @@
          */
         public abstract Shader resize(int width, int height);
     }
-
-    // other subclass could wack the Shader's localmatrix based on the
-    // resize params (e.g. scaletofit, etc.). This could be used to scale
-    // a bitmap to fill the bounds without needing any other special casing.
 }
diff --git a/graphics/java/android/graphics/drawable/shapes/ArcShape.java b/graphics/java/android/graphics/drawable/shapes/ArcShape.java
index c4b239f..85ba0a9 100644
--- a/graphics/java/android/graphics/drawable/shapes/ArcShape.java
+++ b/graphics/java/android/graphics/drawable/shapes/ArcShape.java
@@ -21,31 +21,47 @@
 import android.graphics.Paint;
 
 /**
- * Creates an arc shape. The arc shape starts at a specified
- * angle and sweeps clockwise, drawing slices of pie.
- * The arc can be drawn to a Canvas with its own draw() method,
- * but more graphical control is available if you instead pass
- * the ArcShape to a {@link android.graphics.drawable.ShapeDrawable}.
+ * Creates an arc shape. The arc shape starts at a specified angle and sweeps
+ * clockwise, drawing slices of pie.
+ * <p>
+ * The arc can be drawn to a {@link Canvas} with its own
+ * {@link #draw(Canvas, Paint)} method, but more graphical control is available
+ * if you instead pass the ArcShape to a
+ * {@link android.graphics.drawable.ShapeDrawable}.
  */
 public class ArcShape extends RectShape {
-    private float mStart;
-    private float mSweep;
-    
+    private final float mStartAngle;
+    private final float mSweepAngle;
+
     /**
-     * ArcShape constructor. 
-     * 
+     * ArcShape constructor.
+     *
      * @param startAngle the angle (in degrees) where the arc begins
-     * @param sweepAngle the sweep angle (in degrees). Anything equal to or 
+     * @param sweepAngle the sweep angle (in degrees). Anything equal to or
      *                   greater than 360 results in a complete circle/oval.
      */
     public ArcShape(float startAngle, float sweepAngle) {
-        mStart = startAngle;
-        mSweep = sweepAngle;
+        mStartAngle = startAngle;
+        mSweepAngle = sweepAngle;
     }
-    
+
+    /**
+     * @return the angle (in degrees) where the arc begins
+     */
+    public final float getStartAngle() {
+        return mStartAngle;
+    }
+
+    /**
+     * @return the sweep angle (in degrees)
+     */
+    public final float getSweepAngle() {
+        return mSweepAngle;
+    }
+
     @Override
     public void draw(Canvas canvas, Paint paint) {
-        canvas.drawArc(rect(), mStart, mSweep, true, paint);
+        canvas.drawArc(rect(), mStartAngle, mSweepAngle, true, paint);
     }
 
     @Override
@@ -53,5 +69,10 @@
         // Since we don't support concave outlines, arc shape does not attempt
         // to provide an outline.
     }
+
+    @Override
+    public ArcShape clone() throws CloneNotSupportedException {
+        return (ArcShape) super.clone();
+    }
 }
 
diff --git a/graphics/java/android/graphics/drawable/shapes/OvalShape.java b/graphics/java/android/graphics/drawable/shapes/OvalShape.java
index c9473f0..fb87d28 100644
--- a/graphics/java/android/graphics/drawable/shapes/OvalShape.java
+++ b/graphics/java/android/graphics/drawable/shapes/OvalShape.java
@@ -22,7 +22,8 @@
 import android.graphics.RectF;
 
 /**
- * Defines an oval shape. 
+ * Defines an oval shape.
+ * <p>
  * The oval can be drawn to a Canvas with its own draw() method,
  * but more graphical control is available if you instead pass
  * the OvalShape to a {@link android.graphics.drawable.ShapeDrawable}.
@@ -42,5 +43,10 @@
         outline.setOval((int) Math.ceil(rect.left), (int) Math.ceil(rect.top),
                 (int) Math.floor(rect.right), (int) Math.floor(rect.bottom));
     }
+
+    @Override
+    public OvalShape clone() throws CloneNotSupportedException {
+        return (OvalShape) super.clone();
+    }
 }
 
diff --git a/graphics/java/android/graphics/drawable/shapes/PathShape.java b/graphics/java/android/graphics/drawable/shapes/PathShape.java
index 30b7347..ce5552b 100644
--- a/graphics/java/android/graphics/drawable/shapes/PathShape.java
+++ b/graphics/java/android/graphics/drawable/shapes/PathShape.java
@@ -16,41 +16,44 @@
 
 package android.graphics.drawable.shapes;
 
+import android.annotation.NonNull;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Path;
 
 /**
  * Creates geometric paths, utilizing the {@link android.graphics.Path} class.
+ * <p>
  * The path can be drawn to a Canvas with its own draw() method,
  * but more graphical control is available if you instead pass
  * the PathShape to a {@link android.graphics.drawable.ShapeDrawable}.
  */
 public class PathShape extends Shape {
-    private Path    mPath;
-    private float   mStdWidth;
-    private float   mStdHeight;
-    
-    private float   mScaleX;    // cached from onResize
-    private float   mScaleY;    // cached from onResize
-    
+    private final float mStdWidth;
+    private final float mStdHeight;
+
+    private Path mPath;
+
+    private float mScaleX; // cached from onResize
+    private float mScaleY; // cached from onResize
+
     /**
      * PathShape constructor.
-     * 
-     * @param path       a Path that defines the geometric paths for this shape
-     * @param stdWidth   the standard width for the shape. Any changes to the 
-     *                   width with resize() will result in a width scaled based
-     *                   on the new width divided by this width.
-     * @param stdHeight  the standard height for the shape. Any changes to the 
-     *                   height with resize() will result in a height scaled based
-     *                   on the new height divided by this height.
+     *
+     * @param path a Path that defines the geometric paths for this shape
+     * @param stdWidth the standard width for the shape. Any changes to the
+     *                 width with resize() will result in a width scaled based
+     *                 on the new width divided by this width.
+     * @param stdHeight the standard height for the shape. Any changes to the
+     *                  height with resize() will result in a height scaled based
+     *                  on the new height divided by this height.
      */
-    public PathShape(Path path, float stdWidth, float stdHeight) {
+    public PathShape(@NonNull Path path, float stdWidth, float stdHeight) {
         mPath = path;
         mStdWidth = stdWidth;
         mStdHeight = stdHeight;
     }
-    
+
     @Override
     public void draw(Canvas canvas, Paint paint) {
         canvas.save();
@@ -58,7 +61,7 @@
         canvas.drawPath(mPath, paint);
         canvas.restore();
     }
-    
+
     @Override
     protected void onResize(float width, float height) {
         mScaleX = width / mStdWidth;
@@ -67,7 +70,7 @@
 
     @Override
     public PathShape clone() throws CloneNotSupportedException {
-        PathShape shape = (PathShape) super.clone();
+        final PathShape shape = (PathShape) super.clone();
         shape.mPath = new Path(mPath);
         return shape;
     }
diff --git a/graphics/java/android/graphics/drawable/shapes/RectShape.java b/graphics/java/android/graphics/drawable/shapes/RectShape.java
index 04cf293..e339a21 100644
--- a/graphics/java/android/graphics/drawable/shapes/RectShape.java
+++ b/graphics/java/android/graphics/drawable/shapes/RectShape.java
@@ -23,6 +23,7 @@
 
 /**
  * Defines a rectangle shape.
+ * <p>
  * The rectangle can be drawn to a Canvas with its own draw() method,
  * but more graphical control is available if you instead pass
  * the RectShape to a {@link android.graphics.drawable.ShapeDrawable}.
diff --git a/graphics/java/android/graphics/drawable/shapes/RoundRectShape.java b/graphics/java/android/graphics/drawable/shapes/RoundRectShape.java
index e5253b8..f5cbb24 100644
--- a/graphics/java/android/graphics/drawable/shapes/RoundRectShape.java
+++ b/graphics/java/android/graphics/drawable/shapes/RoundRectShape.java
@@ -16,6 +16,7 @@
 
 package android.graphics.drawable.shapes;
 
+import android.annotation.Nullable;
 import android.graphics.Canvas;
 import android.graphics.Outline;
 import android.graphics.Paint;
@@ -24,40 +25,41 @@
 
 /**
  * Creates a rounded-corner rectangle. Optionally, an inset (rounded) rectangle
- * can be included (to make a sort of "O" shape). 
+ * can be included (to make a sort of "O" shape).
+ * <p>
  * The rounded rectangle can be drawn to a Canvas with its own draw() method,
  * but more graphical control is available if you instead pass
  * the RoundRectShape to a {@link android.graphics.drawable.ShapeDrawable}.
  */
 public class RoundRectShape extends RectShape {
     private float[] mOuterRadii;
-    private RectF   mInset;
+    private RectF mInset;
     private float[] mInnerRadii;
     
     private RectF mInnerRect;
-    private Path  mPath;    // this is what we actually draw
+    private Path mPath; // this is what we actually draw
     
     /**
      * RoundRectShape constructor.
+     * <p>
      * Specifies an outer (round)rect and an optional inner (round)rect.
      *
      * @param outerRadii An array of 8 radius values, for the outer roundrect. 
-     *                   The first two floats are for the 
-     *                   top-left corner (remaining pairs correspond clockwise). 
-     *                   For no rounded corners on the outer rectangle, 
-     *                   pass null.
-     * @param inset      A RectF that specifies the distance from the inner 
-     *                   rect to each side of the outer rect. 
-     *                   For no inner, pass null.
+     *                   The first two floats are for the top-left corner
+     *                   (remaining pairs correspond clockwise). For no rounded
+     *                   corners on the outer rectangle, pass {@code null}.
+     * @param inset A RectF that specifies the distance from the inner
+     *              rect to each side of the outer rect. For no inner, pass
+     *              {@code null}.
      * @param innerRadii An array of 8 radius values, for the inner roundrect.
-     *                   The first two floats are for the 
-     *                   top-left corner (remaining pairs correspond clockwise). 
-     *                   For no rounded corners on the inner rectangle, 
-     *                   pass null.
-     *                   If inset parameter is null, this parameter is ignored. 
+     *                   The first two floats are for the top-left corner
+     *                   (remaining pairs correspond clockwise). For no rounded
+     *                   corners on the inner rectangle, pass {@code null}. If
+     *                   inset parameter is {@code null}, this parameter is
+     *                   ignored.
      */
-    public RoundRectShape(float[] outerRadii, RectF inset,
-                          float[] innerRadii) {
+    public RoundRectShape(@Nullable float[] outerRadii, @Nullable RectF inset,
+            @Nullable float[] innerRadii) {
         if (outerRadii != null && outerRadii.length < 8) {
             throw new ArrayIndexOutOfBoundsException("outer radii must have >= 8 values");
         }
@@ -97,8 +99,7 @@
 
         final RectF rect = rect();
         outline.setRoundRect((int) Math.ceil(rect.left), (int) Math.ceil(rect.top),
-                (int) Math.floor(rect.right), (int) Math.floor(rect.bottom),
-                radius);
+                (int) Math.floor(rect.right), (int) Math.floor(rect.bottom), radius);
     }
 
     @Override
@@ -128,7 +129,7 @@
 
     @Override
     public RoundRectShape clone() throws CloneNotSupportedException {
-        RoundRectShape shape = (RoundRectShape) super.clone();
+        final RoundRectShape shape = (RoundRectShape) super.clone();
         shape.mOuterRadii = mOuterRadii != null ? mOuterRadii.clone() : null;
         shape.mInnerRadii = mInnerRadii != null ? mInnerRadii.clone() : null;
         shape.mInset = new RectF(mInset);
diff --git a/graphics/java/android/graphics/drawable/shapes/Shape.java b/graphics/java/android/graphics/drawable/shapes/Shape.java
index eab8666..30b28f3 100644
--- a/graphics/java/android/graphics/drawable/shapes/Shape.java
+++ b/graphics/java/android/graphics/drawable/shapes/Shape.java
@@ -23,21 +23,25 @@
 
 /**
  * Defines a generic graphical "shape."
- * Any Shape can be drawn to a Canvas with its own draw() method,
- * but more graphical control is available if you instead pass
- * it to a {@link android.graphics.drawable.ShapeDrawable}.
+ * <p>
+ * Any Shape can be drawn to a Canvas with its own draw() method, but more
+ * graphical control is available if you instead pass it to a
+ * {@link android.graphics.drawable.ShapeDrawable}.
+ * <p>
+ * Custom Shape classes must implement {@link #clone()} and return an instance
+ * of the custom Shape class.
  */
 public abstract class Shape implements Cloneable {
     private float mWidth;
     private float mHeight;
-    
+
     /**
      * Returns the width of the Shape.
      */
     public final float getWidth() {
         return mWidth;
     }
-    
+
     /**
      * Returns the height of the Shape.
      */
@@ -46,9 +50,10 @@
     }
 
     /**
-     * Draw this shape into the provided Canvas, with the provided Paint.
+     * Draws this shape into the provided Canvas, with the provided Paint.
+     * <p>
      * Before calling this, you must call {@link #resize(float,float)}.
-     * 
+     *
      * @param canvas the Canvas within which this shape should be drawn
      * @param paint  the Paint object that defines this shape's characteristics
      */
@@ -56,8 +61,9 @@
 
     /**
      * Resizes the dimensions of this shape.
+     * <p>
      * Must be called before {@link #draw(Canvas,Paint)}.
-     * 
+     *
      * @param width the width of the shape (in pixels)
      * @param height the height of the shape (in pixels)
      */
@@ -74,30 +80,34 @@
             onResize(width, height);
         }
     }
-    
+
     /**
      * Checks whether the Shape is opaque.
-     * Default impl returns true. Override if your subclass can be opaque.
-     * 
-     * @return true if any part of the drawable is <em>not</em> opaque. 
+     * <p>
+     * Default impl returns {@code true}. Override if your subclass can be
+     * opaque.
+     *
+     * @return true if any part of the drawable is <em>not</em> opaque.
      */
     public boolean hasAlpha() {
         return true;
     }
-    
+
     /**
      * Callback method called when {@link #resize(float,float)} is executed.
-     * 
+     *
      * @param width the new width of the Shape
      * @param height the new height of the Shape
      */
     protected void onResize(float width, float height) {}
 
     /**
-     * Compute the Outline of the shape and return it in the supplied Outline
-     * parameter. The default implementation does nothing and {@code outline} is not changed.
+     * Computes the Outline of the shape and return it in the supplied Outline
+     * parameter. The default implementation does nothing and {@code outline}
+     * is not changed.
      *
-     * @param outline The Outline to be populated with the result. Should not be null.
+     * @param outline the Outline to be populated with the result. Must be
+     *                non-{@code null}.
      */
     public void getOutline(@NonNull Outline outline) {}
 
@@ -105,5 +115,4 @@
     public Shape clone() throws CloneNotSupportedException {
         return (Shape) super.clone();
     }
-
 }
diff --git a/graphics/java/android/graphics/fonts/FontRequest.java b/graphics/java/android/graphics/fonts/FontRequest.java
index e50df6f..c7a5830 100644
--- a/graphics/java/android/graphics/fonts/FontRequest.java
+++ b/graphics/java/android/graphics/fonts/FontRequest.java
@@ -18,24 +18,56 @@
 import android.annotation.NonNull;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.Base64;
 
 import com.android.internal.util.Preconditions;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
 /**
  * Information about a font request that may be sent to a Font Provider.
  */
 public final class FontRequest implements Parcelable {
     private final String mProviderAuthority;
+    private final String mProviderPackage;
     private final String mQuery;
+    private final List<List<byte[]>> mCertificates;
+
+    /**
+     * @param providerAuthority The authority of the Font Provider to be used for the request. This
+     *         should be a system installed app.
+     * @param providerPackage The package for the Font Provider to be used for the request. This is
+     *         used to verify the identity of the provider.
+     * @param query The query to be sent over to the provider. Refer to your font provider's
+     *         documentation on the format of this string.
+     */
+    public FontRequest(@NonNull String providerAuthority, @NonNull String providerPackage,
+            @NonNull String query) {
+        mProviderAuthority = Preconditions.checkNotNull(providerAuthority);
+        mQuery = Preconditions.checkNotNull(query);
+        mProviderPackage = Preconditions.checkNotNull(providerPackage);
+        mCertificates = Collections.emptyList();
+    }
 
     /**
      * @param providerAuthority The authority of the Font Provider to be used for the request.
      * @param query The query to be sent over to the provider. Refer to your font provider's
-     *              documentation on the format of this string.
+     *         documentation on the format of this string.
+     * @param providerPackage The package for the Font Provider to be used for the request. This is
+     *         used to verify the identity of the provider.
+     * @param certificates The list of sets of hashes for the certificates the provider should be
+     *         signed with. This is used to verify the identity of the provider. Each set in the
+     *         list represents one collection of signature hashes. Refer to your font provider's
+     *         documentation for these values.
      */
-    public FontRequest(@NonNull String providerAuthority, @NonNull String query) {
+    public FontRequest(@NonNull String providerAuthority, @NonNull String providerPackage,
+            @NonNull String query, @NonNull List<List<byte[]>> certificates) {
         mProviderAuthority = Preconditions.checkNotNull(providerAuthority);
+        mProviderPackage = Preconditions.checkNotNull(providerPackage);
         mQuery = Preconditions.checkNotNull(query);
+        mCertificates = Preconditions.checkNotNull(certificates);
     }
 
     /**
@@ -47,6 +79,14 @@
     }
 
     /**
+     * Returns the selected font provider's package. This helps the system verify that the provider
+     * identified by the given authority is the one requested.
+     */
+    public String getProviderPackage() {
+        return mProviderPackage;
+    }
+
+    /**
      * Returns the query string. Refer to your font provider's documentation on the format of this
      * string.
      */
@@ -54,6 +94,14 @@
         return mQuery;
     }
 
+    /**
+     * Returns the list of certificate sets given for this provider. This helps the system verify
+     * that the provider identified by the given authority is the one requested.
+     */
+    public List<List<byte[]>> getCertificates() {
+        return mCertificates;
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -62,12 +110,17 @@
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeString(mProviderAuthority);
+        dest.writeString(mProviderPackage);
         dest.writeString(mQuery);
+        dest.writeList(mCertificates);
     }
 
     private FontRequest(Parcel in) {
         mProviderAuthority = in.readString();
+        mProviderPackage = in.readString();
         mQuery = in.readString();
+        mCertificates = new ArrayList<>();
+        in.readList(mCertificates, null);
     }
 
     public static final Parcelable.Creator<FontRequest> CREATOR =
@@ -85,9 +138,24 @@
 
     @Override
     public String toString() {
-        return "FontRequest {"
+        StringBuilder builder = new StringBuilder();
+        builder.append("FontRequest {"
                 + "mProviderAuthority: " + mProviderAuthority
+                + ", mProviderPackage: " + mProviderPackage
                 + ", mQuery: " + mQuery
-                + "}";
+                + ", mCertificates:");
+        for (int i = 0; i < mCertificates.size(); i++) {
+            builder.append(" [");
+            List<byte[]> set = mCertificates.get(i);
+            for (int j = 0; j < set.size(); j++) {
+                builder.append(" \"");
+                byte[] array = set.get(j);
+                builder.append(Base64.encodeToString(array, Base64.DEFAULT));
+                builder.append("\"");
+            }
+            builder.append(" ]");
+        }
+        builder.append("}");
+        return builder.toString();
     }
 }
diff --git a/graphics/tests/graphicstests/Android.mk b/graphics/tests/graphicstests/Android.mk
deleted file mode 100644
index 8ea44bd..0000000
--- a/graphics/tests/graphicstests/Android.mk
+++ /dev/null
@@ -1,15 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
-LOCAL_PACKAGE_NAME := FrameworksGraphicsTests
-
-include $(BUILD_PACKAGE)
-
diff --git a/graphics/tests/graphicstests/AndroidManifest.xml b/graphics/tests/graphicstests/AndroidManifest.xml
deleted file mode 100644
index e019e28..0000000
--- a/graphics/tests/graphicstests/AndroidManifest.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-  
-          http://www.apache.org/licenses/LICENSE-2.0
-  
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.frameworks.graphicstests">
-    <uses-permission android:name="android.permission.RECEIVE_SMS"/>
-    <uses-permission android:name="android.permission.INTERNET" />
-    <uses-permission android:name="android.permission.READ_CONTACTS" />
-    <uses-permission android:name="android.permission.WRITE_CONTACTS" />
-    <uses-permission android:name="android.permission.WAKE_LOCK" />
-    <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
-    <uses-permission android:name="android.permission.WRITE_APN_SETTINGS" />
-    <uses-permission android:name="android.permission.BROADCAST_STICKY" />
-    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-
- 
-    <application>
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <instrumentation
-    	android:name="android.test.InstrumentationTestRunner"
-    	android:targetPackage="com.android.frameworks.graphicstests"
-    	android:label="Frameworks Graphics Tests" />
-</manifest>
diff --git a/graphics/tests/graphicstests/src/android/graphics/PaintTest.java b/graphics/tests/graphicstests/src/android/graphics/PaintTest.java
deleted file mode 100644
index 318bfb6..0000000
--- a/graphics/tests/graphicstests/src/android/graphics/PaintTest.java
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * 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 android.graphics;
-
-import android.test.AndroidTestCase;
-
-public class PaintTest extends AndroidTestCase {
-    public void testGetTextRunAdvances() {
-        {
-            // LTR
-            String text = "abcdef";
-            assertGetTextRunAdvances(text, 0, text.length(), 0, text.length(), false, true);
-            assertGetTextRunAdvances(text, 1, text.length() - 1, 0, text.length(), false, false);
-        }
-        {
-            // RTL
-            final String text =
-                    "\u0645\u0627\u0020\u0647\u064A\u0020\u0627\u0644\u0634" +
-                    "\u0641\u0631\u0629\u0020\u0627\u0644\u0645\u0648\u062D" +
-                    "\u062F\u0629\u0020\u064A\u0648\u0646\u064A\u0643\u0648" +
-                    "\u062F\u061F";
-            assertGetTextRunAdvances(text, 0, text.length(), 0, text.length(), true, true);
-            assertGetTextRunAdvances(text, 1, text.length() - 1, 0, text.length(), true, false);
-        }
-    }
-
-    private void assertGetTextRunAdvances(String str, int start, int end,
-            int contextStart, int contextEnd, boolean isRtl, boolean compareWithOtherMethods) {
-        Paint p = new Paint();
-
-        final int count = end - start;
-        final float[][] advanceArrays = new float[4][count];
-
-        final float advance = p.getTextRunAdvances(str, start, end, contextStart, contextEnd,
-                isRtl, advanceArrays[0], 0);
-
-        char chars[] = str.toCharArray();
-        final float advance_c = p.getTextRunAdvances(chars, start, count, contextStart,
-                contextEnd - contextStart, isRtl, advanceArrays[1], 0);
-        assertEquals(advance, advance_c, 1.0f);
-
-        for (int c = 1; c < count; ++c) {
-            final float firstPartAdvance = p.getTextRunAdvances(str, start, start + c,
-                    contextStart, contextEnd, isRtl, advanceArrays[2], 0);
-            final float secondPartAdvance = p.getTextRunAdvances(str, start + c, end,
-                    contextStart, contextEnd, isRtl, advanceArrays[2], c);
-            assertEquals(advance, firstPartAdvance + secondPartAdvance, 1.0f);
-
-
-            final float firstPartAdvance_c = p.getTextRunAdvances(chars, start, c,
-                    contextStart, contextEnd - contextStart, isRtl, advanceArrays[3], 0);
-            final float secondPartAdvance_c = p.getTextRunAdvances(chars, start + c,
-                    count - c, contextStart, contextEnd - contextStart, isRtl,
-                    advanceArrays[3], c);
-            assertEquals(advance, firstPartAdvance_c + secondPartAdvance_c, 1.0f);
-            assertEquals(firstPartAdvance, firstPartAdvance_c, 1.0f);
-            assertEquals(secondPartAdvance, secondPartAdvance_c, 1.0f);
-
-            for (int i = 1; i < advanceArrays.length; i++) {
-                for (int j = 0; j < count; j++) {
-                    assertEquals(advanceArrays[0][j], advanceArrays[i][j], 1.0f);
-                }
-            }
-
-            // Compare results with measureText, getRunAdvance, and getTextWidths.
-            if (compareWithOtherMethods && start == contextStart && end == contextEnd) {
-                assertEquals(advance, p.measureText(str, start, end), 1.0f);
-                assertEquals(advance, p.getRunAdvance(
-                        str, start, end, contextStart, contextEnd, isRtl, end), 1.0f);
-
-                final float[] widths = new float[count];
-                p.getTextWidths(str, start, end, widths);
-                for (int i = 0; i < count; i++) {
-                    assertEquals(advanceArrays[0][i], widths[i], 1.0f);
-                }
-            }
-        }
-    }
-
-    public void testGetTextRunAdvances_invalid() {
-        Paint p = new Paint();
-        String text = "test";
-
-        try {
-            p.getTextRunAdvances((String)null, 0, 0, 0, 0, false, null, 0);
-            fail("Should throw an IllegalArgumentException.");
-        } catch (IllegalArgumentException e) {
-        }
-
-        try {
-            p.getTextRunAdvances((CharSequence)null, 0, 0, 0, 0, false, null, 0);
-            fail("Should throw an IllegalArgumentException.");
-        } catch (IllegalArgumentException e) {
-        }
-
-        try {
-            p.getTextRunAdvances((char[])null, 0, 0, 0, 0, false, null, 0);
-            fail("Should throw an IllegalArgumentException.");
-        } catch (IllegalArgumentException e) {
-        }
-
-        try {
-            p.getTextRunAdvances(text, 0, text.length(), 0, text.length(), false,
-                    new float[text.length() - 1], 0);
-            fail("Should throw an IndexOutOfBoundsException.");
-        } catch (IndexOutOfBoundsException e) {
-        }
-
-        try {
-            p.getTextRunAdvances(text, 0, text.length(), 0, text.length(), false,
-                    new float[text.length()], 1);
-            fail("Should throw an IndexOutOfBoundsException.");
-        } catch (IndexOutOfBoundsException e) {
-        }
-
-        // 0 > contextStart
-        try {
-            p.getTextRunAdvances(text, 0, text.length(), -1, text.length(), false, null, 0);
-            fail("Should throw an IndexOutOfBoundsException.");
-        } catch (IndexOutOfBoundsException e) {
-        }
-
-        // contextStart > start
-        try {
-            p.getTextRunAdvances(text, 0, text.length(), 1, text.length(), false, null, 0);
-            fail("Should throw an IndexOutOfBoundsException.");
-        } catch (IndexOutOfBoundsException e) {
-        }
-
-        // start > end
-        try {
-            p.getTextRunAdvances(text, 1, 0, 0, text.length(), false, null, 0);
-            fail("Should throw an IndexOutOfBoundsException.");
-        } catch (IndexOutOfBoundsException e) {
-        }
-
-        // end > contextEnd
-        try {
-            p.getTextRunAdvances(text, 0, text.length(), 0, text.length() - 1, false, null, 0);
-            fail("Should throw an IndexOutOfBoundsException.");
-        } catch (IndexOutOfBoundsException e) {
-        }
-
-        // contextEnd > text.length
-        try {
-            p.getTextRunAdvances(text, 0, text.length(), 0, text.length() + 1, false, null, 0);
-            fail("Should throw an IndexOutOfBoundsException.");
-        } catch (IndexOutOfBoundsException e) {
-        }
-    }
-
-    public void testMeasureTextBidi() {
-        Paint p = new Paint();
-        {
-            String bidiText = "abc \u0644\u063A\u0629 def";
-            p.setBidiFlags(Paint.BIDI_LTR);
-            float width = p.measureText(bidiText, 0, 4);
-            p.setBidiFlags(Paint.BIDI_RTL);
-            width += p.measureText(bidiText, 4, 7);
-            p.setBidiFlags(Paint.BIDI_LTR);
-            width += p.measureText(bidiText, 7, bidiText.length());
-            assertEquals(width, p.measureText(bidiText), 1.0f);
-        }
-        {
-            String bidiText = "abc \u0644\u063A\u0629 def";
-            p.setBidiFlags(Paint.BIDI_DEFAULT_LTR);
-            float width = p.measureText(bidiText, 0, 4);
-            width += p.measureText(bidiText, 4, 7);
-            width += p.measureText(bidiText, 7, bidiText.length());
-            assertEquals(width, p.measureText(bidiText), 1.0f);
-        }
-        {
-            String bidiText = "abc \u0644\u063A\u0629 def";
-            p.setBidiFlags(Paint.BIDI_FORCE_LTR);
-            float width = p.measureText(bidiText, 0, 4);
-            width += p.measureText(bidiText, 4, 7);
-            width += p.measureText(bidiText, 7, bidiText.length());
-            assertEquals(width, p.measureText(bidiText), 1.0f);
-        }
-        {
-            String bidiText = "\u0644\u063A\u0629 abc \u0644\u063A\u0629";
-            p.setBidiFlags(Paint.BIDI_RTL);
-            float width = p.measureText(bidiText, 0, 4);
-            p.setBidiFlags(Paint.BIDI_LTR);
-            width += p.measureText(bidiText, 4, 7);
-            p.setBidiFlags(Paint.BIDI_RTL);
-            width += p.measureText(bidiText, 7, bidiText.length());
-            assertEquals(width, p.measureText(bidiText), 1.0f);
-        }
-        {
-            String bidiText = "\u0644\u063A\u0629 abc \u0644\u063A\u0629";
-            p.setBidiFlags(Paint.BIDI_DEFAULT_RTL);
-            float width = p.measureText(bidiText, 0, 4);
-            width += p.measureText(bidiText, 4, 7);
-            width += p.measureText(bidiText, 7, bidiText.length());
-            assertEquals(width, p.measureText(bidiText), 1.0f);
-        }
-        {
-            String bidiText = "\u0644\u063A\u0629 abc \u0644\u063A\u0629";
-            p.setBidiFlags(Paint.BIDI_FORCE_RTL);
-            float width = p.measureText(bidiText, 0, 4);
-            width += p.measureText(bidiText, 4, 7);
-            width += p.measureText(bidiText, 7, bidiText.length());
-            assertEquals(width, p.measureText(bidiText), 1.0f);
-        }
-    }
-
-    public void testSetGetWordSpacing() {
-        Paint p = new Paint();
-        assertEquals(0.0f, p.getWordSpacing());  // The default value should be 0.
-        p.setWordSpacing(1.0f);
-        assertEquals(1.0f, p.getWordSpacing());
-        p.setWordSpacing(-2.0f);
-        assertEquals(-2.0f, p.getWordSpacing());
-    }
-}
diff --git a/keystore/java/android/security/IKeyChainAliasCallback.aidl b/keystore/java/android/security/IKeyChainAliasCallback.aidl
index 1ea9521..b9d3753 100644
--- a/keystore/java/android/security/IKeyChainAliasCallback.aidl
+++ b/keystore/java/android/security/IKeyChainAliasCallback.aidl
@@ -20,7 +20,7 @@
  *
  * @hide
  */
-interface IKeyChainAliasCallback {
+oneway interface IKeyChainAliasCallback {
 
     void alias(String alias);
 }
diff --git a/keystore/java/android/security/IKeyChainService.aidl b/keystore/java/android/security/IKeyChainService.aidl
index deea972..c4bb72c 100644
--- a/keystore/java/android/security/IKeyChainService.aidl
+++ b/keystore/java/android/security/IKeyChainService.aidl
@@ -15,7 +15,7 @@
  */
 package android.security;
 
-import android.content.pm.ParceledListSlice;
+import android.content.pm.StringParceledListSlice;
 
 /**
  * Caller is required to ensure that {@link KeyStore#unlock
@@ -29,8 +29,8 @@
     byte[] getCertificate(String alias);
     byte[] getCaCertificates(String alias);
 
-    // APIs used by CertInstaller
-    void installCaCertificate(in byte[] caCertificate);
+    // APIs used by CertInstaller and DevicePolicyManager
+    String installCaCertificate(in byte[] caCertificate);
 
     // APIs used by DevicePolicyManager
     boolean installKeyPair(in byte[] privateKey, in byte[] userCert, in byte[] certChain, String alias);
@@ -39,8 +39,8 @@
     // APIs used by Settings
     boolean deleteCaCertificate(String alias);
     boolean reset();
-    ParceledListSlice getUserCaAliases();
-    ParceledListSlice getSystemCaAliases();
+    StringParceledListSlice getUserCaAliases();
+    StringParceledListSlice getSystemCaAliases();
     boolean containsCaAlias(String alias);
     byte[] getEncodedCaCertificate(String alias, boolean includeDeletedSystem);
     List<String> getCaCertificateChainAliases(String rootAlias, boolean includeDeletedSystem);
diff --git a/keystore/java/android/security/keystore/KeyProperties.java b/keystore/java/android/security/keystore/KeyProperties.java
index bf7a779a..d6b1cf1 100644
--- a/keystore/java/android/security/keystore/KeyProperties.java
+++ b/keystore/java/android/security/keystore/KeyProperties.java
@@ -45,7 +45,6 @@
                 PURPOSE_DECRYPT,
                 PURPOSE_SIGN,
                 PURPOSE_VERIFY,
-                PURPOSE_WRAP_KEY,
                 })
     public @interface PurposeEnum {}
 
@@ -70,12 +69,6 @@
     public static final int PURPOSE_VERIFY = 1 << 3;
 
     /**
-     * Purpose of key: wrapping key for secure key import.
-     */
-    public static final int PURPOSE_WRAP_KEY = 1 << 4;
-
-
-    /**
      * @hide
      */
     public static abstract class Purpose {
@@ -91,8 +84,6 @@
                     return KeymasterDefs.KM_PURPOSE_SIGN;
                 case PURPOSE_VERIFY:
                     return KeymasterDefs.KM_PURPOSE_VERIFY;
-                case PURPOSE_WRAP_KEY:
-                    return KeymasterDefs.KM_PURPOSE_WRAP_KEY;
                 default:
                     throw new IllegalArgumentException("Unknown purpose: " + purpose);
             }
@@ -108,8 +99,6 @@
                     return PURPOSE_SIGN;
                 case KeymasterDefs.KM_PURPOSE_VERIFY:
                     return PURPOSE_VERIFY;
-                case KeymasterDefs.KM_PURPOSE_WRAP_KEY:
-                    return PURPOSE_WRAP_KEY;
                 default:
                     throw new IllegalArgumentException("Unknown purpose: " + purpose);
             }
diff --git a/legacy-test/Android.mk b/legacy-test/Android.mk
index 0a814f3..05fec5e 100644
--- a/legacy-test/Android.mk
+++ b/legacy-test/Android.mk
@@ -50,5 +50,5 @@
 LOCAL_SRC_FILES := src/android/test/PerformanceTestCase.java
 LOCAL_MODULE := legacy-performance-test-hostdex
 
-include $(BUILD_HOST_DALVIK_JAVA_LIBRARY)
+include $(BUILD_HOST_DALVIK_STATIC_JAVA_LIBRARY)
 endif  # HOST_OS == linux
diff --git a/libs/androidfw/ApkAssets.cpp b/libs/androidfw/ApkAssets.cpp
index fe68ec0..a5b1d29 100644
--- a/libs/androidfw/ApkAssets.cpp
+++ b/libs/androidfw/ApkAssets.cpp
@@ -18,7 +18,10 @@
 
 #include "androidfw/ApkAssets.h"
 
+#include <algorithm>
+
 #include "android-base/logging.h"
+#include "utils/FileMap.h"
 #include "utils/Trace.h"
 #include "ziparchive/zip_archive.h"
 
@@ -62,13 +65,13 @@
     LOG(WARNING) << "resources.arsc is compressed.";
   }
 
+  loaded_apk->path_ = path;
   loaded_apk->resources_asset_ =
       loaded_apk->Open("resources.arsc", Asset::AccessMode::ACCESS_BUFFER);
   if (loaded_apk->resources_asset_ == nullptr) {
     return {};
   }
 
-  loaded_apk->path_ = path;
   loaded_apk->loaded_arsc_ =
       LoadedArsc::Load(loaded_apk->resources_asset_->getBuffer(true /*wordAligned*/),
                        loaded_apk->resources_asset_->getLength(), system, load_as_shared_library);
@@ -80,37 +83,93 @@
   return std::move(loaded_apk);
 }
 
-std::unique_ptr<Asset> ApkAssets::Open(const std::string& path, Asset::AccessMode /*mode*/) const {
-  ATRACE_NAME("ApkAssets::Open");
+std::unique_ptr<Asset> ApkAssets::Open(const std::string& path, Asset::AccessMode mode) const {
+  ATRACE_CALL();
   CHECK(zip_handle_ != nullptr);
 
   ::ZipString name(path.c_str());
   ::ZipEntry entry;
   int32_t result = ::FindEntry(zip_handle_.get(), name, &entry);
   if (result != 0) {
-    LOG(ERROR) << "No entry '" << path << "' found in APK.";
+    LOG(ERROR) << "No entry '" << path << "' found in APK '" << path_ << "'";
     return {};
   }
 
   if (entry.method == kCompressDeflated) {
-    auto compressed_asset = util::make_unique<_CompressedAsset>();
-    if (compressed_asset->openChunk(::GetFileDescriptor(zip_handle_.get()), entry.offset,
-                                    entry.method, entry.uncompressed_length,
-                                    entry.compressed_length) != NO_ERROR) {
+    std::unique_ptr<FileMap> map = util::make_unique<FileMap>();
+    if (!map->create(path_.c_str(), ::GetFileDescriptor(zip_handle_.get()), entry.offset,
+                     entry.compressed_length, true /*readOnly*/)) {
+      LOG(ERROR) << "Failed to mmap file '" << path << "' in APK '" << path_ << "'";
+      return {};
+    }
+
+    std::unique_ptr<Asset> asset =
+        Asset::createFromCompressedMap(std::move(map), entry.uncompressed_length, mode);
+    if (asset == nullptr) {
       LOG(ERROR) << "Failed to decompress '" << path << "'.";
       return {};
     }
-    return std::move(compressed_asset);
+    return asset;
   } else {
-    auto uncompressed_asset = util::make_unique<_FileAsset>();
-    if (uncompressed_asset->openChunk(path.c_str(), ::GetFileDescriptor(zip_handle_.get()),
-                                      entry.offset, entry.uncompressed_length) != NO_ERROR) {
-      LOG(ERROR) << "Failed to mmap '" << path << "'.";
+    std::unique_ptr<FileMap> map = util::make_unique<FileMap>();
+    if (!map->create(path_.c_str(), ::GetFileDescriptor(zip_handle_.get()), entry.offset,
+                     entry.uncompressed_length, true /*readOnly*/)) {
+      LOG(ERROR) << "Failed to mmap file '" << path << "' in APK '" << path_ << "'";
       return {};
     }
-    return std::move(uncompressed_asset);
+
+    std::unique_ptr<Asset> asset = Asset::createFromUncompressedMap(std::move(map), mode);
+    if (asset == nullptr) {
+      LOG(ERROR) << "Failed to mmap file '" << path << "' in APK '" << path_ << "'";
+      return {};
+    }
+    return asset;
   }
-  return {};
+}
+
+bool ApkAssets::ForEachFile(const std::string& root_path,
+                            const std::function<void(const StringPiece&, FileType)>& f) const {
+  CHECK(zip_handle_ != nullptr);
+
+  std::string root_path_full = root_path;
+  if (root_path_full.back() != '/') {
+    root_path_full += '/';
+  }
+
+  ::ZipString prefix(root_path_full.c_str());
+  void* cookie;
+  if (::StartIteration(zip_handle_.get(), &cookie, &prefix, nullptr) != 0) {
+    return false;
+  }
+
+  ::ZipString name;
+  ::ZipEntry entry;
+
+  // We need to hold back directories because many paths will contain them and we want to only
+  // surface one.
+  std::set<std::string> dirs;
+
+  int32_t result;
+  while ((result = ::Next(cookie, &entry, &name)) == 0) {
+    StringPiece full_file_path(reinterpret_cast<const char*>(name.name), name.name_length);
+    StringPiece leaf_file_path = full_file_path.substr(root_path_full.size());
+    auto iter = std::find(leaf_file_path.begin(), leaf_file_path.end(), '/');
+    if (iter != leaf_file_path.end()) {
+      dirs.insert(
+          leaf_file_path.substr(0, std::distance(leaf_file_path.begin(), iter)).to_string());
+    } else if (!leaf_file_path.empty()) {
+      f(leaf_file_path, kFileTypeRegular);
+    }
+  }
+  ::EndIteration(cookie);
+
+  // Now present the unique directories.
+  for (const std::string& dir : dirs) {
+    f(dir, kFileTypeDirectory);
+  }
+
+  // -1 is end of iteration, anything else is an error.
+  return result == -1;
 }
 
 }  // namespace android
diff --git a/libs/androidfw/Asset.cpp b/libs/androidfw/Asset.cpp
index 8e8c6a2..247458d 100644
--- a/libs/androidfw/Asset.cpp
+++ b/libs/androidfw/Asset.cpp
@@ -23,6 +23,7 @@
 
 #include <androidfw/Asset.h>
 #include <androidfw/StreamingZipInflater.h>
+#include <androidfw/Util.h>
 #include <androidfw/ZipFileRO.h>
 #include <androidfw/ZipUtils.h>
 #include <utils/Atomic.h>
@@ -298,6 +299,22 @@
     return pAsset;
 }
 
+/*static*/ std::unique_ptr<Asset> Asset::createFromUncompressedMap(std::unique_ptr<FileMap> dataMap,
+    AccessMode mode)
+{
+    std::unique_ptr<_FileAsset> pAsset = util::make_unique<_FileAsset>();
+
+    status_t result = pAsset->openChunk(dataMap.get());
+    if (result != NO_ERROR) {
+        return NULL;
+    }
+
+    // We succeeded, so relinquish control of dataMap
+    (void) dataMap.release();
+    pAsset->mAccessMode = mode;
+    return std::move(pAsset);
+}
+
 /*
  * Create a new Asset from compressed data in a memory mapping.
  */
@@ -316,6 +333,21 @@
     return pAsset;
 }
 
+/*static*/ std::unique_ptr<Asset> Asset::createFromCompressedMap(std::unique_ptr<FileMap> dataMap,
+    size_t uncompressedLen, AccessMode mode)
+{
+  std::unique_ptr<_CompressedAsset> pAsset = util::make_unique<_CompressedAsset>();
+
+  status_t result = pAsset->openChunk(dataMap.get(), uncompressedLen);
+  if (result != NO_ERROR) {
+      return NULL;
+  }
+
+  // We succeeded, so relinquish control of dataMap
+  (void) dataMap.release();
+  pAsset->mAccessMode = mode;
+  return std::move(pAsset);
+}
 
 /*
  * Do generic seek() housekeeping.  Pass in the offset/whence values from
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index ef0c967..5667f92 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -138,6 +138,17 @@
   return &package_groups_[idx].dynamic_ref_table;
 }
 
+const DynamicRefTable* AssetManager2::GetDynamicRefTableForCookie(ApkAssetsCookie cookie) const {
+  for (const PackageGroup& package_group : package_groups_) {
+    for (const ApkAssetsCookie& package_cookie : package_group.cookies_) {
+      if (package_cookie == cookie) {
+        return &package_group.dynamic_ref_table;
+      }
+    }
+  }
+  return nullptr;
+}
+
 void AssetManager2::SetConfiguration(const ResTable_config& configuration) {
   const int diff = configuration_.diff(configuration);
   configuration_ = configuration;
@@ -188,6 +199,35 @@
   return OpenNonAsset(new_path, cookie, mode);
 }
 
+std::unique_ptr<AssetDir> AssetManager2::OpenDir(const std::string& dirname) {
+  ATRACE_CALL();
+
+  std::string full_path = "assets/" + dirname;
+  std::unique_ptr<SortedVector<AssetDir::FileInfo>> files =
+      util::make_unique<SortedVector<AssetDir::FileInfo>>();
+
+  // Start from the back.
+  for (auto iter = apk_assets_.rbegin(); iter != apk_assets_.rend(); ++iter) {
+    const ApkAssets* apk_assets = *iter;
+
+    auto func = [&](const StringPiece& name, FileType type) {
+      AssetDir::FileInfo info;
+      info.setFileName(String8(name.data(), name.size()));
+      info.setFileType(type);
+      info.setSourceName(String8(apk_assets->GetPath().c_str()));
+      files->add(info);
+    };
+
+    if (!apk_assets->ForEachFile(full_path, func)) {
+      return {};
+    }
+  }
+
+  std::unique_ptr<AssetDir> asset_dir = util::make_unique<AssetDir>();
+  asset_dir->setFileList(files.release());
+  return asset_dir;
+}
+
 // Search in reverse because that's how we used to do it and we need to preserve behaviour.
 // This is unfortunate, because ClassLoaders delegate to the parent first, so the order
 // is inconsistent for split APKs.
@@ -237,15 +277,15 @@
     desired_config = &density_override_config;
   }
 
-  const uint32_t package_id = get_package_id(resid);
-  const uint8_t type_id = get_type_id(resid);
-  const uint16_t entry_id = get_entry_id(resid);
-
-  if (type_id == 0) {
+  if (!is_valid_resid(resid)) {
     LOG(ERROR) << base::StringPrintf("Invalid ID 0x%08x.", resid);
     return kInvalidCookie;
   }
 
+  const uint32_t package_id = get_package_id(resid);
+  const uint8_t type_idx = get_type_id(resid) - 1;
+  const uint16_t entry_id = get_entry_id(resid);
+
   const uint8_t idx = package_ids_[package_id];
   if (idx == 0xff) {
     LOG(ERROR) << base::StringPrintf("No package ID %02x found for ID 0x%08x.", package_id, resid);
@@ -265,7 +305,7 @@
     uint32_t current_flags = 0;
 
     const LoadedPackage* loaded_package = package_group.packages_[i];
-    if (!loaded_package->FindEntry(type_id - 1, entry_id, *desired_config, &current_entry,
+    if (!loaded_package->FindEntry(type_idx, entry_id, *desired_config, &current_entry,
                                    &current_config, &current_flags)) {
       continue;
     }
@@ -385,16 +425,16 @@
 ApkAssetsCookie AssetManager2::ResolveReference(ApkAssetsCookie cookie, Res_value* in_out_value,
                                                 ResTable_config* in_out_selected_config,
                                                 uint32_t* in_out_flags,
-                                                ResTable_ref* out_last_reference) {
+                                                uint32_t* out_last_reference) {
   ATRACE_CALL();
   constexpr const int kMaxIterations = 20;
 
-  out_last_reference->ident = 0u;
+  *out_last_reference = 0u;
   for (size_t iteration = 0u; in_out_value->dataType == Res_value::TYPE_REFERENCE &&
                               in_out_value->data != 0u && iteration < kMaxIterations;
        iteration++) {
     if (out_last_reference != nullptr) {
-      out_last_reference->ident = in_out_value->data;
+      *out_last_reference = in_out_value->data;
     }
     uint32_t new_flags = 0u;
     cookie = GetResource(in_out_value->data, true /*may_be_bag*/, 0u /*density_override*/,
@@ -405,7 +445,7 @@
     if (in_out_flags != nullptr) {
       *in_out_flags |= new_flags;
     }
-    if (out_last_reference->ident == in_out_value->data) {
+    if (*out_last_reference == in_out_value->data) {
       // This reference can't be resolved, so exit now and let the caller deal with it.
       return cookie;
     }
@@ -832,6 +872,25 @@
   return kInvalidCookie;
 }
 
+ApkAssetsCookie Theme::ResolveAttributeReference(ApkAssetsCookie cookie, Res_value* in_out_value,
+                                                 ResTable_config* in_out_selected_config,
+                                                 uint32_t* in_out_type_spec_flags,
+                                                 uint32_t* out_last_ref) {
+  if (in_out_value->dataType == Res_value::TYPE_ATTRIBUTE) {
+    uint32_t new_flags;
+    cookie = GetAttribute(in_out_value->data, in_out_value, &new_flags);
+    if (cookie == kInvalidCookie) {
+      return kInvalidCookie;
+    }
+
+    if (in_out_type_spec_flags != nullptr) {
+      *in_out_type_spec_flags |= new_flags;
+    }
+  }
+  return asset_manager_->ResolveReference(cookie, in_out_value, in_out_selected_config,
+                                          in_out_type_spec_flags, out_last_ref);
+}
+
 void Theme::Clear() {
   type_spec_flags_ = 0u;
   for (std::unique_ptr<Package>& package : packages_) {
diff --git a/libs/androidfw/CursorWindow.cpp b/libs/androidfw/CursorWindow.cpp
index 166863c..5694115 100644
--- a/libs/androidfw/CursorWindow.cpp
+++ b/libs/androidfw/CursorWindow.cpp
@@ -98,9 +98,14 @@
             if (dupAshmemFd < 0) {
                 result = -errno;
             } else {
+                // the size of the ashmem descriptor can be modified between ashmem_get_size_region
+                // call and mmap, so we'll check again immediately after memory is mapped
                 void* data = ::mmap(NULL, size, PROT_READ, MAP_SHARED, dupAshmemFd, 0);
                 if (data == MAP_FAILED) {
                     result = -errno;
+                } else if (ashmem_get_size_region(dupAshmemFd) != size) {
+                    ::munmap(data, size);
+                    result = BAD_VALUE;
                 } else {
                     CursorWindow* window = new CursorWindow(name, dupAshmemFd,
                             data, size, true /*readOnly*/);
diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp
index db72f48..621d8c0 100644
--- a/libs/androidfw/LoadedArsc.cpp
+++ b/libs/androidfw/LoadedArsc.cpp
@@ -212,7 +212,7 @@
 
 static bool VerifyType(const Chunk& chunk) {
   ATRACE_CALL();
-  const ResTable_type* header = chunk.header<ResTable_type>();
+  const ResTable_type* header = chunk.header<ResTable_type, kResTableTypeMinSize>();
 
   const size_t entry_count = dtohl(header->entryCount);
   if (entry_count > std::numeric_limits<uint16_t>::max()) {
@@ -533,7 +533,7 @@
       } break;
 
       case RES_TABLE_TYPE_TYPE: {
-        const ResTable_type* type = child_chunk.header<ResTable_type>();
+        const ResTable_type* type = child_chunk.header<ResTable_type, kResTableTypeMinSize>();
         if (type == nullptr) {
           LOG(ERROR) << "Chunk RES_TABLE_TYPE_TYPE is too small.";
           return {};
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 763a178..b8d95e4 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -6074,6 +6074,10 @@
     return true;
 }
 
+static bool keyCompare(const ResTable_sparseTypeEntry& entry , uint16_t entryIdx) {
+  return dtohs(entry.idx) < entryIdx;
+}
+
 status_t ResTable::getEntry(
         const PackageGroup* packageGroup, int typeIndex, int entryIndex,
         const ResTable_config* config,
@@ -6115,6 +6119,9 @@
             currentTypeIsOverlay = true;
         }
 
+        // Check that the entry idx is within range of the declared entry count (ResTable_typeSpec).
+        // Particular types (ResTable_type) may be encoded with sparse entries, and so their
+        // entryCount do not need to match.
         if (static_cast<size_t>(realEntryIndex) >= typeSpec->entryCount) {
             ALOGW("For resource 0x%08x, entry index(%d) is beyond type entryCount(%d)",
                     Res_MAKEID(packageGroup->id - 1, typeIndex, entryIndex),
@@ -6169,11 +6176,37 @@
                 continue;
             }
 
-            // Check if there is the desired entry in this type.
             const uint32_t* const eindex = reinterpret_cast<const uint32_t*>(
                     reinterpret_cast<const uint8_t*>(thisType) + dtohs(thisType->header.headerSize));
 
-            uint32_t thisOffset = dtohl(eindex[realEntryIndex]);
+            uint32_t thisOffset;
+
+            // Check if there is the desired entry in this type.
+            if (thisType->flags & ResTable_type::FLAG_SPARSE) {
+                // This is encoded as a sparse map, so perform a binary search.
+                const ResTable_sparseTypeEntry* sparseIndices =
+                        reinterpret_cast<const ResTable_sparseTypeEntry*>(eindex);
+                const ResTable_sparseTypeEntry* result = std::lower_bound(
+                        sparseIndices, sparseIndices + dtohl(thisType->entryCount), realEntryIndex,
+                        keyCompare);
+                if (result == sparseIndices + dtohl(thisType->entryCount)
+                        || dtohs(result->idx) != realEntryIndex) {
+                    // No entry found.
+                    continue;
+                }
+
+                // Extract the offset from the entry. Each offset must be a multiple of 4
+                // so we store it as the real offset divided by 4.
+                thisOffset = dtohs(result->offset) * 4u;
+            } else {
+                if (static_cast<uint32_t>(realEntryIndex) >= dtohl(thisType->entryCount)) {
+                    // Entry does not exist.
+                    continue;
+                }
+
+                thisOffset = dtohl(eindex[realEntryIndex]);
+            }
+
             if (thisOffset == ResTable_type::NO_ENTRY) {
                 // There is no entry for this index and configuration.
                 continue;
@@ -6480,12 +6513,6 @@
                 }
 
                 Type* t = typeList.editItemAt(typeList.size() - 1);
-                if (newEntryCount != t->entryCount) {
-                    ALOGE("ResTable_type entry count inconsistent: given %d, previously %d",
-                        (int)newEntryCount, (int)t->entryCount);
-                    return (mError=BAD_TYPE);
-                }
-
                 if (t->package != package) {
                     ALOGE("No TypeSpec for type %d", type->id);
                     return (mError=BAD_TYPE);
@@ -6532,6 +6559,8 @@
     return NO_ERROR;
 }
 
+DynamicRefTable::DynamicRefTable() : DynamicRefTable(0, false) {}
+
 DynamicRefTable::DynamicRefTable(uint8_t packageId, bool appAsLib)
     : mAssignedPackageId(packageId)
     , mAppAsLib(appAsLib)
@@ -6637,11 +6666,11 @@
     // Do a proper lookup.
     uint8_t translatedId = mLookupTable[packageId];
     if (translatedId == 0) {
-        ALOGV("DynamicRefTable(0x%02x): No mapping for build-time package ID 0x%02x.",
+        ALOGW("DynamicRefTable(0x%02x): No mapping for build-time package ID 0x%02x.",
                 (uint8_t)mAssignedPackageId, (uint8_t)packageId);
         for (size_t i = 0; i < 256; i++) {
             if (mLookupTable[i] != 0) {
-                ALOGV("e[0x%02x] -> 0x%02x", (uint8_t)i, mLookupTable[i]);
+                ALOGW("e[0x%02x] -> 0x%02x", (uint8_t)i, mLookupTable[i]);
             }
         }
         return UNKNOWN_ERROR;
@@ -7096,8 +7125,17 @@
                 thisConfig.copyFromDtoH(type->config);
 
                 String8 configStr = thisConfig.toString();
-                printf("      config %s:\n", configStr.size() > 0
+                printf("      config %s", configStr.size() > 0
                         ? configStr.string() : "(default)");
+                if (type->flags != 0u) {
+                    printf(" flags=0x%02x", type->flags);
+                    if (type->flags & ResTable_type::FLAG_SPARSE) {
+                        printf(" [sparse]");
+                    }
+                }
+
+                printf(":\n");
+
                 size_t entryCount = dtohl(type->entryCount);
                 uint32_t entriesStart = dtohl(type->entriesStart);
                 if ((entriesStart&0x3) != 0) {
@@ -7109,18 +7147,30 @@
                     printf("      NON-INTEGER ResTable_type header.size: 0x%x\n", typeSize);
                     continue;
                 }
-                for (size_t entryIndex=0; entryIndex<entryCount; entryIndex++) {
-                    const uint32_t* const eindex = (const uint32_t*)
-                        (((const uint8_t*)type) + dtohs(type->header.headerSize));
 
-                    uint32_t thisOffset = dtohl(eindex[entryIndex]);
-                    if (thisOffset == ResTable_type::NO_ENTRY) {
-                        continue;
+                const uint32_t* const eindex = (const uint32_t*)
+                        (((const uint8_t*)type) + dtohs(type->header.headerSize));
+                for (size_t entryIndex=0; entryIndex<entryCount; entryIndex++) {
+                    size_t entryId;
+                    uint32_t thisOffset;
+                    if (type->flags & ResTable_type::FLAG_SPARSE) {
+                        const ResTable_sparseTypeEntry* entry =
+                                reinterpret_cast<const ResTable_sparseTypeEntry*>(
+                                        eindex + entryIndex);
+                        entryId = dtohs(entry->idx);
+                        // Offsets are encoded as divided by 4.
+                        thisOffset = static_cast<uint32_t>(dtohs(entry->offset)) * 4u;
+                    } else {
+                        entryId = entryIndex;
+                        thisOffset = dtohl(eindex[entryIndex]);
+                        if (thisOffset == ResTable_type::NO_ENTRY) {
+                            continue;
+                        }
                     }
 
                     uint32_t resID = (0xff000000 & ((packageId)<<24))
                                 | (0x00ff0000 & ((typeIndex+1)<<16))
-                                | (0x0000ffff & (entryIndex));
+                                | (0x0000ffff & (entryId));
                     if (packageId == 0) {
                         pg->dynamicRefTable.lookupResourceId(&resID);
                     }
diff --git a/libs/androidfw/TypeWrappers.cpp b/libs/androidfw/TypeWrappers.cpp
index 06b4040..647aa19 100644
--- a/libs/androidfw/TypeWrappers.cpp
+++ b/libs/androidfw/TypeWrappers.cpp
@@ -16,23 +16,45 @@
 
 #include <androidfw/TypeWrappers.h>
 
+#include <algorithm>
+
 namespace android {
 
+TypeVariant::TypeVariant(const ResTable_type* data) : data(data), mLength(dtohl(data->entryCount)) {
+    if (data->flags & ResTable_type::FLAG_SPARSE) {
+        const uint32_t entryCount = dtohl(data->entryCount);
+        const uintptr_t containerEnd = reinterpret_cast<uintptr_t>(data) + dtohl(data->header.size);
+        const uint32_t* const entryIndices = reinterpret_cast<const uint32_t*>(
+                reinterpret_cast<uintptr_t>(data) + dtohs(data->header.headerSize));
+        if (reinterpret_cast<uintptr_t>(entryIndices) + (sizeof(uint32_t) * entryCount)
+                > containerEnd) {
+            ALOGE("Type's entry indices extend beyond its boundaries");
+            mLength = 0;
+        } else {
+          mLength = ResTable_sparseTypeEntry{entryIndices[entryCount - 1]}.idx + 1;
+        }
+    }
+}
+
 TypeVariant::iterator& TypeVariant::iterator::operator++() {
     mIndex++;
-    if (mIndex > dtohl(mTypeVariant->data->entryCount)) {
-        mIndex = dtohl(mTypeVariant->data->entryCount);
+    if (mIndex > mTypeVariant->mLength) {
+        mIndex = mTypeVariant->mLength;
     }
     return *this;
 }
 
+static bool keyCompare(uint32_t entry, uint16_t index) {
+  return dtohs(ResTable_sparseTypeEntry{entry}.idx) < index;
+}
+
 const ResTable_entry* TypeVariant::iterator::operator*() const {
     const ResTable_type* type = mTypeVariant->data;
-    const uint32_t entryCount = dtohl(type->entryCount);
-    if (mIndex >= entryCount) {
+    if (mIndex >= mTypeVariant->mLength) {
         return NULL;
     }
 
+    const uint32_t entryCount = dtohl(mTypeVariant->data->entryCount);
     const uintptr_t containerEnd = reinterpret_cast<uintptr_t>(type)
             + dtohl(type->header.size);
     const uint32_t* const entryIndices = reinterpret_cast<const uint32_t*>(
@@ -42,7 +64,19 @@
         return NULL;
     }
 
-    const uint32_t entryOffset = dtohl(entryIndices[mIndex]);
+    uint32_t entryOffset;
+    if (type->flags & ResTable_type::FLAG_SPARSE) {
+      auto iter = std::lower_bound(entryIndices, entryIndices + entryCount, mIndex, keyCompare);
+      if (iter == entryIndices + entryCount
+              || dtohs(ResTable_sparseTypeEntry{*iter}.idx) != mIndex) {
+        return NULL;
+      }
+
+      entryOffset = static_cast<uint32_t>(dtohs(ResTable_sparseTypeEntry{*iter}.offset)) * 4u;
+    } else {
+      entryOffset = dtohl(entryIndices[mIndex]);
+    }
+
     if (entryOffset == ResTable_type::NO_ENTRY) {
         return NULL;
     }
diff --git a/libs/androidfw/Util.cpp b/libs/androidfw/Util.cpp
index 202bc8e..575cd18 100644
--- a/libs/androidfw/Util.cpp
+++ b/libs/androidfw/Util.cpp
@@ -41,5 +41,31 @@
   }
 }
 
+std::u16string Utf8ToUtf16(const StringPiece& utf8) {
+  ssize_t utf16_length =
+      utf8_to_utf16_length(reinterpret_cast<const uint8_t*>(utf8.data()), utf8.length());
+  if (utf16_length <= 0) {
+    return {};
+  }
+
+  std::u16string utf16;
+  utf16.resize(utf16_length);
+  utf8_to_utf16(reinterpret_cast<const uint8_t*>(utf8.data()), utf8.length(), &*utf16.begin(),
+                utf16_length + 1);
+  return utf16;
+}
+
+std::string Utf16ToUtf8(const StringPiece16& utf16) {
+  ssize_t utf8_length = utf16_to_utf8_length(utf16.data(), utf16.length());
+  if (utf8_length <= 0) {
+    return {};
+  }
+
+  std::string utf8;
+  utf8.resize(utf8_length);
+  utf16_to_utf8(utf16.data(), utf16.length(), &*utf8.begin(), utf8_length + 1);
+  return utf8;
+}
+
 } // namespace util
 } // namespace android
diff --git a/libs/androidfw/include/androidfw/ApkAssets.h b/libs/androidfw/include/androidfw/ApkAssets.h
index 6d1578c..b7e66fb 100644
--- a/libs/androidfw/include/androidfw/ApkAssets.h
+++ b/libs/androidfw/include/androidfw/ApkAssets.h
@@ -25,6 +25,7 @@
 
 #include "androidfw/Asset.h"
 #include "androidfw/LoadedArsc.h"
+#include "androidfw/misc.h"
 
 namespace android {
 
@@ -38,6 +39,9 @@
   std::unique_ptr<Asset> Open(const std::string& path,
                               Asset::AccessMode mode = Asset::AccessMode::ACCESS_RANDOM) const;
 
+  bool ForEachFile(const std::string& path,
+                   const std::function<void(const StringPiece&, FileType)>& f) const;
+
   inline const std::string& GetPath() const { return path_; }
 
   inline const LoadedArsc* GetLoadedArsc() const { return loaded_arsc_.get(); }
@@ -56,6 +60,7 @@
 
   using ZipArchivePtr =
       std::unique_ptr<typename std::remove_pointer<::ZipArchiveHandle>::type, ZipArchivePtrCloser>;
+
   ZipArchivePtr zip_handle_;
   std::string path_;
   std::unique_ptr<Asset> resources_asset_;
diff --git a/libs/androidfw/include/androidfw/Asset.h b/libs/androidfw/include/androidfw/Asset.h
index 461e773..9d12a35 100644
--- a/libs/androidfw/include/androidfw/Asset.h
+++ b/libs/androidfw/include/androidfw/Asset.h
@@ -24,6 +24,8 @@
 #include <stdio.h>
 #include <sys/types.h>
 
+#include <memory>
+
 #include <utils/Compat.h>
 #include <utils/Errors.h>
 #include <utils/String8.h>
@@ -150,6 +152,7 @@
 
     /* AssetManager needs access to our "create" functions */
     friend class AssetManager;
+    friend class ApkAssets;
 
     /*
      * Create the asset from a named file on disk.
@@ -194,6 +197,9 @@
      */
     static Asset* createFromUncompressedMap(FileMap* dataMap, AccessMode mode);
 
+    static std::unique_ptr<Asset> createFromUncompressedMap(std::unique_ptr<FileMap> dataMap,
+        AccessMode mode);
+
     /*
      * Create the asset from a memory-mapped file segment with compressed
      * data.
@@ -203,6 +209,9 @@
     static Asset* createFromCompressedMap(FileMap* dataMap,
         size_t uncompressedLen, AccessMode mode);
 
+    static std::unique_ptr<Asset> createFromCompressedMap(std::unique_ptr<FileMap> dataMap,
+        size_t uncompressedLen, AccessMode mode);
+
 
     /*
      * Create from a reference-counted chunk of shared memory.
diff --git a/libs/androidfw/include/androidfw/AssetDir.h b/libs/androidfw/include/androidfw/AssetDir.h
index bd89d7d..7aef02d 100644
--- a/libs/androidfw/include/androidfw/AssetDir.h
+++ b/libs/androidfw/include/androidfw/AssetDir.h
@@ -70,6 +70,7 @@
     const AssetDir& operator=(const AssetDir& src);
 
     friend class AssetManager;
+    friend class AssetManager2;
 
     /*
      * This holds information about files in the asset hierarchy.
diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h
index 81cdc46..d2bc6ee 100644
--- a/libs/androidfw/include/androidfw/AssetManager2.h
+++ b/libs/androidfw/include/androidfw/AssetManager2.h
@@ -107,6 +107,9 @@
   // Returns the DynamicRefTable for the given package ID.
   const DynamicRefTable* GetDynamicRefTableForPackage(uint32_t package_id) const;
 
+  // Returns the DynamicRefTable for the ApkAssets represented by the cookie.
+  const DynamicRefTable* GetDynamicRefTableForCookie(ApkAssetsCookie cookie) const;
+
   // Sets/resets the configuration for this AssetManager. This will cause all
   // caches that are related to the configuration change to be invalidated.
   void SetConfiguration(const ResTable_config& configuration);
@@ -143,6 +146,11 @@
   std::unique_ptr<Asset> Open(const std::string& filename, ApkAssetsCookie cookie,
                               Asset::AccessMode mode);
 
+  // Opens the directory specified by `dirname`. The result is an AssetDir that is the combination
+  // of all directories matching `dirname` under the assets/ directory of every ApkAssets loaded.
+  // The entries are sorted by their ASCII name.
+  std::unique_ptr<AssetDir> OpenDir(const std::string& dirname);
+
   // Searches the set of APKs loaded by this AssetManager and opens the first one found.
   // `mode` controls how the file is opened.
   // `out_cookie` is populated with the cookie of the APK this file was found in.
@@ -203,7 +211,7 @@
   // it was not found.
   ApkAssetsCookie ResolveReference(ApkAssetsCookie cookie, Res_value* in_out_value,
                                    ResTable_config* in_out_selected_config, uint32_t* in_out_flags,
-                                   ResTable_ref* out_last_reference);
+                                   uint32_t* out_last_reference);
 
   // Retrieves the best matching bag/map resource with ID `resid`.
   // This method will resolve all parent references for this bag and merge keys with the child.
@@ -298,6 +306,8 @@
 
   inline const AssetManager2* GetAssetManager() const { return asset_manager_; }
 
+  inline AssetManager2* GetAssetManager() { return asset_manager_; }
+
   // Returns a bit mask of configuration changes that will impact this
   // theme (and thus require completely reloading it).
   inline uint32_t GetChangingConfigurations() const { return type_spec_flags_; }
@@ -318,10 +328,10 @@
 
   // This is like AssetManager2::ResolveReference(), but also takes
   // care of resolving attribute references to the theme.
-  ApkAssetsCookie ResolveAttributeReference(Res_value* in_out_value, ApkAssetsCookie src_cookie,
-                                            uint32_t* out_last_ref = nullptr,
+  ApkAssetsCookie ResolveAttributeReference(ApkAssetsCookie cookie, Res_value* in_out_value,
+                                            ResTable_config* in_out_selected_config = nullptr,
                                             uint32_t* in_out_type_spec_flags = nullptr,
-                                            ResTable_config* out_selected_config = nullptr) const;
+                                            uint32_t* out_last_ref = nullptr);
 
  private:
   DISALLOW_COPY_AND_ASSIGN(Theme);
diff --git a/libs/androidfw/include/androidfw/Chunk.h b/libs/androidfw/include/androidfw/Chunk.h
index e87b940..89b588e 100644
--- a/libs/androidfw/include/androidfw/Chunk.h
+++ b/libs/androidfw/include/androidfw/Chunk.h
@@ -48,9 +48,9 @@
   // Returns the size of the header. Caller need not worry about endianness.
   inline size_t header_size() const { return dtohs(device_chunk_->headerSize); }
 
-  template <typename T>
+  template <typename T, size_t MinSize = sizeof(T)>
   inline const T* header() const {
-    if (header_size() >= sizeof(T)) {
+    if (header_size() >= MinSize) {
       return reinterpret_cast<const T*>(device_chunk_);
     }
     return nullptr;
diff --git a/libs/androidfw/include/androidfw/CursorWindow.h b/libs/androidfw/include/androidfw/CursorWindow.h
index f543565..ad64b24 100644
--- a/libs/androidfw/include/androidfw/CursorWindow.h
+++ b/libs/androidfw/include/androidfw/CursorWindow.h
@@ -17,6 +17,7 @@
 #ifndef _ANDROID__DATABASE_WINDOW_H
 #define _ANDROID__DATABASE_WINDOW_H
 
+#include <inttypes.h>
 #include <stddef.h>
 #include <stdint.h>
 
@@ -128,12 +129,13 @@
     inline const char* getFieldSlotValueString(FieldSlot* fieldSlot,
             size_t* outSizeIncludingNull) {
         *outSizeIncludingNull = fieldSlot->data.buffer.size;
-        return static_cast<char*>(offsetToPtr(fieldSlot->data.buffer.offset));
+        return static_cast<char*>(offsetToPtr(
+                fieldSlot->data.buffer.offset, fieldSlot->data.buffer.size));
     }
 
     inline const void* getFieldSlotValueBlob(FieldSlot* fieldSlot, size_t* outSize) {
         *outSize = fieldSlot->data.buffer.size;
-        return offsetToPtr(fieldSlot->data.buffer.offset);
+        return offsetToPtr(fieldSlot->data.buffer.offset, fieldSlot->data.buffer.size);
     }
 
 private:
@@ -166,7 +168,16 @@
     bool mReadOnly;
     Header* mHeader;
 
-    inline void* offsetToPtr(uint32_t offset) {
+    inline void* offsetToPtr(uint32_t offset, uint32_t bufferSize = 0) {
+        if (offset >= mSize) {
+            ALOGE("Offset %" PRIu32 " out of bounds, max value %zu", offset, mSize);
+            return NULL;
+        }
+        if (offset + bufferSize > mSize) {
+            ALOGE("End offset %" PRIu32 " out of bounds, max value %zu",
+                    offset + bufferSize, mSize);
+            return NULL;
+        }
         return static_cast<uint8_t*>(mData) + offset;
     }
 
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index 04a5d95..306ff9a 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -1339,12 +1339,21 @@
 
 /**
  * A collection of resource entries for a particular resource data
- * type. Followed by an array of uint32_t defining the resource
+ * type.
+ *
+ * If the flag FLAG_SPARSE is not set in `flags`, then this struct is
+ * followed by an array of uint32_t defining the resource
  * values, corresponding to the array of type strings in the
  * ResTable_package::typeStrings string block. Each of these hold an
  * index from entriesStart; a value of NO_ENTRY means that entry is
  * not defined.
  *
+ * If the flag FLAG_SPARSE is set in `flags`, then this struct is followed
+ * by an array of ResTable_sparseTypeEntry defining only the entries that
+ * have values for this type. Each entry is sorted by their entry ID such
+ * that a binary search can be performed over the entries. The ID and offset
+ * are encoded in a uint32_t. See ResTabe_sparseTypeEntry.
+ *
  * There may be multiple of these chunks for a particular resource type,
  * supply different configuration variations for the resource values of
  * that type.
@@ -1365,21 +1374,55 @@
     // resource identifier).  0 is invalid.
     uint8_t id;
     
+    enum {
+        // If set, the entry is sparse, and encodes both the entry ID and offset into each entry,
+        // and a binary search is used to find the key. Only available on platforms >= O.
+        // Mark any types that use this with a v26 qualifier to prevent runtime issues on older
+        // platforms.
+        FLAG_SPARSE = 0x01,
+    };
+    uint8_t flags;
+
     // Must be 0.
-    uint8_t res0;
-    // Must be 0.
-    uint16_t res1;
+    uint16_t reserved;
     
     // Number of uint32_t entry indices that follow.
     uint32_t entryCount;
 
     // Offset from header where ResTable_entry data starts.
     uint32_t entriesStart;
-    
-    // Configuration this collection of entries is designed for.
+
+    // Configuration this collection of entries is designed for. This must always be last.
     ResTable_config config;
 };
 
+// The minimum size required to read any version of ResTable_type.
+constexpr size_t kResTableTypeMinSize =
+    sizeof(ResTable_type) - sizeof(ResTable_config) + sizeof(ResTable_config::size);
+
+// Assert that the ResTable_config is always the last field. This poses a problem for extending
+// ResTable_type in the future, as ResTable_config is variable (over different releases).
+static_assert(sizeof(ResTable_type) == offsetof(ResTable_type, config) + sizeof(ResTable_config),
+              "ResTable_config must be last field in ResTable_type");
+
+/**
+ * An entry in a ResTable_type with the flag `FLAG_SPARSE` set.
+ */
+union ResTable_sparseTypeEntry {
+    // Holds the raw uint32_t encoded value. Do not read this.
+    uint32_t entry;
+    struct {
+        // The index of the entry.
+        uint16_t idx;
+
+        // The offset from ResTable_type::entriesStart, divided by 4.
+        uint16_t offset;
+    };
+};
+
+static_assert(sizeof(ResTable_sparseTypeEntry) == sizeof(uint32_t),
+        "ResTable_sparseTypeEntry must be 4 bytes in size");
+
 /**
  * This is the beginning of information about an entry in the resource
  * table.  It holds the reference to the name of this entry, and is
@@ -1554,7 +1597,7 @@
 {
     friend class AssetManager2;
 public:
-    DynamicRefTable() = default;
+    DynamicRefTable();
     DynamicRefTable(uint8_t packageId, bool appAsLib);
 
     // Loads an unmapped reference table from the package.
@@ -1577,10 +1620,10 @@
     }
 
 private:
-    uint8_t                         mAssignedPackageId = 0;
+    uint8_t                         mAssignedPackageId;
     uint8_t                         mLookupTable[256];
     KeyedVector<String16, uint8_t>  mEntries;
-    bool                            mAppAsLib = false;
+    bool                            mAppAsLib;
 };
 
 bool U16StringToInt(const char16_t* s, size_t len, Res_value* outValue);
diff --git a/libs/androidfw/include/androidfw/TypeWrappers.h b/libs/androidfw/include/androidfw/TypeWrappers.h
index f1daf33..5cfe54e5 100644
--- a/libs/androidfw/include/androidfw/TypeWrappers.h
+++ b/libs/androidfw/include/androidfw/TypeWrappers.h
@@ -23,8 +23,7 @@
 namespace android {
 
 struct TypeVariant {
-    TypeVariant(const ResTable_type* data)
-        : data(data) {}
+    TypeVariant(const ResTable_type* data);
 
     class iterator {
     public:
@@ -72,10 +71,13 @@
     }
 
     iterator endEntries() const {
-        return iterator(this, dtohl(data->entryCount));
+        return iterator(this, mLength);
     }
 
     const ResTable_type* data;
+
+private:
+    size_t mLength;
 };
 
 } // namespace android
diff --git a/libs/androidfw/include/androidfw/Util.h b/libs/androidfw/include/androidfw/Util.h
index 3950cf2..e4cd6a8 100644
--- a/libs/androidfw/include/androidfw/Util.h
+++ b/libs/androidfw/include/androidfw/Util.h
@@ -22,6 +22,8 @@
 
 #include "android-base/macros.h"
 
+#include "androidfw/StringPiece.h"
+
 namespace android {
 namespace util {
 
@@ -108,6 +110,12 @@
 
 void ReadUtf16StringFromDevice(const uint16_t* src, size_t len, std::string* out);
 
+// Converts a UTF-8 string to a UTF-16 string.
+std::u16string Utf8ToUtf16(const StringPiece& utf8);
+
+// Converts a UTF-16 string to a UTF-8 string.
+std::string Utf16ToUtf8(const StringPiece16& utf16);
+
 }  // namespace util
 }  // namespace android
 
diff --git a/libs/androidfw/tests/Android.mk b/libs/androidfw/tests/Android.mk
index 19527c5..921fd14 100644
--- a/libs/androidfw/tests/Android.mk
+++ b/libs/androidfw/tests/Android.mk
@@ -45,6 +45,8 @@
 benchmarkFiles := \
     AssetManager2_bench.cpp \
     BenchMain.cpp \
+    BenchmarkHelpers.cpp \
+    SparseEntry_bench.cpp \
     TestHelpers.cpp \
     Theme_bench.cpp
 
diff --git a/libs/androidfw/tests/ApkAssets_test.cpp b/libs/androidfw/tests/ApkAssets_test.cpp
index 6b4a719..c85b0b9 100644
--- a/libs/androidfw/tests/ApkAssets_test.cpp
+++ b/libs/androidfw/tests/ApkAssets_test.cpp
@@ -16,6 +16,9 @@
 
 #include "androidfw/ApkAssets.h"
 
+#include "android-base/file.h"
+#include "android-base/unique_fd.h"
+
 #include "TestHelpers.h"
 #include "data/basic/R.h"
 
@@ -51,4 +54,41 @@
   EXPECT_TRUE(loaded_arsc->GetPackages()[0]->IsDynamic());
 }
 
+TEST(ApkAssetsTest, CreateAndDestroyAssetKeepsApkAssetsOpen) {
+  std::unique_ptr<const ApkAssets> loaded_apk =
+      ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
+  ASSERT_NE(nullptr, loaded_apk);
+
+  {
+    std::unique_ptr<Asset> assets = loaded_apk->Open("res/layout/main.xml", Asset::ACCESS_BUFFER);
+    ASSERT_NE(nullptr, assets);
+  }
+
+  {
+    std::unique_ptr<Asset> assets = loaded_apk->Open("res/layout/main.xml", Asset::ACCESS_BUFFER);
+    ASSERT_NE(nullptr, assets);
+  }
+}
+
+TEST(ApkAssetsTest, OpenUncompressedAssetFd) {
+  std::unique_ptr<const ApkAssets> loaded_apk =
+      ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
+  ASSERT_NE(nullptr, loaded_apk);
+
+  auto asset = loaded_apk->Open("assets/uncompressed.txt", Asset::ACCESS_UNKNOWN);
+  ASSERT_NE(nullptr, asset);
+
+  off64_t start, length;
+  base::unique_fd fd(asset->openFileDescriptor(&start, &length));
+  EXPECT_GE(fd.get(), 0);
+
+  lseek64(fd.get(), start, SEEK_SET);
+
+  std::string buffer;
+  buffer.resize(length);
+  ASSERT_TRUE(base::ReadFully(fd.get(), &*buffer.begin(), length));
+
+  EXPECT_EQ("This should be uncompressed.\n\n", buffer);
+}
+
 }  // namespace android
diff --git a/libs/androidfw/tests/AssetManager2_bench.cpp b/libs/androidfw/tests/AssetManager2_bench.cpp
index 273290a..67de741 100644
--- a/libs/androidfw/tests/AssetManager2_bench.cpp
+++ b/libs/androidfw/tests/AssetManager2_bench.cpp
@@ -22,6 +22,7 @@
 #include "androidfw/AssetManager2.h"
 #include "androidfw/ResourceTypes.h"
 
+#include "BenchmarkHelpers.h"
 #include "TestHelpers.h"
 #include "data/basic/R.h"
 #include "data/libclient/R.h"
@@ -112,34 +113,6 @@
   }
 }
 
-static void GetResourceBenchmarkOld(const std::vector<std::string>& paths,
-                                    const ResTable_config* config, uint32_t resid,
-                                    benchmark::State& state) {
-  AssetManager assetmanager;
-  for (const std::string& path : paths) {
-    if (!assetmanager.addAssetPath(String8(path.c_str()), nullptr /* cookie */,
-                                   false /* appAsLib */, false /* isSystemAssets */)) {
-      state.SkipWithError(base::StringPrintf("Failed to load assets %s", path.c_str()).c_str());
-      return;
-    }
-  }
-
-  if (config != nullptr) {
-    assetmanager.setConfiguration(*config);
-  }
-
-  const ResTable& table = assetmanager.getResources(true);
-
-  Res_value value;
-  ResTable_config selected_config;
-  uint32_t flags;
-
-  while (state.KeepRunning()) {
-    table.getResource(resid, &value, false /*may_be_bag*/, 0u /*density*/, &flags,
-                      &selected_config);
-  }
-}
-
 static void BM_AssetManagerGetResource(benchmark::State& state) {
   GetResourceBenchmark({GetTestDataPath() + "/basic/basic.apk"}, nullptr /*config*/,
                        basic::R::integer::number1, state);
diff --git a/libs/androidfw/tests/AssetManager2_test.cpp b/libs/androidfw/tests/AssetManager2_test.cpp
index 78fbb0f..d8e5abf 100644
--- a/libs/androidfw/tests/AssetManager2_test.cpp
+++ b/libs/androidfw/tests/AssetManager2_test.cpp
@@ -312,12 +312,12 @@
   EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType);
   EXPECT_EQ(basic::R::integer::ref2, value.data);
 
-  ResTable_ref last_ref;
+  uint32_t last_ref;
   cookie = assetmanager.ResolveReference(cookie, &value, &selected_config, &flags, &last_ref);
   ASSERT_NE(kInvalidCookie, cookie);
   EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType);
   EXPECT_EQ(12000u, value.data);
-  EXPECT_EQ(basic::R::integer::ref2, last_ref.ident);
+  EXPECT_EQ(basic::R::integer::ref2, last_ref);
 }
 
 TEST_F(AssetManager2Test, ResolveReferenceToBag) {
@@ -335,12 +335,12 @@
   EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType);
   EXPECT_EQ(basic::R::array::integerArray1, value.data);
 
-  ResTable_ref last_ref;
+  uint32_t last_ref;
   cookie = assetmanager.ResolveReference(cookie, &value, &selected_config, &flags, &last_ref);
   ASSERT_NE(kInvalidCookie, cookie);
   EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType);
   EXPECT_EQ(basic::R::array::integerArray1, value.data);
-  EXPECT_EQ(basic::R::array::integerArray1, last_ref.ident);
+  EXPECT_EQ(basic::R::array::integerArray1, last_ref);
 }
 
 static bool IsConfigurationPresent(const std::set<ResTable_config>& configurations,
diff --git a/libs/androidfw/tests/BenchmarkHelpers.cpp b/libs/androidfw/tests/BenchmarkHelpers.cpp
new file mode 100644
index 0000000..3619b7e
--- /dev/null
+++ b/libs/androidfw/tests/BenchmarkHelpers.cpp
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+#include "BenchmarkHelpers.h"
+
+#include "android-base/stringprintf.h"
+#include "androidfw/AssetManager.h"
+
+namespace android {
+
+void GetResourceBenchmarkOld(const std::vector<std::string>& paths, const ResTable_config* config,
+                             uint32_t resid, benchmark::State& state) {
+  AssetManager assetmanager;
+  for (const std::string& path : paths) {
+    if (!assetmanager.addAssetPath(String8(path.c_str()), nullptr /* cookie */,
+                                   false /* appAsLib */, false /* isSystemAssets */)) {
+      state.SkipWithError(base::StringPrintf("Failed to load assets %s", path.c_str()).c_str());
+      return;
+    }
+  }
+
+  if (config != nullptr) {
+    assetmanager.setConfiguration(*config);
+  }
+
+  const ResTable& table = assetmanager.getResources(true);
+
+  Res_value value;
+  ResTable_config selected_config;
+  uint32_t flags;
+
+  while (state.KeepRunning()) {
+    table.getResource(resid, &value, false /*may_be_bag*/, 0u /*density*/, &flags,
+                      &selected_config);
+  }
+}
+
+}  // namespace android
diff --git a/libs/androidfw/tests/BenchmarkHelpers.h b/libs/androidfw/tests/BenchmarkHelpers.h
new file mode 100644
index 0000000..fc36664
--- /dev/null
+++ b/libs/androidfw/tests/BenchmarkHelpers.h
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+#ifndef TESTS_BENCHMARKHELPERS_H_
+#define TESTS_BENCHMARKHELPERS_H_
+
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+
+#include "androidfw/ResourceTypes.h"
+
+namespace android {
+
+void GetResourceBenchmarkOld(const std::vector<std::string>& paths, const ResTable_config* config,
+                             uint32_t resid, benchmark::State& state);
+
+}  // namespace android
+
+#endif /* TESTS_BENCHMARKHELPERS_H_ */
diff --git a/libs/androidfw/tests/ResTable_test.cpp b/libs/androidfw/tests/ResTable_test.cpp
index ad1cd2b..2df4130 100644
--- a/libs/androidfw/tests/ResTable_test.cpp
+++ b/libs/androidfw/tests/ResTable_test.cpp
@@ -41,6 +41,34 @@
   ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size()));
 }
 
+TEST(ResTableTest, ShouldLoadSparseEntriesSuccessfully) {
+  std::string contents;
+  ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/sparse/sparse.apk", "resources.arsc",
+                                      &contents));
+
+  ResTable table;
+  ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size()));
+
+  ResTable_config config;
+  memset(&config, 0, sizeof(config));
+  config.sdkVersion = 26;
+  table.setParameters(&config);
+
+  String16 name(u"com.android.sparse:integer/foo_9");
+  uint32_t flags;
+  uint32_t resid =
+      table.identifierForName(name.string(), name.size(), nullptr, 0, nullptr, 0, &flags);
+  ASSERT_NE(0u, resid);
+
+  Res_value val;
+  ResTable_config selected_config;
+  ASSERT_GE(
+      table.getResource(resid, &val, false /*mayBeBag*/, 0u /*density*/, &flags, &selected_config),
+      0);
+  EXPECT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+  EXPECT_EQ(900u, val.data);
+}
+
 TEST(ResTableTest, SimpleTypeIsRetrievedCorrectly) {
   std::string contents;
   ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk",
diff --git a/libs/androidfw/tests/SparseEntry_bench.cpp b/libs/androidfw/tests/SparseEntry_bench.cpp
new file mode 100644
index 0000000..1ebf7ce
--- /dev/null
+++ b/libs/androidfw/tests/SparseEntry_bench.cpp
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+#include "androidfw/AssetManager.h"
+#include "androidfw/ResourceTypes.h"
+
+#include "BenchmarkHelpers.h"
+#include "TestHelpers.h"
+#include "data/sparse/R.h"
+
+namespace sparse = com::android::sparse;
+
+namespace android {
+
+static void BM_SparseEntryGetResourceSparseSmall(benchmark::State& state) {
+  ResTable_config config;
+  memset(&config, 0, sizeof(config));
+  config.sdkVersion = 26;
+  GetResourceBenchmarkOld({GetTestDataPath() + "/sparse/sparse.apk"}, &config,
+                          sparse::R::integer::foo_9, state);
+}
+BENCHMARK(BM_SparseEntryGetResourceSparseSmall);
+
+static void BM_SparseEntryGetResourceNotSparseSmall(benchmark::State& state) {
+  ResTable_config config;
+  memset(&config, 0, sizeof(config));
+  config.sdkVersion = 26;
+  GetResourceBenchmarkOld({GetTestDataPath() + "/sparse/not_sparse.apk"}, &config,
+                          sparse::R::integer::foo_9, state);
+}
+BENCHMARK(BM_SparseEntryGetResourceNotSparseSmall);
+
+static void BM_SparseEntryGetResourceSparseLarge(benchmark::State& state) {
+  ResTable_config config;
+  memset(&config, 0, sizeof(config));
+  config.sdkVersion = 26;
+  GetResourceBenchmarkOld({GetTestDataPath() + "/sparse/sparse.apk"}, &config,
+                          sparse::R::string::foo_999, state);
+}
+BENCHMARK(BM_SparseEntryGetResourceSparseLarge);
+
+static void BM_SparseEntryGetResourceNotSparseLarge(benchmark::State& state) {
+  ResTable_config config;
+  memset(&config, 0, sizeof(config));
+  config.sdkVersion = 26;
+  GetResourceBenchmarkOld({GetTestDataPath() + "/sparse/not_sparse.apk"}, &config,
+                          sparse::R::string::foo_999, state);
+}
+BENCHMARK(BM_SparseEntryGetResourceNotSparseLarge);
+
+}  // namespace android
diff --git a/libs/androidfw/tests/TestHelpers.h b/libs/androidfw/tests/TestHelpers.h
index a11ea84..ec78b2a 100644
--- a/libs/androidfw/tests/TestHelpers.h
+++ b/libs/androidfw/tests/TestHelpers.h
@@ -19,6 +19,7 @@
 
 #include <ostream>
 #include <string>
+#include <vector>
 
 #include "androidfw/ResourceTypes.h"
 #include "gtest/gtest.h"
diff --git a/libs/androidfw/tests/data/basic/assets/uncompressed.txt b/libs/androidfw/tests/data/basic/assets/uncompressed.txt
new file mode 100644
index 0000000..c3d39c5
--- /dev/null
+++ b/libs/androidfw/tests/data/basic/assets/uncompressed.txt
@@ -0,0 +1,2 @@
+This should be uncompressed.
+
diff --git a/libs/androidfw/tests/data/basic/basic.apk b/libs/androidfw/tests/data/basic/basic.apk
index 7ee6734..0c17328 100644
--- a/libs/androidfw/tests/data/basic/basic.apk
+++ b/libs/androidfw/tests/data/basic/basic.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/basic/build b/libs/androidfw/tests/data/basic/build
index af0fd87..d619800 100755
--- a/libs/androidfw/tests/data/basic/build
+++ b/libs/androidfw/tests/data/basic/build
@@ -19,4 +19,11 @@
 
 PATH_TO_FRAMEWORK_RES=${ANDROID_BUILD_TOP}/prebuilts/sdk/current/android.jar
 
-aapt package -M AndroidManifest.xml -S res -I $PATH_TO_FRAMEWORK_RES --split hdpi --split xhdpi --split xxhdpi --split fr,de -F basic.apk -f
+aapt package \
+    -M AndroidManifest.xml \
+    -S res \
+    -A assets \
+    -I $PATH_TO_FRAMEWORK_RES \
+    --split hdpi --split xhdpi --split xxhdpi --split fr,de \
+    -F basic.apk \
+    -f
diff --git a/libs/androidfw/tests/data/sparse/.gitignore b/libs/androidfw/tests/data/sparse/.gitignore
new file mode 100644
index 0000000..52e32d4
--- /dev/null
+++ b/libs/androidfw/tests/data/sparse/.gitignore
@@ -0,0 +1 @@
+*.flata
diff --git a/libs/androidfw/tests/data/sparse/AndroidManifest.xml b/libs/androidfw/tests/data/sparse/AndroidManifest.xml
new file mode 100644
index 0000000..27911b6
--- /dev/null
+++ b/libs/androidfw/tests/data/sparse/AndroidManifest.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.sparse">
+    <application />
+</manifest>
diff --git a/libs/androidfw/tests/data/sparse/R.h b/libs/androidfw/tests/data/sparse/R.h
new file mode 100644
index 0000000..243e74f
--- /dev/null
+++ b/libs/androidfw/tests/data/sparse/R.h
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+#ifndef TESTS_DATA_SPARSE_R_H_
+#define TESTS_DATA_SPARSE_R_H_
+
+#include <cstdint>
+
+namespace com {
+namespace android {
+namespace sparse {
+
+struct R {
+  struct integer {
+    enum : uint32_t {
+      foo_0 = 0x7f010000,
+      foo_1 = 0x7f010000,
+      foo_2 = 0x7f010000,
+      foo_3 = 0x7f010000,
+      foo_4 = 0x7f010000,
+      foo_5 = 0x7f010000,
+      foo_6 = 0x7f010000,
+      foo_7 = 0x7f010000,
+      foo_8 = 0x7f010000,
+      foo_9 = 0x7f010000,
+    };
+  };
+
+  struct string {
+    enum : uint32_t {
+      foo_999 = 0x7f0203e7,
+    };
+  };
+};
+
+}  // namespace sparse
+}  // namespace android
+}  // namespace com
+
+#endif /* TESTS_DATA_SPARSE_R_H_ */
diff --git a/libs/androidfw/tests/data/sparse/build b/libs/androidfw/tests/data/sparse/build
new file mode 100755
index 0000000..305593f
--- /dev/null
+++ b/libs/androidfw/tests/data/sparse/build
@@ -0,0 +1,24 @@
+#!/bin/bash
+#
+# 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.
+#
+
+set -e
+
+PATH_TO_FRAMEWORK_RES=${ANDROID_BUILD_TOP}/prebuilts/sdk/current/android.jar
+
+aapt2 compile --dir res -o compiled.flata
+aapt2 link --manifest AndroidManifest.xml -I $PATH_TO_FRAMEWORK_RES -o sparse.apk --enable-sparse-encoding compiled.flata
+aapt2 link --manifest AndroidManifest.xml -I $PATH_TO_FRAMEWORK_RES -o not_sparse.apk compiled.flata
diff --git a/libs/androidfw/tests/data/sparse/gen_strings.sh b/libs/androidfw/tests/data/sparse/gen_strings.sh
new file mode 100755
index 0000000..e7e1d60
--- /dev/null
+++ b/libs/androidfw/tests/data/sparse/gen_strings.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+OUTPUT_default=res/values/strings.xml
+OUTPUT_v26=res/values-v26/strings.xml
+
+echo "<resources>" > $OUTPUT_default
+echo "<resources>" > $OUTPUT_v26
+for i in {0..999}
+do
+    echo "  <string name=\"foo_$i\">$i</string>" >> $OUTPUT_default
+    if [ "$(($i % 3))" -eq "0" ]
+    then
+        echo "  <string name=\"foo_$i\">$(($i * 10))</string>" >> $OUTPUT_v26
+    fi
+done
+echo "</resources>" >> $OUTPUT_default
+echo "</resources>" >> $OUTPUT_v26
+
diff --git a/libs/androidfw/tests/data/sparse/not_sparse.apk b/libs/androidfw/tests/data/sparse/not_sparse.apk
new file mode 100644
index 0000000..599a370
--- /dev/null
+++ b/libs/androidfw/tests/data/sparse/not_sparse.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/sparse/res/values-v26/strings.xml b/libs/androidfw/tests/data/sparse/res/values-v26/strings.xml
new file mode 100644
index 0000000..b6f8299
--- /dev/null
+++ b/libs/androidfw/tests/data/sparse/res/values-v26/strings.xml
@@ -0,0 +1,336 @@
+<resources>
+  <string name="foo_0">0</string>
+  <string name="foo_3">30</string>
+  <string name="foo_6">60</string>
+  <string name="foo_9">90</string>
+  <string name="foo_12">120</string>
+  <string name="foo_15">150</string>
+  <string name="foo_18">180</string>
+  <string name="foo_21">210</string>
+  <string name="foo_24">240</string>
+  <string name="foo_27">270</string>
+  <string name="foo_30">300</string>
+  <string name="foo_33">330</string>
+  <string name="foo_36">360</string>
+  <string name="foo_39">390</string>
+  <string name="foo_42">420</string>
+  <string name="foo_45">450</string>
+  <string name="foo_48">480</string>
+  <string name="foo_51">510</string>
+  <string name="foo_54">540</string>
+  <string name="foo_57">570</string>
+  <string name="foo_60">600</string>
+  <string name="foo_63">630</string>
+  <string name="foo_66">660</string>
+  <string name="foo_69">690</string>
+  <string name="foo_72">720</string>
+  <string name="foo_75">750</string>
+  <string name="foo_78">780</string>
+  <string name="foo_81">810</string>
+  <string name="foo_84">840</string>
+  <string name="foo_87">870</string>
+  <string name="foo_90">900</string>
+  <string name="foo_93">930</string>
+  <string name="foo_96">960</string>
+  <string name="foo_99">990</string>
+  <string name="foo_102">1020</string>
+  <string name="foo_105">1050</string>
+  <string name="foo_108">1080</string>
+  <string name="foo_111">1110</string>
+  <string name="foo_114">1140</string>
+  <string name="foo_117">1170</string>
+  <string name="foo_120">1200</string>
+  <string name="foo_123">1230</string>
+  <string name="foo_126">1260</string>
+  <string name="foo_129">1290</string>
+  <string name="foo_132">1320</string>
+  <string name="foo_135">1350</string>
+  <string name="foo_138">1380</string>
+  <string name="foo_141">1410</string>
+  <string name="foo_144">1440</string>
+  <string name="foo_147">1470</string>
+  <string name="foo_150">1500</string>
+  <string name="foo_153">1530</string>
+  <string name="foo_156">1560</string>
+  <string name="foo_159">1590</string>
+  <string name="foo_162">1620</string>
+  <string name="foo_165">1650</string>
+  <string name="foo_168">1680</string>
+  <string name="foo_171">1710</string>
+  <string name="foo_174">1740</string>
+  <string name="foo_177">1770</string>
+  <string name="foo_180">1800</string>
+  <string name="foo_183">1830</string>
+  <string name="foo_186">1860</string>
+  <string name="foo_189">1890</string>
+  <string name="foo_192">1920</string>
+  <string name="foo_195">1950</string>
+  <string name="foo_198">1980</string>
+  <string name="foo_201">2010</string>
+  <string name="foo_204">2040</string>
+  <string name="foo_207">2070</string>
+  <string name="foo_210">2100</string>
+  <string name="foo_213">2130</string>
+  <string name="foo_216">2160</string>
+  <string name="foo_219">2190</string>
+  <string name="foo_222">2220</string>
+  <string name="foo_225">2250</string>
+  <string name="foo_228">2280</string>
+  <string name="foo_231">2310</string>
+  <string name="foo_234">2340</string>
+  <string name="foo_237">2370</string>
+  <string name="foo_240">2400</string>
+  <string name="foo_243">2430</string>
+  <string name="foo_246">2460</string>
+  <string name="foo_249">2490</string>
+  <string name="foo_252">2520</string>
+  <string name="foo_255">2550</string>
+  <string name="foo_258">2580</string>
+  <string name="foo_261">2610</string>
+  <string name="foo_264">2640</string>
+  <string name="foo_267">2670</string>
+  <string name="foo_270">2700</string>
+  <string name="foo_273">2730</string>
+  <string name="foo_276">2760</string>
+  <string name="foo_279">2790</string>
+  <string name="foo_282">2820</string>
+  <string name="foo_285">2850</string>
+  <string name="foo_288">2880</string>
+  <string name="foo_291">2910</string>
+  <string name="foo_294">2940</string>
+  <string name="foo_297">2970</string>
+  <string name="foo_300">3000</string>
+  <string name="foo_303">3030</string>
+  <string name="foo_306">3060</string>
+  <string name="foo_309">3090</string>
+  <string name="foo_312">3120</string>
+  <string name="foo_315">3150</string>
+  <string name="foo_318">3180</string>
+  <string name="foo_321">3210</string>
+  <string name="foo_324">3240</string>
+  <string name="foo_327">3270</string>
+  <string name="foo_330">3300</string>
+  <string name="foo_333">3330</string>
+  <string name="foo_336">3360</string>
+  <string name="foo_339">3390</string>
+  <string name="foo_342">3420</string>
+  <string name="foo_345">3450</string>
+  <string name="foo_348">3480</string>
+  <string name="foo_351">3510</string>
+  <string name="foo_354">3540</string>
+  <string name="foo_357">3570</string>
+  <string name="foo_360">3600</string>
+  <string name="foo_363">3630</string>
+  <string name="foo_366">3660</string>
+  <string name="foo_369">3690</string>
+  <string name="foo_372">3720</string>
+  <string name="foo_375">3750</string>
+  <string name="foo_378">3780</string>
+  <string name="foo_381">3810</string>
+  <string name="foo_384">3840</string>
+  <string name="foo_387">3870</string>
+  <string name="foo_390">3900</string>
+  <string name="foo_393">3930</string>
+  <string name="foo_396">3960</string>
+  <string name="foo_399">3990</string>
+  <string name="foo_402">4020</string>
+  <string name="foo_405">4050</string>
+  <string name="foo_408">4080</string>
+  <string name="foo_411">4110</string>
+  <string name="foo_414">4140</string>
+  <string name="foo_417">4170</string>
+  <string name="foo_420">4200</string>
+  <string name="foo_423">4230</string>
+  <string name="foo_426">4260</string>
+  <string name="foo_429">4290</string>
+  <string name="foo_432">4320</string>
+  <string name="foo_435">4350</string>
+  <string name="foo_438">4380</string>
+  <string name="foo_441">4410</string>
+  <string name="foo_444">4440</string>
+  <string name="foo_447">4470</string>
+  <string name="foo_450">4500</string>
+  <string name="foo_453">4530</string>
+  <string name="foo_456">4560</string>
+  <string name="foo_459">4590</string>
+  <string name="foo_462">4620</string>
+  <string name="foo_465">4650</string>
+  <string name="foo_468">4680</string>
+  <string name="foo_471">4710</string>
+  <string name="foo_474">4740</string>
+  <string name="foo_477">4770</string>
+  <string name="foo_480">4800</string>
+  <string name="foo_483">4830</string>
+  <string name="foo_486">4860</string>
+  <string name="foo_489">4890</string>
+  <string name="foo_492">4920</string>
+  <string name="foo_495">4950</string>
+  <string name="foo_498">4980</string>
+  <string name="foo_501">5010</string>
+  <string name="foo_504">5040</string>
+  <string name="foo_507">5070</string>
+  <string name="foo_510">5100</string>
+  <string name="foo_513">5130</string>
+  <string name="foo_516">5160</string>
+  <string name="foo_519">5190</string>
+  <string name="foo_522">5220</string>
+  <string name="foo_525">5250</string>
+  <string name="foo_528">5280</string>
+  <string name="foo_531">5310</string>
+  <string name="foo_534">5340</string>
+  <string name="foo_537">5370</string>
+  <string name="foo_540">5400</string>
+  <string name="foo_543">5430</string>
+  <string name="foo_546">5460</string>
+  <string name="foo_549">5490</string>
+  <string name="foo_552">5520</string>
+  <string name="foo_555">5550</string>
+  <string name="foo_558">5580</string>
+  <string name="foo_561">5610</string>
+  <string name="foo_564">5640</string>
+  <string name="foo_567">5670</string>
+  <string name="foo_570">5700</string>
+  <string name="foo_573">5730</string>
+  <string name="foo_576">5760</string>
+  <string name="foo_579">5790</string>
+  <string name="foo_582">5820</string>
+  <string name="foo_585">5850</string>
+  <string name="foo_588">5880</string>
+  <string name="foo_591">5910</string>
+  <string name="foo_594">5940</string>
+  <string name="foo_597">5970</string>
+  <string name="foo_600">6000</string>
+  <string name="foo_603">6030</string>
+  <string name="foo_606">6060</string>
+  <string name="foo_609">6090</string>
+  <string name="foo_612">6120</string>
+  <string name="foo_615">6150</string>
+  <string name="foo_618">6180</string>
+  <string name="foo_621">6210</string>
+  <string name="foo_624">6240</string>
+  <string name="foo_627">6270</string>
+  <string name="foo_630">6300</string>
+  <string name="foo_633">6330</string>
+  <string name="foo_636">6360</string>
+  <string name="foo_639">6390</string>
+  <string name="foo_642">6420</string>
+  <string name="foo_645">6450</string>
+  <string name="foo_648">6480</string>
+  <string name="foo_651">6510</string>
+  <string name="foo_654">6540</string>
+  <string name="foo_657">6570</string>
+  <string name="foo_660">6600</string>
+  <string name="foo_663">6630</string>
+  <string name="foo_666">6660</string>
+  <string name="foo_669">6690</string>
+  <string name="foo_672">6720</string>
+  <string name="foo_675">6750</string>
+  <string name="foo_678">6780</string>
+  <string name="foo_681">6810</string>
+  <string name="foo_684">6840</string>
+  <string name="foo_687">6870</string>
+  <string name="foo_690">6900</string>
+  <string name="foo_693">6930</string>
+  <string name="foo_696">6960</string>
+  <string name="foo_699">6990</string>
+  <string name="foo_702">7020</string>
+  <string name="foo_705">7050</string>
+  <string name="foo_708">7080</string>
+  <string name="foo_711">7110</string>
+  <string name="foo_714">7140</string>
+  <string name="foo_717">7170</string>
+  <string name="foo_720">7200</string>
+  <string name="foo_723">7230</string>
+  <string name="foo_726">7260</string>
+  <string name="foo_729">7290</string>
+  <string name="foo_732">7320</string>
+  <string name="foo_735">7350</string>
+  <string name="foo_738">7380</string>
+  <string name="foo_741">7410</string>
+  <string name="foo_744">7440</string>
+  <string name="foo_747">7470</string>
+  <string name="foo_750">7500</string>
+  <string name="foo_753">7530</string>
+  <string name="foo_756">7560</string>
+  <string name="foo_759">7590</string>
+  <string name="foo_762">7620</string>
+  <string name="foo_765">7650</string>
+  <string name="foo_768">7680</string>
+  <string name="foo_771">7710</string>
+  <string name="foo_774">7740</string>
+  <string name="foo_777">7770</string>
+  <string name="foo_780">7800</string>
+  <string name="foo_783">7830</string>
+  <string name="foo_786">7860</string>
+  <string name="foo_789">7890</string>
+  <string name="foo_792">7920</string>
+  <string name="foo_795">7950</string>
+  <string name="foo_798">7980</string>
+  <string name="foo_801">8010</string>
+  <string name="foo_804">8040</string>
+  <string name="foo_807">8070</string>
+  <string name="foo_810">8100</string>
+  <string name="foo_813">8130</string>
+  <string name="foo_816">8160</string>
+  <string name="foo_819">8190</string>
+  <string name="foo_822">8220</string>
+  <string name="foo_825">8250</string>
+  <string name="foo_828">8280</string>
+  <string name="foo_831">8310</string>
+  <string name="foo_834">8340</string>
+  <string name="foo_837">8370</string>
+  <string name="foo_840">8400</string>
+  <string name="foo_843">8430</string>
+  <string name="foo_846">8460</string>
+  <string name="foo_849">8490</string>
+  <string name="foo_852">8520</string>
+  <string name="foo_855">8550</string>
+  <string name="foo_858">8580</string>
+  <string name="foo_861">8610</string>
+  <string name="foo_864">8640</string>
+  <string name="foo_867">8670</string>
+  <string name="foo_870">8700</string>
+  <string name="foo_873">8730</string>
+  <string name="foo_876">8760</string>
+  <string name="foo_879">8790</string>
+  <string name="foo_882">8820</string>
+  <string name="foo_885">8850</string>
+  <string name="foo_888">8880</string>
+  <string name="foo_891">8910</string>
+  <string name="foo_894">8940</string>
+  <string name="foo_897">8970</string>
+  <string name="foo_900">9000</string>
+  <string name="foo_903">9030</string>
+  <string name="foo_906">9060</string>
+  <string name="foo_909">9090</string>
+  <string name="foo_912">9120</string>
+  <string name="foo_915">9150</string>
+  <string name="foo_918">9180</string>
+  <string name="foo_921">9210</string>
+  <string name="foo_924">9240</string>
+  <string name="foo_927">9270</string>
+  <string name="foo_930">9300</string>
+  <string name="foo_933">9330</string>
+  <string name="foo_936">9360</string>
+  <string name="foo_939">9390</string>
+  <string name="foo_942">9420</string>
+  <string name="foo_945">9450</string>
+  <string name="foo_948">9480</string>
+  <string name="foo_951">9510</string>
+  <string name="foo_954">9540</string>
+  <string name="foo_957">9570</string>
+  <string name="foo_960">9600</string>
+  <string name="foo_963">9630</string>
+  <string name="foo_966">9660</string>
+  <string name="foo_969">9690</string>
+  <string name="foo_972">9720</string>
+  <string name="foo_975">9750</string>
+  <string name="foo_978">9780</string>
+  <string name="foo_981">9810</string>
+  <string name="foo_984">9840</string>
+  <string name="foo_987">9870</string>
+  <string name="foo_990">9900</string>
+  <string name="foo_993">9930</string>
+  <string name="foo_996">9960</string>
+  <string name="foo_999">9990</string>
+</resources>
diff --git a/libs/androidfw/tests/data/sparse/res/values-v26/values.xml b/libs/androidfw/tests/data/sparse/res/values-v26/values.xml
new file mode 100644
index 0000000..b396ad2
--- /dev/null
+++ b/libs/androidfw/tests/data/sparse/res/values-v26/values.xml
@@ -0,0 +1,22 @@
+<?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>
+    <integer name="foo_0">0</integer>
+    <integer name="foo_4">400</integer>
+    <integer name="foo_5">500</integer>
+    <integer name="foo_9">900</integer>
+</resources>
diff --git a/libs/androidfw/tests/data/sparse/res/values/strings.xml b/libs/androidfw/tests/data/sparse/res/values/strings.xml
new file mode 100644
index 0000000..6ff839a
--- /dev/null
+++ b/libs/androidfw/tests/data/sparse/res/values/strings.xml
@@ -0,0 +1,1002 @@
+<resources>
+  <string name="foo_0">0</string>
+  <string name="foo_1">1</string>
+  <string name="foo_2">2</string>
+  <string name="foo_3">3</string>
+  <string name="foo_4">4</string>
+  <string name="foo_5">5</string>
+  <string name="foo_6">6</string>
+  <string name="foo_7">7</string>
+  <string name="foo_8">8</string>
+  <string name="foo_9">9</string>
+  <string name="foo_10">10</string>
+  <string name="foo_11">11</string>
+  <string name="foo_12">12</string>
+  <string name="foo_13">13</string>
+  <string name="foo_14">14</string>
+  <string name="foo_15">15</string>
+  <string name="foo_16">16</string>
+  <string name="foo_17">17</string>
+  <string name="foo_18">18</string>
+  <string name="foo_19">19</string>
+  <string name="foo_20">20</string>
+  <string name="foo_21">21</string>
+  <string name="foo_22">22</string>
+  <string name="foo_23">23</string>
+  <string name="foo_24">24</string>
+  <string name="foo_25">25</string>
+  <string name="foo_26">26</string>
+  <string name="foo_27">27</string>
+  <string name="foo_28">28</string>
+  <string name="foo_29">29</string>
+  <string name="foo_30">30</string>
+  <string name="foo_31">31</string>
+  <string name="foo_32">32</string>
+  <string name="foo_33">33</string>
+  <string name="foo_34">34</string>
+  <string name="foo_35">35</string>
+  <string name="foo_36">36</string>
+  <string name="foo_37">37</string>
+  <string name="foo_38">38</string>
+  <string name="foo_39">39</string>
+  <string name="foo_40">40</string>
+  <string name="foo_41">41</string>
+  <string name="foo_42">42</string>
+  <string name="foo_43">43</string>
+  <string name="foo_44">44</string>
+  <string name="foo_45">45</string>
+  <string name="foo_46">46</string>
+  <string name="foo_47">47</string>
+  <string name="foo_48">48</string>
+  <string name="foo_49">49</string>
+  <string name="foo_50">50</string>
+  <string name="foo_51">51</string>
+  <string name="foo_52">52</string>
+  <string name="foo_53">53</string>
+  <string name="foo_54">54</string>
+  <string name="foo_55">55</string>
+  <string name="foo_56">56</string>
+  <string name="foo_57">57</string>
+  <string name="foo_58">58</string>
+  <string name="foo_59">59</string>
+  <string name="foo_60">60</string>
+  <string name="foo_61">61</string>
+  <string name="foo_62">62</string>
+  <string name="foo_63">63</string>
+  <string name="foo_64">64</string>
+  <string name="foo_65">65</string>
+  <string name="foo_66">66</string>
+  <string name="foo_67">67</string>
+  <string name="foo_68">68</string>
+  <string name="foo_69">69</string>
+  <string name="foo_70">70</string>
+  <string name="foo_71">71</string>
+  <string name="foo_72">72</string>
+  <string name="foo_73">73</string>
+  <string name="foo_74">74</string>
+  <string name="foo_75">75</string>
+  <string name="foo_76">76</string>
+  <string name="foo_77">77</string>
+  <string name="foo_78">78</string>
+  <string name="foo_79">79</string>
+  <string name="foo_80">80</string>
+  <string name="foo_81">81</string>
+  <string name="foo_82">82</string>
+  <string name="foo_83">83</string>
+  <string name="foo_84">84</string>
+  <string name="foo_85">85</string>
+  <string name="foo_86">86</string>
+  <string name="foo_87">87</string>
+  <string name="foo_88">88</string>
+  <string name="foo_89">89</string>
+  <string name="foo_90">90</string>
+  <string name="foo_91">91</string>
+  <string name="foo_92">92</string>
+  <string name="foo_93">93</string>
+  <string name="foo_94">94</string>
+  <string name="foo_95">95</string>
+  <string name="foo_96">96</string>
+  <string name="foo_97">97</string>
+  <string name="foo_98">98</string>
+  <string name="foo_99">99</string>
+  <string name="foo_100">100</string>
+  <string name="foo_101">101</string>
+  <string name="foo_102">102</string>
+  <string name="foo_103">103</string>
+  <string name="foo_104">104</string>
+  <string name="foo_105">105</string>
+  <string name="foo_106">106</string>
+  <string name="foo_107">107</string>
+  <string name="foo_108">108</string>
+  <string name="foo_109">109</string>
+  <string name="foo_110">110</string>
+  <string name="foo_111">111</string>
+  <string name="foo_112">112</string>
+  <string name="foo_113">113</string>
+  <string name="foo_114">114</string>
+  <string name="foo_115">115</string>
+  <string name="foo_116">116</string>
+  <string name="foo_117">117</string>
+  <string name="foo_118">118</string>
+  <string name="foo_119">119</string>
+  <string name="foo_120">120</string>
+  <string name="foo_121">121</string>
+  <string name="foo_122">122</string>
+  <string name="foo_123">123</string>
+  <string name="foo_124">124</string>
+  <string name="foo_125">125</string>
+  <string name="foo_126">126</string>
+  <string name="foo_127">127</string>
+  <string name="foo_128">128</string>
+  <string name="foo_129">129</string>
+  <string name="foo_130">130</string>
+  <string name="foo_131">131</string>
+  <string name="foo_132">132</string>
+  <string name="foo_133">133</string>
+  <string name="foo_134">134</string>
+  <string name="foo_135">135</string>
+  <string name="foo_136">136</string>
+  <string name="foo_137">137</string>
+  <string name="foo_138">138</string>
+  <string name="foo_139">139</string>
+  <string name="foo_140">140</string>
+  <string name="foo_141">141</string>
+  <string name="foo_142">142</string>
+  <string name="foo_143">143</string>
+  <string name="foo_144">144</string>
+  <string name="foo_145">145</string>
+  <string name="foo_146">146</string>
+  <string name="foo_147">147</string>
+  <string name="foo_148">148</string>
+  <string name="foo_149">149</string>
+  <string name="foo_150">150</string>
+  <string name="foo_151">151</string>
+  <string name="foo_152">152</string>
+  <string name="foo_153">153</string>
+  <string name="foo_154">154</string>
+  <string name="foo_155">155</string>
+  <string name="foo_156">156</string>
+  <string name="foo_157">157</string>
+  <string name="foo_158">158</string>
+  <string name="foo_159">159</string>
+  <string name="foo_160">160</string>
+  <string name="foo_161">161</string>
+  <string name="foo_162">162</string>
+  <string name="foo_163">163</string>
+  <string name="foo_164">164</string>
+  <string name="foo_165">165</string>
+  <string name="foo_166">166</string>
+  <string name="foo_167">167</string>
+  <string name="foo_168">168</string>
+  <string name="foo_169">169</string>
+  <string name="foo_170">170</string>
+  <string name="foo_171">171</string>
+  <string name="foo_172">172</string>
+  <string name="foo_173">173</string>
+  <string name="foo_174">174</string>
+  <string name="foo_175">175</string>
+  <string name="foo_176">176</string>
+  <string name="foo_177">177</string>
+  <string name="foo_178">178</string>
+  <string name="foo_179">179</string>
+  <string name="foo_180">180</string>
+  <string name="foo_181">181</string>
+  <string name="foo_182">182</string>
+  <string name="foo_183">183</string>
+  <string name="foo_184">184</string>
+  <string name="foo_185">185</string>
+  <string name="foo_186">186</string>
+  <string name="foo_187">187</string>
+  <string name="foo_188">188</string>
+  <string name="foo_189">189</string>
+  <string name="foo_190">190</string>
+  <string name="foo_191">191</string>
+  <string name="foo_192">192</string>
+  <string name="foo_193">193</string>
+  <string name="foo_194">194</string>
+  <string name="foo_195">195</string>
+  <string name="foo_196">196</string>
+  <string name="foo_197">197</string>
+  <string name="foo_198">198</string>
+  <string name="foo_199">199</string>
+  <string name="foo_200">200</string>
+  <string name="foo_201">201</string>
+  <string name="foo_202">202</string>
+  <string name="foo_203">203</string>
+  <string name="foo_204">204</string>
+  <string name="foo_205">205</string>
+  <string name="foo_206">206</string>
+  <string name="foo_207">207</string>
+  <string name="foo_208">208</string>
+  <string name="foo_209">209</string>
+  <string name="foo_210">210</string>
+  <string name="foo_211">211</string>
+  <string name="foo_212">212</string>
+  <string name="foo_213">213</string>
+  <string name="foo_214">214</string>
+  <string name="foo_215">215</string>
+  <string name="foo_216">216</string>
+  <string name="foo_217">217</string>
+  <string name="foo_218">218</string>
+  <string name="foo_219">219</string>
+  <string name="foo_220">220</string>
+  <string name="foo_221">221</string>
+  <string name="foo_222">222</string>
+  <string name="foo_223">223</string>
+  <string name="foo_224">224</string>
+  <string name="foo_225">225</string>
+  <string name="foo_226">226</string>
+  <string name="foo_227">227</string>
+  <string name="foo_228">228</string>
+  <string name="foo_229">229</string>
+  <string name="foo_230">230</string>
+  <string name="foo_231">231</string>
+  <string name="foo_232">232</string>
+  <string name="foo_233">233</string>
+  <string name="foo_234">234</string>
+  <string name="foo_235">235</string>
+  <string name="foo_236">236</string>
+  <string name="foo_237">237</string>
+  <string name="foo_238">238</string>
+  <string name="foo_239">239</string>
+  <string name="foo_240">240</string>
+  <string name="foo_241">241</string>
+  <string name="foo_242">242</string>
+  <string name="foo_243">243</string>
+  <string name="foo_244">244</string>
+  <string name="foo_245">245</string>
+  <string name="foo_246">246</string>
+  <string name="foo_247">247</string>
+  <string name="foo_248">248</string>
+  <string name="foo_249">249</string>
+  <string name="foo_250">250</string>
+  <string name="foo_251">251</string>
+  <string name="foo_252">252</string>
+  <string name="foo_253">253</string>
+  <string name="foo_254">254</string>
+  <string name="foo_255">255</string>
+  <string name="foo_256">256</string>
+  <string name="foo_257">257</string>
+  <string name="foo_258">258</string>
+  <string name="foo_259">259</string>
+  <string name="foo_260">260</string>
+  <string name="foo_261">261</string>
+  <string name="foo_262">262</string>
+  <string name="foo_263">263</string>
+  <string name="foo_264">264</string>
+  <string name="foo_265">265</string>
+  <string name="foo_266">266</string>
+  <string name="foo_267">267</string>
+  <string name="foo_268">268</string>
+  <string name="foo_269">269</string>
+  <string name="foo_270">270</string>
+  <string name="foo_271">271</string>
+  <string name="foo_272">272</string>
+  <string name="foo_273">273</string>
+  <string name="foo_274">274</string>
+  <string name="foo_275">275</string>
+  <string name="foo_276">276</string>
+  <string name="foo_277">277</string>
+  <string name="foo_278">278</string>
+  <string name="foo_279">279</string>
+  <string name="foo_280">280</string>
+  <string name="foo_281">281</string>
+  <string name="foo_282">282</string>
+  <string name="foo_283">283</string>
+  <string name="foo_284">284</string>
+  <string name="foo_285">285</string>
+  <string name="foo_286">286</string>
+  <string name="foo_287">287</string>
+  <string name="foo_288">288</string>
+  <string name="foo_289">289</string>
+  <string name="foo_290">290</string>
+  <string name="foo_291">291</string>
+  <string name="foo_292">292</string>
+  <string name="foo_293">293</string>
+  <string name="foo_294">294</string>
+  <string name="foo_295">295</string>
+  <string name="foo_296">296</string>
+  <string name="foo_297">297</string>
+  <string name="foo_298">298</string>
+  <string name="foo_299">299</string>
+  <string name="foo_300">300</string>
+  <string name="foo_301">301</string>
+  <string name="foo_302">302</string>
+  <string name="foo_303">303</string>
+  <string name="foo_304">304</string>
+  <string name="foo_305">305</string>
+  <string name="foo_306">306</string>
+  <string name="foo_307">307</string>
+  <string name="foo_308">308</string>
+  <string name="foo_309">309</string>
+  <string name="foo_310">310</string>
+  <string name="foo_311">311</string>
+  <string name="foo_312">312</string>
+  <string name="foo_313">313</string>
+  <string name="foo_314">314</string>
+  <string name="foo_315">315</string>
+  <string name="foo_316">316</string>
+  <string name="foo_317">317</string>
+  <string name="foo_318">318</string>
+  <string name="foo_319">319</string>
+  <string name="foo_320">320</string>
+  <string name="foo_321">321</string>
+  <string name="foo_322">322</string>
+  <string name="foo_323">323</string>
+  <string name="foo_324">324</string>
+  <string name="foo_325">325</string>
+  <string name="foo_326">326</string>
+  <string name="foo_327">327</string>
+  <string name="foo_328">328</string>
+  <string name="foo_329">329</string>
+  <string name="foo_330">330</string>
+  <string name="foo_331">331</string>
+  <string name="foo_332">332</string>
+  <string name="foo_333">333</string>
+  <string name="foo_334">334</string>
+  <string name="foo_335">335</string>
+  <string name="foo_336">336</string>
+  <string name="foo_337">337</string>
+  <string name="foo_338">338</string>
+  <string name="foo_339">339</string>
+  <string name="foo_340">340</string>
+  <string name="foo_341">341</string>
+  <string name="foo_342">342</string>
+  <string name="foo_343">343</string>
+  <string name="foo_344">344</string>
+  <string name="foo_345">345</string>
+  <string name="foo_346">346</string>
+  <string name="foo_347">347</string>
+  <string name="foo_348">348</string>
+  <string name="foo_349">349</string>
+  <string name="foo_350">350</string>
+  <string name="foo_351">351</string>
+  <string name="foo_352">352</string>
+  <string name="foo_353">353</string>
+  <string name="foo_354">354</string>
+  <string name="foo_355">355</string>
+  <string name="foo_356">356</string>
+  <string name="foo_357">357</string>
+  <string name="foo_358">358</string>
+  <string name="foo_359">359</string>
+  <string name="foo_360">360</string>
+  <string name="foo_361">361</string>
+  <string name="foo_362">362</string>
+  <string name="foo_363">363</string>
+  <string name="foo_364">364</string>
+  <string name="foo_365">365</string>
+  <string name="foo_366">366</string>
+  <string name="foo_367">367</string>
+  <string name="foo_368">368</string>
+  <string name="foo_369">369</string>
+  <string name="foo_370">370</string>
+  <string name="foo_371">371</string>
+  <string name="foo_372">372</string>
+  <string name="foo_373">373</string>
+  <string name="foo_374">374</string>
+  <string name="foo_375">375</string>
+  <string name="foo_376">376</string>
+  <string name="foo_377">377</string>
+  <string name="foo_378">378</string>
+  <string name="foo_379">379</string>
+  <string name="foo_380">380</string>
+  <string name="foo_381">381</string>
+  <string name="foo_382">382</string>
+  <string name="foo_383">383</string>
+  <string name="foo_384">384</string>
+  <string name="foo_385">385</string>
+  <string name="foo_386">386</string>
+  <string name="foo_387">387</string>
+  <string name="foo_388">388</string>
+  <string name="foo_389">389</string>
+  <string name="foo_390">390</string>
+  <string name="foo_391">391</string>
+  <string name="foo_392">392</string>
+  <string name="foo_393">393</string>
+  <string name="foo_394">394</string>
+  <string name="foo_395">395</string>
+  <string name="foo_396">396</string>
+  <string name="foo_397">397</string>
+  <string name="foo_398">398</string>
+  <string name="foo_399">399</string>
+  <string name="foo_400">400</string>
+  <string name="foo_401">401</string>
+  <string name="foo_402">402</string>
+  <string name="foo_403">403</string>
+  <string name="foo_404">404</string>
+  <string name="foo_405">405</string>
+  <string name="foo_406">406</string>
+  <string name="foo_407">407</string>
+  <string name="foo_408">408</string>
+  <string name="foo_409">409</string>
+  <string name="foo_410">410</string>
+  <string name="foo_411">411</string>
+  <string name="foo_412">412</string>
+  <string name="foo_413">413</string>
+  <string name="foo_414">414</string>
+  <string name="foo_415">415</string>
+  <string name="foo_416">416</string>
+  <string name="foo_417">417</string>
+  <string name="foo_418">418</string>
+  <string name="foo_419">419</string>
+  <string name="foo_420">420</string>
+  <string name="foo_421">421</string>
+  <string name="foo_422">422</string>
+  <string name="foo_423">423</string>
+  <string name="foo_424">424</string>
+  <string name="foo_425">425</string>
+  <string name="foo_426">426</string>
+  <string name="foo_427">427</string>
+  <string name="foo_428">428</string>
+  <string name="foo_429">429</string>
+  <string name="foo_430">430</string>
+  <string name="foo_431">431</string>
+  <string name="foo_432">432</string>
+  <string name="foo_433">433</string>
+  <string name="foo_434">434</string>
+  <string name="foo_435">435</string>
+  <string name="foo_436">436</string>
+  <string name="foo_437">437</string>
+  <string name="foo_438">438</string>
+  <string name="foo_439">439</string>
+  <string name="foo_440">440</string>
+  <string name="foo_441">441</string>
+  <string name="foo_442">442</string>
+  <string name="foo_443">443</string>
+  <string name="foo_444">444</string>
+  <string name="foo_445">445</string>
+  <string name="foo_446">446</string>
+  <string name="foo_447">447</string>
+  <string name="foo_448">448</string>
+  <string name="foo_449">449</string>
+  <string name="foo_450">450</string>
+  <string name="foo_451">451</string>
+  <string name="foo_452">452</string>
+  <string name="foo_453">453</string>
+  <string name="foo_454">454</string>
+  <string name="foo_455">455</string>
+  <string name="foo_456">456</string>
+  <string name="foo_457">457</string>
+  <string name="foo_458">458</string>
+  <string name="foo_459">459</string>
+  <string name="foo_460">460</string>
+  <string name="foo_461">461</string>
+  <string name="foo_462">462</string>
+  <string name="foo_463">463</string>
+  <string name="foo_464">464</string>
+  <string name="foo_465">465</string>
+  <string name="foo_466">466</string>
+  <string name="foo_467">467</string>
+  <string name="foo_468">468</string>
+  <string name="foo_469">469</string>
+  <string name="foo_470">470</string>
+  <string name="foo_471">471</string>
+  <string name="foo_472">472</string>
+  <string name="foo_473">473</string>
+  <string name="foo_474">474</string>
+  <string name="foo_475">475</string>
+  <string name="foo_476">476</string>
+  <string name="foo_477">477</string>
+  <string name="foo_478">478</string>
+  <string name="foo_479">479</string>
+  <string name="foo_480">480</string>
+  <string name="foo_481">481</string>
+  <string name="foo_482">482</string>
+  <string name="foo_483">483</string>
+  <string name="foo_484">484</string>
+  <string name="foo_485">485</string>
+  <string name="foo_486">486</string>
+  <string name="foo_487">487</string>
+  <string name="foo_488">488</string>
+  <string name="foo_489">489</string>
+  <string name="foo_490">490</string>
+  <string name="foo_491">491</string>
+  <string name="foo_492">492</string>
+  <string name="foo_493">493</string>
+  <string name="foo_494">494</string>
+  <string name="foo_495">495</string>
+  <string name="foo_496">496</string>
+  <string name="foo_497">497</string>
+  <string name="foo_498">498</string>
+  <string name="foo_499">499</string>
+  <string name="foo_500">500</string>
+  <string name="foo_501">501</string>
+  <string name="foo_502">502</string>
+  <string name="foo_503">503</string>
+  <string name="foo_504">504</string>
+  <string name="foo_505">505</string>
+  <string name="foo_506">506</string>
+  <string name="foo_507">507</string>
+  <string name="foo_508">508</string>
+  <string name="foo_509">509</string>
+  <string name="foo_510">510</string>
+  <string name="foo_511">511</string>
+  <string name="foo_512">512</string>
+  <string name="foo_513">513</string>
+  <string name="foo_514">514</string>
+  <string name="foo_515">515</string>
+  <string name="foo_516">516</string>
+  <string name="foo_517">517</string>
+  <string name="foo_518">518</string>
+  <string name="foo_519">519</string>
+  <string name="foo_520">520</string>
+  <string name="foo_521">521</string>
+  <string name="foo_522">522</string>
+  <string name="foo_523">523</string>
+  <string name="foo_524">524</string>
+  <string name="foo_525">525</string>
+  <string name="foo_526">526</string>
+  <string name="foo_527">527</string>
+  <string name="foo_528">528</string>
+  <string name="foo_529">529</string>
+  <string name="foo_530">530</string>
+  <string name="foo_531">531</string>
+  <string name="foo_532">532</string>
+  <string name="foo_533">533</string>
+  <string name="foo_534">534</string>
+  <string name="foo_535">535</string>
+  <string name="foo_536">536</string>
+  <string name="foo_537">537</string>
+  <string name="foo_538">538</string>
+  <string name="foo_539">539</string>
+  <string name="foo_540">540</string>
+  <string name="foo_541">541</string>
+  <string name="foo_542">542</string>
+  <string name="foo_543">543</string>
+  <string name="foo_544">544</string>
+  <string name="foo_545">545</string>
+  <string name="foo_546">546</string>
+  <string name="foo_547">547</string>
+  <string name="foo_548">548</string>
+  <string name="foo_549">549</string>
+  <string name="foo_550">550</string>
+  <string name="foo_551">551</string>
+  <string name="foo_552">552</string>
+  <string name="foo_553">553</string>
+  <string name="foo_554">554</string>
+  <string name="foo_555">555</string>
+  <string name="foo_556">556</string>
+  <string name="foo_557">557</string>
+  <string name="foo_558">558</string>
+  <string name="foo_559">559</string>
+  <string name="foo_560">560</string>
+  <string name="foo_561">561</string>
+  <string name="foo_562">562</string>
+  <string name="foo_563">563</string>
+  <string name="foo_564">564</string>
+  <string name="foo_565">565</string>
+  <string name="foo_566">566</string>
+  <string name="foo_567">567</string>
+  <string name="foo_568">568</string>
+  <string name="foo_569">569</string>
+  <string name="foo_570">570</string>
+  <string name="foo_571">571</string>
+  <string name="foo_572">572</string>
+  <string name="foo_573">573</string>
+  <string name="foo_574">574</string>
+  <string name="foo_575">575</string>
+  <string name="foo_576">576</string>
+  <string name="foo_577">577</string>
+  <string name="foo_578">578</string>
+  <string name="foo_579">579</string>
+  <string name="foo_580">580</string>
+  <string name="foo_581">581</string>
+  <string name="foo_582">582</string>
+  <string name="foo_583">583</string>
+  <string name="foo_584">584</string>
+  <string name="foo_585">585</string>
+  <string name="foo_586">586</string>
+  <string name="foo_587">587</string>
+  <string name="foo_588">588</string>
+  <string name="foo_589">589</string>
+  <string name="foo_590">590</string>
+  <string name="foo_591">591</string>
+  <string name="foo_592">592</string>
+  <string name="foo_593">593</string>
+  <string name="foo_594">594</string>
+  <string name="foo_595">595</string>
+  <string name="foo_596">596</string>
+  <string name="foo_597">597</string>
+  <string name="foo_598">598</string>
+  <string name="foo_599">599</string>
+  <string name="foo_600">600</string>
+  <string name="foo_601">601</string>
+  <string name="foo_602">602</string>
+  <string name="foo_603">603</string>
+  <string name="foo_604">604</string>
+  <string name="foo_605">605</string>
+  <string name="foo_606">606</string>
+  <string name="foo_607">607</string>
+  <string name="foo_608">608</string>
+  <string name="foo_609">609</string>
+  <string name="foo_610">610</string>
+  <string name="foo_611">611</string>
+  <string name="foo_612">612</string>
+  <string name="foo_613">613</string>
+  <string name="foo_614">614</string>
+  <string name="foo_615">615</string>
+  <string name="foo_616">616</string>
+  <string name="foo_617">617</string>
+  <string name="foo_618">618</string>
+  <string name="foo_619">619</string>
+  <string name="foo_620">620</string>
+  <string name="foo_621">621</string>
+  <string name="foo_622">622</string>
+  <string name="foo_623">623</string>
+  <string name="foo_624">624</string>
+  <string name="foo_625">625</string>
+  <string name="foo_626">626</string>
+  <string name="foo_627">627</string>
+  <string name="foo_628">628</string>
+  <string name="foo_629">629</string>
+  <string name="foo_630">630</string>
+  <string name="foo_631">631</string>
+  <string name="foo_632">632</string>
+  <string name="foo_633">633</string>
+  <string name="foo_634">634</string>
+  <string name="foo_635">635</string>
+  <string name="foo_636">636</string>
+  <string name="foo_637">637</string>
+  <string name="foo_638">638</string>
+  <string name="foo_639">639</string>
+  <string name="foo_640">640</string>
+  <string name="foo_641">641</string>
+  <string name="foo_642">642</string>
+  <string name="foo_643">643</string>
+  <string name="foo_644">644</string>
+  <string name="foo_645">645</string>
+  <string name="foo_646">646</string>
+  <string name="foo_647">647</string>
+  <string name="foo_648">648</string>
+  <string name="foo_649">649</string>
+  <string name="foo_650">650</string>
+  <string name="foo_651">651</string>
+  <string name="foo_652">652</string>
+  <string name="foo_653">653</string>
+  <string name="foo_654">654</string>
+  <string name="foo_655">655</string>
+  <string name="foo_656">656</string>
+  <string name="foo_657">657</string>
+  <string name="foo_658">658</string>
+  <string name="foo_659">659</string>
+  <string name="foo_660">660</string>
+  <string name="foo_661">661</string>
+  <string name="foo_662">662</string>
+  <string name="foo_663">663</string>
+  <string name="foo_664">664</string>
+  <string name="foo_665">665</string>
+  <string name="foo_666">666</string>
+  <string name="foo_667">667</string>
+  <string name="foo_668">668</string>
+  <string name="foo_669">669</string>
+  <string name="foo_670">670</string>
+  <string name="foo_671">671</string>
+  <string name="foo_672">672</string>
+  <string name="foo_673">673</string>
+  <string name="foo_674">674</string>
+  <string name="foo_675">675</string>
+  <string name="foo_676">676</string>
+  <string name="foo_677">677</string>
+  <string name="foo_678">678</string>
+  <string name="foo_679">679</string>
+  <string name="foo_680">680</string>
+  <string name="foo_681">681</string>
+  <string name="foo_682">682</string>
+  <string name="foo_683">683</string>
+  <string name="foo_684">684</string>
+  <string name="foo_685">685</string>
+  <string name="foo_686">686</string>
+  <string name="foo_687">687</string>
+  <string name="foo_688">688</string>
+  <string name="foo_689">689</string>
+  <string name="foo_690">690</string>
+  <string name="foo_691">691</string>
+  <string name="foo_692">692</string>
+  <string name="foo_693">693</string>
+  <string name="foo_694">694</string>
+  <string name="foo_695">695</string>
+  <string name="foo_696">696</string>
+  <string name="foo_697">697</string>
+  <string name="foo_698">698</string>
+  <string name="foo_699">699</string>
+  <string name="foo_700">700</string>
+  <string name="foo_701">701</string>
+  <string name="foo_702">702</string>
+  <string name="foo_703">703</string>
+  <string name="foo_704">704</string>
+  <string name="foo_705">705</string>
+  <string name="foo_706">706</string>
+  <string name="foo_707">707</string>
+  <string name="foo_708">708</string>
+  <string name="foo_709">709</string>
+  <string name="foo_710">710</string>
+  <string name="foo_711">711</string>
+  <string name="foo_712">712</string>
+  <string name="foo_713">713</string>
+  <string name="foo_714">714</string>
+  <string name="foo_715">715</string>
+  <string name="foo_716">716</string>
+  <string name="foo_717">717</string>
+  <string name="foo_718">718</string>
+  <string name="foo_719">719</string>
+  <string name="foo_720">720</string>
+  <string name="foo_721">721</string>
+  <string name="foo_722">722</string>
+  <string name="foo_723">723</string>
+  <string name="foo_724">724</string>
+  <string name="foo_725">725</string>
+  <string name="foo_726">726</string>
+  <string name="foo_727">727</string>
+  <string name="foo_728">728</string>
+  <string name="foo_729">729</string>
+  <string name="foo_730">730</string>
+  <string name="foo_731">731</string>
+  <string name="foo_732">732</string>
+  <string name="foo_733">733</string>
+  <string name="foo_734">734</string>
+  <string name="foo_735">735</string>
+  <string name="foo_736">736</string>
+  <string name="foo_737">737</string>
+  <string name="foo_738">738</string>
+  <string name="foo_739">739</string>
+  <string name="foo_740">740</string>
+  <string name="foo_741">741</string>
+  <string name="foo_742">742</string>
+  <string name="foo_743">743</string>
+  <string name="foo_744">744</string>
+  <string name="foo_745">745</string>
+  <string name="foo_746">746</string>
+  <string name="foo_747">747</string>
+  <string name="foo_748">748</string>
+  <string name="foo_749">749</string>
+  <string name="foo_750">750</string>
+  <string name="foo_751">751</string>
+  <string name="foo_752">752</string>
+  <string name="foo_753">753</string>
+  <string name="foo_754">754</string>
+  <string name="foo_755">755</string>
+  <string name="foo_756">756</string>
+  <string name="foo_757">757</string>
+  <string name="foo_758">758</string>
+  <string name="foo_759">759</string>
+  <string name="foo_760">760</string>
+  <string name="foo_761">761</string>
+  <string name="foo_762">762</string>
+  <string name="foo_763">763</string>
+  <string name="foo_764">764</string>
+  <string name="foo_765">765</string>
+  <string name="foo_766">766</string>
+  <string name="foo_767">767</string>
+  <string name="foo_768">768</string>
+  <string name="foo_769">769</string>
+  <string name="foo_770">770</string>
+  <string name="foo_771">771</string>
+  <string name="foo_772">772</string>
+  <string name="foo_773">773</string>
+  <string name="foo_774">774</string>
+  <string name="foo_775">775</string>
+  <string name="foo_776">776</string>
+  <string name="foo_777">777</string>
+  <string name="foo_778">778</string>
+  <string name="foo_779">779</string>
+  <string name="foo_780">780</string>
+  <string name="foo_781">781</string>
+  <string name="foo_782">782</string>
+  <string name="foo_783">783</string>
+  <string name="foo_784">784</string>
+  <string name="foo_785">785</string>
+  <string name="foo_786">786</string>
+  <string name="foo_787">787</string>
+  <string name="foo_788">788</string>
+  <string name="foo_789">789</string>
+  <string name="foo_790">790</string>
+  <string name="foo_791">791</string>
+  <string name="foo_792">792</string>
+  <string name="foo_793">793</string>
+  <string name="foo_794">794</string>
+  <string name="foo_795">795</string>
+  <string name="foo_796">796</string>
+  <string name="foo_797">797</string>
+  <string name="foo_798">798</string>
+  <string name="foo_799">799</string>
+  <string name="foo_800">800</string>
+  <string name="foo_801">801</string>
+  <string name="foo_802">802</string>
+  <string name="foo_803">803</string>
+  <string name="foo_804">804</string>
+  <string name="foo_805">805</string>
+  <string name="foo_806">806</string>
+  <string name="foo_807">807</string>
+  <string name="foo_808">808</string>
+  <string name="foo_809">809</string>
+  <string name="foo_810">810</string>
+  <string name="foo_811">811</string>
+  <string name="foo_812">812</string>
+  <string name="foo_813">813</string>
+  <string name="foo_814">814</string>
+  <string name="foo_815">815</string>
+  <string name="foo_816">816</string>
+  <string name="foo_817">817</string>
+  <string name="foo_818">818</string>
+  <string name="foo_819">819</string>
+  <string name="foo_820">820</string>
+  <string name="foo_821">821</string>
+  <string name="foo_822">822</string>
+  <string name="foo_823">823</string>
+  <string name="foo_824">824</string>
+  <string name="foo_825">825</string>
+  <string name="foo_826">826</string>
+  <string name="foo_827">827</string>
+  <string name="foo_828">828</string>
+  <string name="foo_829">829</string>
+  <string name="foo_830">830</string>
+  <string name="foo_831">831</string>
+  <string name="foo_832">832</string>
+  <string name="foo_833">833</string>
+  <string name="foo_834">834</string>
+  <string name="foo_835">835</string>
+  <string name="foo_836">836</string>
+  <string name="foo_837">837</string>
+  <string name="foo_838">838</string>
+  <string name="foo_839">839</string>
+  <string name="foo_840">840</string>
+  <string name="foo_841">841</string>
+  <string name="foo_842">842</string>
+  <string name="foo_843">843</string>
+  <string name="foo_844">844</string>
+  <string name="foo_845">845</string>
+  <string name="foo_846">846</string>
+  <string name="foo_847">847</string>
+  <string name="foo_848">848</string>
+  <string name="foo_849">849</string>
+  <string name="foo_850">850</string>
+  <string name="foo_851">851</string>
+  <string name="foo_852">852</string>
+  <string name="foo_853">853</string>
+  <string name="foo_854">854</string>
+  <string name="foo_855">855</string>
+  <string name="foo_856">856</string>
+  <string name="foo_857">857</string>
+  <string name="foo_858">858</string>
+  <string name="foo_859">859</string>
+  <string name="foo_860">860</string>
+  <string name="foo_861">861</string>
+  <string name="foo_862">862</string>
+  <string name="foo_863">863</string>
+  <string name="foo_864">864</string>
+  <string name="foo_865">865</string>
+  <string name="foo_866">866</string>
+  <string name="foo_867">867</string>
+  <string name="foo_868">868</string>
+  <string name="foo_869">869</string>
+  <string name="foo_870">870</string>
+  <string name="foo_871">871</string>
+  <string name="foo_872">872</string>
+  <string name="foo_873">873</string>
+  <string name="foo_874">874</string>
+  <string name="foo_875">875</string>
+  <string name="foo_876">876</string>
+  <string name="foo_877">877</string>
+  <string name="foo_878">878</string>
+  <string name="foo_879">879</string>
+  <string name="foo_880">880</string>
+  <string name="foo_881">881</string>
+  <string name="foo_882">882</string>
+  <string name="foo_883">883</string>
+  <string name="foo_884">884</string>
+  <string name="foo_885">885</string>
+  <string name="foo_886">886</string>
+  <string name="foo_887">887</string>
+  <string name="foo_888">888</string>
+  <string name="foo_889">889</string>
+  <string name="foo_890">890</string>
+  <string name="foo_891">891</string>
+  <string name="foo_892">892</string>
+  <string name="foo_893">893</string>
+  <string name="foo_894">894</string>
+  <string name="foo_895">895</string>
+  <string name="foo_896">896</string>
+  <string name="foo_897">897</string>
+  <string name="foo_898">898</string>
+  <string name="foo_899">899</string>
+  <string name="foo_900">900</string>
+  <string name="foo_901">901</string>
+  <string name="foo_902">902</string>
+  <string name="foo_903">903</string>
+  <string name="foo_904">904</string>
+  <string name="foo_905">905</string>
+  <string name="foo_906">906</string>
+  <string name="foo_907">907</string>
+  <string name="foo_908">908</string>
+  <string name="foo_909">909</string>
+  <string name="foo_910">910</string>
+  <string name="foo_911">911</string>
+  <string name="foo_912">912</string>
+  <string name="foo_913">913</string>
+  <string name="foo_914">914</string>
+  <string name="foo_915">915</string>
+  <string name="foo_916">916</string>
+  <string name="foo_917">917</string>
+  <string name="foo_918">918</string>
+  <string name="foo_919">919</string>
+  <string name="foo_920">920</string>
+  <string name="foo_921">921</string>
+  <string name="foo_922">922</string>
+  <string name="foo_923">923</string>
+  <string name="foo_924">924</string>
+  <string name="foo_925">925</string>
+  <string name="foo_926">926</string>
+  <string name="foo_927">927</string>
+  <string name="foo_928">928</string>
+  <string name="foo_929">929</string>
+  <string name="foo_930">930</string>
+  <string name="foo_931">931</string>
+  <string name="foo_932">932</string>
+  <string name="foo_933">933</string>
+  <string name="foo_934">934</string>
+  <string name="foo_935">935</string>
+  <string name="foo_936">936</string>
+  <string name="foo_937">937</string>
+  <string name="foo_938">938</string>
+  <string name="foo_939">939</string>
+  <string name="foo_940">940</string>
+  <string name="foo_941">941</string>
+  <string name="foo_942">942</string>
+  <string name="foo_943">943</string>
+  <string name="foo_944">944</string>
+  <string name="foo_945">945</string>
+  <string name="foo_946">946</string>
+  <string name="foo_947">947</string>
+  <string name="foo_948">948</string>
+  <string name="foo_949">949</string>
+  <string name="foo_950">950</string>
+  <string name="foo_951">951</string>
+  <string name="foo_952">952</string>
+  <string name="foo_953">953</string>
+  <string name="foo_954">954</string>
+  <string name="foo_955">955</string>
+  <string name="foo_956">956</string>
+  <string name="foo_957">957</string>
+  <string name="foo_958">958</string>
+  <string name="foo_959">959</string>
+  <string name="foo_960">960</string>
+  <string name="foo_961">961</string>
+  <string name="foo_962">962</string>
+  <string name="foo_963">963</string>
+  <string name="foo_964">964</string>
+  <string name="foo_965">965</string>
+  <string name="foo_966">966</string>
+  <string name="foo_967">967</string>
+  <string name="foo_968">968</string>
+  <string name="foo_969">969</string>
+  <string name="foo_970">970</string>
+  <string name="foo_971">971</string>
+  <string name="foo_972">972</string>
+  <string name="foo_973">973</string>
+  <string name="foo_974">974</string>
+  <string name="foo_975">975</string>
+  <string name="foo_976">976</string>
+  <string name="foo_977">977</string>
+  <string name="foo_978">978</string>
+  <string name="foo_979">979</string>
+  <string name="foo_980">980</string>
+  <string name="foo_981">981</string>
+  <string name="foo_982">982</string>
+  <string name="foo_983">983</string>
+  <string name="foo_984">984</string>
+  <string name="foo_985">985</string>
+  <string name="foo_986">986</string>
+  <string name="foo_987">987</string>
+  <string name="foo_988">988</string>
+  <string name="foo_989">989</string>
+  <string name="foo_990">990</string>
+  <string name="foo_991">991</string>
+  <string name="foo_992">992</string>
+  <string name="foo_993">993</string>
+  <string name="foo_994">994</string>
+  <string name="foo_995">995</string>
+  <string name="foo_996">996</string>
+  <string name="foo_997">997</string>
+  <string name="foo_998">998</string>
+  <string name="foo_999">999</string>
+</resources>
diff --git a/libs/androidfw/tests/data/sparse/res/values/values.xml b/libs/androidfw/tests/data/sparse/res/values/values.xml
new file mode 100644
index 0000000..5cc42d8
--- /dev/null
+++ b/libs/androidfw/tests/data/sparse/res/values/values.xml
@@ -0,0 +1,28 @@
+<?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>
+    <integer name="foo_0">0</integer>
+    <integer name="foo_1">1</integer>
+    <integer name="foo_2">2</integer>
+    <integer name="foo_3">3</integer>
+    <integer name="foo_4">4</integer>
+    <integer name="foo_5">5</integer>
+    <integer name="foo_6">6</integer>
+    <integer name="foo_7">7</integer>
+    <integer name="foo_8">8</integer>
+    <integer name="foo_9">9</integer>
+</resources>
diff --git a/libs/androidfw/tests/data/sparse/sparse.apk b/libs/androidfw/tests/data/sparse/sparse.apk
new file mode 100644
index 0000000..1f9bba3
--- /dev/null
+++ b/libs/androidfw/tests/data/sparse/sparse.apk
Binary files differ
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index ff40c8a..ec8d63ec 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -47,6 +47,7 @@
     renderthread/RenderThread.cpp \
     renderthread/TimeLord.cpp \
     renderthread/Frame.cpp \
+    service/GraphicsStatsService.cpp \
     thread/TaskManager.cpp \
     utils/Blur.cpp \
     utils/GLUtils.cpp \
@@ -186,6 +187,7 @@
     external/skia/src/effects \
     external/skia/src/image \
     external/skia/src/utils \
+    external/icu/icu4c/source/common \
     external/harfbuzz_ng/src \
     external/freetype/include
 
@@ -293,6 +295,7 @@
     tests/unit/GlopBuilderTests.cpp \
     tests/unit/GpuMemoryTrackerTests.cpp \
     tests/unit/GradientCacheTests.cpp \
+    tests/unit/GraphicsStatsServiceTests.cpp \
     tests/unit/LayerUpdateQueueTests.cpp \
     tests/unit/LeakCheckTests.cpp \
     tests/unit/LinearAllocatorTests.cpp \
diff --git a/libs/hwui/BakedOpState.cpp b/libs/hwui/BakedOpState.cpp
index 9f98241..9823a02 100644
--- a/libs/hwui/BakedOpState.cpp
+++ b/libs/hwui/BakedOpState.cpp
@@ -31,7 +31,7 @@
 }
 
 ResolvedRenderState::ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot,
-        const RecordedOp& recordedOp, bool expandForStroke) {
+        const RecordedOp& recordedOp, bool expandForStroke, bool expandForPathTexture) {
     // resolvedMatrix = parentMatrix * localMatrix
     transform.loadMultiply(*snapshot.transform, recordedOp.localMatrix);
 
@@ -40,6 +40,8 @@
     if (CC_UNLIKELY(expandForStroke)) {
         // account for non-hairline stroke
         clippedBounds.outset(recordedOp.paint->getStrokeWidth() * 0.5f);
+    } else if (CC_UNLIKELY(expandForPathTexture)) {
+        clippedBounds.outset(1);
     }
     transform.mapRect(clippedBounds);
     if (CC_UNLIKELY(expandForStroke
@@ -111,7 +113,7 @@
         Snapshot& snapshot, const RecordedOp& recordedOp) {
     if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;
     BakedOpState* bakedState = allocator.create_trivial<BakedOpState>(
-            allocator, snapshot, recordedOp, false);
+            allocator, snapshot, recordedOp, false, false);
     if (bakedState->computedState.clippedBounds.isEmpty()) {
         // bounds are empty, so op is rejected
         allocator.rewindIfLastAlloc(bakedState);
@@ -127,14 +129,14 @@
 }
 
 BakedOpState* BakedOpState::tryStrokeableOpConstruct(LinearAllocator& allocator,
-        Snapshot& snapshot, const RecordedOp& recordedOp, StrokeBehavior strokeBehavior) {
+        Snapshot& snapshot, const RecordedOp& recordedOp, StrokeBehavior strokeBehavior,
+        bool expandForPathTexture) {
     if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;
-    bool expandForStroke = (strokeBehavior == StrokeBehavior::StyleDefined)
-            ? (recordedOp.paint && recordedOp.paint->getStyle() != SkPaint::kFill_Style)
-            : true;
+    bool expandForStroke = (strokeBehavior == StrokeBehavior::Forced
+            || (recordedOp.paint && recordedOp.paint->getStyle() != SkPaint::kFill_Style));
 
     BakedOpState* bakedState = allocator.create_trivial<BakedOpState>(
-           allocator, snapshot, recordedOp, expandForStroke);
+           allocator, snapshot, recordedOp, expandForStroke, expandForPathTexture);
     if (bakedState->computedState.clippedBounds.isEmpty()) {
         // bounds are empty, so op is rejected
         // NOTE: this won't succeed if a clip was allocated
diff --git a/libs/hwui/BakedOpState.h b/libs/hwui/BakedOpState.h
index e1441fc..7b0b34f 100644
--- a/libs/hwui/BakedOpState.h
+++ b/libs/hwui/BakedOpState.h
@@ -53,7 +53,7 @@
 class ResolvedRenderState {
 public:
     ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot,
-            const RecordedOp& recordedOp, bool expandForStroke);
+            const RecordedOp& recordedOp, bool expandForStroke, bool expandForPathTexture);
 
     // Constructor for unbounded ops *with* transform/clip
     ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot,
@@ -117,7 +117,8 @@
     };
 
     static BakedOpState* tryStrokeableOpConstruct(LinearAllocator& allocator,
-            Snapshot& snapshot, const RecordedOp& recordedOp, StrokeBehavior strokeBehavior);
+            Snapshot& snapshot, const RecordedOp& recordedOp, StrokeBehavior strokeBehavior,
+            bool expandForPathTexture);
 
     static BakedOpState* tryShadowOpConstruct(LinearAllocator& allocator,
             Snapshot& snapshot, const ShadowOp* shadowOpPtr);
@@ -140,8 +141,8 @@
     friend class LinearAllocator;
 
     BakedOpState(LinearAllocator& allocator, Snapshot& snapshot,
-            const RecordedOp& recordedOp, bool expandForStroke)
-            : computedState(allocator, snapshot, recordedOp, expandForStroke)
+            const RecordedOp& recordedOp, bool expandForStroke, bool expandForPathTexture)
+            : computedState(allocator, snapshot, recordedOp, expandForStroke, expandForPathTexture)
             , alpha(snapshot.alpha)
             , roundRectClipState(snapshot.roundRectClipState)
             , op(&recordedOp) {}
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 7c2e78c..19063e3 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -133,7 +133,7 @@
      * this function returns GL_SRGB8_ALPHA8, otherwise it returns GL_RGBA
      */
     constexpr GLint rgbaInternalFormat(bool needSRGB = true) const {
-        return extensions().hasSRGB() && needSRGB ? GL_SRGB8_ALPHA8 : GL_RGBA;
+        return extensions().hasLinearBlending() && needSRGB ? GL_SRGB8_ALPHA8 : GL_RGBA;
     }
 
     /**
diff --git a/libs/hwui/Extensions.cpp b/libs/hwui/Extensions.cpp
index 00238a2..1e71cb0 100644
--- a/libs/hwui/Extensions.cpp
+++ b/libs/hwui/Extensions.cpp
@@ -20,6 +20,8 @@
 #include "Properties.h"
 #include "utils/StringUtils.h"
 
+#include <cutils/compiler.h>
+
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
 
@@ -28,14 +30,6 @@
 namespace android {
 namespace uirenderer {
 
-// Debug
-#if DEBUG_EXTENSIONS
-    #define EXT_LOGD(...) ALOGD(__VA_ARGS__)
-#else
-    #define EXT_LOGD(...)
-#endif
-
-
 Extensions::Extensions() {
     const char* version = (const char*) glGetString(GL_VERSION);
 
@@ -66,17 +60,18 @@
     mHas4BitStencil = extensions.has("GL_OES_stencil4");
     mHasUnpackSubImage = extensions.has("GL_EXT_unpack_subimage");
 
-#ifdef ANDROID_ENABLE_LINEAR_BLENDING
     mHasSRGB = mVersionMajor >= 3 || extensions.has("GL_EXT_sRGB");
     mHasSRGBWriteControl = extensions.has("GL_EXT_sRGB_write_control");
 
+#ifdef ANDROID_ENABLE_LINEAR_BLENDING
     // If linear blending is enabled, the device must have (ES3.0 or EXT_sRGB)
     // and EXT_sRGB_write_control
     LOG_ALWAYS_FATAL_IF(!mHasSRGB, "Linear blending requires ES 3.0 or EXT_sRGB");
     LOG_ALWAYS_FATAL_IF(!mHasSRGBWriteControl, "Linear blending requires EXT_sRGB_write_control");
+
+    mHasLinearBlending = true;
 #else
-    mHasSRGB = false;
-    mHasSRGBWriteControl = false;
+    mHasLinearBlending = false;
 #endif
 }
 
diff --git a/libs/hwui/Extensions.h b/libs/hwui/Extensions.h
index 2c38507..0ecfdb1 100644
--- a/libs/hwui/Extensions.h
+++ b/libs/hwui/Extensions.h
@@ -17,11 +17,6 @@
 #ifndef ANDROID_HWUI_EXTENSIONS_H
 #define ANDROID_HWUI_EXTENSIONS_H
 
-#include <cutils/compiler.h>
-
-#include <string>
-#include <unordered_set>
-
 namespace android {
 namespace uirenderer {
 
@@ -45,6 +40,7 @@
     inline bool hasFloatTextures() const { return mVersionMajor >= 3; }
     inline bool hasSRGB() const { return mHasSRGB; }
     inline bool hasSRGBWriteControl() const { return hasSRGB() && mHasSRGBWriteControl; }
+    inline bool hasLinearBlending() const { return hasSRGB() && mHasLinearBlending; }
 
     inline int getMajorGlVersion() const { return mVersionMajor; }
     inline int getMinorGlVersion() const { return mVersionMinor; }
@@ -59,6 +55,7 @@
     bool mHasUnpackSubImage;
     bool mHasSRGB;
     bool mHasSRGBWriteControl;
+    bool mHasLinearBlending;
 
     int mVersionMajor;
     int mVersionMinor;
diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp
index 35ff635..86f9a5d 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -78,7 +78,7 @@
     // Render all layers to be updated, in order. Defer in reverse order, so that they'll be
     // updated in the order they're passed in (mLayerBuilders are issued to Renderer in reverse)
     for (int i = layers.entries().size() - 1; i >= 0; i--) {
-        RenderNode* layerNode = layers.entries()[i].renderNode;
+        RenderNode* layerNode = layers.entries()[i].renderNode.get();
         // only schedule repaint if node still on layer - possible it may have been
         // removed during a dropped frame, but layers may still remain scheduled so
         // as not to lose info on what portion is damaged
@@ -562,10 +562,11 @@
  * for paint's style on the bounds being computed.
  */
 BakedOpState* FrameBuilder::deferStrokeableOp(const RecordedOp& op, batchid_t batchId,
-        BakedOpState::StrokeBehavior strokeBehavior) {
+        BakedOpState::StrokeBehavior strokeBehavior, bool expandForPathTexture) {
     // Note: here we account for stroke when baking the op
     BakedOpState* bakedState = BakedOpState::tryStrokeableOpConstruct(
-            mAllocator, *mCanvasState.writableSnapshot(), op, strokeBehavior);
+            mAllocator, *mCanvasState.writableSnapshot(), op,
+            strokeBehavior, expandForPathTexture);
     if (!bakedState) return nullptr; // quick rejected
 
     if (op.opId == RecordedOpId::RectOp && op.paint->getStyle() != SkPaint::kStroke_Style) {
@@ -590,7 +591,10 @@
 }
 
 void FrameBuilder::deferArcOp(const ArcOp& op) {
-    deferStrokeableOp(op, tessBatchId(op));
+    // Pass true below since arcs have a tendency to draw outside their expected bounds within
+    // their path textures. Passing true makes it more likely that we'll scissor, instead of
+    // corrupting the frame by drawing outside of clip bounds.
+    deferStrokeableOp(op, tessBatchId(op), BakedOpState::StrokeBehavior::StyleDefined, true);
 }
 
 static bool hasMergeableClip(const BakedOpState& state) {
@@ -748,7 +752,7 @@
 void FrameBuilder::deferTextOp(const TextOp& op) {
     BakedOpState* bakedState = BakedOpState::tryStrokeableOpConstruct(
             mAllocator, *mCanvasState.writableSnapshot(), op,
-            BakedOpState::StrokeBehavior::StyleDefined);
+            BakedOpState::StrokeBehavior::StyleDefined, false);
     if (!bakedState) return; // quick rejected
 
     batchid_t batchId = textBatchId(*(op.paint));
diff --git a/libs/hwui/FrameBuilder.h b/libs/hwui/FrameBuilder.h
index b915443..46048f7 100644
--- a/libs/hwui/FrameBuilder.h
+++ b/libs/hwui/FrameBuilder.h
@@ -211,7 +211,8 @@
     }
 
     BakedOpState* deferStrokeableOp(const RecordedOp& op, batchid_t batchId,
-            BakedOpState::StrokeBehavior strokeBehavior = BakedOpState::StrokeBehavior::StyleDefined);
+            BakedOpState::StrokeBehavior strokeBehavior = BakedOpState::StrokeBehavior::StyleDefined,
+            bool expandForPathTexture = false);
 
     /**
      * Declares all FrameBuilder::deferXXXXOp() methods for every RecordedOp type.
diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp
index 71bee93..18bfcc2 100644
--- a/libs/hwui/GradientCache.cpp
+++ b/libs/hwui/GradientCache.cpp
@@ -68,7 +68,7 @@
         , mMaxSize(Properties::gradientCacheSize)
         , mUseFloatTexture(extensions.hasFloatTextures())
         , mHasNpot(extensions.hasNPot())
-        , mHasSRGB(extensions.hasSRGB()) {
+        , mHasLinearBlending(extensions.hasLinearBlending()) {
     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
 
     mCache.setOnEntryRemovedListener(this);
@@ -263,7 +263,7 @@
     if (mUseFloatTexture) {
         texture->upload(GL_RGBA16F, width, height, GL_RGBA, GL_FLOAT, pixels);
     } else {
-        GLint internalFormat = mHasSRGB ? GL_SRGB8_ALPHA8 : GL_RGBA;
+        GLint internalFormat = mHasLinearBlending ? GL_SRGB8_ALPHA8 : GL_RGBA;
         texture->upload(internalFormat, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
     }
 
diff --git a/libs/hwui/GradientCache.h b/libs/hwui/GradientCache.h
index 5e35435..f299a40 100644
--- a/libs/hwui/GradientCache.h
+++ b/libs/hwui/GradientCache.h
@@ -170,7 +170,7 @@
     GLint mMaxTextureSize;
     bool mUseFloatTexture;
     bool mHasNpot;
-    bool mHasSRGB;
+    bool mHasLinearBlending;
 
     mutable Mutex mLock;
 }; // class GradientCache
diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp
index 2132c2b..7be71ee 100644
--- a/libs/hwui/JankTracker.cpp
+++ b/libs/hwui/JankTracker.cpp
@@ -110,7 +110,7 @@
 }
 
 // Only called when dumping stats, less performance sensitive
-static uint32_t frameTimeForFrameCountIndex(uint32_t index) {
+int32_t JankTracker::frameTimeForFrameCountIndex(uint32_t index) {
     index = index + kBucketMinThreshold;
     if (index > kBucket2msIntervals) {
         index += (index - kBucket2msIntervals);
@@ -123,6 +123,10 @@
     return index;
 }
 
+int32_t JankTracker::frameTimeForSlowFrameCountIndex(uint32_t index) {
+    return (index * kSlowFrameBucketIntervalMs) + kSlowFrameBucketStartMs;
+}
+
 JankTracker::JankTracker(const DisplayInfo& displayInfo) {
     // By default this will use malloc memory. It may be moved later to ashmem
     // if there is shared space for it and a request comes in to do that.
@@ -161,8 +165,25 @@
     mData = nullptr;
 }
 
+void JankTracker::rotateStorage() {
+    // If we are mapped we want to stop using the ashmem backend and switch to malloc
+    // We are expecting a switchStorageToAshmem call to follow this, but it's not guaranteed
+    // If we aren't sitting on top of ashmem then just do a reset() as it's functionally
+    // equivalent do a free, malloc, reset.
+    if (mIsMapped) {
+        freeData();
+        mData = new ProfileData;
+    }
+    reset();
+}
+
 void JankTracker::switchStorageToAshmem(int ashmemfd) {
     int regionSize = ashmem_get_size_region(ashmemfd);
+    if (regionSize < 0) {
+        int err = errno;
+        ALOGW("Failed to get ashmem region size from fd %d, err %d %s", ashmemfd, err, strerror(err));
+        return;
+    }
     if (regionSize < static_cast<int>(sizeof(ProfileData))) {
         ALOGW("Ashmem region is too small! Received %d, required %u",
                 regionSize, static_cast<unsigned int>(sizeof(ProfileData)));
@@ -279,15 +300,19 @@
     }
 }
 
-void JankTracker::dumpBuffer(const void* buffer, size_t bufsize, int fd) {
-    if (bufsize < sizeof(ProfileData)) {
-        return;
+void JankTracker::dumpData(int fd, const ProfileDataDescription* description, const ProfileData* data) {
+    if (description) {
+        switch (description->type) {
+            case JankTrackerType::Generic:
+                break;
+            case JankTrackerType::Package:
+                dprintf(fd, "\nPackage: %s", description->name.c_str());
+                break;
+            case JankTrackerType::Window:
+                dprintf(fd, "\nWindow: %s", description->name.c_str());
+                break;
+        }
     }
-    const ProfileData* data = reinterpret_cast<const ProfileData*>(buffer);
-    dumpData(data, fd);
-}
-
-void JankTracker::dumpData(const ProfileData* data, int fd) {
     if (sFrameStart != FrameInfoIndex::IntendedVsync) {
         dprintf(fd, "\nNote: Data has been filtered!");
     }
@@ -308,7 +333,7 @@
                 data->frameCounts[i]);
     }
     for (size_t i = 0; i < data->slowFrameCounts.size(); i++) {
-        dprintf(fd, " %zums=%u", (i * kSlowFrameBucketIntervalMs) + kSlowFrameBucketStartMs,
+        dprintf(fd, " %ums=%u", frameTimeForSlowFrameCountIndex(i),
                 data->slowFrameCounts[i]);
     }
     dprintf(fd, "\n");
diff --git a/libs/hwui/JankTracker.h b/libs/hwui/JankTracker.h
index 8b482d5..6ff5d89 100644
--- a/libs/hwui/JankTracker.h
+++ b/libs/hwui/JankTracker.h
@@ -54,29 +54,50 @@
     nsecs_t statStartTime;
 };
 
+enum class JankTrackerType {
+    // The default, means there's no description set
+    Generic,
+    // The profile data represents a package
+    Package,
+    // The profile data is for a specific window
+    Window,
+};
+
+// Metadata about the ProfileData being collected
+struct ProfileDataDescription {
+    JankTrackerType type;
+    std::string name;
+};
+
 // TODO: Replace DrawProfiler with this
 class JankTracker {
 public:
     explicit JankTracker(const DisplayInfo& displayInfo);
     ~JankTracker();
 
+    void setDescription(JankTrackerType type, const std::string&& name) {
+        mDescription.type = type;
+        mDescription.name = name;
+    }
+
     void addFrame(const FrameInfo& frame);
 
-    void dump(int fd) { dumpData(mData, fd); }
+    void dump(int fd) { dumpData(fd, &mDescription, mData); }
     void reset();
 
+    void rotateStorage();
     void switchStorageToAshmem(int ashmemfd);
 
     uint32_t findPercentile(int p) { return findPercentile(mData, p); }
-
-    ANDROID_API static void dumpBuffer(const void* buffer, size_t bufsize, int fd);
+    static int32_t frameTimeForFrameCountIndex(uint32_t index);
+    static int32_t frameTimeForSlowFrameCountIndex(uint32_t index);
 
 private:
     void freeData();
     void setFrameInterval(nsecs_t frameIntervalNanos);
 
     static uint32_t findPercentile(const ProfileData* data, int p);
-    static void dumpData(const ProfileData* data, int fd);
+    static void dumpData(int fd, const ProfileDataDescription* description, const ProfileData* data);
 
     std::array<int64_t, NUM_BUCKETS> mThresholds;
     int64_t mFrameInterval;
@@ -90,6 +111,7 @@
     nsecs_t mDequeueTimeForgiveness = 0;
     ProfileData* mData;
     bool mIsMapped = false;
+    ProfileDataDescription mDescription;
 };
 
 } /* namespace uirenderer */
diff --git a/libs/hwui/LayerUpdateQueue.h b/libs/hwui/LayerUpdateQueue.h
index 5b1a854..38f3596 100644
--- a/libs/hwui/LayerUpdateQueue.h
+++ b/libs/hwui/LayerUpdateQueue.h
@@ -19,6 +19,7 @@
 
 #include "Rect.h"
 #include "utils/Macros.h"
+#include <utils/StrongPointer.h>
 
 #include <vector>
 #include <unordered_map>
@@ -35,7 +36,7 @@
         Entry(RenderNode* renderNode, const Rect& damage)
                 : renderNode(renderNode)
                 , damage(damage) {}
-        RenderNode* renderNode;
+        sp<RenderNode> renderNode;
         Rect damage;
     };
 
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index ca05648..40ab778 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -418,7 +418,7 @@
 
 ProgramCache::ProgramCache(Extensions& extensions)
         : mHasES3(extensions.getMajorGlVersion() >= 3)
-        , mHasSRGB(extensions.hasSRGB()) {
+        , mHasLinearBlending(extensions.hasLinearBlending()) {
 }
 
 ProgramCache::~ProgramCache() {
@@ -642,11 +642,11 @@
     }
     if (description.hasBitmap || ((description.hasTexture || description.hasExternalTexture) &&
             !description.hasAlpha8Texture)) {
-        shader.append(gFS_OETF[description.hasLinearTexture && !mHasSRGB]);
+        shader.append(gFS_OETF[description.hasLinearTexture && !mHasLinearBlending]);
     }
     if (description.hasGradient) {
         shader.append(gFS_Gradient_Functions);
-        shader.append(gFS_Gradient_Preamble[mHasSRGB]);
+        shader.append(gFS_Gradient_Preamble[mHasLinearBlending]);
     }
 
     // Begin the shader
diff --git a/libs/hwui/ProgramCache.h b/libs/hwui/ProgramCache.h
index c2f715d..cedd854b 100644
--- a/libs/hwui/ProgramCache.h
+++ b/libs/hwui/ProgramCache.h
@@ -59,7 +59,7 @@
     std::map<programid, std::unique_ptr<Program>> mCache;
 
     const bool mHasES3;
-    const bool mHasSRGB;
+    const bool mHasLinearBlending;
 }; // class ProgramCache
 
 }; // namespace uirenderer
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index 09e34bf..aad81df 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -211,12 +211,15 @@
         return sRenderPipelineType;
     }
     char prop[PROPERTY_VALUE_MAX];
-    property_get(PROPERTY_DEFAULT_RENDERER, prop, "opengl");
+    property_get(PROPERTY_RENDERER, prop, "opengl");
     if (!strcmp(prop, "skiagl") ) {
+        ALOGD("Skia GL Pipeline");
         sRenderPipelineType = RenderPipelineType::SkiaGL;
     } else if (!strcmp(prop, "skiavk") ) {
+        ALOGD("Skia Vulkan Pipeline");
         sRenderPipelineType = RenderPipelineType::SkiaVulkan;
     } else { //"opengl"
+        ALOGD("HWUI GL Pipeline");
         sRenderPipelineType = RenderPipelineType::OpenGL;
     }
     return sRenderPipelineType;
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 6dc0cb3..9db6449 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -156,7 +156,7 @@
  * Allows to set rendering pipeline mode to OpenGL (default), Skia OpenGL
  * or Vulkan.
  */
-#define PROPERTY_DEFAULT_RENDERER "debug.hwui.default_renderer"
+#define PROPERTY_RENDERER "debug.hwui.renderer"
 
 ///////////////////////////////////////////////////////////////////////////////
 // Runtime configuration properties
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 2e33609..374c1b1 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -268,7 +268,7 @@
 
 // Geometry
 void RecordingCanvas::drawPoints(const float* points, int floatCount, const SkPaint& paint) {
-    if (CC_UNLIKELY(floatCount < 2 || PaintUtils::paintWillNotDraw(paint))) return;
+    if (CC_UNLIKELY(floatCount < 2 || paint.nothingToDraw())) return;
     floatCount &= ~0x1; // round down to nearest two
 
     addOp(alloc().create_trivial<PointsOp>(
@@ -279,7 +279,7 @@
 }
 
 void RecordingCanvas::drawLines(const float* points, int floatCount, const SkPaint& paint) {
-    if (CC_UNLIKELY(floatCount < 4 || PaintUtils::paintWillNotDraw(paint))) return;
+    if (CC_UNLIKELY(floatCount < 4 || paint.nothingToDraw())) return;
     floatCount &= ~0x3; // round down to nearest four
 
     addOp(alloc().create_trivial<LinesOp>(
@@ -290,7 +290,7 @@
 }
 
 void RecordingCanvas::drawRect(float left, float top, float right, float bottom, const SkPaint& paint) {
-    if (CC_UNLIKELY(PaintUtils::paintWillNotDraw(paint))) return;
+    if (CC_UNLIKELY(paint.nothingToDraw())) return;
 
     addOp(alloc().create_trivial<RectOp>(
             Rect(left, top, right, bottom),
@@ -333,7 +333,7 @@
 }
 
 void RecordingCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) {
-    if (CC_UNLIKELY(PaintUtils::paintWillNotDraw(paint))) return;
+    if (CC_UNLIKELY(paint.nothingToDraw())) return;
 
     if (paint.getStyle() == SkPaint::kFill_Style
             && (!paint.isAntiAlias() || mState.currentTransform()->isSimple())) {
@@ -362,7 +362,7 @@
 
 void RecordingCanvas::drawRoundRect(float left, float top, float right, float bottom,
             float rx, float ry, const SkPaint& paint) {
-    if (CC_UNLIKELY(PaintUtils::paintWillNotDraw(paint))) return;
+    if (CC_UNLIKELY(paint.nothingToDraw())) return;
 
     if (CC_LIKELY(MathUtils::isPositive(rx) || MathUtils::isPositive(ry))) {
         addOp(alloc().create_trivial<RoundRectOp>(
@@ -398,7 +398,7 @@
 
 void RecordingCanvas::drawCircle(float x, float y, float radius, const SkPaint& paint) {
     // TODO: move to Canvas.h
-    if (CC_UNLIKELY(radius <= 0 || PaintUtils::paintWillNotDraw(paint))) return;
+    if (CC_UNLIKELY(radius <= 0 || paint.nothingToDraw())) return;
 
     drawOval(x - radius, y - radius, x + radius, y + radius, paint);
 }
@@ -419,7 +419,7 @@
 }
 
 void RecordingCanvas::drawOval(float left, float top, float right, float bottom, const SkPaint& paint) {
-    if (CC_UNLIKELY(PaintUtils::paintWillNotDraw(paint))) return;
+    if (CC_UNLIKELY(paint.nothingToDraw())) return;
 
     addOp(alloc().create_trivial<OvalOp>(
             Rect(left, top, right, bottom),
@@ -430,7 +430,7 @@
 
 void RecordingCanvas::drawArc(float left, float top, float right, float bottom,
         float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) {
-    if (CC_UNLIKELY(PaintUtils::paintWillNotDraw(paint))) return;
+    if (CC_UNLIKELY(paint.nothingToDraw())) return;
 
     if (fabs(sweepAngle) >= 360.0f) {
         drawOval(left, top, right, bottom, paint);
@@ -445,7 +445,7 @@
 }
 
 void RecordingCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
-    if (CC_UNLIKELY(PaintUtils::paintWillNotDraw(paint))) return;
+    if (CC_UNLIKELY(paint.nothingToDraw())) return;
 
     addOp(alloc().create_trivial<PathOp>(
             Rect(path.getBounds()),
@@ -543,7 +543,7 @@
 void RecordingCanvas::drawGlyphs(const uint16_t* glyphs, const float* positions, int glyphCount,
             const SkPaint& paint, float x, float y, float boundsLeft, float boundsTop,
             float boundsRight, float boundsBottom, float totalAdvance) {
-    if (!glyphs || !positions || glyphCount <= 0 || PaintUtils::paintWillNotDrawText(paint)) return;
+    if (!glyphs || !positions || glyphCount <= 0 || paint.nothingToDraw()) return;
     glyphs = refBuffer<glyph_t>(glyphs, glyphCount);
     positions = refBuffer<float>(positions, glyphCount * 2);
 
@@ -563,7 +563,7 @@
         glyphs[0] = layout.getGlyphId(i);
         float x = hOffset + layout.getX(i);
         float y = vOffset + layout.getY(i);
-        if (PaintUtils::paintWillNotDrawText(paint)) return;
+        if (paint.nothingToDraw()) return;
         const uint16_t* tempGlyphs = refBuffer<glyph_t>(glyphs, 1);
         addOp(alloc().create_trivial<TextOnPathOp>(
                 *(mState.currentSnapshot()->transform),
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index c57b1b3..51a7d00 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -443,7 +443,7 @@
 
 void SkiaCanvas::drawPoints(const float* points, int count, const SkPaint& paint,
                             SkCanvas::PointMode mode) {
-    if (CC_UNLIKELY(count < 2 || PaintUtils::paintWillNotDraw(paint))) return;
+    if (CC_UNLIKELY(count < 2 || paint.nothingToDraw())) return;
     // convert the floats into SkPoints
     count >>= 1;    // now it is the number of points
     std::unique_ptr<SkPoint[]> pts(new SkPoint[count]);
@@ -469,49 +469,49 @@
 }
 
 void SkiaCanvas::drawLines(const float* points, int count, const SkPaint& paint) {
-    if (CC_UNLIKELY(count < 4 || PaintUtils::paintWillNotDraw(paint))) return;
+    if (CC_UNLIKELY(count < 4 || paint.nothingToDraw())) return;
     this->drawPoints(points, count, paint, SkCanvas::kLines_PointMode);
 }
 
 void SkiaCanvas::drawRect(float left, float top, float right, float bottom,
         const SkPaint& paint) {
-    if (CC_UNLIKELY(PaintUtils::paintWillNotDraw(paint))) return;
+    if (CC_UNLIKELY(paint.nothingToDraw())) return;
     mCanvas->drawRectCoords(left, top, right, bottom, paint);
 
 }
 
 void SkiaCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) {
-    if (CC_UNLIKELY(PaintUtils::paintWillNotDraw(paint))) return;
+    if (CC_UNLIKELY(paint.nothingToDraw())) return;
     mCanvas->drawRegion(region, paint);
 }
 
 void SkiaCanvas::drawRoundRect(float left, float top, float right, float bottom,
         float rx, float ry, const SkPaint& paint) {
-    if (CC_UNLIKELY(PaintUtils::paintWillNotDraw(paint))) return;
+    if (CC_UNLIKELY(paint.nothingToDraw())) return;
     SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
     mCanvas->drawRoundRect(rect, rx, ry, paint);
 }
 
 void SkiaCanvas::drawCircle(float x, float y, float radius, const SkPaint& paint) {
-    if (CC_UNLIKELY(radius <= 0 || PaintUtils::paintWillNotDraw(paint))) return;
+    if (CC_UNLIKELY(radius <= 0 || paint.nothingToDraw())) return;
     mCanvas->drawCircle(x, y, radius, paint);
 }
 
 void SkiaCanvas::drawOval(float left, float top, float right, float bottom, const SkPaint& paint) {
-    if (CC_UNLIKELY(PaintUtils::paintWillNotDraw(paint))) return;
+    if (CC_UNLIKELY(paint.nothingToDraw())) return;
     SkRect oval = SkRect::MakeLTRB(left, top, right, bottom);
     mCanvas->drawOval(oval, paint);
 }
 
 void SkiaCanvas::drawArc(float left, float top, float right, float bottom,
         float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) {
-    if (CC_UNLIKELY(PaintUtils::paintWillNotDraw(paint))) return;
+    if (CC_UNLIKELY(paint.nothingToDraw())) return;
     SkRect arc = SkRect::MakeLTRB(left, top, right, bottom);
     mCanvas->drawArc(arc, startAngle, sweepAngle, useCenter, paint);
 }
 
 void SkiaCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
-    if (CC_UNLIKELY(PaintUtils::paintWillNotDraw(paint))) return;
+    if (CC_UNLIKELY(paint.nothingToDraw())) return;
     SkRect rect;
     SkRRect roundRect;
     if (path.isOval(&rect)) {
@@ -698,7 +698,7 @@
         const SkPaint& paint, float x, float y,
         float boundsLeft, float boundsTop, float boundsRight, float boundsBottom,
         float totalAdvance) {
-     if (!text || !positions || count <= 0 || PaintUtils::paintWillNotDrawText(paint)) return;
+     if (!text || !positions || count <= 0 || paint.nothingToDraw()) return;
     // Set align to left for drawing, as we don't want individual
     // glyphs centered or right-aligned; the offset above takes
     // care of all alignment.
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 9239986..760c10c 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -217,6 +217,7 @@
     const float height = outData->bitmapTexture->height();
 
     description->hasBitmap = true;
+    description->hasLinearTexture = outData->bitmapTexture->isLinear();
     description->isShaderBitmapExternal = hwuiBitmap->isHardware();
     // gralloc doesn't support non-clamp modes
     if (hwuiBitmap->isHardware() || (!caches.extensions().hasNPot()
diff --git a/libs/hwui/Texture.cpp b/libs/hwui/Texture.cpp
index 0dbd767..cfc2744 100644
--- a/libs/hwui/Texture.cpp
+++ b/libs/hwui/Texture.cpp
@@ -241,21 +241,23 @@
     }
 }
 
-SkBitmap Texture::uploadToN32(const SkBitmap& bitmap, bool hasSRGB, sk_sp<SkColorSpace> sRGB) {
+SkBitmap Texture::uploadToN32(const SkBitmap& bitmap, bool hasLinearBlending,
+        sk_sp<SkColorSpace> sRGB) {
     SkBitmap rgbaBitmap;
     rgbaBitmap.allocPixels(SkImageInfo::MakeN32(bitmap.width(), bitmap.height(),
-            bitmap.info().alphaType(), hasSRGB ? sRGB : nullptr));
+            bitmap.info().alphaType(), hasLinearBlending ? sRGB : nullptr));
     rgbaBitmap.eraseColor(0);
     SkCanvas canvas(rgbaBitmap);
     canvas.drawBitmap(bitmap, 0.0f, 0.0f, nullptr);
     return rgbaBitmap;
 }
 
-bool Texture::hasUnsupportedColorType(const SkImageInfo& info, bool hasSRGB, SkColorSpace* sRGB) {
+bool Texture::hasUnsupportedColorType(const SkImageInfo& info, bool hasLinearBlending,
+        SkColorSpace* sRGB) {
     bool needSRGB = info.colorSpace() == sRGB;
     return info.colorType() == kARGB_4444_SkColorType
         || info.colorType() == kIndex_8_SkColorType
-        || (info.colorType() == kRGB_565_SkColorType && hasSRGB && needSRGB);
+        || (info.colorType() == kRGB_565_SkColorType && hasLinearBlending && needSRGB);
 }
 
 
@@ -295,11 +297,11 @@
     mCaches.textureState().bindTexture(mTarget, mId);
 
     // TODO: Handle sRGB gray bitmaps
-    bool hasSRGB = mCaches.extensions().hasSRGB();
-    if (CC_UNLIKELY(hasUnsupportedColorType(bitmap.info(), hasSRGB, sRGB.get()))) {
+    bool hasLinearBlending = mCaches.extensions().hasLinearBlending();
+    if (CC_UNLIKELY(hasUnsupportedColorType(bitmap.info(), hasLinearBlending, sRGB.get()))) {
         SkBitmap skBitmap;
         bitmap.getSkBitmap(&skBitmap);
-        SkBitmap rgbaBitmap = uploadToN32(skBitmap, hasSRGB, std::move(sRGB));
+        SkBitmap rgbaBitmap = uploadToN32(skBitmap, hasLinearBlending, std::move(sRGB));
         uploadToTexture(needsAlloc, internalFormat, format, type, rgbaBitmap.rowBytesAsPixels(),
                 rgbaBitmap.bytesPerPixel(), rgbaBitmap.width(),
                 rgbaBitmap.height(), rgbaBitmap.getPixels());
diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h
index ce9d4dc..e7fbf20 100644
--- a/libs/hwui/Texture.h
+++ b/libs/hwui/Texture.h
@@ -40,8 +40,10 @@
  */
 class Texture : public GpuMemoryTracker {
 public:
-    static SkBitmap uploadToN32(const SkBitmap& bitmap, bool hasSRGB, sk_sp<SkColorSpace> sRGB);
-    static bool hasUnsupportedColorType(const SkImageInfo& info, bool hasSRGB, SkColorSpace* sRGB);
+    static SkBitmap uploadToN32(const SkBitmap& bitmap,
+            bool hasLinearBlending, sk_sp<SkColorSpace> sRGB);
+    static bool hasUnsupportedColorType(const SkImageInfo& info,
+            bool hasLinearBlending, SkColorSpace* sRGB);
     static void colorTypeToGlFormatAndType(const Caches& caches, SkColorType colorType,
             bool needSRGB, GLint* outInternalFormat, GLint* outFormat, GLint* outType);
 
diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h
index a55b061..db4ff39 100644
--- a/libs/hwui/TextureCache.h
+++ b/libs/hwui/TextureCache.h
@@ -19,6 +19,8 @@
 
 #include <SkBitmap.h>
 
+#include <cutils/compiler.h>
+
 #include <utils/LruCache.h>
 #include <utils/Mutex.h>
 
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index f9730c9..72a9f4e 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -30,8 +30,6 @@
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 
-#include <gui/IGraphicBufferAlloc.h>
-#include <gui/ISurfaceComposer.h>
 #include <private/gui/ComposerService.h>
 #include <binder/IServiceManager.h>
 #include <ui/PixelFormat.h>
@@ -219,13 +217,6 @@
     renderThread.eglManager().initialize();
     uirenderer::Caches& caches = uirenderer::Caches::getInstance();
 
-    sp<ISurfaceComposer> composer(ComposerService::getComposerService());
-    sp<IGraphicBufferAlloc> alloc(composer->createGraphicBufferAlloc());
-    if (alloc == NULL) {
-        ALOGW("createGraphicBufferAlloc() failed in GraphicBuffer.create()");
-        return nullptr;
-    }
-
     const SkImageInfo& info = skBitmap.info();
     if (info.colorType() == kUnknown_SkColorType || info.colorType() == kAlpha_8_SkColorType) {
         ALOGW("unable to create hardware bitmap of colortype: %d", info.colorType());
@@ -234,26 +225,28 @@
 
     sk_sp<SkColorSpace> sRGB = SkColorSpace::MakeSRGB();
     bool needSRGB = skBitmap.info().colorSpace() == sRGB.get();
-    bool hasSRGB = caches.extensions().hasSRGB();
+    bool hasLinearBlending = caches.extensions().hasLinearBlending();
     GLint format, type, internalFormat;
     uirenderer::Texture::colorTypeToGlFormatAndType(caches, skBitmap.colorType(),
             needSRGB, &internalFormat, &format, &type);
 
     PixelFormat pixelFormat = internalFormatToPixelFormat(internalFormat);
-    status_t error;
-    sp<GraphicBuffer> buffer = alloc->createGraphicBuffer(info.width(), info.height(), pixelFormat,
-            1, GraphicBuffer::USAGE_HW_TEXTURE | GraphicBuffer::USAGE_SW_WRITE_NEVER
-            | GraphicBuffer::USAGE_SW_READ_NEVER , &error);
+    sp<GraphicBuffer> buffer = new GraphicBuffer(info.width(), info.height(), pixelFormat,
+            GraphicBuffer::USAGE_HW_TEXTURE |
+            GraphicBuffer::USAGE_SW_WRITE_NEVER |
+            GraphicBuffer::USAGE_SW_READ_NEVER,
+            std::string("Bitmap::allocateHardwareBitmap pid [") + std::to_string(getpid()) + "]");
 
-    if (!buffer.get()) {
+    status_t error = buffer->initCheck();
+    if (error < 0) {
         ALOGW("createGraphicBuffer() failed in GraphicBuffer.create()");
         return nullptr;
     }
 
     SkBitmap bitmap;
     if (CC_UNLIKELY(uirenderer::Texture::hasUnsupportedColorType(skBitmap.info(),
-            hasSRGB, sRGB.get()))) {
-        bitmap = uirenderer::Texture::uploadToN32(skBitmap, hasSRGB, std::move(sRGB));
+            hasLinearBlending, sRGB.get()))) {
+        bitmap = uirenderer::Texture::uploadToN32(skBitmap, hasLinearBlending, std::move(sRGB));
     } else {
         bitmap = skBitmap;
     }
diff --git a/libs/hwui/hwui/Canvas.cpp b/libs/hwui/hwui/Canvas.cpp
index 2dc8ce8..c64a89d 100644
--- a/libs/hwui/hwui/Canvas.cpp
+++ b/libs/hwui/hwui/Canvas.cpp
@@ -45,7 +45,7 @@
     } else {
         flags = paint.getFlags();
     }
-    if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) {
+    if (flags & (SkPaint::kUnderlineText_ReserveFlag | SkPaint::kStrikeThruText_ReserveFlag)) {
         // Same values used by Skia
         const float kStdStrikeThru_Offset   = (-6.0f / 21.0f);
         const float kStdUnderline_Offset    = (1.0f / 9.0f);
@@ -55,12 +55,12 @@
         SkScalar right = x + length;
         float textSize = paint.getTextSize();
         float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f);
-        if (flags & SkPaint::kUnderlineText_Flag) {
+        if (flags & SkPaint::kUnderlineText_ReserveFlag) {
             SkScalar top = y + textSize * kStdUnderline_Offset - 0.5f * strokeWidth;
             SkScalar bottom = y + textSize * kStdUnderline_Offset + 0.5f * strokeWidth;
             drawRect(left, top, right, bottom, paint);
         }
-        if (flags & SkPaint::kStrikeThruText_Flag) {
+        if (flags & SkPaint::kStrikeThruText_ReserveFlag) {
             SkScalar top = y + textSize * kStdStrikeThru_Offset - 0.5f * strokeWidth;
             SkScalar bottom = y + textSize * kStdStrikeThru_Offset + 0.5f * strokeWidth;
             drawRect(left, top, right, bottom, paint);
@@ -153,8 +153,8 @@
     // minikin may modify the original paint
     Paint paint(origPaint);
 
-    minikin::Layout layout;
-    MinikinUtils::doLayout(&layout, &paint, bidiFlags, typeface, text, start, count, contextCount);
+    minikin::Layout layout = MinikinUtils::doLayout(
+            &paint, bidiFlags, typeface, text, start, count, contextCount);
 
     size_t nGlyphs = layout.nGlyphs();
     std::unique_ptr<uint16_t[]> glyphs(new uint16_t[nGlyphs]);
@@ -205,8 +205,8 @@
 void Canvas::drawTextOnPath(const uint16_t* text, int count, int bidiFlags, const SkPath& path,
         float hOffset, float vOffset, const Paint& paint, Typeface* typeface) {
     Paint paintCopy(paint);
-    minikin::Layout layout;
-    MinikinUtils::doLayout(&layout, &paintCopy, bidiFlags, typeface, text, 0, count, count);
+    minikin::Layout layout = MinikinUtils::doLayout(
+            &paintCopy, bidiFlags, typeface, text, 0, count, count);
     hOffset += MinikinUtils::hOffsetForTextAlign(&paintCopy, layout, path);
 
     // Set align to left for drawing, as we don't want individual
diff --git a/libs/hwui/hwui/MinikinSkia.cpp b/libs/hwui/hwui/MinikinSkia.cpp
index 6a00379..ba4e3a4 100644
--- a/libs/hwui/hwui/MinikinSkia.cpp
+++ b/libs/hwui/hwui/MinikinSkia.cpp
@@ -25,9 +25,9 @@
 namespace android {
 
 MinikinFontSkia::MinikinFontSkia(sk_sp<SkTypeface> typeface, const void* fontData, size_t fontSize,
-        int ttcIndex) :
+        int ttcIndex, const std::vector<minikin::FontVariation>& axes) :
     minikin::MinikinFont(typeface->uniqueID()), mTypeface(std::move(typeface)), mFontData(fontData),
-    mFontSize(fontSize), mTtcIndex(ttcIndex) {
+    mFontSize(fontSize), mTtcIndex(ttcIndex), mAxes(axes) {
 }
 
 static void MinikinFontSkia_SetSkiaPaint(const minikin::MinikinFont* font, SkPaint* skPaint,
@@ -87,7 +87,11 @@
     return mTtcIndex;
 }
 
-minikin::MinikinFont* MinikinFontSkia::createFontWithVariation(
+const std::vector<minikin::FontVariation>& MinikinFontSkia::GetAxes() const {
+    return mAxes;
+}
+
+std::shared_ptr<minikin::MinikinFont> MinikinFontSkia::createFontWithVariation(
         const std::vector<minikin::FontVariation>& variations) const {
     SkFontMgr::FontParameters params;
 
@@ -106,7 +110,8 @@
     sk_sp<SkFontMgr> fm(SkFontMgr::RefDefault());
     sk_sp<SkTypeface> face(fm->createFromStream(stream, params));
 
-    return new MinikinFontSkia(std::move(face), mFontData, mFontSize, ttcIndex);
+    return std::make_shared<MinikinFontSkia>(std::move(face), mFontData, mFontSize, ttcIndex,
+            variations);
 }
 
 uint32_t MinikinFontSkia::packPaintFlags(const SkPaint* paint) {
diff --git a/libs/hwui/hwui/MinikinSkia.h b/libs/hwui/hwui/MinikinSkia.h
index 249b0cb..6c12485 100644
--- a/libs/hwui/hwui/MinikinSkia.h
+++ b/libs/hwui/hwui/MinikinSkia.h
@@ -29,7 +29,7 @@
 class ANDROID_API MinikinFontSkia : public minikin::MinikinFont {
 public:
     explicit MinikinFontSkia(sk_sp<SkTypeface> typeface, const void* fontData, size_t fontSize,
-        int ttcIndex);
+        int ttcIndex, const std::vector<minikin::FontVariation>& axes);
 
     float GetHorizontalAdvance(uint32_t glyph_id,
         const minikin::MinikinPaint &paint) const;
@@ -44,7 +44,8 @@
     const void* GetFontData() const;
     size_t GetFontSize() const;
     int GetFontIndex() const;
-    minikin::MinikinFont* createFontWithVariation(
+    const std::vector<minikin::FontVariation>& GetAxes() const;
+    std::shared_ptr<minikin::MinikinFont> createFontWithVariation(
             const std::vector<minikin::FontVariation>&) const;
 
     static uint32_t packPaintFlags(const SkPaint* paint);
@@ -61,6 +62,7 @@
     const void* mFontData;
     size_t mFontSize;
     int mTtcIndex;
+    std::vector<minikin::FontVariation> mAxes;
 };
 
 }  // namespace android
diff --git a/libs/hwui/hwui/MinikinUtils.cpp b/libs/hwui/hwui/MinikinUtils.cpp
index 713e509..d1871ff 100644
--- a/libs/hwui/hwui/MinikinUtils.cpp
+++ b/libs/hwui/hwui/MinikinUtils.cpp
@@ -27,9 +27,8 @@
 namespace android {
 
 minikin::FontStyle MinikinUtils::prepareMinikinPaint(minikin::MinikinPaint* minikinPaint,
-        minikin::FontCollection** pFont, const Paint* paint, Typeface* typeface) {
+        const Paint* paint, Typeface* typeface) {
     const Typeface* resolvedFace = Typeface::resolveDefault(typeface);
-    *pFont = resolvedFace->fFontCollection;
     minikin::FontStyle resolved = resolvedFace->fStyle;
 
     /* Prepare minikin FontStyle */
@@ -54,23 +53,23 @@
     return minikinStyle;
 }
 
-void MinikinUtils::doLayout(minikin::Layout* layout, const Paint* paint, int bidiFlags,
+minikin::Layout MinikinUtils::doLayout(const Paint* paint, int bidiFlags,
         Typeface* typeface, const uint16_t* buf, size_t start, size_t count,
         size_t bufSize) {
-    minikin::FontCollection *font;
     minikin::MinikinPaint minikinPaint;
-    minikin::FontStyle minikinStyle = prepareMinikinPaint(&minikinPaint, &font, paint, typeface);
-    layout->setFontCollection(font);
-    layout->doLayout(buf, start, count, bufSize, bidiFlags, minikinStyle, minikinPaint);
+    minikin::FontStyle minikinStyle = prepareMinikinPaint(&minikinPaint, paint, typeface);
+    minikin::Layout layout(Typeface::resolveDefault(typeface)->fFontCollection);
+    layout.doLayout(buf, start, count, bufSize, bidiFlags, minikinStyle, minikinPaint);
+    return layout;
 }
 
 float MinikinUtils::measureText(const Paint* paint, int bidiFlags, Typeface* typeface,
         const uint16_t* buf, size_t start, size_t count, size_t bufSize, float *advances) {
-    minikin::FontCollection *font;
     minikin::MinikinPaint minikinPaint;
-    minikin::FontStyle minikinStyle = prepareMinikinPaint(&minikinPaint, &font, paint, typeface);
+    minikin::FontStyle minikinStyle = prepareMinikinPaint(&minikinPaint, paint, typeface);
+    Typeface* resolvedTypeface = Typeface::resolveDefault(typeface);
     return minikin::Layout::measureText(buf, start, count, bufSize, bidiFlags, minikinStyle,
-            minikinPaint, font, advances);
+            minikinPaint, resolvedTypeface->fFontCollection, advances);
 }
 
 bool MinikinUtils::hasVariationSelector(Typeface* typeface, uint32_t codepoint, uint32_t vs) {
diff --git a/libs/hwui/hwui/MinikinUtils.h b/libs/hwui/hwui/MinikinUtils.h
index d6f64d2..0f22adc 100644
--- a/libs/hwui/hwui/MinikinUtils.h
+++ b/libs/hwui/hwui/MinikinUtils.h
@@ -35,9 +35,9 @@
 class MinikinUtils {
 public:
     ANDROID_API static minikin::FontStyle prepareMinikinPaint(minikin::MinikinPaint* minikinPaint,
-            minikin::FontCollection** pFont, const Paint* paint, Typeface* typeface);
+            const Paint* paint, Typeface* typeface);
 
-    ANDROID_API static void doLayout(minikin::Layout* layout, const Paint* paint, int bidiFlags,
+    ANDROID_API static minikin::Layout doLayout(const Paint* paint, int bidiFlags,
             Typeface* typeface, const uint16_t* buf, size_t start, size_t count,
             size_t bufSize);
 
@@ -56,11 +56,11 @@
     ANDROID_API static void forFontRun(const minikin::Layout& layout, Paint* paint, F& f) {
         float saveSkewX = paint->getTextSkewX();
         bool savefakeBold = paint->isFakeBoldText();
-        minikin::MinikinFont* curFont = NULL;
+        const minikin::MinikinFont* curFont = nullptr;
         size_t start = 0;
         size_t nGlyphs = layout.nGlyphs();
         for (size_t i = 0; i < nGlyphs; i++) {
-          minikin::MinikinFont* nextFont = layout.getFont(i);
+            const minikin::MinikinFont* nextFont = layout.getFont(i);
             if (i > 0 && nextFont != curFont) {
                 MinikinFontSkia::populateSkPaint(paint, curFont, layout.getFakery(start));
                 f(start, i);
diff --git a/libs/hwui/hwui/Typeface.cpp b/libs/hwui/hwui/Typeface.cpp
index b69b0cb..4b8575a 100644
--- a/libs/hwui/hwui/Typeface.cpp
+++ b/libs/hwui/hwui/Typeface.cpp
@@ -64,7 +64,6 @@
     Typeface* result = new Typeface;
     if (result != nullptr) {
         result->fFontCollection = resolvedFace->fFontCollection;
-        result->fFontCollection->Ref();
         result->fSkiaStyle = style;
         result->fBaseWeight = resolvedFace->fBaseWeight;
         resolveStyle(result);
@@ -83,7 +82,6 @@
             // None of passed axes are supported by this collection.
             // So we will reuse the same collection with incrementing reference count.
             result->fFontCollection = resolvedFace->fFontCollection;
-            result->fFontCollection->Ref();
         }
         result->fSkiaStyle = resolvedFace->fSkiaStyle;
         result->fBaseWeight = resolvedFace->fBaseWeight;
@@ -97,7 +95,6 @@
     Typeface* result = new Typeface;
     if (result != nullptr) {
         result->fFontCollection = resolvedFace->fFontCollection;
-        result->fFontCollection->Ref();
         result->fSkiaStyle = resolvedFace->fSkiaStyle;
         result->fBaseWeight = weight;
         resolveStyle(result);
@@ -105,18 +102,19 @@
     return result;
 }
 
-Typeface* Typeface::createFromFamilies(const std::vector<minikin::FontFamily*>& families) {
+Typeface* Typeface::createFromFamilies(
+        std::vector<std::shared_ptr<minikin::FontFamily>>&& families) {
     Typeface* result = new Typeface;
-    result->fFontCollection = new minikin::FontCollection(families);
+    result->fFontCollection.reset(new minikin::FontCollection(families));
     if (families.empty()) {
         ALOGW("createFromFamilies creating empty collection");
         result->fSkiaStyle = SkTypeface::kNormal;
     } else {
         const minikin::FontStyle defaultStyle;
-        minikin::FontFamily* firstFamily = reinterpret_cast<minikin::FontFamily*>(families[0]);
-        minikin::MinikinFont* mf = firstFamily->getClosestMatch(defaultStyle).font;
-        if (mf != NULL) {
-            SkTypeface* skTypeface = reinterpret_cast<MinikinFontSkia*>(mf)->GetSkTypeface();
+        const std::shared_ptr<minikin::FontFamily>& firstFamily = families[0];
+        const minikin::MinikinFont* mf = firstFamily->getClosestMatch(defaultStyle).font;
+        if (mf != nullptr) {
+            SkTypeface* skTypeface = reinterpret_cast<const MinikinFontSkia*>(mf)->GetSkTypeface();
             // TODO: probably better to query more precise style from family, will be important
             // when we open up API to access 100..900 weights
             result->fSkiaStyle = skTypeface->style();
@@ -129,11 +127,6 @@
     return result;
 }
 
-void Typeface::unref() {
-    fFontCollection->Unref();
-    delete this;
-}
-
 void Typeface::setDefault(Typeface* face) {
     gDefaultTypeface = face;
 }
@@ -150,14 +143,12 @@
     sk_sp<SkTypeface> typeface = SkTypeface::MakeFromStream(fontData.release());
     LOG_ALWAYS_FATAL_IF(typeface == nullptr, "Failed to make typeface from %s", kRobotoFont);
 
-    minikin::MinikinFont* font = new MinikinFontSkia(std::move(typeface), data, st.st_size, 0);
-    minikin::FontFamily* family = new minikin::FontFamily(
-                 std::vector<minikin::Font>({ minikin::Font(font, minikin::FontStyle()) }));
-    font->Unref();
-
-    std::vector<minikin::FontFamily*> typefaces = { family };
-    minikin::FontCollection *collection = new minikin::FontCollection(typefaces);
-    family->Unref();
+    std::shared_ptr<minikin::MinikinFont> font = std::make_shared<MinikinFontSkia>(
+            std::move(typeface), data, st.st_size, 0, std::vector<minikin::FontVariation>());
+    std::shared_ptr<minikin::FontFamily> family = std::make_shared<minikin::FontFamily>(
+            std::vector<minikin::Font>({ minikin::Font(std::move(font), minikin::FontStyle()) }));
+    std::shared_ptr<minikin::FontCollection> collection =
+            std::make_shared<minikin::FontCollection>(std::move(family));
 
     Typeface* hwTypeface = new Typeface();
     hwTypeface->fFontCollection = collection;
diff --git a/libs/hwui/hwui/Typeface.h b/libs/hwui/hwui/Typeface.h
index 4392ebc..19a4f6c5 100644
--- a/libs/hwui/hwui/Typeface.h
+++ b/libs/hwui/hwui/Typeface.h
@@ -23,11 +23,12 @@
 #include <cutils/compiler.h>
 #include <minikin/FontCollection.h>
 #include <vector>
+#include <memory>
 
 namespace android {
 
 struct ANDROID_API Typeface {
-  minikin::FontCollection *fFontCollection;
+    std::shared_ptr<minikin::FontCollection> fFontCollection;
 
     // style used for constructing and querying Typeface objects
     SkTypeface::Style fSkiaStyle;
@@ -37,8 +38,6 @@
     // resolved style actually used for rendering
     minikin::FontStyle fStyle;
 
-    void unref();
-
     static Typeface* resolveDefault(Typeface* src);
 
     static Typeface* createFromTypeface(Typeface* src, SkTypeface::Style style);
@@ -48,7 +47,8 @@
 
     static Typeface* createWeightAlias(Typeface* src, int baseweight);
 
-    static Typeface* createFromFamilies(const std::vector<minikin::FontFamily*>& families);
+    static Typeface* createFromFamilies(
+            std::vector<std::shared_ptr<minikin::FontFamily>>&& families);
 
     static void setDefault(Typeface* face);
 
diff --git a/libs/hwui/hwui_static_deps.mk b/libs/hwui/hwui_static_deps.mk
index a75fd6a..8826cfc 100644
--- a/libs/hwui/hwui_static_deps.mk
+++ b/libs/hwui/hwui_static_deps.mk
@@ -22,11 +22,12 @@
     libskia \
     libui \
     libgui \
-    libprotobuf-cpp-lite \
+    libprotobuf-cpp-full \
     libharfbuzz_ng \
     libft2 \
     libminikin \
-    libandroidfw
+    libandroidfw \
+    libRScpp
 
-# enable RENDERSCRIPT
-LOCAL_SHARED_LIBRARIES += libRScpp
+LOCAL_STATIC_LIBRARIES += \
+    libplatformprotos
diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
index 117395b..39f11b8 100644
--- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
+++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
@@ -197,12 +197,12 @@
             if (needsLayer) {
                 canvas->saveLayer(bounds, &paint);
             }
-            canvas->drawDrawable(displayList->mDrawable.get());
+            displayList->draw(canvas);
             if (needsLayer) {
                 canvas->restore();
             }
         } else {
-            canvas->drawDrawable(displayList->mDrawable.get());
+            displayList->draw(canvas);
         }
     }
 }
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
index b4babcb..496f7ba 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
@@ -27,10 +27,6 @@
 namespace uirenderer {
 namespace skiapipeline {
 
-SkiaDisplayList::SkiaDisplayList(SkRect bounds) : mDrawable(SkLiteDL::New(bounds)) {
-    SkASSERT(projectionReceiveIndex == -1);
-}
-
 void SkiaDisplayList::syncContents() {
     for (auto& functor : mChildFunctors) {
         functor.syncFunctor();
@@ -41,7 +37,7 @@
 }
 
 bool SkiaDisplayList::reuseDisplayList(RenderNode* node, renderthread::CanvasContext* context) {
-    reset(SkRect::MakeEmpty());
+    reset();
     node->attachAvailableList(this);
     return true;
 }
@@ -102,10 +98,10 @@
     return isDirty;
 }
 
-void SkiaDisplayList::reset(SkRect bounds) {
+void SkiaDisplayList::reset() {
     mProjectionReceiver = nullptr;
 
-    mDrawable->reset(bounds);
+    mDisplayList.reset();
 
     mMutableImages.clear();
     mVectorDrawables.clear();
@@ -119,7 +115,7 @@
 
 void SkiaDisplayList::output(std::ostream& output, uint32_t level) {
     DumpOpsCanvas canvas(output, level, *this);
-    mDrawable->draw(&canvas, nullptr);
+    mDisplayList.draw(&canvas);
 }
 
 }; // namespace skiapipeline
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.h b/libs/hwui/pipeline/skia/SkiaDisplayList.h
index 439b999..6ee5922 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.h
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.h
@@ -22,7 +22,7 @@
 
 #include <deque>
 #include <SkLiteDL.h>
-#include <SkPictureRecorder.h>
+#include <SkLiteRecorder.h>
 
 namespace android {
 namespace uirenderer {
@@ -39,22 +39,22 @@
  */
 class SkiaDisplayList : public DisplayList {
 public:
-    SkiaDisplayList(SkRect bounds);
+    SkiaDisplayList() { SkASSERT(projectionReceiveIndex == -1); }
     virtual ~SkiaDisplayList() {
         /* Given that we are using a LinearStdAllocator to store some of the
          * SkDrawable contents we must ensure that any other object that is
          * holding a reference to those drawables is destroyed prior to their
          * deletion.
          */
-        mDrawable.reset();
+        mDisplayList.reset();
     }
 
     /**
      * This resets the DisplayList so that it behaves as if the object were newly
-     * constructed with the provided bounds.  The reuse avoids any overhead
-     * associated with destroying the SkLiteDL as well as the deques and vectors.
+     * constructed.  The reuse avoids any overhead associated with destroying
+     * the SkLiteDL as well as the deques and vectors.
      */
-    void reset(SkRect bounds);
+    void reset();
 
     /**
      * Use the linear allocator to create any SkDrawables needed by the display
@@ -72,7 +72,7 @@
     /**
      * Returns true if the DisplayList does not have any recorded content
      */
-    bool isEmpty() const override { return mDrawable->empty(); }
+    bool isEmpty() const override { return mDisplayList.empty(); }
 
     /**
      * Returns true if this list directly contains a GLFunctor drawing command.
@@ -126,18 +126,24 @@
      */
     inline bool containsProjectionReceiver() const { return mProjectionReceiver; }
 
+    void attachRecorder(SkLiteRecorder* recorder, const SkIRect& bounds) {
+        recorder->reset(&mDisplayList, bounds);
+    }
+
+    void draw(SkCanvas* canvas) { mDisplayList.draw(canvas); }
+
     void output(std::ostream& output, uint32_t level) override;
 
     /**
      * We use std::deque here because (1) we need to iterate through these
-     * elements and (2) mDrawable holds pointers to the elements, so they cannot
-     * relocate.
+     * elements and (2) mDisplayList holds pointers to the elements, so they
+     * cannot relocate.
      */
     std::deque<RenderNodeDrawable> mChildNodes;
     std::deque<GLFunctorDrawable> mChildFunctors;
     std::vector<SkImage*> mMutableImages;
     std::vector<VectorDrawableRoot*> mVectorDrawables;
-    sk_sp<SkLiteDL> mDrawable;
+    SkLiteDL mDisplayList;
 
     //mProjectionReceiver points to a child node (stored in mChildNodes) that is as a projection
     //receiver. It is set at record time and used at both prepare and draw tree traversals to
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index f2b0eb3..ae13131 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -26,7 +26,6 @@
 #include "SkiaProfileRenderer.h"
 #include "utils/TraceUtils.h"
 
-#include <android/native_window.h>
 #include <cutils/properties.h>
 #include <strings.h>
 
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 430d6be..11dc1f4 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -80,7 +80,7 @@
 void SkiaPipeline::renderLayersImpl(const LayerUpdateQueue& layers, bool opaque) {
     // Render all layers that need to be updated, in order.
     for (size_t i = 0; i < layers.entries().size(); i++) {
-        RenderNode* layerNode = layers.entries()[i].renderNode;
+        RenderNode* layerNode = layers.entries()[i].renderNode.get();
         // only schedule repaint if node still on layer - possible it may have been
         // removed during a dropped frame, but layers may still remain scheduled so
         // as not to lose info on what portion is damaged
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index dbe0296..559d268 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -39,14 +39,11 @@
     if (renderNode) {
         mDisplayList = renderNode->detachAvailableList();
     }
-    SkRect bounds = SkRect::MakeWH(width, height);
-    if (mDisplayList) {
-        mDisplayList->reset(bounds);
-    } else {
-        mDisplayList.reset(new SkiaDisplayList(bounds));
+    if (!mDisplayList) {
+        mDisplayList.reset(new SkiaDisplayList());
     }
 
-    mRecorder.reset(mDisplayList->mDrawable.get());
+    mDisplayList->attachRecorder(&mRecorder, SkIRect::MakeWH(width, height));
     SkiaCanvas::reset(&mRecorder);
 }
 
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index c63dce1..d28e605 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -31,7 +31,6 @@
 #include <GrTypes.h>
 #include <vk/GrVkTypes.h>
 
-#include <android/native_window.h>
 #include <cutils/properties.h>
 #include <strings.h>
 
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
index 7dfc2ee..8bce990 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -174,13 +174,15 @@
     meshState().disableTexCoordsVertexArray();
     debugOverdraw(false, false);
     // TODO: We need a way to know whether the functor is sRGB aware (b/32072673)
-    if (mCaches->extensions().hasSRGBWriteControl()) {
+    if (mCaches->extensions().hasLinearBlending() &&
+            mCaches->extensions().hasSRGBWriteControl()) {
         glDisable(GL_FRAMEBUFFER_SRGB_EXT);
     }
 }
 
 void RenderState::resumeFromFunctorInvoke() {
-    if (mCaches->extensions().hasSRGBWriteControl()) {
+    if (mCaches->extensions().hasLinearBlending() &&
+            mCaches->extensions().hasSRGBWriteControl()) {
         glEnable(GL_FRAMEBUFFER_SRGB_EXT);
     }
 
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index a53e5e0..02a9ffa 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -590,6 +590,7 @@
 }
 
 void CanvasContext::dumpFrames(int fd) {
+    mJankTracker.dump(fd);
     FILE* file = fdopen(fd, "a");
     fprintf(file, "\n\n---PROFILEDATA---\n");
     for (size_t i = 0; i < static_cast<size_t>(FrameInfoIndex::NumIndexes); i++) {
@@ -615,6 +616,10 @@
     mRenderThread.jankTracker().reset();
 }
 
+void CanvasContext::setName(const std::string&& name) {
+    mJankTracker.setDescription(JankTrackerType::Window, std::move(name));
+}
+
 void CanvasContext::serializeDisplayListTree() {
 #if ENABLE_RENDERNODE_SERIALIZATION
     using namespace google::protobuf::io;
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index aa01caa..738c091 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -155,8 +155,7 @@
     void dumpFrames(int fd);
     void resetFrameStats();
 
-    void setName(const std::string&& name) { mName = name; }
-    const std::string& name() { return mName; }
+    void setName(const std::string&& name);
 
     void serializeDisplayListTree();
 
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 7020be0..44af5fd 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -106,7 +106,10 @@
 
     // Now that extensions are loaded, pick a swap behavior
     if (Properties::enablePartialUpdates) {
-        if (Properties::useBufferAge && EglExtensions.bufferAge) {
+        // An Adreno driver bug is causing rendering problems for SkiaGL with
+        // buffer age swap behavior (b/31957043).  To temporarily workaround,
+        // we will use preserved swap behavior.
+        if (Properties::useBufferAge && EglExtensions.bufferAge && !Properties::isSkiaEnabled()) {
             mSwapBehavior = SwapBehavior::BufferAge;
         } else {
             mSwapBehavior = SwapBehavior::Preserved;
@@ -130,7 +133,7 @@
         LOG_ALWAYS_FATAL_IF(!glInterface.get());
 
         GrContextOptions options;
-        options.fDisableDistanceFieldPaths = true;
+        options.fGpuPathRenderers &= ~GrContextOptions::GpuPathRenderers::kDistanceField;
         options.fAllowPathMaskCaching = true;
         mRenderThread.setGrContext(GrContext::Create(GrBackend::kOpenGL_GrBackend,
                 (GrBackendContext)glInterface.get(), options));
diff --git a/libs/hwui/renderthread/OpenGLPipeline.cpp b/libs/hwui/renderthread/OpenGLPipeline.cpp
index acd6110..e1ae585 100644
--- a/libs/hwui/renderthread/OpenGLPipeline.cpp
+++ b/libs/hwui/renderthread/OpenGLPipeline.cpp
@@ -24,7 +24,6 @@
 #include "renderstate/RenderState.h"
 #include "OpenGLReadback.h"
 
-#include <android/native_window.h>
 #include <cutils/properties.h>
 #include <strings.h>
 
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 11614fa..a1f1717 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -487,9 +487,22 @@
 
 void RenderProxy::setProcessStatsBuffer(int fd) {
     SETUP_TASK(setProcessStatsBuffer);
-    args->thread = &mRenderThread;
+    auto& rt = RenderThread::getInstance();
+    args->thread = &rt;
     args->fd = dup(fd);
-    post(task);
+    rt.queue(task);
+}
+
+CREATE_BRIDGE1(rotateProcessStatsBuffer, RenderThread* thread) {
+    args->thread->jankTracker().rotateStorage();
+    return nullptr;
+}
+
+void RenderProxy::rotateProcessStatsBuffer() {
+    SETUP_TASK(rotateProcessStatsBuffer);
+    auto& rt = RenderThread::getInstance();
+    args->thread = &rt;
+    rt.queue(task);
 }
 
 int RenderProxy::getRenderThreadTid() {
@@ -690,7 +703,9 @@
     SignalingRenderTask syncTask(task, &mSyncMutex, &mSyncCondition);
     AutoMutex _lock(mSyncMutex);
     mRenderThread.queue(&syncTask);
-    mSyncCondition.wait(mSyncMutex);
+    while (!syncTask.hasRun()) {
+        mSyncCondition.wait(mSyncMutex);
+    }
     return retval;
 }
 
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 1629090..a60ed55 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -113,7 +113,8 @@
     uint32_t frameTimePercentile(int p);
     ANDROID_API static void dumpGraphicsMemory(int fd);
 
-    ANDROID_API void setProcessStatsBuffer(int fd);
+    ANDROID_API static void rotateProcessStatsBuffer();
+    ANDROID_API static void setProcessStatsBuffer(int fd);
     ANDROID_API int getRenderThreadTid();
 
     ANDROID_API void serializeDisplayListTree();
diff --git a/libs/hwui/renderthread/RenderTask.cpp b/libs/hwui/renderthread/RenderTask.cpp
index b14f580..928a4ef 100644
--- a/libs/hwui/renderthread/RenderTask.cpp
+++ b/libs/hwui/renderthread/RenderTask.cpp
@@ -26,6 +26,7 @@
 void SignalingRenderTask::run() {
     mTask->run();
     mLock->lock();
+    mHasRun = true;
     mSignal->signal();
     mLock->unlock();
 }
diff --git a/libs/hwui/renderthread/RenderTask.h b/libs/hwui/renderthread/RenderTask.h
index 9ea671b..a7acf91 100644
--- a/libs/hwui/renderthread/RenderTask.h
+++ b/libs/hwui/renderthread/RenderTask.h
@@ -60,13 +60,15 @@
 public:
     // Takes ownership of task, caller owns lock and signal
     SignalingRenderTask(RenderTask* task, Mutex* lock, Condition* signal)
-            : mTask(task), mLock(lock), mSignal(signal) {}
+            : mTask(task), mLock(lock), mSignal(signal), mHasRun(false) {}
     virtual void run() override;
+    bool hasRun() const { return mHasRun; }
 
 private:
     RenderTask* mTask;
     Mutex* mLock;
     Condition* mSignal;
+    bool mHasRun;
 };
 
 typedef void* (*RunnableMethod)(void* data);
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index e13d0ce..e32fd63 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -374,7 +374,9 @@
 
     AutoMutex _lock(mutex);
     queue(&syncTask);
-    condition.wait(mutex);
+    while (!syncTask.hasRun()) {
+        condition.wait(mutex);
+    }
 }
 
 void RenderThread::queueAtFront(RenderTask* task) {
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index d121bcf..9bc5985 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -74,6 +74,7 @@
 };
 
 class ANDROID_API RenderThread : public Thread {
+    PREVENT_COPY_AND_ASSIGN(RenderThread);
 public:
     // RenderThread takes complete ownership of tasks that are queued
     // and will delete them after they are run
diff --git a/libs/hwui/service/GraphicsStatsService.cpp b/libs/hwui/service/GraphicsStatsService.cpp
new file mode 100644
index 0000000..ab6420e
--- /dev/null
+++ b/libs/hwui/service/GraphicsStatsService.cpp
@@ -0,0 +1,287 @@
+/*
+ * 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.
+ */
+
+#include "GraphicsStatsService.h"
+
+#include "JankTracker.h"
+
+#include <frameworks/base/core/proto/android/service/graphicsstats.pb.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <log/log.h>
+
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+namespace android {
+namespace uirenderer {
+
+using namespace google::protobuf;
+
+constexpr int32_t sCurrentFileVersion = 1;
+constexpr int32_t sHeaderSize = 4;
+static_assert(sizeof(sCurrentFileVersion) == sHeaderSize, "Header size is wrong");
+
+constexpr int sHistogramSize =
+        std::tuple_size<decltype(ProfileData::frameCounts)>::value +
+        std::tuple_size<decltype(ProfileData::slowFrameCounts)>::value;
+
+static void mergeProfileDataIntoProto(service::GraphicsStatsProto* proto,
+        const std::string& package, int versionCode, int64_t startTime, int64_t endTime,
+        const ProfileData* data);
+static void dumpAsTextToFd(service::GraphicsStatsProto* proto, int outFd);
+
+bool GraphicsStatsService::parseFromFile(const std::string& path, service::GraphicsStatsProto* output) {
+
+    int fd = open(path.c_str(), O_RDONLY);
+    if (fd == -1) {
+        int err = errno;
+        // The file not existing is normal for addToDump(), so only log if
+        // we get an unexpected error
+        if (err != ENOENT) {
+            ALOGW("Failed to open '%s', errno=%d (%s)", path.c_str(), err, strerror(err));
+        }
+        return false;
+    }
+    uint32_t file_version;
+    ssize_t bytesRead = read(fd, &file_version, sHeaderSize);
+    if (bytesRead != sHeaderSize || file_version != sCurrentFileVersion) {
+        ALOGW("Failed to read '%s', bytesRead=%zd file_version=%d", path.c_str(), bytesRead,
+                file_version);
+        close(fd);
+        return false;
+    }
+
+    io::FileInputStream input(fd);
+    bool success = output->ParseFromZeroCopyStream(&input);
+    if (input.GetErrno() != 0) {
+        ALOGW("Error reading from fd=%d, path='%s' err=%d (%s)",
+                fd, path.c_str(), input.GetErrno(), strerror(input.GetErrno()));
+        success = false;
+    } else if (!success) {
+        ALOGW("Parse failed on '%s' error='%s'",
+                path.c_str(), output->InitializationErrorString().c_str());
+    }
+    close(fd);
+    return success;
+}
+
+void mergeProfileDataIntoProto(service::GraphicsStatsProto* proto, const std::string& package,
+        int versionCode, int64_t startTime, int64_t endTime, const ProfileData* data) {
+    if (proto->stats_start() == 0 || proto->stats_start() > startTime) {
+        proto->set_stats_start(startTime);
+    }
+    if (proto->stats_end() == 0 || proto->stats_end() < endTime) {
+        proto->set_stats_end(endTime);
+    }
+    proto->set_package_name(package);
+    proto->set_version_code(versionCode);
+    auto summary = proto->mutable_summary();
+    summary->set_total_frames(summary->total_frames() + data->totalFrameCount);
+    summary->set_janky_frames(summary->janky_frames() + data->jankFrameCount);
+    summary->set_missed_vsync_count(
+            summary->missed_vsync_count() + data->jankTypeCounts[kMissedVsync]);
+    summary->set_high_input_latency_count(
+            summary->high_input_latency_count() + data->jankTypeCounts[kHighInputLatency]);
+    summary->set_slow_ui_thread_count(
+            summary->slow_ui_thread_count() + data->jankTypeCounts[kSlowUI]);
+    summary->set_slow_bitmap_upload_count(
+            summary->slow_bitmap_upload_count() + data->jankTypeCounts[kSlowSync]);
+    summary->set_slow_draw_count(
+            summary->slow_draw_count() + data->jankTypeCounts[kSlowRT]);
+
+    bool creatingHistogram = false;
+    if (proto->histogram_size() == 0) {
+        proto->mutable_histogram()->Reserve(sHistogramSize);
+        creatingHistogram = true;
+    } else if (proto->histogram_size() != sHistogramSize) {
+        LOG_ALWAYS_FATAL("Histogram size mismatch, proto is %d expected %d",
+                proto->histogram_size(), sHistogramSize);
+    }
+    for (size_t i = 0; i < data->frameCounts.size(); i++) {
+        service::GraphicsStatsHistogramBucketProto* bucket;
+        int32_t renderTime = JankTracker::frameTimeForFrameCountIndex(i);
+        if (creatingHistogram) {
+            bucket = proto->add_histogram();
+            bucket->set_render_millis(renderTime);
+        } else {
+            bucket = proto->mutable_histogram(i);
+            LOG_ALWAYS_FATAL_IF(bucket->render_millis() != renderTime,
+                    "Frame time mistmatch %d vs. %d", bucket->render_millis(), renderTime);
+        }
+        bucket->set_frame_count(bucket->frame_count() + data->frameCounts[i]);
+    }
+    for (size_t i = 0; i < data->slowFrameCounts.size(); i++) {
+        service::GraphicsStatsHistogramBucketProto* bucket;
+        int32_t renderTime = JankTracker::frameTimeForSlowFrameCountIndex(i);
+        if (creatingHistogram) {
+            bucket = proto->add_histogram();
+            bucket->set_render_millis(renderTime);
+        } else {
+            constexpr int offset = std::tuple_size<decltype(ProfileData::frameCounts)>::value;
+            bucket = proto->mutable_histogram(offset + i);
+            LOG_ALWAYS_FATAL_IF(bucket->render_millis() != renderTime,
+                    "Frame time mistmatch %d vs. %d", bucket->render_millis(), renderTime);
+        }
+        bucket->set_frame_count(bucket->frame_count() + data->slowFrameCounts[i]);
+    }
+}
+
+static int32_t findPercentile(service::GraphicsStatsProto* proto, int percentile) {
+    int32_t pos = percentile * proto->summary().total_frames() / 100;
+    int32_t remaining = proto->summary().total_frames() - pos;
+    for (auto it = proto->histogram().rbegin(); it != proto->histogram().rend(); ++it) {
+        remaining -= it->frame_count();
+        if (remaining <= 0) {
+            return it->render_millis();
+        }
+    }
+    return 0;
+}
+
+void dumpAsTextToFd(service::GraphicsStatsProto* proto, int fd) {
+    // This isn't a full validation, just enough that we can deref at will
+    LOG_ALWAYS_FATAL_IF(proto->package_name().empty()
+            || !proto->has_summary(), "package_name() '%s' summary %d",
+            proto->package_name().c_str(), proto->has_summary());
+    dprintf(fd, "\nPackage: %s", proto->package_name().c_str());
+    dprintf(fd, "\nVersion: %d", proto->version_code());
+    dprintf(fd, "\nStats since: %lldns", proto->stats_start());
+    dprintf(fd, "\nStats end: %lldns", proto->stats_end());
+    auto summary = proto->summary();
+    dprintf(fd, "\nTotal frames rendered: %d", summary.total_frames());
+    dprintf(fd, "\nJanky frames: %d (%.2f%%)", summary.janky_frames(),
+            (float) summary.janky_frames() / (float) summary.total_frames() * 100.0f);
+    dprintf(fd, "\n50th percentile: %dms", findPercentile(proto, 50));
+    dprintf(fd, "\n90th percentile: %dms", findPercentile(proto, 90));
+    dprintf(fd, "\n95th percentile: %dms", findPercentile(proto, 95));
+    dprintf(fd, "\n99th percentile: %dms", findPercentile(proto, 99));
+    dprintf(fd, "\nNumber Missed Vsync: %d", summary.missed_vsync_count());
+    dprintf(fd, "\nNumber High input latency: %d", summary.high_input_latency_count());
+    dprintf(fd, "\nNumber Slow UI thread: %d", summary.slow_ui_thread_count());
+    dprintf(fd, "\nNumber Slow bitmap uploads: %d", summary.slow_bitmap_upload_count());
+    dprintf(fd, "\nNumber Slow issue draw commands: %d", summary.slow_draw_count());
+    dprintf(fd, "\nHISTOGRAM:");
+    for (const auto& it : proto->histogram()) {
+        dprintf(fd, " %dms=%d", it.render_millis(), it.frame_count());
+    }
+    dprintf(fd, "\n");
+}
+
+void GraphicsStatsService::saveBuffer(const std::string& path, const std::string& package,
+        int versionCode, int64_t startTime, int64_t endTime, const ProfileData* data) {
+    service::GraphicsStatsProto statsProto;
+    if (!parseFromFile(path, &statsProto)) {
+        statsProto.Clear();
+    }
+    mergeProfileDataIntoProto(&statsProto, package, versionCode, startTime, endTime, data);
+    // Although we might not have read any data from the file, merging the existing data
+    // should always fully-initialize the proto
+    LOG_ALWAYS_FATAL_IF(!statsProto.IsInitialized(), "%s",
+            statsProto.InitializationErrorString().c_str());
+    LOG_ALWAYS_FATAL_IF(statsProto.package_name().empty()
+            || !statsProto.has_summary(), "package_name() '%s' summary %d",
+            statsProto.package_name().c_str(), statsProto.has_summary());
+    int outFd = open(path.c_str(), O_CREAT | O_RDWR | O_TRUNC, 0660);
+    if (outFd <= 0) {
+        int err = errno;
+        ALOGW("Failed to open '%s', error=%d (%s)", path.c_str(), err, strerror(err));
+        return;
+    }
+    int wrote = write(outFd, &sCurrentFileVersion, sHeaderSize);
+    if (wrote != sHeaderSize) {
+        int err = errno;
+        ALOGW("Failed to write header to '%s', returned=%d errno=%d (%s)",
+                path.c_str(), wrote, err, strerror(err));
+        close(outFd);
+        return;
+    }
+    {
+        io::FileOutputStream output(outFd);
+        bool success = statsProto.SerializeToZeroCopyStream(&output) && output.Flush();
+        if (output.GetErrno() != 0) {
+            ALOGW("Error writing to fd=%d, path='%s' err=%d (%s)",
+                    outFd, path.c_str(), output.GetErrno(), strerror(output.GetErrno()));
+            success = false;
+        } else if (!success) {
+            ALOGW("Serialize failed on '%s' unknown error", path.c_str());
+        }
+    }
+    close(outFd);
+}
+
+class GraphicsStatsService::Dump {
+public:
+    Dump(int outFd, DumpType type) : mFd(outFd), mType(type) {}
+    int fd() { return mFd; }
+    DumpType type() { return mType; }
+    service::GraphicsStatsServiceDumpProto& proto() { return mProto; }
+private:
+    int mFd;
+    DumpType mType;
+    service::GraphicsStatsServiceDumpProto mProto;
+};
+
+GraphicsStatsService::Dump* GraphicsStatsService::createDump(int outFd, DumpType type) {
+    return new Dump(outFd, type);
+}
+
+void GraphicsStatsService::addToDump(Dump* dump, const std::string& path, const std::string& package,
+        int versionCode, int64_t startTime, int64_t endTime, const ProfileData* data) {
+    service::GraphicsStatsProto statsProto;
+    if (!path.empty() && !parseFromFile(path, &statsProto)) {
+        statsProto.Clear();
+    }
+    if (data) {
+        mergeProfileDataIntoProto(&statsProto, package, versionCode, startTime, endTime, data);
+    }
+    if (!statsProto.IsInitialized()) {
+        ALOGW("Failed to load profile data from path '%s' and data %p",
+                path.empty() ? "<empty>" : path.c_str(), data);
+        return;
+    }
+
+    if (dump->type() == DumpType::Protobuf) {
+        dump->proto().add_stats()->CopyFrom(statsProto);
+    } else {
+        dumpAsTextToFd(&statsProto, dump->fd());
+    }
+}
+
+void GraphicsStatsService::addToDump(Dump* dump, const std::string& path) {
+    service::GraphicsStatsProto statsProto;
+    if (!parseFromFile(path, &statsProto)) {
+        return;
+    }
+    if (dump->type() == DumpType::Protobuf) {
+        dump->proto().add_stats()->CopyFrom(statsProto);
+    } else {
+        dumpAsTextToFd(&statsProto, dump->fd());
+    }
+}
+
+void GraphicsStatsService::finishDump(Dump* dump) {
+    if (dump->type() == DumpType::Protobuf) {
+        io::FileOutputStream stream(dump->fd());
+        dump->proto().SerializeToZeroCopyStream(&stream);
+    }
+    delete dump;
+}
+
+} /* namespace uirenderer */
+} /* namespace android */
\ No newline at end of file
diff --git a/libs/hwui/service/GraphicsStatsService.h b/libs/hwui/service/GraphicsStatsService.h
new file mode 100644
index 0000000..d0fd60e
--- /dev/null
+++ b/libs/hwui/service/GraphicsStatsService.h
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <string>
+
+#include "JankTracker.h"
+#include "utils/Macros.h"
+
+namespace android {
+namespace service {
+class GraphicsStatsProto;
+}
+
+namespace uirenderer {
+
+/*
+ * The exported entry points used by GraphicsStatsService.java in f/b/services/core
+ *
+ * NOTE: Avoid exporting a requirement on the protobuf itself. Keep the usage
+ * of the generated protobuf classes internal to libhwui.so to minimize library
+ * bloat.
+ */
+class GraphicsStatsService {
+public:
+    class Dump;
+    enum class DumpType {
+        Text,
+        Protobuf,
+    };
+
+    ANDROID_API static void saveBuffer(const std::string& path, const std::string& package,
+            int versionCode, int64_t startTime, int64_t endTime, const ProfileData* data);
+
+    ANDROID_API static Dump* createDump(int outFd, DumpType type);
+    ANDROID_API static void addToDump(Dump* dump, const std::string& path, const std::string& package,
+            int versionCode, int64_t startTime, int64_t endTime, const ProfileData* data);
+    ANDROID_API static void addToDump(Dump* dump, const std::string& path);
+    ANDROID_API static void finishDump(Dump* dump);
+
+    // Visible for testing
+    static bool parseFromFile(const std::string& path, service::GraphicsStatsProto* output);
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
\ No newline at end of file
diff --git a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
index 83b01e9..a461426 100644
--- a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
+++ b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
@@ -17,10 +17,6 @@
 #include "TestSceneBase.h"
 #include "utils/Color.h"
 
-#include <gui/IGraphicBufferAlloc.h>
-#include <gui/ISurfaceComposer.h>
-#include <private/gui/ComposerService.h>
-#include <binder/IServiceManager.h>
 #include <ui/PixelFormat.h>
 #include <SkGradientShader.h>
 #include <SkImagePriv.h>
@@ -39,14 +35,11 @@
     void createContent(int width, int height, Canvas& canvas) override {
         canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
 
-        status_t error;
-        sp<ISurfaceComposer> composer(ComposerService::getComposerService());
-        sp<IGraphicBufferAlloc> alloc(composer->createGraphicBufferAlloc());
         uint32_t usage = GraphicBuffer::USAGE_HW_TEXTURE
                 | GraphicBuffer::USAGE_SW_READ_NEVER
                 | GRALLOC_USAGE_SW_WRITE_RARELY;
-        sp<GraphicBuffer> buffer = alloc->createGraphicBuffer(400, 200, PIXEL_FORMAT_RGBA_8888, 1,
-                usage, &error);
+
+        sp<GraphicBuffer> buffer = new GraphicBuffer(400, 200, PIXEL_FORMAT_RGBA_8888, usage);
 
         unsigned char* pixels = nullptr;
         buffer->lock(GraphicBuffer::USAGE_SW_WRITE_RARELY, ((void**)&pixels));
@@ -88,4 +81,4 @@
         return image->makeShader(SkShader::TileMode::kClamp_TileMode,
                 SkShader::TileMode::kClamp_TileMode);
     }
-};
\ No newline at end of file
+};
diff --git a/libs/hwui/tests/unit/BakedOpStateTests.cpp b/libs/hwui/tests/unit/BakedOpStateTests.cpp
index 0f8e047..d51db2e 100644
--- a/libs/hwui/tests/unit/BakedOpStateTests.cpp
+++ b/libs/hwui/tests/unit/BakedOpStateTests.cpp
@@ -35,7 +35,7 @@
     {
         // recorded with transform, no parent transform
         auto parentSnapshot = TestUtils::makeSnapshot(Matrix4::identity(), Rect(100, 200));
-        ResolvedRenderState state(allocator, *parentSnapshot, recordedOp, false);
+        ResolvedRenderState state(allocator, *parentSnapshot, recordedOp, false, false);
         EXPECT_MATRIX_APPROX_EQ(state.transform, translate10x20);
         EXPECT_EQ(Rect(100, 200), state.clipRect());
         EXPECT_EQ(Rect(40, 60, 100, 200), state.clippedBounds); // translated and also clipped
@@ -44,7 +44,7 @@
     {
         // recorded with transform and parent transform
         auto parentSnapshot = TestUtils::makeSnapshot(translate10x20, Rect(100, 200));
-        ResolvedRenderState state(allocator, *parentSnapshot, recordedOp, false);
+        ResolvedRenderState state(allocator, *parentSnapshot, recordedOp, false, false);
 
         Matrix4 expectedTranslate;
         expectedTranslate.loadTranslate(20, 40, 0);
@@ -70,14 +70,14 @@
     {
         // recorded with transform, no parent transform
         auto parentSnapshot = TestUtils::makeSnapshot(Matrix4::identity(), Rect(100, 200));
-        ResolvedRenderState state(allocator, *parentSnapshot, recordedOp, false);
+        ResolvedRenderState state(allocator, *parentSnapshot, recordedOp, false, false);
         EXPECT_EQ(Rect(-10, -20, 90, 180), state.computeLocalSpaceClip())
             << "Local clip rect should be 100x200, offset by -10,-20";
     }
     {
         // recorded with transform + parent transform
         auto parentSnapshot = TestUtils::makeSnapshot(translate10x20, Rect(100, 200));
-        ResolvedRenderState state(allocator, *parentSnapshot, recordedOp, false);
+        ResolvedRenderState state(allocator, *parentSnapshot, recordedOp, false, false);
         EXPECT_EQ(Rect(-10, -20, 80, 160), state.computeLocalSpaceClip())
             << "Local clip rect should be 90x190, offset by -10,-20";
     }
@@ -170,7 +170,7 @@
         snapshotMatrix.loadScale(testCase.scale, testCase.scale, 1);
         auto parentSnapshot = TestUtils::makeSnapshot(snapshotMatrix, Rect(200, 200));
 
-        ResolvedRenderState state(allocator, *parentSnapshot, recordedOp, true);
+        ResolvedRenderState state(allocator, *parentSnapshot, recordedOp, true, false);
         testCase.validator(state);
     }
 }
@@ -234,7 +234,7 @@
         RectOp rejectOp(Rect(100, 200), Matrix4::identity(), &clip, &paint);
         auto snapshot = TestUtils::makeSnapshot(Matrix4::identity(), Rect()); // Note: empty clip
         auto bakedState = BakedOpState::tryStrokeableOpConstruct(allocator, *snapshot, rejectOp,
-                BakedOpState::StrokeBehavior::StyleDefined);
+                BakedOpState::StrokeBehavior::StyleDefined, false);
 
         EXPECT_EQ(nullptr, bakedState);
         EXPECT_GT(8u, allocator.usedSize()); // no significant allocation space used for rejected op
@@ -248,7 +248,7 @@
         RectOp rejectOp(Rect(50, 50, 150, 150), Matrix4::identity(), &clip, &paint);
         auto snapshot = TestUtils::makeSnapshot(Matrix4::identity(), Rect(200, 200));
         auto bakedState = BakedOpState::tryStrokeableOpConstruct(allocator, *snapshot, rejectOp,
-                BakedOpState::StrokeBehavior::StyleDefined);
+                BakedOpState::StrokeBehavior::StyleDefined, false);
 
         ASSERT_NE(nullptr, bakedState);
         EXPECT_EQ(Rect(45, 45, 155, 155), bakedState->computedState.clippedBounds);
@@ -263,7 +263,7 @@
         RectOp rejectOp(Rect(50, 50, 150, 150), Matrix4::identity(), &clip, &paint);
         auto snapshot = TestUtils::makeSnapshot(Matrix4::identity(), Rect(200, 200));
         auto bakedState = BakedOpState::tryStrokeableOpConstruct(allocator, *snapshot, rejectOp,
-                BakedOpState::StrokeBehavior::Forced);
+                BakedOpState::StrokeBehavior::Forced, false);
 
         ASSERT_NE(nullptr, bakedState);
         EXPECT_EQ(Rect(45, 45, 155, 155), bakedState->computedState.clippedBounds);
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index a391d1e..a329980 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -171,6 +171,35 @@
     EXPECT_EQ(1, renderer.getIndex());
 }
 
+
+RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, arcStrokeClip) {
+    class ArcStrokeClipTestRenderer : public TestRendererBase {
+    public:
+        void onArcOp(const ArcOp& op, const BakedOpState& state) override {
+            EXPECT_EQ(0, mIndex++);
+            EXPECT_EQ(Rect(25, 25, 175, 175), op.unmappedBounds);
+            EXPECT_EQ(Rect(25, 25, 175, 175), state.computedState.clippedBounds);
+            EXPECT_EQ(OpClipSideFlags::Full, state.computedState.clipSideFlags)
+                    << "Arc op clipped conservatively, since path texture may be expanded";
+        }
+    };
+
+    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
+            [](RenderProperties& props, RecordingCanvas& canvas) {
+        canvas.clipRect(25, 25, 175, 175, SkClipOp::kIntersect);
+        SkPaint aaPaint;
+        aaPaint.setAntiAlias(true);
+        canvas.drawArc(25, 25, 175, 175, 40, 180, true, aaPaint);
+    });
+    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
+            sLightGeometry, Caches::getInstance());
+    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
+
+    ArcStrokeClipTestRenderer renderer;
+    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+    EXPECT_EQ(1, renderer.getIndex());
+}
+
 RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, simpleRejection) {
     auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
             [](RenderProperties& props, RecordingCanvas& canvas) {
@@ -579,7 +608,7 @@
         SkPaint textPaint;
         textPaint.setAntiAlias(true);
         textPaint.setTextSize(20);
-        textPaint.setStrikeThruText(true);
+        textPaint.setFlags(textPaint.getFlags() | SkPaint::kStrikeThruText_ReserveFlag);
         textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
         for (int i = 0; i < LOOPS; i++) {
             TestUtils::drawUtf8ToCanvas(&canvas, "test text", textPaint, 10, 100 * (i + 1));
diff --git a/libs/hwui/tests/unit/GraphicsStatsServiceTests.cpp b/libs/hwui/tests/unit/GraphicsStatsServiceTests.cpp
new file mode 100644
index 0000000..cfe1134
--- /dev/null
+++ b/libs/hwui/tests/unit/GraphicsStatsServiceTests.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "service/GraphicsStatsService.h"
+
+#include <frameworks/base/core/proto/android/service/graphicsstats.pb.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+using namespace android;
+using namespace android::uirenderer;
+
+std::string findRootPath() {
+    char path[1024];
+    ssize_t r = readlink("/proc/self/exe", path, 1024);
+    // < 1023 because we need room for the null terminator
+    if (r <= 0 || r > 1023) {
+        int err = errno;
+        fprintf(stderr, "Failed to read from /proc/self/exe; r=%zd, err=%d (%s)\n",
+                r, err, strerror(err));
+        exit(EXIT_FAILURE);
+    }
+    while (--r > 0) {
+        if (path[r] == '/') {
+            path[r] = '\0';
+            return std::string(path);
+        }
+    }
+    return std::string();
+}
+
+// No code left untested
+TEST(GraphicsStats, findRootPath) {
+    std::string expected = "/data/nativetest/hwui_unit_tests";
+    EXPECT_EQ(expected, findRootPath());
+}
+
+TEST(GraphicsStats, saveLoad) {
+    std::string path = findRootPath() + "/test_saveLoad";
+    std::string packageName = "com.test.saveLoad";
+    ProfileData mockData;
+    mockData.jankFrameCount = 20;
+    mockData.totalFrameCount = 100;
+    mockData.statStartTime = 10000;
+    // Fill with patterned data we can recognize but which won't map to a
+    // memset or basic for iteration count
+    for (size_t i = 0; i < mockData.frameCounts.size(); i++) {
+        mockData.frameCounts[i] = ((i % 10) + 1) * 2;
+    }
+    for (size_t i = 0; i < mockData.slowFrameCounts.size(); i++) {
+        mockData.slowFrameCounts[i] = (i % 5) + 1;
+    }
+    GraphicsStatsService::saveBuffer(path, packageName, 5, 3000, 7000, &mockData);
+    service::GraphicsStatsProto loadedProto;
+    EXPECT_TRUE(GraphicsStatsService::parseFromFile(path, &loadedProto));
+    // Clean up the file
+    unlink(path.c_str());
+
+    EXPECT_EQ(packageName, loadedProto.package_name());
+    EXPECT_EQ(5, loadedProto.version_code());
+    EXPECT_EQ(3000, loadedProto.stats_start());
+    EXPECT_EQ(7000, loadedProto.stats_end());
+    // ASSERT here so we don't continue with a nullptr deref crash if this is false
+    ASSERT_TRUE(loadedProto.has_summary());
+    EXPECT_EQ(20, loadedProto.summary().janky_frames());
+    EXPECT_EQ(100, loadedProto.summary().total_frames());
+    EXPECT_EQ(mockData.frameCounts.size() + mockData.slowFrameCounts.size(),
+            (size_t) loadedProto.histogram_size());
+    for (size_t i = 0; i < (size_t) loadedProto.histogram_size(); i++) {
+        int expectedCount, expectedBucket;
+        if (i < mockData.frameCounts.size()) {
+            expectedCount = ((i % 10) + 1) * 2;
+            expectedBucket = JankTracker::frameTimeForFrameCountIndex(i);
+        } else {
+            int temp = i - mockData.frameCounts.size();
+            expectedCount = (temp % 5) + 1;
+            expectedBucket = JankTracker::frameTimeForSlowFrameCountIndex(temp);
+        }
+        EXPECT_EQ(expectedCount, loadedProto.histogram().Get(i).frame_count());
+        EXPECT_EQ(expectedBucket, loadedProto.histogram().Get(i).render_millis());
+    }
+}
+
+TEST(GraphicsStats, merge) {
+    std::string path = findRootPath() + "/test_merge";
+    std::string packageName = "com.test.merge";
+    ProfileData mockData;
+    mockData.jankFrameCount = 20;
+    mockData.totalFrameCount = 100;
+    mockData.statStartTime = 10000;
+    // Fill with patterned data we can recognize but which won't map to a
+    // memset or basic for iteration count
+    for (size_t i = 0; i < mockData.frameCounts.size(); i++) {
+        mockData.frameCounts[i] = ((i % 10) + 1) * 2;
+    }
+    for (size_t i = 0; i < mockData.slowFrameCounts.size(); i++) {
+        mockData.slowFrameCounts[i] = (i % 5) + 1;
+    }
+    GraphicsStatsService::saveBuffer(path, packageName, 5, 3000, 7000, &mockData);
+    mockData.jankFrameCount = 50;
+    mockData.totalFrameCount = 500;
+    for (size_t i = 0; i < mockData.frameCounts.size(); i++) {
+        mockData.frameCounts[i] = (i % 5) + 1;
+    }
+    for (size_t i = 0; i < mockData.slowFrameCounts.size(); i++) {
+        mockData.slowFrameCounts[i] = ((i % 10) + 1) * 2;
+    }
+    GraphicsStatsService::saveBuffer(path, packageName, 5, 7050, 10000, &mockData);
+
+    service::GraphicsStatsProto loadedProto;
+    EXPECT_TRUE(GraphicsStatsService::parseFromFile(path, &loadedProto));
+    // Clean up the file
+    unlink(path.c_str());
+
+    EXPECT_EQ(packageName, loadedProto.package_name());
+    EXPECT_EQ(5, loadedProto.version_code());
+    EXPECT_EQ(3000, loadedProto.stats_start());
+    EXPECT_EQ(10000, loadedProto.stats_end());
+    // ASSERT here so we don't continue with a nullptr deref crash if this is false
+    ASSERT_TRUE(loadedProto.has_summary());
+    EXPECT_EQ(20 + 50, loadedProto.summary().janky_frames());
+    EXPECT_EQ(100 + 500, loadedProto.summary().total_frames());
+    EXPECT_EQ(mockData.frameCounts.size() + mockData.slowFrameCounts.size(),
+            (size_t) loadedProto.histogram_size());
+    for (size_t i = 0; i < (size_t) loadedProto.histogram_size(); i++) {
+        int expectedCount, expectedBucket;
+        if (i < mockData.frameCounts.size()) {
+            expectedCount = ((i % 10) + 1) * 2;
+            expectedCount += (i % 5) + 1;
+            expectedBucket = JankTracker::frameTimeForFrameCountIndex(i);
+        } else {
+            int temp = i - mockData.frameCounts.size();
+            expectedCount = (temp % 5) + 1;
+            expectedCount += ((temp % 10) + 1) * 2;
+            expectedBucket = JankTracker::frameTimeForSlowFrameCountIndex(temp);
+        }
+        EXPECT_EQ(expectedCount, loadedProto.histogram().Get(i).frame_count());
+        EXPECT_EQ(expectedBucket, loadedProto.histogram().Get(i).render_millis());
+    }
+}
\ No newline at end of file
diff --git a/libs/hwui/tests/unit/LayerUpdateQueueTests.cpp b/libs/hwui/tests/unit/LayerUpdateQueueTests.cpp
index 4db1cb9..91c7514 100644
--- a/libs/hwui/tests/unit/LayerUpdateQueueTests.cpp
+++ b/libs/hwui/tests/unit/LayerUpdateQueueTests.cpp
@@ -48,11 +48,11 @@
 
     EXPECT_EQ(3u, queue.entries().size());
 
-    EXPECT_EQ(a.get(), queue.entries()[0].renderNode);
+    EXPECT_EQ(a.get(), queue.entries()[0].renderNode.get());
     EXPECT_EQ(Rect(25, 25, 75, 75), queue.entries()[0].damage);
-    EXPECT_EQ(b.get(), queue.entries()[1].renderNode);
+    EXPECT_EQ(b.get(), queue.entries()[1].renderNode.get());
     EXPECT_EQ(Rect(100, 100, 200, 200), queue.entries()[1].damage); // clipped to bounds
-    EXPECT_EQ(c.get(), queue.entries()[2].renderNode);
+    EXPECT_EQ(c.get(), queue.entries()[2].renderNode.get());
     EXPECT_EQ(Rect(0, 0, 1, 1), queue.entries()[2].damage); // rounded out
 }
 
@@ -65,7 +65,7 @@
 
     EXPECT_EQ(1u, queue.entries().size());
 
-    EXPECT_EQ(a.get(), queue.entries()[0].renderNode);
+    EXPECT_EQ(a.get(), queue.entries()[0].renderNode.get());
     EXPECT_EQ(Rect(10, 10, 40, 40), queue.entries()[0].damage);
 }
 
diff --git a/libs/hwui/tests/unit/RecordingCanvasTests.cpp b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
index 669f03c..b2ea9ac 100644
--- a/libs/hwui/tests/unit/RecordingCanvasTests.cpp
+++ b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
@@ -200,8 +200,18 @@
         paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
         for (int i = 0; i < 2; i++) {
             for (int j = 0; j < 2; j++) {
-                paint.setUnderlineText(i != 0);
-                paint.setStrikeThruText(j != 0);
+                uint32_t flags = paint.getFlags();
+                if (i != 0) {
+                    flags |= SkPaint::kUnderlineText_ReserveFlag;
+                } else {
+                    flags &= ~SkPaint::kUnderlineText_ReserveFlag;
+                }
+                if (j != 0) {
+                    flags |= SkPaint::kStrikeThruText_ReserveFlag;
+                } else {
+                    flags &= ~SkPaint::kStrikeThruText_ReserveFlag;
+                }
+                paint.setFlags(flags);
                 TestUtils::drawUtf8ToCanvas(&canvas, "test text", paint, 25, 25);
             }
         }
diff --git a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
index f21b3f7..cbea501 100644
--- a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
@@ -44,9 +44,9 @@
                 canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
             });
 
-    auto skLiteDL = SkLiteDL::New(SkRect::MakeWH(1, 1));
+    SkLiteDL skLiteDL;
     SkLiteRecorder canvas;
-    canvas.reset(skLiteDL.get());
+    canvas.reset(&skLiteDL, SkIRect::MakeWH(1, 1));
     canvas.translate(100, 100);
     RenderNodeDrawable drawable(rootNode.get(), &canvas);
 
diff --git a/libs/hwui/tests/unit/RenderNodeTests.cpp b/libs/hwui/tests/unit/RenderNodeTests.cpp
index 2925243..eda4a9d 100644
--- a/libs/hwui/tests/unit/RenderNodeTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeTests.cpp
@@ -331,7 +331,7 @@
     // damage rect.
     EXPECT_TRUE(rootNode->getDisplayList()->hasVectorDrawables());
     EXPECT_FALSE(info.layerUpdateQueue->entries().empty());
-    EXPECT_EQ(rootNode.get(), info.layerUpdateQueue->entries().at(0).renderNode);
+    EXPECT_EQ(rootNode.get(), info.layerUpdateQueue->entries().at(0).renderNode.get());
     EXPECT_EQ(uirenderer::Rect(0, 0, 200, 400), info.layerUpdateQueue->entries().at(0).damage);
     canvasContext->destroy();
 }
diff --git a/libs/hwui/tests/unit/SkiaCanvasTests.cpp b/libs/hwui/tests/unit/SkiaCanvasTests.cpp
index 0ac09ac..7fb75dc 100644
--- a/libs/hwui/tests/unit/SkiaCanvasTests.cpp
+++ b/libs/hwui/tests/unit/SkiaCanvasTests.cpp
@@ -18,6 +18,7 @@
 
 #include <gtest/gtest.h>
 #include <RecordingCanvas.h>
+#include <SkBlurDrawLooper.h>
 #include <SkPicture.h>
 #include <SkPictureRecorder.h>
 
@@ -59,3 +60,21 @@
     EXPECT_EQ(directOp->unmappedBounds, pictureOp->unmappedBounds);
     EXPECT_EQ(directOp->localMatrix, pictureOp->localMatrix);
 }
+
+TEST(SkiaCanvas, drawShadowLayer) {
+    auto surface = SkSurface::MakeRasterN32Premul(10, 10);
+    SkiaCanvas canvas(surface->getCanvas());
+
+    // clear to white
+    canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrc);
+
+    SkPaint paint;
+    // it is transparent to ensure that we still draw the rect since it has a looper
+    paint.setColor(SK_ColorTRANSPARENT);
+    // this is how view's shadow layers are implemented
+    paint.setLooper(SkBlurDrawLooper::Make(0xF0000000, 6.0f, 0, 10));
+    canvas.drawRect(3, 3, 7, 7, paint);
+
+    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorWHITE);
+    ASSERT_NE(TestUtils::getColor(surface, 5, 5), SK_ColorWHITE);
+}
diff --git a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
index be460bf..dd8f4b4 100644
--- a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
+++ b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
@@ -30,16 +30,13 @@
 using namespace android::uirenderer::skiapipeline;
 
 TEST(SkiaDisplayList, create) {
-    SkRect bounds = SkRect::MakeWH(200, 200);
-    SkiaDisplayList skiaDL(bounds);
+    SkiaDisplayList skiaDL;
     ASSERT_TRUE(skiaDL.isEmpty());
     ASSERT_FALSE(skiaDL.mProjectionReceiver);
-    ASSERT_EQ(skiaDL.mDrawable->getBounds(), bounds);
 }
 
 TEST(SkiaDisplayList, reset) {
-    SkRect bounds = SkRect::MakeWH(200, 200);
-    SkiaDisplayList skiaDL(bounds);
+    SkiaDisplayList skiaDL;
 
     SkCanvas dummyCanvas;
     RenderNodeDrawable drawable(nullptr, &dummyCanvas);
@@ -47,10 +44,9 @@
     skiaDL.mChildFunctors.emplace_back(nullptr, nullptr, &dummyCanvas);
     skiaDL.mMutableImages.push_back(nullptr);
     skiaDL.mVectorDrawables.push_back(nullptr);
-    skiaDL.mDrawable->drawAnnotation(bounds, "testAnnotation", nullptr);
+    skiaDL.mDisplayList.drawAnnotation(SkRect::MakeWH(200, 200), "testAnnotation", nullptr);
     skiaDL.mProjectionReceiver = &drawable;
 
-    ASSERT_EQ(skiaDL.mDrawable->getBounds(), bounds);
     ASSERT_FALSE(skiaDL.mChildNodes.empty());
     ASSERT_FALSE(skiaDL.mChildFunctors.empty());
     ASSERT_FALSE(skiaDL.mMutableImages.empty());
@@ -58,10 +54,8 @@
     ASSERT_FALSE(skiaDL.isEmpty());
     ASSERT_TRUE(skiaDL.mProjectionReceiver);
 
-    bounds = SkRect::MakeWH(100, 100);
-    skiaDL.reset(bounds);
+    skiaDL.reset();
 
-    ASSERT_EQ(skiaDL.mDrawable->getBounds(), bounds);
     ASSERT_TRUE(skiaDL.mChildNodes.empty());
     ASSERT_TRUE(skiaDL.mChildFunctors.empty());
     ASSERT_TRUE(skiaDL.mMutableImages.empty());
@@ -79,7 +73,7 @@
     ASSERT_EQ(availableList.get(), nullptr);
 
     // attach a displayList for reuse
-    SkiaDisplayList skiaDL(SkRect::MakeWH(200, 200));
+    SkiaDisplayList skiaDL;
     ASSERT_TRUE(skiaDL.reuseDisplayList(renderNode.get(), nullptr));
 
     // detach the list that you just attempted to reuse
@@ -93,13 +87,13 @@
 }
 
 TEST(SkiaDisplayList, syncContexts) {
-    SkRect bounds = SkRect::MakeWH(200, 200);
-    SkiaDisplayList skiaDL(bounds);
+    SkiaDisplayList skiaDL;
 
     SkCanvas dummyCanvas;
     TestUtils::MockFunctor functor;
     skiaDL.mChildFunctors.emplace_back(&functor, nullptr, &dummyCanvas);
 
+    SkRect bounds = SkRect::MakeWH(200, 200);
     VectorDrawableRoot vectorDrawable(new VectorDrawable::Group());
     vectorDrawable.mutateStagingProperties()->setBounds(bounds);
     skiaDL.mVectorDrawables.push_back(&vectorDrawable);
@@ -127,7 +121,7 @@
     DamageAccumulator damageAccumulator;
     info.damageAccumulator = &damageAccumulator;
 
-    SkiaDisplayList skiaDL(SkRect::MakeWH(200, 200));
+    SkiaDisplayList skiaDL;
 
     // prepare with a clean VD
     VectorDrawableRoot cleanVD(new VectorDrawable::Group());
@@ -170,8 +164,7 @@
 }
 
 TEST(SkiaDisplayList, updateChildren) {
-    SkRect bounds = SkRect::MakeWH(200, 200);
-    SkiaDisplayList skiaDL(bounds);
+    SkiaDisplayList skiaDL;
 
     sp<RenderNode> renderNode = new RenderNode();
     SkCanvas dummyCanvas;
diff --git a/libs/hwui/utils/Color.h b/libs/hwui/utils/Color.h
index 0950eb8..4a27ca2f 100644
--- a/libs/hwui/utils/Color.h
+++ b/libs/hwui/utils/Color.h
@@ -121,4 +121,4 @@
 } /* namespace uirenderer */
 } /* namespace android */
 
-#endif /* TEST_UTILS_H */
+#endif /* COLOR_H */
diff --git a/libs/hwui/utils/PaintUtils.h b/libs/hwui/utils/PaintUtils.h
index 845a3ea..2673be1c 100644
--- a/libs/hwui/utils/PaintUtils.h
+++ b/libs/hwui/utils/PaintUtils.h
@@ -39,21 +39,6 @@
         return GL_NEAREST;
     }
 
-    // TODO: move to a method on android:Paint? replace with SkPaint::nothingToDraw()?
-    static inline bool paintWillNotDraw(const SkPaint& paint) {
-        return paint.getAlpha() == 0
-                && !paint.getColorFilter()
-                && paint.getBlendMode() == SkBlendMode::kSrcOver;
-    }
-
-    // TODO: move to a method on android:Paint? replace with SkPaint::nothingToDraw()?
-    static inline bool paintWillNotDrawText(const SkPaint& paint) {
-        return paint.getAlpha() == 0
-                && paint.getLooper() == nullptr
-                && !paint.getColorFilter()
-                && paint.getBlendMode() == SkBlendMode::kSrcOver;
-    }
-
     static bool isOpaquePaint(const SkPaint* paint) {
         if (!paint) return true; // default (paintless) behavior is SrcOver, black
 
diff --git a/libs/input/Android.mk b/libs/input/Android.mk
index 2bbfdcc..e824275 100644
--- a/libs/input/Android.mk
+++ b/libs/input/Android.mk
@@ -28,7 +28,8 @@
     libgui \
     libui \
     libinput \
-    libinputflinger
+    libinputflinger \
+    libnativewindow
 
 LOCAL_C_INCLUDES := \
     frameworks/native/services
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index fc31f32..8f341a8 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -113,5 +113,6 @@
     // for reporting callback completion
     void locationCallbackFinished(ILocationListener listener);
 
-
+    // used by gts tests to verify throttling whitelist
+    String[] getBackgroundThrottlingWhitelist();
 }
diff --git a/media/java/android/media/AudioFocusRequest.java b/media/java/android/media/AudioFocusRequest.java
new file mode 100644
index 0000000..1b75a78
--- /dev/null
+++ b/media/java/android/media/AudioFocusRequest.java
@@ -0,0 +1,321 @@
+/*
+ * 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 android.media;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.media.AudioManager.OnAudioFocusChangeListener;
+import android.os.Handler;
+import android.os.Looper;
+
+/**
+ * A class to encapsulate information about an audio focus request.
+ * An {@code AudioFocusRequest} instance is built by {@link Builder}, and is used to
+ * request and abandon audio focus, respectively
+ * with {@link AudioManager#requestAudioFocus(AudioFocusRequest)} and
+ * {@link AudioManager#abandonAudioFocusRequest(AudioFocusRequest)}.
+ * <p>In the context of describing audio focus, the term "ducking" is used. It describes a temporary
+ * lowering of the audio level of an application in response to another application playing audio
+ * concurrently. An example is during the playback of driving directions,
+ * a user listening to music expects the music to "duck" during the playback of the message
+ * announcing directions.
+ */
+// TODO use this class to provide more documentation about audio focus and the new behaviors
+//      describe up to N, and after.
+public final class AudioFocusRequest {
+
+    // default attributes for the request when not specified
+    private final static AudioAttributes FOCUS_DEFAULT_ATTR = new AudioAttributes.Builder()
+            .setUsage(AudioAttributes.USAGE_MEDIA).build();
+
+    private final OnAudioFocusChangeListener mFocusListener; // may be null
+    private final Handler mListenerHandler;                  // may be null
+    private final AudioAttributes mAttr;                     // never null
+    private final int mFocusGain;
+    private final int mFlags;
+
+    //TODO implement use of optional handler
+    private AudioFocusRequest(OnAudioFocusChangeListener listener, Handler handler,
+            AudioAttributes attr, int focusGain, int flags) {
+        mFocusListener = listener;
+        mListenerHandler = handler;
+        mFocusGain = focusGain;
+        mAttr = attr;
+        mFlags = flags;
+    }
+
+    /**
+     * @hide
+     * Checks whether a focus gain constant is a valid value for an audio focus request.
+     * @param focusGain value to check
+     * @return true if focusGain is a valid value for an audio focus request.
+     */
+    final static boolean isValidFocusGain(int focusGain) {
+        switch (focusGain) {
+            case AudioManager.AUDIOFOCUS_GAIN:
+            case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT:
+            case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK:
+            case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    /**
+     * Returns the focus change listener set for this {@code AudioFocusRequest}.
+     * @return null if no {@link AudioManager.OnAudioFocusChangeListener} was set.
+     */
+    public @Nullable OnAudioFocusChangeListener getOnAudioFocusChangeListener() {
+        return mFocusListener;
+    }
+
+    /**
+     * Returns the {@link Handler} to be used for the focus change listener.
+     * @return the same {@code Handler} set in.
+     *   {@link Builder#setOnAudioFocusChangeListener(OnAudioFocusChangeListener, Handler)}, or null
+     *   if no listener was set.
+     */
+    public @Nullable Handler getOnAudioFocusChangeListenerHandler() {
+        return mListenerHandler;
+    }
+
+    /**
+     * Returns the {@link AudioAttributes} set for this {@code AudioFocusRequest}, or the default
+     * attributes if none were set.
+     * @return non-null {@link AudioAttributes}.
+     */
+    public @NonNull AudioAttributes getAudioAttributes() {
+        return mAttr;
+    }
+
+    /**
+     * Returns the type of audio focus request configured for this {@code AudioFocusRequest}.
+     * @return one of {@link AudioManager#AUDIOFOCUS_GAIN},
+     * {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT},
+     * {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK}, and
+     * {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE}.
+     */
+    public int getFocusGain() {
+        return mFocusGain;
+    }
+
+    /**
+     * Returns whether the application that would use this {@code AudioFocusRequest} would pause
+     * when it is requested to duck.
+     * @return the duck/pause behavior.
+     */
+    public boolean willPauseWhenDucked() {
+        return (mFlags & AudioManager.AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS)
+                == AudioManager.AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS;
+    }
+
+    /**
+     * Returns whether the application that would use this {@code AudioFocusRequest} supports
+     * a focus gain granted after a temporary request failure.
+     * @return whether delayed focus gain is supported.
+     */
+    public boolean acceptsDelayedFocusGain() {
+        return (mFlags & AudioManager.AUDIOFOCUS_FLAG_DELAY_OK)
+                == AudioManager.AUDIOFOCUS_FLAG_DELAY_OK;
+    }
+
+    int getFlags() {
+        return mFlags;
+    }
+
+    /**
+     * Builder class for {@link AudioFocusRequest} objects.
+     * <p> Here is an example where {@code Builder} is used to define the
+     * {@link AudioFocusRequest} for requesting audio focus:
+     *
+     * <pre class="prettyprint">
+     * mAudioManager = (AudioManager) Context.getSystemService(Context.AUDIO_SERVICE);
+     * mPlaybackAttributes = new AudioAttributes.Builder()
+     *         .setUsage(AudioAttributes.USAGE_GAME)
+     *         .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
+     *         .build();
+     * mFocusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
+     *         .setAudioAttributes(mPlaybackAttributes)
+     *         .setAcceptsDelayedFocusGain(true)
+     *         .setOnAudioFocusChangeListener(mMyFocusListener, mMyHandler)
+     *         .build();
+     * mMediaPlayer = new MediaPlayer();
+     *  ...
+     * mMediaPlayer.setAudioAttributes(mPlaybackAttributes);
+     *  ...
+     * mAudioManager.requestAudioFocus(mFocusRequest);
+     *  ...
+     * mAudioManager.abandonAudioFocusRequest(mFocusRequest);
+     * </pre>
+     *
+     */
+    public static final class Builder {
+        private OnAudioFocusChangeListener mFocusListener;
+        private Handler mListenerHandler;
+        private AudioAttributes mAttr = FOCUS_DEFAULT_ATTR;
+        private int mFocusGain;
+        private boolean mPausesOnDuck = false;
+        private boolean mDelayedFocus = false;
+
+        /**
+         * Constructs a new {@code Builder}, and specifies how audio focus
+         * will be requested. Valid values for focus requests are
+         * {@link AudioManager#AUDIOFOCUS_GAIN}, {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT},
+         * {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK}, and
+         * {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE}.
+         * <p>By default there is no focus change listener, and the <code>AudioAttributes</code>
+         * have a usage of {@link AudioAttributes#USAGE_MEDIA}.
+         * @param focusGain the type of audio focus gain that will be requested
+         * @throws IllegalArgumentException thrown when an invalid focus gain type is used
+         */
+        public Builder(int focusGain) {
+            setFocusGain(focusGain);
+        }
+
+        /**
+         * Constructs a new {@code Builder} with all the properties of the {@code AudioFocusRequest}
+         * passed as parameter.
+         * Use this method when you want a new request to differ only by some properties.
+         * @param requestToCopy the non-null {@code AudioFocusRequest} to build a duplicate from.
+         * @throws IllegalArgumentException thrown when a null {@code AudioFocusRequest} is used.
+         */
+        public Builder(@NonNull AudioFocusRequest requestToCopy) {
+            if (requestToCopy == null) {
+                throw new IllegalArgumentException("Illegal null AudioFocusRequest");
+            }
+            mAttr = requestToCopy.mAttr;
+            mFocusListener = requestToCopy.mFocusListener;
+            mListenerHandler = requestToCopy.mListenerHandler;
+            mFocusGain = requestToCopy.mFocusGain;
+            mPausesOnDuck = requestToCopy.willPauseWhenDucked();
+            mDelayedFocus = requestToCopy.acceptsDelayedFocusGain();
+        }
+
+        /**
+         * Sets the type of focus gain that will be requested.
+         * Use this method to replace the focus gain when building a request by modifying an
+         * existing {@code AudioFocusRequest} instance.
+         * @param focusGain the type of audio focus gain that will be requested.
+         * @return this {@code Builder} instance
+         * @throws IllegalArgumentException thrown when an invalid focus gain type is used
+         */
+        public @NonNull Builder setFocusGain(int focusGain) {
+            if (!isValidFocusGain(focusGain)) {
+                throw new IllegalArgumentException("Illegal audio focus gain type " + focusGain);
+            }
+            mFocusGain = focusGain;
+            return this;
+        }
+
+        /**
+         * Sets the listener called when audio focus changes after being requested with
+         *   {@link AudioManager#requestAudioFocus(AudioFocusRequest)}, and until being abandoned
+         *   with {@link AudioManager#abandonAudioFocusRequest(AudioFocusRequest)}.
+         *   Note that only focus changes (gains and losses) affecting the focus owner are reported,
+         *   not gains and losses of other focus requesters in the system.
+         * @param listener the listener receiving the focus change notifications.
+         * @param handler the {@link Handler} for the thread on which to execute
+         *   the notifications. If {@code null}, the {@code Handler} associated with the main
+         *   {@link Looper} will be used.
+         * @return this {@code Builder} instance.
+         * @throws IllegalArgumentException thrown when a non-null handler is used with a null
+         *   listener.
+         */
+        public @NonNull Builder setOnAudioFocusChangeListener(
+                @Nullable OnAudioFocusChangeListener listener, @Nullable Handler handler) {
+            if (listener == null && handler != null) {
+                throw new IllegalArgumentException(
+                        "Illegal non-null handler without a focus listener");
+            }
+            mFocusListener = listener;
+            mListenerHandler = handler;
+            return this;
+        }
+
+        /**
+         * Sets the {@link AudioAttributes} to be associated with the focus request, and which
+         * describe the use case describing why focus is requested.
+         * As the focus requests typically precede audio playback, this information is used on
+         * certain platforms to declare the subsequent playback use case. It is therefore good
+         * practice to use in this method the same {@code AudioAttributes} as used for
+         * playback, see for example {@link MediaPlayer#setAudioAttributes(AudioAttributes)} in
+         * {@code MediaPlayer} or {@link AudioTrack.Builder#setAudioAttributes(AudioAttributes)}
+         * in {@code AudioTrack}.
+         * @param attributes the {@link AudioAttributes} for the focus request.
+         * @return this {@code Builder} instance.
+         * @throws IllegalArgumentException thrown when using null for the attributes.
+         */
+        public @NonNull Builder setAudioAttributes(@NonNull AudioAttributes attributes) {
+            if (attributes == null) {
+                throw new IllegalArgumentException("Illegal null AudioAttributes");
+            }
+            mAttr = attributes;
+            return this;
+        }
+
+        /**
+         * Declare the intended behavior of the application with regards to audio ducking.
+         * See more details in the {@link AudioFocusRequest} class documentation.
+         * @param pauseOnDuck use {@code true} if the application intends to pause audio playback
+         *    when losing focus with {@link AudioManager#AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK}.
+         *    If {@code true}, note that you must also set a focus listener to receive such an
+         *    event, with
+         *    {@link #setOnAudioFocusChangeListener(OnAudioFocusChangeListener, Handler)}.
+         * @return this {@code Builder} instance.
+         */
+        public @NonNull Builder setWillPauseWhenDucked(boolean pauseOnDuck) {
+            mPausesOnDuck = pauseOnDuck;
+            return this;
+        }
+
+        /**
+         * Marks this focus request as compatible with delayed focus.
+         * See more details about delayed focus in the {@link AudioFocusRequest} class
+         * documentation.
+         * @param acceptsDelayedFocusGain use {@code true} if the application supports delayed
+         *    focus. If {@code true}, note that you must also set a focus listener to be notified
+         *    of delayed focus gain, with
+         *    {@link #setOnAudioFocusChangeListener(OnAudioFocusChangeListener, Handler)}.
+         * @return this {@code Builder} instance
+         */
+        public @NonNull Builder setAcceptsDelayedFocusGain(boolean acceptsDelayedFocusGain) {
+            mDelayedFocus = acceptsDelayedFocusGain;
+            return this;
+        }
+
+        /**
+         * Builds a new {@code AudioFocusRequest} instance combining all the information gathered
+         * by this {@code Builder}'s configuration methods.
+         * @return the {@code AudioFocusRequest} instance qualified by all the properties set
+         *   on this {@code Builder}.
+         * @throws IllegalArgumentException thrown when focus request is set to accept delayed
+         *    focus, or to pause on duck, but no focus change listener was set.
+         */
+        public AudioFocusRequest build() {
+            if ((mDelayedFocus || mPausesOnDuck) && (mFocusListener == null)) {
+                throw new IllegalArgumentException(
+                        "Can't use delayed focus or pause on duck without a listener");
+            }
+            final int flags = 0
+                    | (mDelayedFocus ? AudioManager.AUDIOFOCUS_FLAG_DELAY_OK : 0)
+                    | (mPausesOnDuck ? AudioManager.AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS : 0);
+            return new AudioFocusRequest(mFocusListener, mListenerHandler,
+                    mAttr, mFocusGain, flags);
+        }
+    }
+}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index a4f2a7e..dc69a69 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -1981,8 +1981,7 @@
     }
 
     /**
-     * @hide
-     * Used to indicate no audio focus has been gained or lost.
+     * Used to indicate no audio focus has been gained or lost, or requested.
      */
     public static final int AUDIOFOCUS_NONE = 0;
 
@@ -2210,11 +2209,11 @@
      */
     public static final int AUDIOFOCUS_REQUEST_GRANTED = 1;
      /**
-      * @hide
       * A focus change request whose granting is delayed: the request was successful, but the
       * requester will only be granted audio focus once the condition that prevented immediate
       * granting has ended.
-      * See {@link #requestAudioFocus(OnAudioFocusChangeListener, AudioAttributes, int, int)}
+      * See {@link #requestAudioFocus(AudioFocusRequest)} and
+      * {@link AudioFocusRequest.Builder#setAcceptsDelayedFocusGain(boolean)}
       */
     public static final int AUDIOFOCUS_REQUEST_DELAYED = 2;
 
@@ -2294,6 +2293,44 @@
             | AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS | AUDIOFOCUS_FLAG_LOCK;
 
     /**
+     * Request audio focus.
+     * See the {@link AudioFocusRequest} for information about the options available to configure
+     * your request, and notification of focus gain and loss.
+     * @param focusRequest a {@link AudioFocusRequest} instance used to configure how focus is
+     *   requested.
+     * @return {@link #AUDIOFOCUS_REQUEST_FAILED}, {@link #AUDIOFOCUS_REQUEST_GRANTED}
+     *     or {@link #AUDIOFOCUS_REQUEST_DELAYED}.
+     *     <br>Note that the return value is never {@link #AUDIOFOCUS_REQUEST_DELAYED} when focus
+     *     is requested without building the {@link AudioFocusRequest} with
+     *     {@link AudioFocusRequest.Builder#setAcceptsDelayedFocusGain(boolean)} set to
+     *     {@code true}.
+     * @throws IllegalArgumentException if passed a null argument
+     */
+    public int requestAudioFocus(@NonNull AudioFocusRequest focusRequest) {
+        if (focusRequest == null) {
+            throw new IllegalArgumentException("Illegal null AudioFocusRequest");
+        }
+        return requestAudioFocus(focusRequest.getOnAudioFocusChangeListener(),
+                focusRequest.getAudioAttributes(),
+                focusRequest.getFocusGain(), focusRequest.getFlags(), null /* no AudioPolicy*/);
+    }
+
+    /**
+     *  Abandon audio focus. Causes the previous focus owner, if any, to receive focus.
+     *  @param focusRequest the {@link AudioFocusRequest} that was used when requesting focus
+     *      with {@link #requestAudioFocus(AudioFocusRequest)}.
+     *  @return {@link #AUDIOFOCUS_REQUEST_FAILED} or {@link #AUDIOFOCUS_REQUEST_GRANTED}
+     *  @throws IllegalArgumentException if passed a null argument
+     */
+    public int abandonAudioFocusRequest(@NonNull AudioFocusRequest focusRequest) {
+        if (focusRequest == null) {
+            throw new IllegalArgumentException("Illegal null AudioFocusRequest");
+        }
+        return abandonAudioFocus(focusRequest.getOnAudioFocusChangeListener(),
+                focusRequest.getAudioAttributes());
+    }
+
+    /**
      * @hide
      * Request audio focus.
      * Send a request to obtain the audio focus. This method differs from
@@ -2373,8 +2410,7 @@
         if (requestAttributes == null) {
             throw new IllegalArgumentException("Illegal null AudioAttributes argument");
         }
-        if ((durationHint < AUDIOFOCUS_GAIN) ||
-                (durationHint > AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE)) {
+        if (!AudioFocusRequest.isValidFocusGain(durationHint)) {
             throw new IllegalArgumentException("Invalid duration hint");
         }
         if (flags != (flags & AUDIOFOCUS_FLAGS_SYSTEM)) {
diff --git a/media/java/android/media/AudioPlaybackConfiguration.java b/media/java/android/media/AudioPlaybackConfiguration.java
index dd9c6a7..6b8a279 100644
--- a/media/java/android/media/AudioPlaybackConfiguration.java
+++ b/media/java/android/media/AudioPlaybackConfiguration.java
@@ -366,11 +366,18 @@
      * @param pw
      */
     public void dump(PrintWriter pw) {
-        pw.println("  ID:" + mPlayerIId
-                + " -- type:" + toLogFriendlyPlayerType(mPlayerType)
-                + " -- u/pid:" + mClientUid +"/" + mClientPid
-                + " -- state:" + toLogFriendlyPlayerState(mPlayerState)
-                + " -- attr:" + mPlayerAttr);
+        pw.println("  " + toLogFriendlyString(this));
+    }
+
+    /**
+     * @hide
+     */
+    public static String toLogFriendlyString(AudioPlaybackConfiguration apc) {
+        return new String("ID:" + apc.mPlayerIId
+                + " -- type:" + toLogFriendlyPlayerType(apc.mPlayerType)
+                + " -- u/pid:" + apc.mClientUid +"/" + apc.mClientPid
+                + " -- state:" + toLogFriendlyPlayerState(apc.mPlayerState)
+                + " -- attr:" + apc.mPlayerAttr);
     }
 
     public static final Parcelable.Creator<AudioPlaybackConfiguration> CREATOR
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index ddd8a65..7f5d3a0 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -79,6 +79,7 @@
  */
 public class AudioTrack extends PlayerBase
                         implements AudioRouting
+                                 , VolumeAutomation
 {
     //---------------------------------------------------------
     // Constants
@@ -1753,6 +1754,12 @@
         return native_getVolumeShaperState(id);
     }
 
+    @Override
+    public @NonNull VolumeShaper createVolumeShaper(
+            @NonNull VolumeShaper.Configuration configuration) {
+        return new VolumeShaper(configuration, this);
+    }
+
     /**
      * Sets the playback sample rate for this track. This sets the sampling rate at which
      * the audio data will be consumed and played back
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index fa4796a..5855984 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -192,7 +192,7 @@
 
     oneway void releasePlayer(in int piid);
 
-    void disableRingtoneSync();
+    void disableRingtoneSync(in int userId);
 
     int getFocusRampTimeMs(in int focusGain, in AudioAttributes attr);
 
diff --git a/media/java/android/media/MediaCas.java b/media/java/android/media/MediaCas.java
new file mode 100644
index 0000000..2e22132
--- /dev/null
+++ b/media/java/android/media/MediaCas.java
@@ -0,0 +1,656 @@
+/*
+ * 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 android.media;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+import android.util.Singleton;
+
+/**
+ * MediaCas can be used to obtain keys for descrambling protected media streams, in
+ * conjunction with {@link android.media.MediaDescrambler}. The MediaCas APIs are
+ * designed to support conditional access such as those in the ISO/IEC13818-1.
+ * The CA system is identified by a 16-bit integer CA_system_id. The scrambling
+ * algorithms are usually proprietary and implemented by vendor-specific CA plugins
+ * installed on the device.
+ * <p>
+ * The app is responsible for constructing a MediaCas object for the CA system it
+ * intends to use. The app can query if a certain CA system is supported using static
+ * method {@link #isSystemIdSupported}. It can also obtain the entire list of supported
+ * CA systems using static method {@link #enumeratePlugins}.
+ * <p>
+ * Once the MediaCas object is constructed, the app should properly provision it by
+ * using method {@link #provision} and/or {@link #processEmm}. The EMMs (Entitlement
+ * management messages) can be distributed out-of-band, or in-band with the stream.
+ * <p>
+ * To descramble elementary streams, the app first calls {@link #openSession} to
+ * generate a sessionId that will uniquely identify a session. A session provides
+ * a context for subsequent key updates and descrambling activities. The ECMs
+ * (Entitlement control messages) are sent to the session via method {@link #processEcm}.
+ * <p>
+ * The app next constructs a MediaDescrambler object, and initializes it with the
+ * sessionId using {@link MediaDescrambler#setMediaCasSession}. This ties the
+ * descrambler to the session, and the descrambler can then be used to descramble
+ * content secured with the session's key, either during extraction, or during decoding
+ * with {@link android.media.MediaCodec}.
+ * <p>
+ * If the app handles sample extraction using its own extractor, it can use
+ * MediaDescrambler to descramble samples into clear buffers (if the session's license
+ * doesn't require secure decoders), or descramble a small amount of data to retrieve
+ * information necessary for the downstream pipeline to process the sample (if the
+ * session's license requires secure decoders).
+ * <p>
+ * If the session requires a secure decoder, a MediaDescrambler needs to be provided to
+ * MediaCodec to descramble samples queued by {@link MediaCodec#queueSecureInputBuffer}
+ * into protected buffers. The app should use {@link MediaCodec#configure(MediaFormat,
+ * android.view.Surface, int, MediaDescrambler)} instead of the normal {@link
+ * MediaCodec#configure(MediaFormat, android.view.Surface, MediaCrypto, int)} method
+ * to configure MediaCodec.
+ * <p>
+ * <h3>Using Android's MediaExtractor</h3>
+ * <p>
+ * If the app uses {@link MediaExtractor}, it can delegate the CAS session
+ * management to MediaExtractor by calling {@link MediaExtractor#setMediaCas}.
+ * MediaExtractor will take over and call {@link #openSession}, {@link #processEmm}
+ * and/or {@link #processEcm}, etc.. if necessary.
+ * <p>
+ * When using {@link MediaExtractor}, the app would still need a MediaDescrambler
+ * to use with {@link MediaCodec} if the licensing requires a secure decoder. The
+ * sessionId of the descrambler can be retrieved by {@link MediaExtractor#getDrmInitData}
+ * and used to initialize a MediaDescrambler object for MediaCodec.
+ * <p>
+ * TODO: determine exception handling schemes.
+ * <p>
+ * <h3>Listeners</h3>
+ * <p>The app may register a listener to receive events from the CA system using
+ * method {@link #setEventListener}. The exact format of the event is scheme-specific
+ * and is not specified by this API.
+ */
+public final class MediaCas {
+    private static final String TAG = "MediaCas";
+    private final ParcelableCasData mCasData = new ParcelableCasData();
+    private ICas mICas;
+    private EventListener mListener;
+    private HandlerThread mHandlerThread;
+    private EventHandler mEventHandler;
+
+    private static final Singleton<IMediaCasService> gDefault =
+            new Singleton<IMediaCasService>() {
+        @Override
+        protected IMediaCasService create() {
+            return IMediaCasService.Stub.asInterface(
+                    ServiceManager.getService("media.cas"));
+        }
+    };
+
+    static IMediaCasService getService() {
+        return gDefault.get();
+    }
+
+    private void validateInternalStates() {
+        if (mICas == null) {
+            throw new IllegalStateException();
+        }
+    }
+
+    private void cleanupAndRethrowIllegalState() {
+        mICas = null;
+        throw new IllegalStateException();
+    }
+
+    private class EventHandler extends Handler
+    {
+        private static final int MSG_CAS_EVENT = 0;
+
+        public EventHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            if (msg.what == MSG_CAS_EVENT) {
+                mListener.onEvent(MediaCas.this, msg.arg1, msg.arg2, (byte[]) msg.obj);
+            }
+        }
+    }
+
+    private final ICasListener.Stub mBinder = new ICasListener.Stub() {
+        @Override
+        public void onEvent(int event, int arg, @Nullable byte[] data)
+                throws RemoteException {
+            mEventHandler.sendMessage(mEventHandler.obtainMessage(
+                    EventHandler.MSG_CAS_EVENT, event, arg, data));
+        }
+    };
+
+    /**
+     * Class for parceling byte array data over ICas binder.
+     */
+    static class ParcelableCasData implements Parcelable {
+        private byte[] mData;
+        private int mOffset;
+        private int mLength;
+
+        ParcelableCasData() {
+            mData = null;
+            mOffset = mLength = 0;
+        }
+
+        private ParcelableCasData(Parcel in) {
+            this();
+        }
+
+        void set(@NonNull byte[] data, int offset, int length) {
+            mData = data;
+            mOffset = offset;
+            mLength = length;
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeByteArray(mData, mOffset, mLength);
+        }
+
+        public static final Parcelable.Creator<ParcelableCasData> CREATOR
+                = new Parcelable.Creator<ParcelableCasData>() {
+            public ParcelableCasData createFromParcel(Parcel in) {
+                return new ParcelableCasData(in);
+            }
+
+            public ParcelableCasData[] newArray(int size) {
+                return new ParcelableCasData[size];
+            }
+        };
+    }
+
+    /**
+     * Describe a CAS plugin with its CA_system_ID and string name.
+     *
+     * Returned as results of {@link #enumeratePlugins}.
+     *
+     */
+    public static class PluginDescriptor {
+        private final int mCASystemId;
+        private final String mName;
+
+        private PluginDescriptor() {
+            mCASystemId = 0xffff;
+            mName = null;
+        }
+
+        PluginDescriptor(int CA_system_id, String name) {
+            mCASystemId = CA_system_id;
+            mName = name;
+        }
+
+        public int getSystemId() {
+            return mCASystemId;
+        }
+
+        @NonNull
+        public String getName() {
+            return mName;
+        }
+
+        @Override
+        public String toString() {
+            return "PluginDescriptor {" + mCASystemId + ", " + mName + "}";
+        }
+    }
+
+    /**
+     * Class for parceling CAS plugin descriptors over IMediaCasService binder.
+     */
+    static class ParcelableCasPluginDescriptor
+        extends PluginDescriptor implements Parcelable {
+
+        private ParcelableCasPluginDescriptor(int CA_system_id, String name) {
+            super(CA_system_id, name);
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            Log.w(TAG, "ParcelableCasPluginDescriptor.writeToParcel shouldn't be called!");
+        }
+
+        public static final Parcelable.Creator<ParcelableCasPluginDescriptor> CREATOR
+                = new Parcelable.Creator<ParcelableCasPluginDescriptor>() {
+            public ParcelableCasPluginDescriptor createFromParcel(Parcel in) {
+                int CA_system_id = in.readInt();
+                String name = in.readString();
+                return new ParcelableCasPluginDescriptor(CA_system_id, name);
+            }
+
+            public ParcelableCasPluginDescriptor[] newArray(int size) {
+                return new ParcelableCasPluginDescriptor[size];
+            }
+        };
+    }
+
+    /**
+     * Query if a certain CA system is supported on this device.
+     *
+     * @param CA_system_id the id of the CA system.
+     *
+     * @return Whether the specified CA system is supported on this device.
+     */
+    public static boolean isSystemIdSupported(int CA_system_id) {
+        IMediaCasService service = getService();
+
+        if (service != null) {
+            try {
+                return service.isSystemIdSupported(CA_system_id);
+            } catch (RemoteException e) {
+            }
+        }
+        return false;
+    }
+
+    /**
+     * List all available CA plugins on the device.
+     *
+     * @return an array of descriptors for the available CA plugins.
+     */
+    public static PluginDescriptor[] enumeratePlugins() {
+        IMediaCasService service = getService();
+
+        if (service != null) {
+            try {
+                ParcelableCasPluginDescriptor[] descriptors = service.enumeratePlugins();
+                if (descriptors.length == 0) {
+                    return null;
+                }
+                PluginDescriptor[] results = new PluginDescriptor[descriptors.length];
+                for (int i = 0; i < results.length; i++) {
+                    results[i] = descriptors[i];
+                }
+                return results;
+            } catch (RemoteException e) {
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Instantiate a CA system of the specified system id.
+     *
+     * @param CA_system_id The system id of the CA system.
+     *
+     * @throws UnsupportedCasException if the device does not support the
+     * specified CA system.
+     */
+    public MediaCas(int CA_system_id) throws UnsupportedCasException {
+        try {
+            mICas = getService().createPlugin(CA_system_id, mBinder);
+        } catch(Exception e) {
+            Log.e(TAG, "Failed to create plugin: " + e);
+            mICas = null;
+        } finally {
+            if (mICas == null) {
+                throw new UnsupportedCasException(
+                        "Unsupported CA_system_id " + CA_system_id);
+            }
+        }
+    }
+
+    IBinder getBinder() {
+        validateInternalStates();
+
+        return mICas.asBinder();
+    }
+
+    /**
+     * An interface registered by the caller to {@link #setEventListener}
+     * to receives scheme-specific notifications from a MediaCas instance.
+     */
+    public interface EventListener {
+        /**
+         * Notify the listener of a scheme-specific event from the CA system.
+         *
+         * @param MediaCas the MediaCas object to receive this event.
+         * @param event an integer whose meaning is scheme-specific.
+         * @param arg an integer whose meaning is scheme-specific.
+         * @param data a byte array of data whose format and meaning are
+         * scheme-specific.
+         */
+        void onEvent(MediaCas MediaCas, int event, int arg, @Nullable byte[] data);
+    }
+
+    /**
+     * Set an event listener to receive notifications from the MediaCas instance.
+     *
+     * @param listener the event listener to be set.
+     * @param handler the handler whose looper the event listener will be called on.
+     * If handler is null, we'll try to use current thread's looper, or the main
+     * looper. If neither are available, an internal thread will be created instead.
+     */
+    public void setEventListener(
+            @Nullable EventListener listener, @Nullable Handler handler) {
+        mListener = listener;
+
+        if (mListener == null) {
+            mEventHandler = null;
+            return;
+        }
+
+        Looper looper = (handler != null) ? handler.getLooper() : null;
+        if (looper == null
+                && (looper = Looper.myLooper()) == null
+                && (looper = Looper.getMainLooper()) == null) {
+            if (mHandlerThread == null || !mHandlerThread.isAlive()) {
+                mHandlerThread = new HandlerThread("MediaCasEventThread",
+                        Process.THREAD_PRIORITY_FOREGROUND);
+                mHandlerThread.start();
+            }
+            looper = mHandlerThread.getLooper();
+        }
+        mEventHandler = new EventHandler(looper);
+    }
+
+    /*
+     * TODO: handle ServiceSpecificException from the IMediaCas
+     * All Drm-specific failures will be thrown by mICas as
+     * ServiceSpecificException exception with Drm error code.
+     * These need to be re-thrown as crypto exceptions.
+     */
+
+    /**
+     * Send the private data for the CA system.
+     *
+     * @param data byte array of the private data.
+     *
+     * @throws IllegalStateException if the MediaCas instance is not valid.
+     */
+    /*
+     * TODO: need to re-throw DRM-specific exceptions
+     */
+    public void setPrivateData(@NonNull byte[] data) {
+        validateInternalStates();
+
+        try {
+            mICas.setPrivateData(data);
+        } catch (RemoteException e) {
+            cleanupAndRethrowIllegalState();
+        }
+    }
+
+    /**
+     * Open a session for the specified program.
+     *
+     * @param programNumber program_number of the program (as in ISO/IEC13818-1).
+     *
+     * @return session id of the newly opened session.
+     *
+     * @throws IllegalStateException if the MediaCas instance is not valid,
+     * or IllegalArgumentException if a session for the program already exists.
+     */
+    public byte[] openSession(int programNumber) {
+        validateInternalStates();
+
+        try {
+            return mICas.openSession(programNumber);
+        } catch (RemoteException e) {
+            cleanupAndRethrowIllegalState();
+        }
+        return null;
+    }
+
+    /**
+     * Open a session for the specified stream.
+     *
+     * @param programNumber program_number of the stream (as in ISO/IEC13818-1).
+     * @param elementaryPID elementary_PID of the stream (as in ISO/IEC13818-1).
+     *
+     * @return session id of the newly opened session.
+     *
+     * @throws IllegalStateException if the MediaCas instance is not valid,
+     * or IllegalArgumentException if a session for the stream already exists.
+     */
+    public byte[] openSession(int programNumber, int elementaryPID) {
+        validateInternalStates();
+
+        try {
+            return mICas.openSessionForStream(programNumber, elementaryPID);
+        } catch (RemoteException e) {
+            cleanupAndRethrowIllegalState();
+        }
+        return null;
+    }
+
+    /**
+     * Close the specified session.
+     *
+     * @param sessionId the session to be closed.
+     *
+     * @throws IllegalStateException if the MediaCas instance is not valid,
+     * or IllegalArgumentException if the session is not valid.
+     */
+    public void closeSession(@NonNull byte[] sessionId) {
+        validateInternalStates();
+
+        try {
+            mICas.closeSession(sessionId);
+        } catch (RemoteException e) {
+            cleanupAndRethrowIllegalState();
+        }
+    }
+
+    /**
+     * Set the private data for a session.
+     *
+     * @param sessionId the session for which the private data is intended.
+     * @param data byte array of the private data.
+     *
+     * @throws IllegalStateException if the MediaCas instance is not valid,
+     * or IllegalArgumentException if the session is not valid.
+     */
+    /*
+     * TODO: need to re-throw DRM-specific exceptions
+     */
+    public void setSessionPrivateData(@NonNull byte[] sessionId, @NonNull byte[] data) {
+        validateInternalStates();
+
+        try {
+            mICas.setSessionPrivateData(sessionId, data);
+        } catch (RemoteException e) {
+            cleanupAndRethrowIllegalState();
+        }
+    }
+
+    /**
+     * Send a received ECM packet to the specified session of the CA system.
+     *
+     * @param sessionId the session for which the ECM is intended.
+     * @param data byte array of the ECM data.
+     * @param offset position within data where the ECM data begins.
+     * @param length length of the data (starting from offset).
+     *
+     * @throws IllegalStateException if the MediaCas instance is not valid,
+     * or IllegalArgumentException if the session is not valid.
+     */
+    /*
+     * TODO: need to re-throw DRM-specific exceptions
+     */
+    public void processEcm(
+            @NonNull byte[] sessionId, @NonNull byte[] data, int offset, int length) {
+        validateInternalStates();
+
+        try {
+            mCasData.set(data, offset, length);
+            mICas.processEcm(sessionId, mCasData);
+        } catch (RemoteException e) {
+            cleanupAndRethrowIllegalState();
+        }
+    }
+
+    /**
+     * Send a received ECM packet to the specified session of the CA system.
+     * This is similar to {@link #processEcm(byte[], byte[], int, int)}
+     * except that the entire byte array is sent.
+     *
+     * @param sessionId the session for which the ECM is intended.
+     * @param data byte array of the ECM data.
+     *
+     * @throws IllegalStateException if the MediaCas instance is not valid,
+     * or IllegalArgumentException if the session is not valid.
+     */
+    /*
+     * TODO: need to re-throw DRM-specific exceptions
+     */
+    public void processEcm(@NonNull byte[] sessionId, @NonNull byte[] data) {
+        processEcm(sessionId, data, 0, data.length);
+    }
+
+    /**
+     * Send a received EMM packet to the CA system.
+     *
+     * @param data byte array of the EMM data.
+     * @param offset position within data where the EMM data begins.
+     * @param length length of the data (starting from offset).
+     *
+     * @throws IllegalStateException if the MediaCas instance is not valid.
+     */
+    /*
+     * TODO: need to re-throw DRM-specific exceptions
+     */
+    public void processEmm(@NonNull byte[] data, int offset, int length) {
+        validateInternalStates();
+
+        try {
+            mCasData.set(data, offset, length);
+            mICas.processEmm(mCasData);
+        } catch (RemoteException e) {
+            cleanupAndRethrowIllegalState();
+        }
+    }
+
+    /**
+     * Send a received EMM packet to the CA system. This is similar to
+     * {@link #processEmm(byte[], int, int)} except that the entire byte
+     * array is sent.
+     *
+     * @param data byte array of the EMM data.
+     *
+     * @throws IllegalStateException if the MediaCas instance is not valid.
+     */
+    /*
+     * TODO: need to re-throw DRM-specific exceptions
+     */
+    public void processEmm(@NonNull byte[] data) {
+        processEmm(data, 0, data.length);
+    }
+
+    /**
+     * Send an event to a CA system. The format of the event is scheme-specific
+     * and is opaque to the framework.
+     *
+     * @param event an integer denoting a scheme-specific event to be sent.
+     * @param arg a scheme-specific integer argument for the event.
+     * @param data a byte array containing scheme-specific data for the event.
+     *
+     * @throws IllegalStateException if the MediaCas instance is not valid.
+     */
+    public void sendEvent(int event, int arg, @Nullable byte[] data) {
+        validateInternalStates();
+
+        try {
+            mICas.sendEvent(event, arg, data);
+        } catch (RemoteException e) {
+            cleanupAndRethrowIllegalState();
+        }
+    }
+
+    /**
+     * Initiate a provisioning operation for a CA system.
+     *
+     * @param provisionString string containing information needed for the
+     * provisioning operation, the format of which is scheme and implementation
+     * specific.
+     *
+     * @throws IllegalStateException if the MediaCas instance is not valid.
+     */
+    public void provision(@NonNull String provisionString) {
+        validateInternalStates();
+
+        try {
+            mICas.provision(provisionString);
+        } catch (RemoteException e) {
+            cleanupAndRethrowIllegalState();
+        }
+    }
+
+    /**
+     * Notify the CA system to refresh entitlement keys.
+     *
+     * @param refreshType the type of the refreshment.
+     * @param refreshData private data associated with the refreshment.
+     *
+     * @throws IllegalStateException if the MediaCas instance is not valid.
+     */
+    /*
+     * TODO: define enums for refreshType
+     */
+    public void refreshEntitlements(int refreshType, @Nullable byte[] refreshData) {
+        validateInternalStates();
+
+        try {
+            mICas.refreshEntitlements(refreshType, refreshData);
+        } catch (RemoteException e) {
+            cleanupAndRethrowIllegalState();
+        }
+    }
+
+    /**
+     * Release the MediaCas instance.
+     */
+    public void release() {
+        if (mICas != null) {
+            try {
+                mICas.release();
+            } catch (RemoteException e) {
+            } finally {
+                mICas = null;
+            }
+        }
+    }
+
+    @Override
+    protected void finalize() {
+        release();
+    }
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/logging/legacy/Util.java b/media/java/android/media/MediaCasException.java
similarity index 75%
copy from core/java/com/android/internal/logging/legacy/Util.java
copy to media/java/android/media/MediaCasException.java
index 99f71ca..1d5d3cd 100644
--- a/core/java/com/android/internal/logging/legacy/Util.java
+++ b/media/java/android/media/MediaCasException.java
@@ -13,13 +13,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.internal.logging.legacy;
+
+package android.media;
 
 /**
- * Created by cwren on 11/21/16.
+ * Base class for MediaCas exceptions
  */
-public class Util {
-    public static boolean debug() {
-        return false;
+public class MediaCasException extends Exception {
+    public MediaCasException(String detailMessage) {
+        super(detailMessage);
     }
 }
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 75ccffe..d264127 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -25,6 +25,7 @@
 import android.media.MediaCodecInfo.CodecCapabilities;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
 import android.view.Surface;
@@ -1567,6 +1568,13 @@
      */
     public static final int BUFFER_FLAG_END_OF_STREAM = 4;
 
+    /**
+     * This indicates that the buffer only contains part of a frame,
+     * and the decoder should batch the data until a buffer without
+     * this flag appears before decoding the frame.
+     */
+    public static final int BUFFER_FLAG_PARTIAL_FRAME = 8;
+
     /** @hide */
     @IntDef(
         flag = true,
@@ -1575,6 +1583,7 @@
             BUFFER_FLAG_KEY_FRAME,
             BUFFER_FLAG_CODEC_CONFIG,
             BUFFER_FLAG_END_OF_STREAM,
+            BUFFER_FLAG_PARTIAL_FRAME,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface BufferFlag {}
@@ -1851,6 +1860,48 @@
             @Nullable MediaFormat format,
             @Nullable Surface surface, @Nullable MediaCrypto crypto,
             @ConfigureFlag int flags) {
+        configure(format, surface, crypto, null, flags);
+    }
+
+    /**
+     * Configure a component to be used with a descrambler.
+     * @param format The format of the input data (decoder) or the desired
+     *               format of the output data (encoder). Passing {@code null}
+     *               as {@code format} is equivalent to passing an
+     *               {@link MediaFormat#MediaFormat an empty mediaformat}.
+     * @param surface Specify a surface on which to render the output of this
+     *                decoder. Pass {@code null} as {@code surface} if the
+     *                codec does not generate raw video output (e.g. not a video
+     *                decoder) and/or if you want to configure the codec for
+     *                {@link ByteBuffer} output.
+     * @param flags   Specify {@link #CONFIGURE_FLAG_ENCODE} to configure the
+     *                component as an encoder.
+     * @param descrambler Specify a descrambler object to facilitate secure
+     *                descrambling of the media data. descrambler must not be
+     *                null if this method is used. For non-secure codecs, use
+     *                {@link #configure} and with null crypto parameter.
+     * @throws IllegalArgumentException if the surface has been released (or is invalid),
+     * or the format is unacceptable (e.g. missing a mandatory key),
+     * or the flags are not set properly
+     * (e.g. missing {@link #CONFIGURE_FLAG_ENCODE} for an encoder).
+     * @throws IllegalStateException if not in the Uninitialized state.
+     * @throws CryptoException upon DRM error.
+     * @throws CodecException upon codec error.
+     */
+    public void configure(
+            @Nullable MediaFormat format, @Nullable Surface surface,
+            @ConfigureFlag int flags, @NonNull MediaDescrambler descrambler) {
+        configure(format, surface, null, descrambler.getBinder(), flags);
+    }
+
+    private void configure(
+            @Nullable MediaFormat format, @Nullable Surface surface,
+            @Nullable MediaCrypto crypto, @Nullable IBinder descramblerBinder,
+            @ConfigureFlag int flags) {
+        if (crypto != null && descramblerBinder != null) {
+            throw new IllegalArgumentException("Can't use crypto and descrambler together!");
+        }
+
         String[] keys = null;
         Object[] values = null;
 
@@ -1881,7 +1932,7 @@
 
         mHasSurface = surface != null;
 
-        native_configure(keys, values, surface, crypto, flags);
+        native_configure(keys, values, surface, crypto, descramblerBinder, flags);
     }
 
     /**
@@ -1959,7 +2010,8 @@
 
     private native final void native_configure(
             @Nullable String[] keys, @Nullable Object[] values,
-            @Nullable Surface surface, @Nullable MediaCrypto crypto, @ConfigureFlag int flags);
+            @Nullable Surface surface, @Nullable MediaCrypto crypto,
+            @Nullable IBinder descramblerBinder, @ConfigureFlag int flags);
 
     /**
      * Requests a Surface to use as the input to an encoder, in place of input buffers.  This
@@ -3136,9 +3188,55 @@
     /**
      *  Returns Analytics/Metrics data about the current content being
      *
-     * @return a Bundle containint the set of attributes and values available
+     * @return a Bundle containing the set of attributes and values available
      * for the media being handled by this instance of MediaCodec
      *
+     *  <table style="width: 0%">
+     *   <thead>
+     *    <tr>
+     *     <th>Key</th>
+     *     <th>Type</th>
+     *     <th>Description</th>
+     *    </tr>
+     *   </thead>
+     *   <tbody>
+     *    <tr>
+     *     <td>{@code "codec"}</td>
+     *     <td>String</td>
+     *     <td>Identifies the particular codec in use</td>
+     *    </tr><tr>
+     *     <td>{@code "mime"}</td>
+     *     <td>String</td>
+     *     <td>Mime type of the media being encoded/decoded</td>
+     *    </tr><tr>
+     *     <td>{@code "mode"}</td>
+     *     <td>String</td>
+     *     <td>"Audio" or "Video"</td>
+     *    </tr><tr>
+     *     <td>{@code "secure"}</td>
+     *     <td>Integer</td>
+     *     <td>Indicates whether the code is operating on secure content and
+     *         may also use capabilities in android.media.MediaCrypto</td>
+     *    </tr><tr>
+     *     <td>{@code "height"}</td>
+     *     <td>Integer</td>
+     *     <td>Height (pixels); valid only when mode=video</td>
+     *    </tr><tr>
+     *     <td>{@code "width"}</td>
+     *     <td>Integer</td>
+     *     <td>Width (pixels); valid only when mode=video</td>
+     *    </tr><tr>
+     *     <td>{@code "rotation"}</td>
+     *     <td>Integer</td>
+     *     <td>rotation (degrees) to orient the video onto the target surface;
+     *         valid only when mode=video. Note there may be additional
+     *         rotations applied when the surface is mapped to the screen.</td>
+     *    </tr>
+     *   </tbody>
+     *  </table>
+     *
+     *  Additional fields specific to individual codecs will also appear in
+     *  the return value.
      */
     public native Bundle getMetrics();
 
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 8ada295f..c157a47 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -460,6 +460,11 @@
         public static final String FEATURE_TunneledPlayback       = "tunneled-playback";
 
         /**
+         * <b>video decoder only</b>: codec supports queuing partial frames.
+         */
+        public static final String FEATURE_PartialFrame = "partial-frame";
+
+        /**
          * <b>video encoder only</b>: codec supports intra refresh.
          */
         public static final String FEATURE_IntraRefresh = "intra-refresh";
@@ -489,6 +494,7 @@
             new Feature(FEATURE_AdaptivePlayback, (1 << 0), true),
             new Feature(FEATURE_SecurePlayback,   (1 << 1), false),
             new Feature(FEATURE_TunneledPlayback, (1 << 2), false),
+            new Feature(FEATURE_PartialFrame,     (1 << 3), false),
         };
 
         private static final Feature[] encoderFeatures = {
@@ -1113,6 +1119,10 @@
                 sampleRates = new int[] { 8000 };
                 bitRates = Range.create(13000, 13000);
                 maxChannels = 1;
+            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AC3)) {
+                maxChannels = 6;
+            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_EAC3)) {
+                maxChannels = 16;
             } else {
                 Log.w(TAG, "Unsupported mime " + mime);
                 mParent.mError |= ERROR_UNSUPPORTED;
diff --git a/media/java/android/media/MediaDescrambler.java b/media/java/android/media/MediaDescrambler.java
new file mode 100644
index 0000000..f5eede8
--- /dev/null
+++ b/media/java/android/media/MediaDescrambler.java
@@ -0,0 +1,249 @@
+/*
+ * 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 android.media;
+
+import android.annotation.NonNull;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.nio.ByteBuffer;
+
+/**
+ * MediaDescrambler class can be used in conjunction with {@link android.media.MediaCodec}
+ * and {@link android.media.MediaExtractor} to decode media data scrambled by conditional
+ * access (CA) systems such as those in the ISO/IEC13818-1.
+ *
+ * A MediaDescrambler object is initialized from a session opened by a MediaCas object,
+ * and can be used to descramble media streams scrambled with that session's keys.
+ *
+ * Scrambling schemes are identified by 16-bit unsigned integer as in CA_system_id.
+ *
+ */
+public final class MediaDescrambler {
+    private static final String TAG = "MediaDescrambler";
+    private IDescrambler mIDescrambler;
+
+    private final void validateInternalStates() {
+        if (mIDescrambler == null) {
+            throw new IllegalStateException();
+        }
+    }
+
+    private final void cleanupAndRethrowIllegalState() {
+        mIDescrambler = null;
+        throw new IllegalStateException();
+    }
+
+    /**
+     * Class for parceling descrambling parameters over IDescrambler binder.
+     */
+    static class DescrambleInfo implements Parcelable {
+        private DescrambleInfo() {
+            // TODO: implement
+        }
+
+        private DescrambleInfo(Parcel in) {
+            // TODO: disable
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            // TODO: implement
+        }
+
+        public static final Parcelable.Creator<DescrambleInfo> CREATOR
+                = new Parcelable.Creator<DescrambleInfo>() {
+            public DescrambleInfo createFromParcel(Parcel in) {
+                return new DescrambleInfo(in);
+            }
+
+            public DescrambleInfo[] newArray(int size) {
+                return new DescrambleInfo[size];
+            }
+        };
+    }
+
+    /**
+     * Instantiate a MediaDescrambler.
+     *
+     * @param CA_system_id The system id of the scrambling scheme.
+     *
+     * @throws UnsupportedCasException if the scrambling scheme is not supported.
+     */
+    public MediaDescrambler(int CA_system_id) throws UnsupportedCasException {
+        try {
+            mIDescrambler = MediaCas.getService().createDescrambler(CA_system_id);
+        } catch(Exception e) {
+            Log.e(TAG, "Failed to create descrambler: " + e);
+            mIDescrambler = null;
+        } finally {
+            if (mIDescrambler == null) {
+                throw new UnsupportedCasException("Unsupported CA_system_id " + CA_system_id);
+            }
+        }
+        native_setup(mIDescrambler.asBinder());
+    }
+
+    IBinder getBinder() {
+        validateInternalStates();
+
+        return mIDescrambler.asBinder();
+    }
+
+    /*
+     * TODO: handle ServiceSpecificException from the mIDescrambler
+     * All Drm-specific failures will be thrown by mIDescrambler as
+     * ServiceSpecificException exception with Drm error code.
+     * These need to be re-thrown as crypto exceptions.
+     */
+
+    /**
+     * Query if the scrambling scheme requires the use of a secure decoder
+     * to decode data of the given mime type.
+     *
+     * @param mime The mime type of the media data
+     *
+     * @throws IllegalStateException if the descrambler instance is not valid.
+     */
+    public final boolean requiresSecureDecoderComponent(@NonNull String mime) {
+        validateInternalStates();
+
+        try {
+            return mIDescrambler.requiresSecureDecoderComponent(mime);
+        } catch (RemoteException e) {
+            cleanupAndRethrowIllegalState();
+        }
+        return true;
+    }
+
+    /**
+     * Associate a MediaCas session with this MediaDescrambler instance.
+     * The MediaCas session is used to securely load decryption keys for
+     * the descrambler. The crypto keys loaded through the MediaCas session
+     * may be selected for use during the descrambling operation performed
+     * by {@link android.media.MediaExtractor or @link
+     * android.media.MediaCodec#queueSecureInputBuffer} by specifying even
+     * or odd key in the {@link android.media.MediaCodec.CryptoInfo#key} field.
+     *
+     * @param sessionId the MediaCas sessionId to associate with this
+     * MediaDescrambler instance.
+     *
+     * @throws IllegalStateException if the descrambler instance is not valid,
+     * or IllegalArgumentException if the sessionId is not valid.
+     */
+    public final void setMediaCasSession(@NonNull byte[] sessionId) {
+        validateInternalStates();
+
+        try {
+            mIDescrambler.setMediaCasSession(sessionId);
+        } catch (RemoteException e) {
+            cleanupAndRethrowIllegalState();
+        }
+    }
+
+    /**
+     * Descramble a ByteBuffer of data described by a
+     * {@link android.media.MediaCodec.CryptoInfo} structure.
+     *
+     * @param srcBuf ByteBuffer containing the scrambled data.
+     * @param srcPos position within src where the scrambled data starts.
+     * @param dstBuf ByteBuffer to descramble into. If null, descrambling will happen
+     * in-place and src will be used as dst.
+     * @param dstPos position within dst to put the descrambled data.
+     * @param cryptoInfo a {@link android.media.MediaCodec.CryptoInfo} structure
+     * describing the subsamples contained in src.
+     *
+     * @return number of bytes that have been successfully descrambled, with negative
+     * values indicating errors.
+     *
+     * @throws IllegalStateException if the descrambler instance is not valid.
+     */
+    /*
+     * TODO: throw DRM-specific exception if decrambling is failing.
+     */
+    public final int descramble(
+            @NonNull ByteBuffer srcBuf, int srcPos, ByteBuffer dstBuf, int dstPos,
+            @NonNull MediaCodec.CryptoInfo cryptoInfo) {
+        validateInternalStates();
+
+        if (cryptoInfo.numSubSamples <= 0) {
+            throw new IllegalArgumentException(
+                    "Invalid CryptoInfo: invalid numSubSamples=" + cryptoInfo.numSubSamples);
+        } else if (cryptoInfo.numBytesOfClearData == null
+                && cryptoInfo.numBytesOfEncryptedData == null) {
+            throw new IllegalArgumentException(
+                    "Invalid CryptoInfo: clearData and encryptedData size arrays are both null!");
+        } else if (cryptoInfo.numBytesOfClearData != null
+                && cryptoInfo.numBytesOfClearData.length < cryptoInfo.numSubSamples) {
+            throw new IllegalArgumentException(
+                    "Invalid CryptoInfo: numBytesOfClearData is too small!");
+        } else if (cryptoInfo.numBytesOfEncryptedData != null
+                && cryptoInfo.numBytesOfEncryptedData.length < cryptoInfo.numSubSamples) {
+            throw new IllegalArgumentException(
+                    "Invalid CryptoInfo: numBytesOfEncryptedData is too small!");
+        } else if (cryptoInfo.key == null || cryptoInfo.key.length != 16) {
+            throw new IllegalArgumentException(
+                    "Invalid CryptoInfo: key array is invalid!");
+        }
+
+        return native_descramble(
+                cryptoInfo.key[0],
+                cryptoInfo.numSubSamples,
+                cryptoInfo.numBytesOfClearData,
+                cryptoInfo.numBytesOfEncryptedData,
+                srcBuf, srcPos, dstBuf, dstPos);
+    }
+
+    public final void release() {
+        if (mIDescrambler != null) {
+            try {
+                mIDescrambler.release();
+            } catch (RemoteException e) {
+            } finally {
+                mIDescrambler = null;
+            }
+        }
+        native_release();
+    }
+
+    @Override
+    protected void finalize() {
+        release();
+    }
+
+    private static native final void native_init();
+    private native final void native_setup(@NonNull IBinder decramblerBinder);
+    private native final void native_release();
+    private native final int native_descramble(
+            byte key, int numSubSamples, int[] numBytesOfClearData, int[] numBytesOfEncryptedData,
+            @NonNull ByteBuffer srcBuf, int srcOffset, ByteBuffer dstBuf, int dstOffset);
+
+    static {
+        System.loadLibrary("media_jni");
+        native_init();
+    }
+
+    private long mNativeContext;
+}
\ No newline at end of file
diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index 2ca36ea..b9e409d 100644
--- a/media/java/android/media/MediaExtractor.java
+++ b/media/java/android/media/MediaExtractor.java
@@ -247,6 +247,22 @@
     public native final void setDataSource(
             @NonNull FileDescriptor fd, long offset, long length) throws IOException;
 
+    /**
+     * Sets the MediaCas instance to use. This should be called after a
+     * successful setDataSource() if at least one track reports mime type
+     * of {@link android.media.MediaFormat#MIMETYPE_AUDIO_SCRAMBLED}
+     * or {@link android.media.MediaFormat#MIMETYPE_VIDEO_SCRAMBLED}.
+     * Stream parsing will not proceed until a valid MediaCas object
+     * is provided.
+     *
+     * @param mediaCas the MediaCas object to use.
+     */
+    public final void setMediaCas(@NonNull MediaCas mediaCas) {
+        nativeSetMediaCas(mediaCas.getBinder());
+    }
+
+    private native final void nativeSetMediaCas(@NonNull IBinder casBinder);
+
     @Override
     protected void finalize() {
         native_finalize();
@@ -290,6 +306,31 @@
                     return initDataMap.get(schemeUuid);
                 }
             };
+        } else if (formatMap.containsKey("mime")
+                && "video/mp2ts".equals(formatMap.get("mime"))) {
+            final Map<UUID, DrmInitData.SchemeInitData> initDataMap =
+                    new HashMap<UUID, DrmInitData.SchemeInitData>();
+
+            int numTracks = getTrackCount();
+            for (int i = 0; i < numTracks; ++i) {
+                Map<String, Object> trackFormatMap = getTrackFormatNative(i);
+                if (!trackFormatMap.containsKey("cas")) {
+                    continue;
+                }
+                ByteBuffer buf = (ByteBuffer) trackFormatMap.get("cas");
+                buf.rewind();
+                final byte[] data = new byte[buf.remaining()];
+                buf.get(data);
+                initDataMap.put(new UUID(0, i), new DrmInitData.SchemeInitData("cas", data));
+            }
+            if (initDataMap.isEmpty()) {
+                return null;
+            }
+            return new DrmInitData() {
+                public SchemeInitData get(UUID schemeUuid) {
+                    return initDataMap.get(schemeUuid);
+                }
+            };
         } else {
             int numTracks = getTrackCount();
             for (int i = 0; i < numTracks; ++i) {
@@ -307,8 +348,8 @@
                     }
                 };
             }
+            return null;
         }
-        return null;
     }
 
     /**
@@ -557,12 +598,22 @@
      */
     public static final int SAMPLE_FLAG_ENCRYPTED = 2;
 
+    /**
+     * This indicates that the buffer only contains part of a frame,
+     * and the decoder should batch the data until a buffer without
+     * this flag appears before decoding the frame.
+     *
+     * @see MediaCodec#BUFFER_FLAG_PARTIAL_FRAME
+     */
+    public static final int SAMPLE_FLAG_PARTIAL_FRAME = 4;
+
     /** @hide */
     @IntDef(
         flag = true,
         value = {
             SAMPLE_FLAG_SYNC,
             SAMPLE_FLAG_ENCRYPTED,
+            SAMPLE_FLAG_PARTIAL_FRAME,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface SampleFlag {}
@@ -605,6 +656,33 @@
      * @return the set of keys and values available for the media being
      * handled by this instance of MediaExtractor
      *
+     *  <table style="width: 0%">
+     *   <thead>
+     *    <tr>
+     *     <th>Key</th>
+     *     <th>Type</th>
+     *     <th>Description</th>
+     *    </tr>
+     *   </thead>
+     *   <tbody>
+     *    <tr>
+     *     <td>{@code "fmt"}</td>
+     *     <td>String</td>
+     *     <td>The container format (which determines the handler)</td>
+     *    </tr><tr>
+     *     <td>{@code "mime"}</td>
+     *     <td>String</td>
+     *     <td>Mime type of the container.</td>
+     *    </tr><tr>
+     *     <td>{@code "ntrk"}</td>
+     *     <td>Integer</td>
+     *     <td>Number of tracks in the container</td>
+     *    </tr>
+     *   </tbody>
+     *  </table>
+     *
+     *  Additional fields specific to individual codecs will also appear in
+     *  the return value.
      */
     public native Bundle getMetrics();
 
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index d74aa81..e77c00b 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -53,6 +53,7 @@
  *         time-interval between key frames.
  *         Float support added in {@link android.os.Build.VERSION_CODES#N_MR1}</td></tr>
  * <tr><td>{@link #KEY_INTRA_REFRESH_PERIOD}</td><td>Integer</td><td><b>encoder-only</b>, optional</td></tr>
+ * <tr><td>{@link #KEY_LATENCY}</td><td>Integer</td><td><b>encoder-only</b>, optional</td></tr>
  * <tr><td>{@link #KEY_MAX_WIDTH}</td><td>Integer</td><td><b>decoder-only</b>, optional, max-resolution width</td></tr>
  * <tr><td>{@link #KEY_MAX_HEIGHT}</td><td>Integer</td><td><b>decoder-only</b>, optional, max-resolution height</td></tr>
  * <tr><td>{@link #KEY_REPEAT_PREVIOUS_FRAME_AFTER}</td><td>Long</td><td><b>encoder in surface-mode
@@ -105,6 +106,8 @@
     public static final String MIMETYPE_VIDEO_H263 = "video/3gpp";
     public static final String MIMETYPE_VIDEO_MPEG2 = "video/mpeg2";
     public static final String MIMETYPE_VIDEO_RAW = "video/raw";
+    public static final String MIMETYPE_VIDEO_DOLBY_VISION = "video/dolby-vision";
+    public static final String MIMETYPE_VIDEO_SCRAMBLED = "video/scrambled";
 
     public static final String MIMETYPE_AUDIO_AMR_NB = "audio/3gpp";
     public static final String MIMETYPE_AUDIO_AMR_WB = "audio/amr-wb";
@@ -120,7 +123,7 @@
     public static final String MIMETYPE_AUDIO_MSGSM = "audio/gsm";
     public static final String MIMETYPE_AUDIO_AC3 = "audio/ac3";
     public static final String MIMETYPE_AUDIO_EAC3 = "audio/eac3";
-    public static final String MIMETYPE_VIDEO_DOLBY_VISION = "video/dolby-vision";
+    public static final String MIMETYPE_AUDIO_SCRAMBLED = "audio/scrambled";
 
     /**
      * MIME type for WebVTT subtitle data.
@@ -575,6 +578,18 @@
     public static final String KEY_LEVEL = "level";
 
     /**
+    * An optional key describing the desired encoder latency in frames. This is an optional
+    * parameter that applies only to video encoders. If encoder supports it, it should ouput
+    * at least one output frame after being queued the specified number of frames. This key
+    * is ignored if the video encoder does not support the latency feature. Use the output
+    * format to verify that this feature was enabled and the actual value used by the encoder.
+    * <p>
+    * If the key is not specified, the default latency will be implenmentation specific.
+    * The associated value is an integer.
+    */
+    public static final String KEY_LATENCY = "latency";
+
+    /**
      * A key describing the desired clockwise rotation on an output surface.
      * This key is only used when the codec is configured using an output surface.
      * The associated value is an integer, representing degrees. Supported values
diff --git a/media/java/android/media/MediaMuxer.java b/media/java/android/media/MediaMuxer.java
index aacce91..832b297 100644
--- a/media/java/android/media/MediaMuxer.java
+++ b/media/java/android/media/MediaMuxer.java
@@ -68,44 +68,46 @@
 
  <h4>Metadata Track</h4>
  <p>
-  Metadata is usefule in carrying extra information that correlated with video or audio to
-  facilate offline processing, e.g. gyro signals from the sensor. Meatadata track is only
-  supported in MP4 format. When adding a metadata track, track's mime format must start with
-  prefix "application/", e.g. "applicaton/gyro". Metadata's format/layout will be defined by
-  the application. The generated MP4 file uses TextMetaDataSampleEntry defined in section 12.3.3.2
-  of the ISOBMFF to signal the metadata's mime format. When using {@link android.media.MediaExtractor}
-  to extract the file with metadata track, the mime format of the metadata will be extracted into
-  {@link android.media.MediaFormat}.
+  Per-frame metadata is useful in carrying extra information that correlated with video or audio to
+  facilitate offline processing, e.g. gyro signals from the sensor could help video stabilization when
+  doing offline processing. Metaadata track is only supported in MP4 container. When adding a new
+  metadata track, track's mime format must start with prefix "application/", e.g. "applicaton/gyro".
+  Metadata's format/layout will be defined by the application. Writing metadata is nearly the same as
+  writing video/audio data except that the data will not be from mediacodec. Application just needs
+  to pass the bytebuffer that contains the metadata and also the associated timestamp to the
+  {@link #writeSampleData} api. The timestamp must be in the same time base as video and audio. The
+  generated MP4 file uses TextMetaDataSampleEntry defined in section 12.3.3.2 of the ISOBMFF to signal
+  the metadata's mime format. When using{@link android.media.MediaExtractor} to extract the file with
+  metadata track, the mime format of the metadata will be extracted into {@link android.media.MediaFormat}.
 
  <pre class=prettyprint>
    MediaMuxer muxer = new MediaMuxer("temp.mp4", OutputFormat.MUXER_OUTPUT_MPEG_4);
-   // More often, the MediaFormat will be retrieved from MediaCodec.getOutputFormat()
-   // or MediaExtractor.getTrackFormat().
+   // SetUp Video/Audio Tracks.
    MediaFormat audioFormat = new MediaFormat(...);
    MediaFormat videoFormat = new MediaFormat(...);
+   int audioTrackIndex = muxer.addTrack(audioFormat);
+   int videoTrackIndex = muxer.addTrack(videoFormat);
 
    // Setup Metadata Track
    MediaFormat metadataFormat = new MediaFormat(...);
    metadataFormat.setString(KEY_MIME, "application/gyro");
-
-   int audioTrackIndex = muxer.addTrack(audioFormat);
-   int videoTrackIndex = muxer.addTrack(videoFormat);
    int metadataTrackIndex = muxer.addTrack(metadataFormat);
-   ByteBuffer inputBuffer = ByteBuffer.allocate(bufferSize);
-   boolean finished = false;
-   BufferInfo bufferInfo = new BufferInfo();
 
    muxer.start();
-   while(!finished) {
-     // getInputBuffer() will fill the inputBuffer with one frame of encoded
-     // sample from either MediaCodec or MediaExtractor, set isAudioSample to
-     // true when the sample is audio data, set up all the fields of bufferInfo,
-     // and return true if there are no more samples.
-     finished = getInputBuffer(inputBuffer, sampleType, bufferInfo);
-     if (!finished) {
-       int currentTrackIndex = getTrackIndex(sampleType);
-       muxer.writeSampleData(currentTrackIndex, inputBuffer, bufferInfo);
-     }
+   while(..) {
+       // Allocate bytebuffer and write gyro data(x,y,z) into it.
+       ByteBuffer metaData = ByteBuffer.allocate(bufferSize);
+       metaData.putFloat(x);
+       metaData.putFloat(y);
+       metaData.putFloat(z);
+       BufferInfo metaInfo = new BufferInfo();
+       // Associate this metadata with the video frame by setting
+       // the same timestamp as the video frame.
+       metaInfo.presentationTimeUs = currentVideoTrackTimeUs;
+       metaInfo.offset = 0;
+       metaInfo.flags = 0;
+       metaInfo.size = bufferSize;
+       muxer.writeSampleData(metadataTrackIndex, metaData, metaInfo);
    };
    muxer.stop();
    muxer.release();
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 5008a5f..b85c911 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -579,6 +579,7 @@
  */
 public class MediaPlayer extends PlayerBase
                          implements SubtitleController.Listener
+                                  , VolumeAutomation
 {
     /**
        Constant to retrieve only the new metadata since the last
@@ -1250,6 +1251,11 @@
     public void prepare() throws IOException, IllegalStateException {
         _prepare();
         scanInternalSubtitleTracks();
+
+        // DrmInfo, if any, has been resolved by now.
+        synchronized (mDrmLock) {
+            mDrmInfoResolved = true;
+        }
     }
 
     private native void _prepare() throws IOException, IllegalStateException;
@@ -1373,6 +1379,12 @@
         return native_getVolumeShaperState(id);
     }
 
+    @Override
+    public @NonNull VolumeShaper createVolumeShaper(
+            @NonNull VolumeShaper.Configuration configuration) {
+        return new VolumeShaper(configuration, this);
+    }
+
     private native int native_applyVolumeShaper(
             @NonNull VolumeShaper.Configuration configuration,
             @NonNull VolumeShaper.Operation operation);
@@ -1486,6 +1498,64 @@
      *
      * @return the a map of attributes and values available for this video
      * player or null if no metrics are available.
+     *
+     *  <table style="width: 0%">
+     *   <thead>
+     *    <tr>
+     *     <th>Key</th>
+     *     <th>Type</th>
+     *     <th>Description</th>
+     *    </tr>
+     *   </thead>
+     *   <tbody>
+     *    <tr>
+     *     <td>{@code "video/codec"}</td>
+     *     <td>String</td>
+     *     <td>Identifies the video codec in use</td>
+     *    </tr><tr>
+     *     <td>{@code "video/mime"}</td>
+     *     <td>String</td>
+     *     <td>Mime type of the video being encoded/decoded</td>
+     *    </tr><tr>
+     *     <td>{@code "audio/codec"}</td>
+     *     <td>String</td>
+     *     <td>Identifies the audio codec in use</td>
+     *    </tr><tr>
+     *     <td>{@code "audio/mime"}</td>
+     *     <td>String</td>
+     *     <td>Mime type of the audio being encoded/decoded</td>
+     *    </tr><tr>
+     *     <td>{@code "ht"}</td>
+     *     <td>Integer</td>
+     *     <td>Height (pixels); valid only when mode=video</td>
+     *    </tr><tr>
+     *     <td>{@code "wid"}</td>
+     *     <td>Integer</td>
+     *     <td>Width (pixels); valid only when mode=video</td>
+     *    </tr><tr>
+     *     <td>{@code "frame"}</td>
+     *     <td>Integer</td>
+     *     <td>Number of decoded video frames sent to the display</td>
+     *    </tr><tr>
+     *     <td>{@code "dropped"}</td>
+     *     <td>Integer</td>
+     *     <td>Number of decoded video frames that were not sent to display.
+     *         These frames were dropped by the player.</td>
+     *    </tr><tr>
+     *     <td>{@code "durationMs"}</td>
+     *     <td>Integer</td>
+     *     <td>The length of the media being played (in ms), e.g. "This video lasts for 30000 milliseconds". </td>
+     *    </tr><tr>
+     *     <td>{@code "playingMs"}</td>
+     *     <td>Integer</td>
+     *     <td>The time the media has been played (in ms). If you watch a
+     *         30 second twice through, this will report 60000 ms.</td>
+     *    </tr>
+     *   </tbody>
+     *  </table>
+     *
+     *  Additional fields specific to individual codecs will also appear in
+     *  the return value.
      */
     public native Bundle getMetrics();
 
@@ -3142,12 +3212,6 @@
                     sendMessage(msg2);
                 }
 
-                // MEDIA_DRM_INFO is fired (if available) before MEDIA_PREPARED.
-                // An empty mDrmInfo indicates prepared is done but the source is not DRM protected.
-                // Setting this before the callback so onPreparedListener can call getDrmInfo to
-                // get the right state
-                mDrmInfoResolved = true;
-
                 OnPreparedListener onPreparedListener = mOnPreparedListener;
                 if (onPreparedListener != null)
                     onPreparedListener.onPrepared(mMediaPlayer);
@@ -3159,12 +3223,14 @@
                 if (msg.obj == null) {
                     Log.w(TAG, "MEDIA_DRM_INFO msg.obj=NULL");
                 } else if (msg.obj instanceof Parcel) {
-                    Parcel parcel = (Parcel)msg.obj;
-                    DrmInfo drmInfo = new DrmInfo(parcel);
+                    // The parcel was parsed already in postEventFromNative
+                    DrmInfo drmInfo = null;
 
                     OnDrmInfoHandlerDelegate onDrmInfoHandlerDelegate;
                     synchronized (mDrmLock) {
-                        mDrmInfo = drmInfo.makeCopy();
+                        if (mOnDrmInfoHandlerDelegate != null && mDrmInfo != null) {
+                            drmInfo = mDrmInfo.makeCopy();
+                        }
                         // local copy while keeping the lock
                         onDrmInfoHandlerDelegate = mOnDrmInfoHandlerDelegate;
                     }
@@ -3359,10 +3425,43 @@
             return;
         }
 
-        if (what == MEDIA_INFO && arg1 == MEDIA_INFO_STARTED_AS_NEXT) {
-            // this acquires the wakelock if needed, and sets the client side state
-            mp.start();
+        switch (what) {
+        case MEDIA_INFO:
+            if (arg1 == MEDIA_INFO_STARTED_AS_NEXT) {
+                // this acquires the wakelock if needed, and sets the client side state
+                mp.start();
+            }
+            break;
+
+        case MEDIA_DRM_INFO:
+            // We need to derive mDrmInfo before prepare() returns so processing it here
+            // before the notification is sent to EventHandler below. EventHandler runs in the
+            // notification looper so its handleMessage might process the event after prepare()
+            // has returned.
+            Log.v(TAG, "postEventFromNative MEDIA_DRM_INFO");
+            if (obj instanceof Parcel) {
+                Parcel parcel = (Parcel)obj;
+                DrmInfo drmInfo = new DrmInfo(parcel);
+                synchronized (mp.mDrmLock) {
+                    mp.mDrmInfo = drmInfo;
+                }
+            } else {
+                Log.w(TAG, "MEDIA_DRM_INFO msg.obj of unexpected type " + obj);
+            }
+            break;
+
+        case MEDIA_PREPARED:
+            // By this time, we've learned about DrmInfo's presence or absence. This is meant
+            // mainly for prepareAsync() use case. For prepare(), this still can run to a race
+            // condition b/c MediaPlayerNative releases the prepare() lock before calling notify
+            // so we also set mDrmInfoResolved in prepare().
+            synchronized (mp.mDrmLock) {
+                mp.mDrmInfoResolved = true;
+            }
+            break;
+
         }
+
         if (mp.mEventHandler != null) {
             Message m = mp.mEventHandler.obtainMessage(what, arg1, arg2, obj);
             mp.mEventHandler.sendMessage(m);
@@ -4086,16 +4185,16 @@
      * If the device has not been provisioned before, this call also provisions the device
      * which involves accessing the provisioning server and can take a variable time to
      * complete depending on the network connectivity.
-     * If OnDrmPreparedListener is registered, prepareDrm() runs in non-blocking
+     * If {@code OnDrmPreparedListener} is registered, prepareDrm() runs in non-blocking
      * mode by launching the provisioning in the background and returning. The listener
      * will be called when provisioning and preperation has finished. If a
-     * OnDrmPreparedListener is not registered, prepareDrm() waits till provisioning
+     * {@code OnDrmPreparedListener} is not registered, prepareDrm() waits till provisioning
      * and preperation has finished, i.e., runs in blocking mode.
      * <p>
-     * If OnDrmPreparedListener is registered, it is called to indicated the DRM session
-     * being ready regardless of blocking or non-blocking mode. The application should
-     * not make any assumption about its call sequence (e.g., before or after prepareDrm
-     * returns) or the thread context that will execute the listener.
+     * If {@code OnDrmPreparedListener} is registered, it is called to indicate the DRM
+     * session being ready. The application should not make any assumption about its call
+     * sequence (e.g., before or after prepareDrm returns), or the thread context that will
+     * execute the listener (unless the listener is registered with a handler thread).
      * <p>
      *
      * @param uuid The UUID of the crypto scheme.
diff --git a/media/java/android/media/PlayerBase.java b/media/java/android/media/PlayerBase.java
index b397b45..1f5986f 100644
--- a/media/java/android/media/PlayerBase.java
+++ b/media/java/android/media/PlayerBase.java
@@ -58,7 +58,7 @@
     protected float mAuxEffectSendLevel = 0.0f;
 
     // for AppOps
-    private IAppOpsService mAppOps;
+    private IAppOpsService mAppOps; // may be null
     private IAppOpsCallback mAppOpsCallback;
     private boolean mHasAppOpsPlayAudio = true; // sync'd on mLock
     private final Object mLock = new Object();
@@ -251,7 +251,9 @@
             Log.e(TAG, "Error talking to audio service, the player will still be tracked", e);
         }
         try {
-            mAppOps.stopWatchingMode(mAppOpsCallback);
+            if (mAppOps != null) {
+                mAppOps.stopWatchingMode(mAppOpsCallback);
+            }
         } catch (RemoteException e) {
             // nothing to do here, the object is supposed to be released anyway
         }
@@ -264,9 +266,12 @@
     void updateAppOpsPlayAudio_sync() {
         boolean oldHasAppOpsPlayAudio = mHasAppOpsPlayAudio;
         try {
-            final int mode = mAppOps.checkAudioOperation(AppOpsManager.OP_PLAY_AUDIO,
+            int mode = AppOpsManager.MODE_IGNORED;
+            if (mAppOps != null) {
+                mode = mAppOps.checkAudioOperation(AppOpsManager.OP_PLAY_AUDIO,
                     mAttributes.getUsage(),
                     Process.myUid(), ActivityThread.currentPackageName());
+            }
             mHasAppOpsPlayAudio = (mode == AppOpsManager.MODE_ALLOWED);
         } catch (RemoteException e) {
             mHasAppOpsPlayAudio = false;
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index 8a1027b..e774c71 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -103,10 +103,6 @@
      */
     public static final int TYPE_ALL = TYPE_RINGTONE | TYPE_NOTIFICATION | TYPE_ALARM;
 
-    private static final int[] RINGTONE_TYPES = {
-            TYPE_RINGTONE, TYPE_NOTIFICATION, TYPE_ALARM
-    };
-    
     // </attr>
     
     /**
@@ -773,30 +769,17 @@
     }
 
     /**
-     * Disables Settings.System.SYNC_PARENT_SOUNDS, copying the parent's ringtones to the current
-     * profile
+     * Disables Settings.System.SYNC_PARENT_SOUNDS.
      *
      * @hide
      */
-    @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
     public static void disableSyncFromParent(Context userContext) {
-        // Must disable sync first so that ringtone copy below doesn't get redirected to parent
-        Settings.Secure.putIntForUser(userContext.getContentResolver(),
-                Settings.Secure.SYNC_PARENT_SOUNDS, 0 /* false */, userContext.getUserId());
-
-        // Copy ringtones from parent profile
-        UserManager um = UserManager.get(userContext);
-        UserInfo parentInfo = um.getProfileParent(userContext.getUserId());
-        if (parentInfo != null) {
-            final Context targetContext = createPackageContextAsUser(userContext, parentInfo.id);
-            if (targetContext != null) {
-                for (int ringtoneType : RINGTONE_TYPES) {
-                    Uri ringtoneUri = getActualDefaultRingtoneUri(targetContext, ringtoneType);
-                    // Add user id of parent so that custom ringtones can be read and played
-                    RingtoneManager.setActualDefaultRingtoneUri(userContext, ringtoneType,
-                            maybeAddUserId(ringtoneUri, parentInfo.id));
-                }
-            }
+        IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
+        IAudioService audioService = IAudioService.Stub.asInterface(b);
+        try {
+            audioService.disableRingtoneSync(userContext.getUserId());
+        } catch (RemoteException e) {
+            Log.e(TAG, "Unable to disable ringtone sync.");
         }
     }
 
@@ -851,22 +834,15 @@
      * @see #getActualDefaultRingtoneUri(Context, int)
      */
     public static void setActualDefaultRingtoneUri(Context context, int type, Uri ringtoneUri) {
-        final ContentResolver resolver = context.getContentResolver();
-
-        if (Settings.Secure.getString(resolver, Settings.Secure.SYNC_PARENT_SOUNDS).equals("1")) {
-            // Sync is enabled, so we need to disable it
-            IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
-            IAudioService audioService = IAudioService.Stub.asInterface(b);
-            try {
-                audioService.disableRingtoneSync();
-            } catch (RemoteException e) {
-                Log.e(TAG, "Unable to disable ringtone sync.");
-                return;
-            }
-        }
-
         String setting = getSettingForType(type);
         if (setting == null) return;
+
+        final ContentResolver resolver = context.getContentResolver();
+        if (Settings.Secure.getIntForUser(resolver, Settings.Secure.SYNC_PARENT_SOUNDS, 0,
+                    context.getUserId()) == 1) {
+            // Parent sound override is enabled. Disable it using the audio service.
+            disableSyncFromParent(context);
+        }
         if(!isInternalRingtoneUri(ringtoneUri)) {
             ringtoneUri = ContentProvider.maybeAddUserId(ringtoneUri, context.getUserId());
         }
diff --git a/core/java/com/android/internal/logging/legacy/Util.java b/media/java/android/media/UnsupportedCasException.java
similarity index 66%
copy from core/java/com/android/internal/logging/legacy/Util.java
copy to media/java/android/media/UnsupportedCasException.java
index 99f71ca..3167637 100644
--- a/core/java/com/android/internal/logging/legacy/Util.java
+++ b/media/java/android/media/UnsupportedCasException.java
@@ -13,13 +13,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.internal.logging.legacy;
+
+package android.media;
 
 /**
- * Created by cwren on 11/21/16.
+ * Exception thrown when an attempt is made to construct a MediaCas object
+ * using a CA_system_id that is not supported by the device
  */
-public class Util {
-    public static boolean debug() {
-        return false;
+public final class UnsupportedCasException extends MediaCasException {
+    public UnsupportedCasException(String detailMessage) {
+        super(detailMessage);
     }
 }
diff --git a/media/java/android/media/VolumeAutomation.java b/media/java/android/media/VolumeAutomation.java
new file mode 100644
index 0000000..dff8801
--- /dev/null
+++ b/media/java/android/media/VolumeAutomation.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+import android.annotation.NonNull;
+import android.media.VolumeShaper.Configuration;
+
+/**
+ * {@code VolumeAutomation} defines an interface for automatic volume control
+ * of {@link AudioTrack} and {@link MediaPlayer} objects.
+ */
+public interface VolumeAutomation {
+    /**
+     * Returns a {@link VolumeShaper} object that can be used modify the volume envelope
+     * of the player or track.
+     *
+     * @param configuration the {@link VolumeShaper.Configuration configuration}
+     *        that specifies the curve and duration to use.
+     * @return a {@code VolumeShaper} object
+     * @throws IllegalArgumentException if the configuration is not allowed by the player.
+     * @throws IllegalStateException if too many VolumeShapers are requested or the state of
+     * the player does not permit its creation (e.g. player is released).
+     */
+    public @NonNull VolumeShaper createVolumeShaper(
+            @NonNull VolumeShaper.Configuration configuration);
+}
diff --git a/media/java/android/media/VolumeShaper.java b/media/java/android/media/VolumeShaper.java
index 77af359..796d6f3 100644
--- a/media/java/android/media/VolumeShaper.java
+++ b/media/java/android/media/VolumeShaper.java
@@ -23,69 +23,26 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.lang.AutoCloseable;
 import java.lang.ref.WeakReference;
+import java.util.Arrays;
 import java.util.Objects;
 
 /**
- * TODO: remove @hide
  * The {@code VolumeShaper} class is used to automatically control audio volume during media
- * playback, allowing for simple implementation of transition effects and ducking.
+ * playback, allowing simple implementation of transition effects and ducking.
  *
  * The {@link VolumeShaper} appears as an additional scaling on the audio output,
- * and can be used independently of track or stream volume controls.
+ * and adjusts independently of track or stream volume controls.
  */
-public final class VolumeShaper {
+public final class VolumeShaper implements AutoCloseable {
     /* member variables */
     private int mId;
-    private final WeakReference<PlayerBase> mPlayerBase;
-    private final WeakReference<PlayerProxy> mPlayerProxy;
-
-    /**
-     * Constructs a {@code VolumeShaper} from a {@link VolumeShaper.Configuration} and an
-     * {@link AudioTrack}.
-     *
-     * @param configuration
-     * @param audioTrack
-     */
-    public VolumeShaper(@NonNull Configuration configuration, @NonNull AudioTrack audioTrack) {
-        this(configuration, (PlayerBase)audioTrack);
-    }
-
-    /**
-     * Constructs a {@code VolumeShaper} from a {@link VolumeShaper.Configuration} and a
-     * {@link MediaPlayer}.
-     *
-     * @param configuration
-     * @param mediaPlayer
-     */
-    public VolumeShaper(@NonNull Configuration configuration, @NonNull MediaPlayer mediaPlayer) {
-        this(configuration, (PlayerBase)mediaPlayer);
-    }
+    private final WeakReference<PlayerBase> mWeakPlayerBase;
 
     /* package */ VolumeShaper(
             @NonNull Configuration configuration, @NonNull PlayerBase playerBase) {
-        mPlayerBase = new WeakReference<PlayerBase>(playerBase);
-        mPlayerProxy = null;
-        mId = applyPlayer(configuration, new Operation.Builder().defer().build());
-    }
-
-    /**
-     * @hide
-     * TODO SystemApi
-     * Constructs a {@code VolumeShaper} from a {@link VolumeShaper.Configuration} and a
-     * {@code PlayerProxy} object.  The PlayerProxy object requires that the configuration
-     * be set with a system VolumeShaper id (this is a reserved value).
-     *
-     * @param configuration
-     * @param playerProxy
-     */
-    public VolumeShaper(
-            @NonNull Configuration configuration, @NonNull PlayerProxy playerProxy) {
-        if (configuration.getId() < 0) {
-            throw new IllegalArgumentException("playerProxy configuration id must be specified");
-        }
-        mPlayerProxy = new WeakReference<PlayerProxy>(playerProxy);
-        mPlayerBase = null;
+        mWeakPlayerBase = new WeakReference<PlayerBase>(playerBase);
         mId = applyPlayer(configuration, new Operation.Builder().defer().build());
     }
 
@@ -95,7 +52,7 @@
 
     /**
      * Applies the {@link VolumeShaper.Operation} to the {@code VolumeShaper}.
-     * @param operation
+     * @param operation the {@code operation} to apply.
      */
     public void apply(@NonNull Operation operation) {
         /* void */ applyPlayer(new VolumeShaper.Configuration(mId), operation);
@@ -103,17 +60,16 @@
 
     /**
      * Replaces the current {@code VolumeShaper}
-     * configuration with a new configuration.
+     * {@code configuration} with a new {@code configuration}.
      *
-     * This can be used to dynamically change the {@code VolumeShaper}
-     * configuration by joining several
-     * {@code VolumeShaper} configurations together.
-     * This is useful if the user changes the volume while the
-     * {@code VolumeShaper} is in effect.
+     * This allows the user to change the volume shape
+     * while the existing {@code VolumeShaper} is in effect.
      *
-     * @param configuration
-     * @param operation
-     * @param join
+     * @param configuration the new {@code configuration} to use.
+     * @param operation the operation to apply to the {@code VolumeShaper}
+     * @param join if true, match the start volume of the
+     *             new {@code configuration} to the current volume of the existing
+     *             {@code VolumeShaper}, to avoid discontinuity.
      */
     public void replace(
             @NonNull Configuration configuration, @NonNull Operation operation, boolean join) {
@@ -132,10 +88,11 @@
     }
 
     /**
-     * Releases the {@code VolumeShaper}. Any volume scale due to the
+     * Releases the {@code VolumeShaper} object; any volume scale due to the
      * {@code VolumeShaper} is removed.
      */
-    public void release() {
+    @Override
+    public void close() {
         try {
             /* void */ applyPlayer(
                     new VolumeShaper.Configuration(mId),
@@ -143,17 +100,14 @@
         } catch (IllegalStateException ise) {
             ; // ok
         }
-        if (mPlayerBase != null) {
-            mPlayerBase.clear();
-        }
-        if (mPlayerProxy != null) {
-            mPlayerProxy.clear();
+        if (mWeakPlayerBase != null) {
+            mWeakPlayerBase.clear();
         }
     }
 
     @Override
     protected void finalize() {
-        release(); // ensure we remove the native volume shaper
+        close(); // ensure we remove the native volume shaper
     }
 
     /**
@@ -162,26 +116,14 @@
      * @param configuration
      * @param operation
      * @return id a non-negative shaper id.
+     * @throws IllegalStateException if the player has been deallocated or is uninitialized.
      */
     private int applyPlayer(
             @NonNull VolumeShaper.Configuration configuration,
             @NonNull VolumeShaper.Operation operation) {
         final int id;
-        if (mPlayerProxy != null) {
-            // The PlayerProxy accepts only one way transactions so
-            // the Configuration must have an id set to one of the system
-            // ids (a positive value less than 16).
-            PlayerProxy player = mPlayerProxy.get();
-            if (player == null) {
-                throw new IllegalStateException("player deallocated");
-            }
-            id = configuration.getId();
-            if (id < 0) {
-                throw new IllegalArgumentException("proxy requires configuration with id");
-            }
-            player.applyVolumeShaper(configuration, operation);
-        } else if (mPlayerBase != null) {
-            PlayerBase player = mPlayerBase.get();
+        if (mWeakPlayerBase != null) {
+            PlayerBase player = mWeakPlayerBase.get();
             if (player == null) {
                 throw new IllegalStateException("player deallocated");
             }
@@ -207,17 +149,12 @@
      * Internal call to retrieve the current VolumeShaper state.
      * @param id
      * @return the current {@vode VolumeShaper.State}
+     * @throws IllegalStateException if the player has been deallocated or is uninitialized.
      */
     private @NonNull VolumeShaper.State getStatePlayer(int id) {
         final VolumeShaper.State state;
-        if (mPlayerProxy != null) {
-            PlayerProxy player = mPlayerProxy.get();
-            if (player == null) {
-                throw new IllegalStateException("player deallocated");
-            }
-            throw new IllegalStateException("getStatePlayer not permitted through proxy");
-        } else if (mPlayerBase != null) {
-            PlayerBase player = mPlayerBase.get();
+        if (mWeakPlayerBase != null) {
+            PlayerBase player = mWeakPlayerBase.get();
             if (player == null) {
                 throw new IllegalStateException("player deallocated");
             }
@@ -232,11 +169,17 @@
     }
 
     /**
-     * The {@code VolumeShaper.Configuration} class contains curve shape
-     * and parameter information for constructing a {@code VolumeShaper}.
-     * This curve shape and parameter information is specified
-     * on {@code VolumeShaper} creation
-     * and may be replaced through {@link VolumeShaper#replace}.
+     * The {@code VolumeShaper.Configuration} class contains curve
+     * and duration information.
+     * It is constructed by the {@link VolumeShaper.Configuration.Builder}.
+     * <p>
+     * A {@code VolumeShaper.Configuration} is used by
+     * {@link VolumeAutomation#createVolumeShaper(Configuration)
+     * VolumeAutomation.createVolumeShaper(Configuration)} to create
+     * a {@code VolumeShaper} and
+     * by {@link VolumeShaper#replace(Configuration, Operation, boolean)
+     * VolumeShaper.replace(Configuration, Operation, boolean)}
+     * to replace an existing {@code configuration}.
      */
     public static final class Configuration implements Parcelable {
         private static final int MAXIMUM_CURVE_POINTS = 16;
@@ -304,9 +247,9 @@
 
         /**
          * Cubic interpolated volume curve
-         * with local monotonicity preservation.
+         * that preserves local monotonicity.
          * So long as the control points are locally monotonic,
-         * the curve interpolation will also be locally monotonic.
+         * the curve interpolation between those points are monotonic.
          * This is useful for cubic spline interpolated
          * volume ramps and ducks.
          */
@@ -322,6 +265,7 @@
         public @interface OptionFlag {}
 
         /**
+         * @hide
          * Use a dB full scale volume range for the volume curve.
          *<p>
          * The volume scale is typically from 0.f to 1.f on a linear scale;
@@ -331,6 +275,7 @@
         public static final int OPTION_FLAG_VOLUME_IN_DBFS = (1 << 0);
 
         /**
+         * @hide
          * Use clock time instead of media time.
          *<p>
          * The default implementation of {@code VolumeShaper} is to apply
@@ -348,7 +293,8 @@
 
         /**
          * A one second linear ramp from silence to full volume.
-         * Use {@link VolumeShaper.Builder#reflectTimes()} to generate
+         * Use {@link VolumeShaper.Builder#reflectTimes()}
+         * or {@link VolumeShaper.Builder#invertVolumes()} to generate
          * the matching linear duck.
          */
         public static final Configuration LINEAR_RAMP = new VolumeShaper.Configuration.Builder()
@@ -360,7 +306,8 @@
 
         /**
          * A one second cubic ramp from silence to full volume.
-         * Use {@link VolumeShaper.Builder#reflectTimes()} to generate
+         * Use {@link VolumeShaper.Builder#reflectTimes()}
+         * or {@link VolumeShaper.Builder#invertVolumes()} to generate
          * the matching cubic duck.
          */
         public static final Configuration CUBIC_RAMP = new VolumeShaper.Configuration.Builder()
@@ -371,17 +318,19 @@
                 .build();
 
         /**
-         * A one second sine curve for energy preserving cross fades.
+         * A one second sine curve
+         * from silence to full volume for energy preserving cross fades.
          * Use {@link VolumeShaper.Builder#reflectTimes()} to generate
          * the matching cosine duck.
          */
         public static final Configuration SINE_RAMP;
 
         /**
-         * A one second sine-squared s-curve ramp.
+         * A one second sine-squared s-curve ramp
+         * from silence to full volume.
          * Use {@link VolumeShaper.Builder#reflectTimes()}
          * or {@link VolumeShaper.Builder#invertVolumes()} to generate
-         * the matching s-curve duck.
+         * the matching sine-squared s-curve duck.
          */
         public static final Configuration SCURVE_RAMP;
 
@@ -419,31 +368,34 @@
         private final int mId;
 
         // valid when mType is TYPE_SCALE
-        private final int mInterpolatorType;
         private final int mOptionFlags;
         private final double mDurationMs;
+        private final int mInterpolatorType;
         private final float[] mTimes;
         private final float[] mVolumes;
 
         @Override
         public String toString() {
-            return "VolumeShaper.Configuration["
-                    + "mType=" + mType
+            return "VolumeShaper.Configuration{"
+                    + "mType = " + mType
+                    + ", mId = " + mId
                     + (mType == TYPE_ID
-                    ? ",mId" + mId
-                    : ",mInterpolatorType=" + mInterpolatorType
-                    + ",mOptionFlags=" + mOptionFlags
-                    + ",mDurationMs=" + mDurationMs
-                    + ",mTimes[]=" + mTimes
-                    + ",mVolumes[]=" + mVolumes
-                    + "]");
+                        ? "}"
+                        : ", mOptionFlags = 0x" + Integer.toHexString(mOptionFlags).toUpperCase()
+                        + ", mDurationMs = " + mDurationMs
+                        + ", mInterpolatorType = " + mInterpolatorType
+                        + ", mTimes[] = " + Arrays.toString(mTimes)
+                        + ", mVolumes[] = " + Arrays.toString(mVolumes)
+                        + "}");
         }
 
         @Override
         public int hashCode() {
             return mType == TYPE_ID
                     ? Objects.hash(mType, mId)
-                    : Objects.hash(mType, mInterpolatorType, mDurationMs, mTimes, mVolumes);
+                    : Objects.hash(mType, mId,
+                            mOptionFlags, mDurationMs, mInterpolatorType,
+                            Arrays.hashCode(mTimes), Arrays.hashCode(mVolumes));
         }
 
         @Override
@@ -451,12 +403,17 @@
             if (!(o instanceof Configuration)) return false;
             if (o == this) return true;
             final Configuration other = (Configuration) o;
-            return mType == other.mType &&
-                    (mType == TYPE_ID ? mId == other.mId
-                    : mInterpolatorType == other.mInterpolatorType
-                    && mDurationMs == other.mDurationMs
-                    && mTimes == other.mTimes
-                    && mVolumes == other.mVolumes);
+            // Note that exact floating point equality may not be guaranteed
+            // for a theoretically idempotent operation; for example,
+            // there are many cases where a + b - b != a.
+            return mType == other.mType
+                    && mId == other.mId
+                    && (mType == TYPE_ID
+                        ||  (mOptionFlags == other.mOptionFlags
+                            && mDurationMs == other.mDurationMs
+                            && mInterpolatorType == other.mInterpolatorType
+                            && Arrays.equals(mTimes, other.mTimes)
+                            && Arrays.equals(mVolumes, other.mVolumes)));
         }
 
         @Override
@@ -466,14 +423,22 @@
 
         @Override
         public void writeToParcel(Parcel dest, int flags) {
+            // this needs to match the native VolumeShaper.Configuration parceling
             dest.writeInt(mType);
             dest.writeInt(mId);
             if (mType != TYPE_ID) {
-                dest.writeInt(mInterpolatorType);
                 dest.writeInt(mOptionFlags);
                 dest.writeDouble(mDurationMs);
-                dest.writeFloatArray(mTimes);
-                dest.writeFloatArray(mVolumes);
+                // this needs to match the native Interpolator parceling
+                dest.writeInt(mInterpolatorType);
+                dest.writeFloat(0.f); // first slope
+                dest.writeFloat(0.f); // last slope
+                // mTimes and mVolumes should have the same length.
+                dest.writeInt(mTimes.length);
+                for (int i = 0; i < mTimes.length; ++i) {
+                    dest.writeFloat(mTimes[i]);
+                    dest.writeFloat(mVolumes[i]);
+                }
             }
         }
 
@@ -481,19 +446,34 @@
                 = new Parcelable.Creator<VolumeShaper.Configuration>() {
             @Override
             public VolumeShaper.Configuration createFromParcel(Parcel p) {
+                // this needs to match the native VolumeShaper.Configuration parceling
                 final int type = p.readInt();
                 final int id = p.readInt();
                 if (type == TYPE_ID) {
                     return new VolumeShaper.Configuration(id);
                 } else {
+                    final int optionFlags = p.readInt();
+                    final double durationMs = p.readDouble();
+                    // this needs to match the native Interpolator parceling
+                    final int interpolatorType = p.readInt();
+                    final float firstSlope = p.readFloat(); // ignored
+                    final float lastSlope = p.readFloat();  // ignored
+                    final int length = p.readInt();
+                    final float[] times = new float[length];
+                    final float[] volumes = new float[length];
+                    for (int i = 0; i < length; ++i) {
+                        times[i] = p.readFloat();
+                        volumes[i] = p.readFloat();
+                    }
+
                     return new VolumeShaper.Configuration(
                         type,
-                        id,                    // id
-                        p.readInt(),           // interpolatorType
-                        p.readInt(),           // optionFlags
-                        p.readDouble(),        // durationMs
-                        p.createFloatArray(),  // times
-                        p.createFloatArray()); // volumes
+                        id,
+                        optionFlags,
+                        durationMs,
+                        interpolatorType,
+                        times,
+                        volumes);
                 }
             }
 
@@ -504,6 +484,7 @@
         };
 
         /**
+         * @hide
          * Constructs a volume shaper from an id.
          *
          * This is an opaque handle for controlling a {@code VolumeShaper} that has
@@ -516,7 +497,7 @@
          * @param id
          * @throws IllegalArgumentException if id is negative.
          */
-        private Configuration(int id) {
+        public Configuration(int id) {
             if (id < 0) {
                 throw new IllegalArgumentException("negative id " + id);
             }
@@ -535,22 +516,23 @@
          */
         private Configuration(@Type int type,
                 int id,
-                @InterpolatorType int interpolatorType,
                 @OptionFlag int optionFlags,
                 double durationMs,
+                @InterpolatorType int interpolatorType,
                 @NonNull float[] times,
                 @NonNull float[] volumes) {
             mType = type;
             mId = id;
-            mInterpolatorType = interpolatorType;
             mOptionFlags = optionFlags;
             mDurationMs = durationMs;
+            mInterpolatorType = interpolatorType;
             // Builder should have cloned these arrays already.
             mTimes = times;
             mVolumes = volumes;
         }
 
         /**
+         * @hide
          * Returns the {@code VolumeShaper} type.
          */
         public @Type int getType() {
@@ -573,6 +555,7 @@
         }
 
         /**
+         * @hide
          * Returns the option flags
          */
         public @OptionFlag int getOptionFlags() {
@@ -584,7 +567,7 @@
         }
 
         /**
-         * Returns the duration of the effect in milliseconds.
+         * Returns the duration of the volume shape in milliseconds.
          */
         public double getDurationMs() {
             return mDurationMs;
@@ -619,8 +602,12 @@
          * @return null if no error, or the reason in a {@code String} for an error.
          */
         private static @Nullable String checkCurveForErrors(
-                @NonNull float[] times, @NonNull float[] volumes, boolean log) {
-            if (times.length != volumes.length) {
+                @Nullable float[] times, @Nullable float[] volumes, boolean log) {
+            if (times == null) {
+                return "times array must be non-null";
+            } else if (volumes == null) {
+                return "volumes array must be non-null";
+            } else if (times.length != volumes.length) {
                 return "array length must match";
             } else if (times.length < 2) {
                 return "array length must be at least 2";
@@ -656,7 +643,15 @@
             return null; // no errors
         }
 
-        private static void checkValidVolume(float volume, boolean log) {
+        private static void checkCurveForErrorsAndThrowException(
+                @Nullable float[] times, @Nullable float[] volumes, boolean log) {
+            final String error = checkCurveForErrors(times, volumes, log);
+            if (error != null) {
+                throw new IllegalArgumentException(error);
+            }
+        }
+
+        private static void checkValidVolumeAndThrowException(float volume, boolean log) {
             if (log) {
                 if (!(volume <= 0.f) /* handle nan */) {
                     throw new IllegalArgumentException("dbfs volume must be 0.f or less");
@@ -706,21 +701,22 @@
             private int mType = TYPE_SCALE;
             private int mId = -1; // invalid
             private int mInterpolatorType = INTERPOLATOR_TYPE_CUBIC;
-            private int mOptionFlags = 0;
+            private int mOptionFlags = OPTION_FLAG_CLOCK_TIME;
             private double mDurationMs = 1000.;
             private float[] mTimes = null;
             private float[] mVolumes = null;
 
             /**
-             * Constructs a new Builder with the defaults.
+             * Constructs a new {@code Builder} with the defaults.
              */
             public Builder() {
             }
 
             /**
-             * Constructs a new Builder from a given {@code VolumeShaper.Configuration}
+             * Constructs a new {@code Builder} with settings
+             * copied from a given {@code VolumeShaper.Configuration}.
              * @param configuration prototypical configuration
-             *        which will be reused in the new Builder.
+             *        which will be reused in the new {@code Builder}.
              */
             public Builder(@NonNull Configuration configuration) {
                 mType = configuration.getType();
@@ -728,19 +724,22 @@
                 mOptionFlags = configuration.getAllOptionFlags();
                 mInterpolatorType = configuration.getInterpolatorType();
                 mDurationMs = configuration.getDurationMs();
-                mTimes = configuration.getTimes();
-                mVolumes = configuration.getVolumes();
+                mTimes = configuration.getTimes().clone();
+                mVolumes = configuration.getVolumes().clone();
             }
 
             /**
              * @hide
-             * TODO make SystemApi
-             *
-             * Set the id for system defined shapers.
-             * @param id
-             * @return
+             * Set the {@code id} for system defined shapers.
+             * @param id the {@code id} to set. If non-negative, then it is used.
+             *        If -1, then the system is expected to assign one.
+             * @return the same {@code Builder} instance.
+             * @throws IllegalArgumentException if {@code id} < -1.
              */
             public @NonNull Builder setId(int id) {
+                if (id < -1) {
+                    throw new IllegalArgumentException("invalid id: " + id);
+                }
                 mId = id;
                 return this;
             }
@@ -751,7 +750,11 @@
              * If omitted the interplator type is {@link #INTERPOLATOR_TYPE_CUBIC}.
              *
              * @param interpolatorType method of interpolation used for the volume curve.
-             * @return the same Builder instance.
+             *        One of {@link #INTERPOLATOR_TYPE_STEP},
+             *        {@link #INTERPOLATOR_TYPE_LINEAR},
+             *        {@link #INTERPOLATOR_TYPE_CUBIC},
+             *        {@link #INTERPOLATOR_TYPE_CUBIC_MONOTONIC}.
+             * @return the same {@code Builder} instance.
              * @throws IllegalArgumentException if {@code interpolatorType} is not valid.
              */
             public @NonNull Builder setInterpolatorType(@InterpolatorType int interpolatorType) {
@@ -770,6 +773,7 @@
             }
 
             /**
+             * @hide
              * Sets the optional flags
              *
              * If omitted, flags are 0. If {@link #OPTION_FLAG_VOLUME_IN_DBFS} has
@@ -777,7 +781,7 @@
              * volume domain has changed.
              *
              * @param optionFlags new value to replace the old {@code optionFlags}.
-             * @return the same Builder instance.
+             * @return the same {@code Builder} instance.
              * @throws IllegalArgumentException if flag is not recognized.
              */
             public @NonNull Builder setOptionFlags(@OptionFlag int optionFlags) {
@@ -794,8 +798,9 @@
              * If omitted, the default duration is 1 second.
              *
              * @param durationMs
-             * @return the same Builder instance.
-             * @throws IllegalArgumentException if duration is not positive.
+             * @return the same {@code Builder} instance.
+             * @throws IllegalArgumentException if {@code durationMs}
+             *         is not strictly positive.
              */
             public @NonNull Builder setDurationMs(double durationMs) {
                 if (durationMs <= 0.) {
@@ -817,25 +822,26 @@
              * and no greater than {@link VolumeShaper.Configuration#getMaximumCurvePoints()}.
              * <p>
              * The volume curve is normalized as follows:
-             * (1) time (x) coordinates should be monotonically increasing, from 0.f to 1.f;
-             * (2) volume (y) coordinates must be within 0.f to 1.f for linear and be non-positive
-             *     for log scaling.
+             * time (x) coordinates should be monotonically increasing, from 0.f to 1.f;
+             * volume (y) coordinates must be within 0.f to 1.f.
              * <p>
-             * The time scale is set by {@link #setDurationMs} in seconds.
+             * The time scale is set by {@link #setDurationMs}.
              * <p>
              * @param times an array of float values representing
              *        the time line of the volume curve.
              * @param volumes an array of float values representing
              *        the amplitude of the volume curve.
-             * @return the same Builder instance.
+             * @return the same {@code Builder} instance.
              * @throws IllegalArgumentException if {@code times} or {@code volumes} is invalid.
              */
+
+            /* Note: volume (y) coordinates must be non-positive for log scaling,
+             * if {@link VolumeShaper.Configuration#OPTION_FLAG_VOLUME_IN_DBFS} is set.
+             */
+
             public @NonNull Builder setCurve(@NonNull float[] times, @NonNull float[] volumes) {
-                String error = checkCurveForErrors(
+                checkCurveForErrorsAndThrowException(
                         times, volumes, (mOptionFlags & OPTION_FLAG_VOLUME_IN_DBFS) != 0);
-                if (error != null) {
-                    throw new IllegalArgumentException(error);
-                }
                 mTimes = times.clone();
                 mVolumes = volumes.clone();
                 return this;
@@ -846,14 +852,20 @@
              * the shaper changes volume from the end
              * to the start.
              *
-             * @return the same Builder instance.
+             * @return the same {@code Builder} instance.
+             * @throws IllegalArgumentException if curve has not been set.
              */
             public @NonNull Builder reflectTimes() {
+                checkCurveForErrorsAndThrowException(
+                        mTimes, mVolumes, (mOptionFlags & OPTION_FLAG_VOLUME_IN_DBFS) != 0);
                 int i;
                 for (i = 0; i < mTimes.length / 2; ++i) {
-                    float temp = mTimes[0];
+                    float temp = mTimes[i];
                     mTimes[i] = 1.f - mTimes[mTimes.length - 1 - i];
                     mTimes[mTimes.length - 1 - i] = 1.f - temp;
+                    temp = mVolumes[i];
+                    mVolumes[i] = mVolumes[mVolumes.length - 1 - i];
+                    mVolumes[mVolumes.length - 1 - i] = temp;
                 }
                 if ((mTimes.length & 1) != 0) {
                     mTimes[i] = 1.f - mTimes[i];
@@ -865,24 +877,25 @@
              * Inverts the volume curve so that the max volume
              * becomes the min volume and vice versa.
              *
-             * @return the same Builder instance.
+             * @return the same {@code Builder} instance.
+             * @throws IllegalArgumentException if curve has not been set.
              */
             public @NonNull Builder invertVolumes() {
-                if (mVolumes.length >= 2) {
-                    float min = mVolumes[0];
-                    float max = mVolumes[0];
-                    for (int i = 1; i < mVolumes.length; ++i) {
-                        if (mVolumes[i] < min) {
-                            min = mVolumes[i];
-                        } else if (mVolumes[i] > max) {
-                            max = mVolumes[i];
-                        }
+                checkCurveForErrorsAndThrowException(
+                        mTimes, mVolumes, (mOptionFlags & OPTION_FLAG_VOLUME_IN_DBFS) != 0);
+                float min = mVolumes[0];
+                float max = mVolumes[0];
+                for (int i = 1; i < mVolumes.length; ++i) {
+                    if (mVolumes[i] < min) {
+                        min = mVolumes[i];
+                    } else if (mVolumes[i] > max) {
+                        max = mVolumes[i];
                     }
+                }
 
-                    final float maxmin = max + min;
-                    for (int i = 0; i < mVolumes.length; ++i) {
-                        mVolumes[i] = maxmin - mVolumes[i];
-                    }
+                final float maxmin = max + min;
+                for (int i = 0; i < mVolumes.length; ++i) {
+                    mVolumes[i] = maxmin - mVolumes[i];
                 }
                 return this;
             }
@@ -893,12 +906,15 @@
              * Keeps the start volume the same.
              * This works best if the volume curve is monotonic.
              *
-             * @return the same Builder instance.
-             * @throws IllegalArgumentException if volume is not valid.
+             * @param volume the target end volume to use.
+             * @return the same {@code Builder} instance.
+             * @throws IllegalArgumentException if {@code volume}
+             *         is not valid or if curve has not been set.
              */
             public @NonNull Builder scaleToEndVolume(float volume) {
                 final boolean log = (mOptionFlags & OPTION_FLAG_VOLUME_IN_DBFS) != 0;
-                checkValidVolume(volume, log);
+                checkCurveForErrorsAndThrowException(mTimes, mVolumes, log);
+                checkValidVolumeAndThrowException(volume, log);
                 final float startVolume = mVolumes[0];
                 final float endVolume = mVolumes[mVolumes.length - 1];
                 if (endVolume == startVolume) {
@@ -924,12 +940,15 @@
              * Keeps the end volume the same.
              * This works best if the volume curve is monotonic.
              *
-             * @return the same Builder instance.
-             * @throws IllegalArgumentException if volume is not valid.
+             * @param volume the target start volume to use.
+             * @return the same {@code Builder} instance.
+             * @throws IllegalArgumentException if {@code volume}
+             *         is not valid or if curve has not been set.
              */
             public @NonNull Builder scaleToStartVolume(float volume) {
                 final boolean log = (mOptionFlags & OPTION_FLAG_VOLUME_IN_DBFS) != 0;
-                checkValidVolume(volume, log);
+                checkCurveForErrorsAndThrowException(mTimes, mVolumes, log);
+                checkValidVolumeAndThrowException(volume, log);
                 final float startVolume = mVolumes[0];
                 final float endVolume = mVolumes[mVolumes.length - 1];
                 if (endVolume == startVolume) {
@@ -951,16 +970,14 @@
             /**
              * Builds a new {@link VolumeShaper} object.
              *
-             * @return a new {@link VolumeShaper} object
+             * @return a new {@link VolumeShaper} object.
+             * @throws IllegalArgumentException if curve is not properly set.
              */
             public @NonNull Configuration build() {
-                String error = checkCurveForErrors(
+                checkCurveForErrorsAndThrowException(
                         mTimes, mVolumes, (mOptionFlags & OPTION_FLAG_VOLUME_IN_DBFS) != 0);
-                if (error != null) {
-                    throw new IllegalArgumentException(error);
-                }
-                return new Configuration(mType, mId, mInterpolatorType, mOptionFlags,
-                        mDurationMs, mTimes, mVolumes);
+                return new Configuration(mType, mId, mOptionFlags, mDurationMs,
+                        mInterpolatorType, mTimes, mVolumes);
             }
         } // Configuration.Builder
     } // Configuration
@@ -972,6 +989,8 @@
     public static final class Operation implements Parcelable {
         /**
          * Forward playback from current volume time position.
+         * At the end of the {@code VolumeShaper} curve,
+         * the last volume value persists.
          */
         public static final Operation PLAY =
                 new VolumeShaper.Operation.Builder()
@@ -979,6 +998,8 @@
 
         /**
          * Reverse playback from current volume time position.
+         * When the position reaches the start of the {@code VolumeShaper} curve,
+         * the first volume value persists.
          */
         public static final Operation REVERSE =
                 new VolumeShaper.Operation.Builder()
@@ -1033,6 +1054,13 @@
          */
         private static final int FLAG_DEFER = 1 << 3;
 
+        /**
+         * Use the id specified in the configuration, creating
+         * VolumeShaper as needed; the configuration should be
+         * TYPE_SCALE.
+         */
+        private static final int FLAG_CREATE_IF_NEEDED = 1 << 4;
+
         private static final int FLAG_PUBLIC_ALL = FLAG_REVERSE | FLAG_TERMINATE;
 
         private final int mFlags;
@@ -1040,10 +1068,10 @@
 
         @Override
         public String toString() {
-            return "VolumeShaper.Operation["
-                    + "mFlags=" + mFlags
-                    + ",mReplaceId" + mReplaceId
-                    + "]";
+            return "VolumeShaper.Operation{"
+                    + "mFlags = 0x" + Integer.toHexString(mFlags).toUpperCase()
+                    + ", mReplaceId = " + mReplaceId
+                    + "}";
         }
 
         @Override
@@ -1056,6 +1084,8 @@
             if (!(o instanceof Operation)) return false;
             if (o == this) return true;
             final Operation other = (Operation) o;
+            // if xOffset (native field only) is brought into Java
+            // we need to do proper NaN comparison as that is allowed.
             return mFlags == other.mFlags
                     && mReplaceId == other.mReplaceId;
         }
@@ -1067,17 +1097,24 @@
 
         @Override
         public void writeToParcel(Parcel dest, int flags) {
+            // this needs to match the native VolumeShaper.Operation parceling
             dest.writeInt(mFlags);
             dest.writeInt(mReplaceId);
+            dest.writeFloat(Float.NaN); // xOffset (ignored at Java level)
         }
 
         public static final Parcelable.Creator<VolumeShaper.Operation> CREATOR
                 = new Parcelable.Creator<VolumeShaper.Operation>() {
             @Override
             public VolumeShaper.Operation createFromParcel(Parcel p) {
+                // this needs to match the native VolumeShaper.Operation parceling
+                final int flags = p.readInt();
+                final int replaceId = p.readInt();
+                final float xOffset = p.readFloat(); // ignored at Java level
+
                 return new VolumeShaper.Operation(
-                        p.readInt()     // flags
-                        , p.readInt()); // replaceId
+                        flags
+                        , replaceId);
             }
 
             @Override
@@ -1120,15 +1157,13 @@
             }
 
             /**
-             * Replaces the previous {@code VolumeShaper}.
+             * Replaces the previous {@code VolumeShaper} specified by id.
              * It has no other effect if the {@code VolumeShaper} is
-             * already expired. If the replaceId is the same as the id associated with
-             * the {@code VolumeShaper} in a {@code setVolumeShaper()} call,
-             * an error is returned.
-             * @param handle is a previous volumeShaper {@code VolumeShaper}.
-             * @param join the start to match the current volume of the previous
-             * shaper.
-             * @return the same Builder instance.
+             * already expired.
+             * @param id the id of the previous {@code VolumeShaper}.
+             * @param join if true, match the volume of the previous
+             * shaper to the start volume of the new {@code VolumeShaper}.
+             * @return the same {@code Builder} instance.
              */
             public @NonNull Builder replace(int id, boolean join) {
                 mReplaceId = id;
@@ -1142,7 +1177,7 @@
 
             /**
              * Defers all operations.
-             * @return the same Builder instance.
+             * @return the same {@code Builder} instance.
              */
             public @NonNull Builder defer() {
                 mFlags |= FLAG_DEFER;
@@ -1152,7 +1187,7 @@
             /**
              * Terminates the VolumeShaper.
              * Do not call directly, use {@link VolumeShaper#release()}.
-             * @return the same Builder instance.
+             * @return the same {@code Builder} instance.
              */
             public @NonNull Builder terminate() {
                 mFlags |= FLAG_TERMINATE;
@@ -1161,7 +1196,7 @@
 
             /**
              * Reverses direction.
-             * @return the same Builder instance.
+             * @return the same {@code Builder} instance.
              */
             public @NonNull Builder reverse() {
                 mFlags ^= FLAG_REVERSE;
@@ -1169,11 +1204,23 @@
             }
 
             /**
+             * Use the id specified in the configuration, creating
+             * VolumeShaper as needed; the configuration should be
+             * TYPE_SCALE.
+             * @return the same {@code Builder} instance.
+             */
+            public @NonNull Builder createIfNeeded() {
+                mFlags |= FLAG_CREATE_IF_NEEDED;
+                return this;
+            }
+
+            /**
              * Sets the operation flag.  Do not call this directly but one of the
              * other builder methods.
              *
              * @param flags new value for {@code flags}, consisting of ORed flags.
-             * @return the same Builder instance.
+             * @return the same {@code Builder} instance.
+             * @throws IllegalArgumentException if {@code flags} contains invalid set bits.
              */
             private @NonNull Builder setFlags(@Flag int flags) {
                 if ((flags & ~FLAG_PUBLIC_ALL) != 0) {
@@ -1207,10 +1254,10 @@
 
         @Override
         public String toString() {
-            return "VolumeShaper.State["
-                    + "mVolume=" + mVolume
-                    + ",mXOffset" + mXOffset
-                    + "]";
+            return "VolumeShaper.State{"
+                    + "mVolume = " + mVolume
+                    + ", mXOffset = " + mXOffset
+                    + "}";
         }
 
         @Override
diff --git a/media/java/android/media/midi/MidiDevice.java b/media/java/android/media/midi/MidiDevice.java
index f79cd06..4b43260 100644
--- a/media/java/android/media/midi/MidiDevice.java
+++ b/media/java/android/media/midi/MidiDevice.java
@@ -35,6 +35,10 @@
  * Instances of this class are created by {@link MidiManager#openDevice}.
  */
 public final class MidiDevice implements Closeable {
+    static {
+        System.loadLibrary("media_jni");
+    }
+
     private static final String TAG = "MidiDevice";
 
     private final MidiDeviceInfo mDeviceInfo;
@@ -43,6 +47,7 @@
     private final IBinder mClientToken;
     private final IBinder mDeviceToken;
     private boolean mIsDeviceClosed;
+    private boolean mIsMirroredToNative;
 
     private final CloseGuard mGuard = CloseGuard.get();
 
@@ -209,10 +214,45 @@
         }
     }
 
+    /**
+     * Makes Midi Device available to the Native API
+     * @hide
+     */
+    public void mirrorToNative() throws IOException {
+        if (mIsDeviceClosed || mIsMirroredToNative) {
+            return;
+        }
+
+        int result = mirrorToNative(mDeviceServer.asBinder(), mDeviceInfo.getId());
+        if (result != 0) {
+            throw new IOException("Failed mirroring to native: " + result);
+        }
+
+        mIsMirroredToNative = true;
+    }
+
+    /**
+     * Makes Midi Device no longer available to the Native API
+     * @hide
+     */
+    public void removeFromNative() throws IOException {
+        if (!mIsMirroredToNative) {
+            return;
+        }
+
+        int result = removeFromNative(mDeviceInfo.getId());
+        if (result != 0) {
+            throw new IOException("Failed removing from native: " + result);
+        }
+
+        mIsMirroredToNative = false;
+    }
+
     @Override
     public void close() throws IOException {
         synchronized (mGuard) {
             if (!mIsDeviceClosed) {
+                removeFromNative();
                 mGuard.close();
                 mIsDeviceClosed = true;
                 try {
@@ -238,4 +278,7 @@
     public String toString() {
         return ("MidiDevice: " + mDeviceInfo.toString());
     }
+
+    private native int mirrorToNative(IBinder deviceServerBinder, int uid);
+    private native int removeFromNative(int uid);
 }
diff --git a/media/java/android/media/session/ICallback.aidl b/media/java/android/media/session/ICallback.aidl
new file mode 100644
index 0000000..322bffa
--- /dev/null
+++ b/media/java/android/media/session/ICallback.aidl
@@ -0,0 +1,35 @@
+/* Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.session;
+
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.media.session.MediaSession;
+import android.view.KeyEvent;
+
+/**
+ * @hide
+ */
+oneway interface ICallback {
+    void onMediaKeyEventDispatchedToMediaSession(in KeyEvent event,
+            in MediaSession.Token sessionToken);
+    void onMediaKeyEventDispatchedToMediaButtonReceiver(in KeyEvent event,
+            in ComponentName mediaButtonReceiver);
+
+    void onAddressedPlayerChangedToMediaSession(in MediaSession.Token sessionToken);
+    void onAddressedPlayerChangedToMediaButtonReceiver(in ComponentName mediaButtonReceiver);
+}
+
diff --git a/media/java/android/media/session/ISessionManager.aidl b/media/java/android/media/session/ISessionManager.aidl
index 8a98773..5fcb430 100644
--- a/media/java/android/media/session/ISessionManager.aidl
+++ b/media/java/android/media/session/ISessionManager.aidl
@@ -18,8 +18,9 @@
 import android.content.ComponentName;
 import android.media.IRemoteVolumeController;
 import android.media.session.IActiveSessionsListener;
-import android.media.session.IOnVolumeKeyLongPressListener;
+import android.media.session.ICallback;
 import android.media.session.IOnMediaKeyListener;
+import android.media.session.IOnVolumeKeyLongPressListener;
 import android.media.session.ISession;
 import android.media.session.ISessionCallback;
 import android.os.Bundle;
@@ -45,7 +46,7 @@
     // For PhoneWindowManager to precheck media keys
     boolean isGlobalPriorityActive();
 
+    void setCallback(in ICallback callback);
     void setOnVolumeKeyLongPressListener(in IOnVolumeKeyLongPressListener listener);
     void setOnMediaKeyListener(in IOnMediaKeyListener listener);
 }
-
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index 80d2a0c..83793ae 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -71,6 +71,7 @@
 
     private Context mContext;
 
+    private CallbackImpl mCallback;
     private OnVolumeKeyLongPressListenerImpl mOnVolumeKeyLongPressListener;
     private OnMediaKeyListenerImpl mOnMediaKeyListener;
 
@@ -411,6 +412,36 @@
     }
 
     /**
+     * Set a {@link Callback}.
+     *
+     * <p>System can only have a single callback, and the callback can only be set by
+     * Bluetooth service process.
+     *
+     * @param callback A {@link Callback}. {@code null} to reset.
+     * @param handler The handler on which the callback should be invoked, or {@code null}
+     *            if the callback should be invoked on the calling thread's looper.
+     * @hide
+     */
+    public void setCallback(@Nullable Callback callback, @Nullable Handler handler) {
+        synchronized (mLock) {
+            try {
+                if (callback == null) {
+                    mCallback = null;
+                    mService.setCallback(null);
+                } else {
+                    if (handler == null) {
+                        handler = new Handler();
+                    }
+                    mCallback = new CallbackImpl(callback, handler);
+                    mService.setCallback(mCallback);
+                }
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to set media key callback", e);
+            }
+        }
+    }
+
+    /**
      * Listens for changes to the list of active sessions. This can be added
      * using {@link #addOnActiveSessionsChangedListener}.
      */
@@ -439,12 +470,65 @@
     public interface OnMediaKeyListener {
         /**
          * Called when the media key is pressed.
+         * <p>If the listener consumes the initial down event (i.e. ACTION_DOWN with
+         * repeat count zero), it must also comsume all following key events.
+         * (i.e. ACTION_DOWN with repeat count more than zero, and ACTION_UP).
          * <p>If it takes more than 1s to return, the key event will be sent to
          * other media sessions.
          */
         boolean onMediaKey(KeyEvent event);
     }
 
+    /**
+     * Callbacks for the media session service.
+     *
+     * <p>Called when a media key event is dispatched or the addressed player is changed.
+     * The addressed player is either the media session or the media button receiver that will
+     * receive media key events.
+     * @hide
+     */
+    public static abstract class Callback {
+        /**
+         * Called when a media key event is dispatched to the media session
+         * through the media session service.
+         *
+         * @param event Dispatched media key event.
+         * @param sessionToken The media session's token.
+         */
+        public abstract void onMediaKeyEventDispatched(KeyEvent event,
+                MediaSession.Token sessionToken);
+
+        /**
+         * Called when a media key event is dispatched to the media button receiver
+         * through the media session service.
+         * <p>MediaSessionService may broadcast key events to the media button receiver
+         * when reviving playback after the media session is released.
+         *
+         * @param event Dispatched media key event.
+         * @param mediaButtonReceiver The media button receiver.
+         */
+        public abstract void onMediaKeyEventDispatched(KeyEvent event,
+                ComponentName mediaButtonReceiver);
+
+        /**
+         * Called when the addressed player is changed to a media session.
+         * <p>One of the {@ #onAddressedPlayerChanged} will be also called immediately after
+         * {@link #setCallback} if the addressed player exists.
+         *
+         * @param sessionToken The media session's token.
+         */
+        public abstract void onAddressedPlayerChanged(MediaSession.Token sessionToken);
+
+        /**
+         * Called when the addressed player is changed to the media button receiver.
+         * <p>One of the {@ #onAddressedPlayerChanged} will be also called immediately after
+         * {@link #setCallback} if the addressed player exists.
+         *
+         * @param mediaButtonReceiver The media button receiver.
+         */
+        public abstract void onAddressedPlayerChanged(ComponentName mediaButtonReceiver);
+    }
+
     private static final class SessionsChangedWrapper {
         private Context mContext;
         private OnActiveSessionsChangedListener mListener;
@@ -534,9 +618,64 @@
                 public void run() {
                     boolean handled = mListener.onMediaKey(event);
                     Log.d(TAG, "The media key listener is returned " + handled);
-                    result.send(
-                            handled ? RESULT_MEDIA_KEY_HANDLED : RESULT_MEDIA_KEY_NOT_HANDLED,
-                            null);
+                    if (result != null) {
+                        result.send(
+                                handled ? RESULT_MEDIA_KEY_HANDLED : RESULT_MEDIA_KEY_NOT_HANDLED,
+                                null);
+                    }
+                }
+            });
+        }
+    }
+
+    private static final class CallbackImpl extends ICallback.Stub {
+        private final Callback mCallback;
+        private final Handler mHandler;
+
+        public CallbackImpl(@NonNull Callback callback, @NonNull Handler handler) {
+            mCallback = callback;
+            mHandler = handler;
+        }
+
+        @Override
+        public void onMediaKeyEventDispatchedToMediaSession(KeyEvent event,
+                MediaSession.Token sessionToken) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mCallback.onMediaKeyEventDispatched(event, sessionToken);
+                }
+            });
+        }
+
+        @Override
+        public void onMediaKeyEventDispatchedToMediaButtonReceiver(KeyEvent event,
+                ComponentName mediaButtonReceiver) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mCallback.onMediaKeyEventDispatched(event, mediaButtonReceiver);
+                }
+            });
+        }
+
+        @Override
+        public void onAddressedPlayerChangedToMediaSession(MediaSession.Token sessionToken) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mCallback.onAddressedPlayerChanged(sessionToken);
+                }
+            });
+        }
+
+        @Override
+        public void onAddressedPlayerChangedToMediaButtonReceiver(
+                ComponentName mediaButtonReceiver) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mCallback.onAddressedPlayerChanged(mediaButtonReceiver);
                 }
             });
         }
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index 77946a6..6e15d8d 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -25,6 +25,7 @@
 import android.content.ContentUris;
 import android.content.Intent;
 import android.net.Uri;
+import android.os.Bundle;
 import android.os.IBinder;
 import android.provider.BaseColumns;
 import android.text.TextUtils;
@@ -69,9 +70,171 @@
     private static final String PATH_PROGRAM = "program";
     private static final String PATH_RECORDED_PROGRAM = "recorded_program";
     private static final String PATH_PREVIEW_PROGRAM = "preview_program";
+    private static final String PATH_WATCH_NEXT_PROGRAM = "watch_next_program";
     private static final String PATH_PASSTHROUGH = "passthrough";
 
     /**
+     * Activity Action: sent by an application telling the system to set the given channel as
+     * browsable. This is only relevant to channels with {@link Channels#TYPE_PREVIEW} type.
+     *
+     * <p>The intent must contain the following bundle parameters:
+     * <ul>
+     *     <li>{@link #EXTRA_CHANNEL_ID}: ID for the {@link Channels#TYPE_PREVIEW} channel as a long
+     *     integer.</li>
+     *     <li>{@link #EXTRA_PACKAGE_NAME}: the package name of the requesting application.</li>
+     * </ul>
+     */
+    public static final String ACTION_MAKE_CHANNEL_BROWSABLE =
+            "android.media.tv.action.MAKE_CHANNEL_BROWSABLE";
+
+    /**
+     * Broadcast Action: sent by the system to tell the target TV input that one of its preview
+     * program's browsable state is disabled, i.e., it will no longer be shown to users, which, for
+     * example, might be a result of users' interaction with UI. The input is expected to delete the
+     * preview program from the content provider.
+     *
+     * <p>The intent must contain the following bundle parameter:
+     * <ul>
+     *     <li>{@link #EXTRA_PREVIEW_PROGRAM_ID}: the disabled preview program ID.</li>
+     * </ul>
+     */
+    public static final String ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED =
+            "android.media.tv.action.PREVIEW_PROGRAM_BROWSABLE_DISABLED";
+
+    /**
+     * Broadcast Action: sent by the system to tell the target TV input that one of its "watch next"
+     * program's browsable state is disabled, i.e., it will no longer be shown to users, which, for
+     * example, might be a result of users' interaction with UI. The input is expected to delete the
+     * "watch next" program from the content provider.
+     *
+     * <p>The intent must contain the following bundle parameter:
+     * <ul>
+     *     <li>{@link #EXTRA_WATCH_NEXT_PROGRAM_ID}: the disabled "watch next" program ID.</li>
+     * </ul>
+     */
+    public static final String ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED =
+            "android.media.tv.action.WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED";
+
+    /**
+     * Broadcast Action: sent by the system to tell the target TV input that one of its existing
+     * preview programs is added to the watch next programs table by user.
+     *
+     * <p>The intent must contain the following bundle parameters:
+     * <ul>
+     *     <li>{@link #EXTRA_PREVIEW_PROGRAM_ID}: the ID of the existing preview program.</li>
+     *     <li>{@link #EXTRA_WATCH_NEXT_PROGRAM_ID}: the ID of the new watch next program.</li>
+     * </ul>
+     */
+    public static final String ACTION_PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT =
+            "android.media.tv.action.PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT";
+
+    /** The key for a bundle parameter containing a channel ID as a long integer */
+    public static final String EXTRA_CHANNEL_ID = "android.media.tv.extra.CHANNEL_ID";
+
+    /** The key for a bundle parameter containing a package name as a string. */
+    public static final String EXTRA_PACKAGE_NAME = "android.media.tv.extra.PACKAGE_NAME";
+
+    /** The key for a bundle parameter containing a program ID as a long integer. */
+    public static final String EXTRA_PREVIEW_PROGRAM_ID =
+            "android.media.tv.extra.PREVIEW_PROGRAM_ID";
+
+    /** The key for a bundle parameter containing a watch next program ID as a long integer. */
+    public static final String EXTRA_WATCH_NEXT_PROGRAM_ID =
+            "android.media.tv.extra.WATCH_NEXT_PROGRAM_ID";
+
+    /**
+     * The method name to get existing columns in the given table of the specified content provider.
+     *
+     * <p>The method caller must provide the following parameter:
+     * <ul>
+     *     <li>{@code arg}: The content URI of the target table as a {@link String}.</li>
+     * </ul>
+
+     * <p>On success, the returned {@link android.os.Bundle} will include existing column names
+     * with the key {@link #EXTRA_EXISTING_COLUMN_NAMES}. Otherwise, the return value will be {@code null}.
+     *
+     * @see ContentResolver#call(Uri, String, String, Bundle)
+     * @see #EXTRA_EXISTING_COLUMN_NAMES
+     * @hide
+     */
+    @SystemApi
+    public static final String METHOD_GET_COLUMNS = "get_columns";
+
+    /**
+     * The method name to add a new column in the given table of the specified content provider.
+     *
+     * <p>The method caller must provide the following parameter:
+     * <ul>
+     *     <li>{@code arg}: The content URI of the target table as a {@link String}.</li>
+     *     <li>{@code extra}: Name, data type, and default value of the new column in a Bundle:
+     *         <ul>
+     *             <li>{@link #EXTRA_COLUMN_NAME} the column name as a {@link String}.</li>
+     *             <li>{@link #EXTRA_DATA_TYPE} the data type as a {@link String}.</li>
+     *             <li>{@link #EXTRA_DEFAULT_VALUE} the default value as a {@link String}.
+     *                 (optional)</li>
+     *         </ul>
+     *     </li>
+     * </ul>
+     *
+     * <p>On success, the returned {@link android.os.Bundle} will include current colum names after
+     * the addition operation with the key {@link #EXTRA_EXISTING_COLUMN_NAMES}. Otherwise, the
+     * return value will be {@code null}.
+     *
+     * @see ContentResolver#call(Uri, String, String, Bundle)
+     * @see #EXTRA_COLUMN_NAME
+     * @see #EXTRA_DATA_TYPE
+     * @see #EXTRA_DEFAULT_VALUE
+     * @see #EXTRA_EXISTING_COLUMN_NAMES
+     * @hide
+     */
+    @SystemApi
+    public static final String METHOD_ADD_COLUMN = "add_column";
+
+    /**
+     * The key for a returned {@link Bundle} value containing existing column names in the given
+     * table as an {@link ArrayList} of {@link String}.
+     *
+     * @see #METHOD_GET_COLUMNS
+     * @see #METHOD_ADD_COLUMN
+     * @hide
+     */
+    @SystemApi
+    public static final String EXTRA_EXISTING_COLUMN_NAMES =
+            "android.media.tv.extra.EXISTING_COLUMN_NAMES";
+
+    /**
+     * The key for a {@link Bundle} parameter containing the new column name to be added in the
+     * given table as a non-empty {@link CharSequence}.
+     *
+     * @see #METHOD_ADD_COLUMN
+     * @hide
+     */
+    @SystemApi
+    public static final String EXTRA_COLUMN_NAME = "android.media.tv.extra.COLUMN_NAME";
+
+    /**
+     * The key for a {@link Bundle} parameter containing the data type of the new column to be added
+     * in the given table as a non-empty {@link CharSequence}, which should be one of the following
+     * values: {@code "TEXT"}, {@code "INTEGER"}, {@code "REAL"}, or {@code "BLOB"}.
+     *
+     * @see #METHOD_ADD_COLUMN
+     * @hide
+     */
+    @SystemApi
+    public static final String EXTRA_DATA_TYPE = "android.media.tv.extra.DATA_TYPE";
+
+    /**
+     * The key for a {@link Bundle} parameter containing the default value of the new column to be
+     * added in the given table as a {@link CharSequence}, which represents a valid default value
+     * according to the data type provided with {@link #EXTRA_DATA_TYPE}.
+     *
+     * @see #METHOD_ADD_COLUMN
+     * @hide
+     */
+    @SystemApi
+    public static final String EXTRA_DEFAULT_VALUE = "android.media.tv.extra.DEFAULT_VALUE";
+
+    /**
      * An optional query, update or delete URI parameter that allows the caller to specify TV input
      * ID to filter channels.
      * @hide
@@ -328,6 +491,15 @@
     }
 
     /**
+     * Builds a URI that points to a specific watch next program.
+     *
+     * @param watchNextProgramId The ID of the watch next program to point to.
+     */
+    public static final Uri buildWatchNextProgramUri(long watchNextProgramId) {
+        return ContentUris.withAppendedId(WatchNextPrograms.CONTENT_URI, watchNextProgramId);
+    }
+
+    /**
      * Builds a URI that points to a specific program the user watched.
      *
      * @param watchedProgramId The ID of the watched program to point to.
@@ -399,17 +571,6 @@
      */
     public interface BaseProgramColumns extends BaseTvColumns {
         /**
-         * The ID of the TV channel that provides this TV program.
-         *
-         * <p>This is a part of the channel URI and matches to {@link BaseColumns#_ID}.
-         *
-         * <p>This is a required field.
-         *
-         * <p>Type: INTEGER (long)
-         */
-        public static final String COLUMN_CHANNEL_ID = "channel_id";
-
-        /**
          * The title of this TV program.
          *
          * <p>If this program is an episodic TV show, it is recommended that the title is the series
@@ -673,6 +834,591 @@
         public static final String COLUMN_VERSION_NUMBER = "version_number";
     }
 
+    /**
+     * Common base for the tables of preview programs.
+     */
+    public interface BasePreviewProgramColumns extends BaseProgramColumns {
+
+        /** @hide */
+        @StringDef({
+                TYPE_MOVIE,
+                TYPE_TV_SERIES,
+                TYPE_TV_SEASON,
+                TYPE_TV_EPISODE,
+                TYPE_CLIP,
+                TYPE_EVENT,
+                TYPE_CHANNEL,
+                TYPE_TRACK,
+                TYPE_ALBUM,
+                TYPE_ARTIST,
+                TYPE_PLAYLIST,
+                TYPE_STATION,
+        })
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface Type {}
+
+        /**
+         * The program type for movie.
+         *
+         * @see #COLUMN_TYPE
+         */
+        public static final String TYPE_MOVIE = "TYPE_MOVIE";
+
+        /**
+         * The program type for TV series.
+         *
+         * @see #COLUMN_TYPE
+         */
+        public static final String TYPE_TV_SERIES = "TYPE_TV_SERIES";
+
+        /**
+         * The program type for TV season.
+         *
+         * @see #COLUMN_TYPE
+         */
+        public static final String TYPE_TV_SEASON = "TYPE_TV_SEASON";
+
+        /**
+         * The program type for TV episode.
+         *
+         * @see #COLUMN_TYPE
+         */
+        public static final String TYPE_TV_EPISODE = "TYPE_TV_EPISODE";
+
+        /**
+         * The program type for clip.
+         *
+         * @see #COLUMN_TYPE
+         */
+        public static final String TYPE_CLIP = "TYPE_CLIP";
+
+        /**
+         * The program type for event.
+         *
+         * @see #COLUMN_TYPE
+         */
+        public static final String TYPE_EVENT = "TYPE_EVENT";
+
+        /**
+         * The program type for channel.
+         *
+         * @see #COLUMN_TYPE
+         */
+        public static final String TYPE_CHANNEL = "TYPE_CHANNEL";
+
+        /**
+         * The program type for track.
+         *
+         * @see #COLUMN_TYPE
+         */
+        public static final String TYPE_TRACK = "TYPE_TRACK";
+
+        /**
+         * The program type for album.
+         *
+         * @see #COLUMN_TYPE
+         */
+        public static final String TYPE_ALBUM = "TYPE_ALBUM";
+
+        /**
+         * The program type for artist.
+         *
+         * @see #COLUMN_TYPE
+         */
+        public static final String TYPE_ARTIST = "TYPE_ARTIST";
+
+        /**
+         * The program type for playlist.
+         *
+         * @see #COLUMN_TYPE
+         */
+        public static final String TYPE_PLAYLIST = "TYPE_PLAYLIST";
+
+        /**
+         * The program type for station.
+         *
+         * @see #COLUMN_TYPE
+         */
+        public static final String TYPE_STATION = "TYPE_STATION";
+
+        /** @hide */
+        @StringDef({
+                ASPECT_RATIO_16_9,
+                ASPECT_RATIO_3_2,
+                ASPECT_RATIO_1_1,
+                ASPECT_RATIO_2_3,
+        })
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface AspectRatio {}
+
+        /**
+         * The aspect ratio for 16:9.
+         *
+         * @see #COLUMN_POSTER_ART_ASPECT_RATIO
+         * @see #COLUMN_THUMBNAIL_ASPECT_RATIO
+         */
+        public static final String ASPECT_RATIO_16_9 = "ASPECT_RATIO_16_9";
+
+        /**
+         * The aspect ratio for 3:2.
+         *
+         * @see #COLUMN_POSTER_ART_ASPECT_RATIO
+         * @see #COLUMN_THUMBNAIL_ASPECT_RATIO
+         */
+        public static final String ASPECT_RATIO_3_2 = "ASPECT_RATIO_3_2";
+
+        /**
+         * The aspect ratio for 1:1.
+         *
+         * @see #COLUMN_POSTER_ART_ASPECT_RATIO
+         * @see #COLUMN_THUMBNAIL_ASPECT_RATIO
+         */
+        public static final String ASPECT_RATIO_1_1 = "ASPECT_RATIO_1_1";
+
+        /**
+         * The aspect ratio for 2:3.
+         *
+         * @see #COLUMN_POSTER_ART_ASPECT_RATIO
+         * @see #COLUMN_THUMBNAIL_ASPECT_RATIO
+         */
+        public static final String ASPECT_RATIO_2_3 = "ASPECT_RATIO_2_3";
+
+        /** @hide */
+        @StringDef({
+                AVAILABILITY_AVAILABLE,
+                AVAILABILITY_FREE_WITH_SUBSCRIPTION,
+                AVAILABILITY_PAID_CONTENT,
+        })
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface Availability {}
+
+        /**
+         * The availability for "available to this user".
+         *
+         * @see #COLUMN_AVAILABILITY
+         */
+        public static final String AVAILABILITY_AVAILABLE = "AVAILABILITY_AVAILABLE";
+
+        /**
+         * The availability for "free with subscription".
+         *
+         * @see #COLUMN_AVAILABILITY
+         */
+        public static final String AVAILABILITY_FREE_WITH_SUBSCRIPTION =
+                "AVAILABILITY_FREE_WITH_SUBSCRIPTION";
+
+        /**
+         * The availability for "paid content, either to-own or rental
+         * (user has not purchased/rented).
+         *
+         * @see #COLUMN_AVAILABILITY
+         */
+        public static final String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT";
+
+        /** @hide */
+        @StringDef({
+                INTERACTION_TYPE_LISTENS,
+                INTERACTION_TYPE_FOLLOWERS,
+                INTERACTION_TYPE_FANS,
+                INTERACTION_TYPE_LIKES,
+                INTERACTION_TYPE_THUMBS,
+                INTERACTION_TYPE_VIEWS,
+                INTERACTION_TYPE_VIEWERS,
+        })
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface InteractionType {}
+
+        /**
+         * The interaction type for "listens".
+         *
+         * @see #COLUMN_INTERACTION_TYPE
+         */
+        public static final String INTERACTION_TYPE_LISTENS = "INTERACTION_TYPE_LISTENS";
+
+        /**
+         * The interaction type for "followers".
+         *
+         * @see #COLUMN_INTERACTION_TYPE
+         */
+        public static final String INTERACTION_TYPE_FOLLOWERS = "INTERACTION_TYPE_FOLLOWERS";
+
+        /**
+         * The interaction type for "fans".
+         *
+         * @see #COLUMN_INTERACTION_TYPE
+         */
+        public static final String INTERACTION_TYPE_FANS = "INTERACTION_TYPE_FANS";
+
+        /**
+         * The interaction type for "likes".
+         *
+         * @see #COLUMN_INTERACTION_TYPE
+         */
+        public static final String INTERACTION_TYPE_LIKES = "INTERACTION_TYPE_LIKES";
+
+        /**
+         * The interaction type for "thumbs".
+         *
+         * @see #COLUMN_INTERACTION_TYPE
+         */
+        public static final String INTERACTION_TYPE_THUMBS = "INTERACTION_TYPE_THUMBS";
+
+        /**
+         * The interaction type for "views".
+         *
+         * @see #COLUMN_INTERACTION_TYPE
+         */
+        public static final String INTERACTION_TYPE_VIEWS = "INTERACTION_TYPE_VIEWS";
+
+        /**
+         * The interaction type for "viewers".
+         *
+         * @see #COLUMN_INTERACTION_TYPE
+         */
+        public static final String INTERACTION_TYPE_VIEWERS = "INTERACTION_TYPE_VIEWERS";
+
+        /** @hide */
+        @StringDef({
+                REVIEW_RATING_STYLE_STARS,
+                REVIEW_RATING_STYLE_THUMBS_UP_DOWN,
+                REVIEW_RATING_STYLE_PERCENTAGE,
+        })
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface ReviewRatingStyle {}
+
+        /**
+         * The review rating style for five star rating.
+         *
+         * @see #COLUMN_REVIEW_RATING_STYLE
+         */
+        public static final String REVIEW_RATING_STYLE_STARS = "REVIEW_RATING_STYLE_STARS";
+
+        /**
+         * The review rating style for thumbs-up and thumbs-down rating.
+         *
+         * @see #COLUMN_REVIEW_RATING_STYLE
+         */
+        public static final String REVIEW_RATING_STYLE_THUMBS_UP_DOWN =
+                "REVIEW_RATING_STYLE_THUMBS_UP_DOWN";
+
+        /**
+         * The review rating style for 0 to 100 point system.
+         *
+         * @see #COLUMN_REVIEW_RATING_STYLE
+         */
+        public static final String REVIEW_RATING_STYLE_PERCENTAGE =
+                "REVIEW_RATING_STYLE_PERCENTAGE";
+
+        /**
+         * The type of this program content.
+         *
+         * <p>The value should match one of the followings:
+         * {@link #TYPE_MOVIE},
+         * {@link #TYPE_TV_SERIES},
+         * {@link #TYPE_TV_SEASON},
+         * {@link #TYPE_TV_EPISODE},
+         * {@link #TYPE_CLIP},
+         * {@link #TYPE_EVENT},
+         * {@link #TYPE_CHANNEL},
+         * {@link #TYPE_TRACK},
+         * {@link #TYPE_ALBUM},
+         * {@link #TYPE_ARTIST},
+         * {@link #TYPE_PLAYLIST}, and
+         * {@link #TYPE_STATION}.
+         *
+         * <p>This is a required field if the program is from a {@link Channels#TYPE_PREVIEW}
+         * channel.
+         *
+         * <p>Type: TEXT
+         */
+        public static final String COLUMN_TYPE = "type";
+
+        /**
+         * The aspect ratio of the poster art for this TV program.
+         *
+         * <p>The value should match one of the followings:
+         * {@link #ASPECT_RATIO_16_9},
+         * {@link #ASPECT_RATIO_3_2},
+         * {@link #ASPECT_RATIO_1_1}, and
+         * {@link #ASPECT_RATIO_2_3}.
+         *
+         * <p>Type: TEXT
+         */
+        public static final String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
+
+        /**
+         * The aspect ratio of the thumbnail for this TV program.
+         *
+         * <p>The value should match one of the followings:
+         * {@link #ASPECT_RATIO_16_9},
+         * {@link #ASPECT_RATIO_3_2},
+         * {@link #ASPECT_RATIO_1_1}, and
+         * {@link #ASPECT_RATIO_2_3}.
+         *
+         * <p>Type: TEXT
+         */
+        public static final String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
+
+        /**
+         * The URI for the logo of this TV program.
+         *
+         * <p>This is a small badge shown on top of the poster art or thumbnail representing the
+         * source of the content.
+         *
+         * <p>The data in the column must be a URL, or a URI in one of the following formats:
+         *
+         * <ul>
+         * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
+         * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})
+         * </li>
+         * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
+         * </ul>
+         *
+         * <p>Can be empty.
+         *
+         * <p>Type: TEXT
+         */
+        public static final String COLUMN_LOGO_URI = "logo_uri";
+
+        /**
+         * The availability of this TV program.
+         *
+         * <p>The value should match one of the followings:
+         * {@link #AVAILABILITY_AVAILABLE},
+         * {@link #AVAILABILITY_FREE_WITH_SUBSCRIPTION}, and
+         * {@link #AVAILABILITY_PAID_CONTENT}.
+         *
+         * <p>Type: TEXT
+         */
+        public static final String COLUMN_AVAILABILITY = "availability";
+
+        /**
+         * The starting price of this TV program.
+         *
+         * <p>This indicates the lowest regular acquisition cost of the content. It is only used
+         * if the availability of the program is {@link #AVAILABILITY_PAID_CONTENT}.
+         *
+         * <p>Type: TEXT
+         * @see #COLUMN_OFFER_PRICE
+         */
+        public static final String COLUMN_STARTING_PRICE = "starting_price";
+
+        /**
+         * The offer price of this TV program.
+         *
+         * <p>This is the promotional cost of the content. It is only used if the availability of
+         * the program is {@link #AVAILABILITY_PAID_CONTENT}.
+         *
+         * <p>Type: TEXT
+         * @see #COLUMN_STARTING_PRICE
+         */
+        public static final String COLUMN_OFFER_PRICE = "offer_price";
+
+        /**
+         * The release date of this TV program.
+         *
+         * <p>The value should be in the form of either "yyyy-MM-dd" or "yyyy".
+         *
+         * <p>Type: TEXT
+         */
+        public static final String COLUMN_RELEASE_DATE = "release_date";
+
+        /**
+         * The count of the items included in this TV program.
+         *
+         * <p>This is only relevant if the program represents a collection of items such as series,
+         * episodes, or music tracks.
+         *
+         * <p>Type: INTEGER
+         */
+        public static final String COLUMN_ITEM_COUNT = "item_count";
+
+        /**
+         * The flag indicating whether this TV program is live or not.
+         *
+         * <p>A value of 1 indicates that the content is airing and should be consumed now, a value
+         * of 0 indicates that the content is off the air and does not need to be consumed at the
+         * present time. If not specified, the value is set to 0 (not live) by default.
+         *
+         * <p>Type: INTEGER (boolean)
+         */
+        public static final String COLUMN_LIVE = "live";
+
+        /**
+         * The internal ID used by individual TV input services.
+         *
+         * <p>This is internal to the provider that inserted it, and should not be decoded by other
+         * apps.
+         *
+         * <p>Can be empty.
+         *
+         * <p>Type: TEXT
+         */
+        public static final String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
+
+        /**
+         * The URI for the preview video.
+         *
+         * <p>This is only relevant to {@link Channels#TYPE_PREVIEW}. The data in the column must be
+         * a URL, or a URI in one of the following formats:
+         *
+         * <ul>
+         * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
+         * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})
+         * </li>
+         * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
+         * </ul>
+         *
+         * <p>Can be empty.
+         *
+         * <p>Type: TEXT
+         */
+        public static final String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri";
+
+        /**
+         * The last playback position (in milliseconds) of the preview video.
+         *
+         * <p>This is only relevant to {@link Channels#TYPE_PREVIEW}.
+         *
+         * <p>Can be empty.
+         *
+         * <p>Type: INTEGER
+         */
+        public static final String COLUMN_LAST_PLAYBACK_POSITION_MILLIS =
+                "last_playback_position_millis";
+
+        /**
+         * The duration (in milliseconds) of the preview video.
+         *
+         * <p>This is only relevant to {@link Channels#TYPE_PREVIEW}.
+         *
+         * <p>Can be empty.
+         *
+         * <p>Type: INTEGER
+         */
+        public static final String COLUMN_DURATION_MILLIS = "duration_millis";
+
+        /**
+         * The intent URI which is launched when the preview video is selected.
+         *
+         * <p>The URI is created using {@link Intent#toUri} with {@link Intent#URI_INTENT_SCHEME}
+         * and converted back to the original intent with {@link Intent#parseUri}. The intent is
+         * launched when the user selects the preview video item.
+         *
+         * <p>Can be empty.
+         *
+         * <p>Type: TEXT
+         */
+        public static final String COLUMN_APP_LINK_INTENT_URI =
+                "app_link_intent_uri";
+
+        /**
+         * The flag indicating whether this program is transient or not.
+         *
+         * <p>A value of 1 indicates that the channel will be automatically removed by the system on
+         * reboot, and a value of 0 indicates that the channel is persistent across reboot. If not
+         * specified, this value is set to 0 (not transient) by default.
+         *
+         * <p>Type: INTEGER (boolean)
+         * @see Channels#COLUMN_TRANSIENT
+         * @hide
+         */
+        @SystemApi
+        public static final String COLUMN_TRANSIENT = "transient";
+
+        /**
+         * The type of interaction for this TV program.
+         *
+         * <p> The value should match one of the followings:
+         * {@link #INTERACTION_TYPE_LISTENS},
+         * {@link #INTERACTION_TYPE_FOLLOWERS},
+         * {@link #INTERACTION_TYPE_FANS},
+         * {@link #INTERACTION_TYPE_LIKES},
+         * {@link #INTERACTION_TYPE_THUMBS},
+         * {@link #INTERACTION_TYPE_VIEWS}, and
+         * {@link #INTERACTION_TYPE_VIEWERS}.
+         *
+         * <p>Type: TEXT
+         * @see #COLUMN_INTERACTION_COUNT
+         */
+        public static final String COLUMN_INTERACTION_TYPE = "interaction_type";
+
+        /**
+         * The interaction count for this program.
+         *
+         * <p>This indicates the number of times interaction has happened.
+         *
+         * <p>Type: INTEGER (long)
+         * @see #COLUMN_INTERACTION_TYPE
+         */
+        public static final String COLUMN_INTERACTION_COUNT = "interaction_count";
+
+        /**
+         * The author or artist of this content.
+         *
+         * <p>Type: TEXT
+         */
+        public static final String COLUMN_AUTHOR = "author";
+
+        /**
+         * The review rating score style used for {@link #COLUMN_REVIEW_RATING}.
+         *
+         * <p> The value should match one of the followings: {@link #REVIEW_RATING_STYLE_STARS},
+         * {@link #REVIEW_RATING_STYLE_THUMBS_UP_DOWN}, and {@link #REVIEW_RATING_STYLE_PERCENTAGE}.
+         *
+         * <p>Type: TEXT
+         * @see #COLUMN_REVIEW_RATING
+         */
+        public static final String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
+
+        /**
+         * The review rating score for this program.
+         *
+         * <p>The format of the value is dependent on {@link #COLUMN_REVIEW_RATING_STYLE}. If the
+         * style is {@link #REVIEW_RATING_STYLE_STARS}, the value should be a real number between
+         * 0.0 and 5.0. (e.g. "4.5") If the style is {@link #REVIEW_RATING_STYLE_THUMBS_UP_DOWN},
+         * the value should be two integers, one for thumbs-up count and the other for thumbs-down
+         * count, with a comma between them. (e.g. "200,40") If the style is
+         * {@link #REVIEW_RATING_STYLE_PERCENTAGE}, the value shoule be a real number between 0 and
+         * 100. (e.g. "99.9")
+         *
+         * <p>Type: TEXT
+         * @see #COLUMN_REVIEW_RATING_STYLE
+         */
+        public static final String COLUMN_REVIEW_RATING = "review_rating";
+
+        /**
+         * The flag indicating whether this TV program is browsable or not.
+         *
+         * <p>This column can only be set by applications having proper system permission. For
+         * other applications, this is a read-only column.
+         *
+         * <p>A value of 1 indicates that the program is browsable and can be shown to users in
+         * the UI. A value of 0 indicates that the program should be hidden from users and the
+         * application who changes this value to 0 should send
+         * {@link #ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED} to the owner of the program
+         * to notify this change.
+         *
+         * <p>This value is set to 1 (browsable) by default.
+         *
+         * <p>Type: INTEGER (boolean)
+         */
+        public static final String COLUMN_BROWSABLE = "browsable";
+
+        /**
+         * The content ID of this TV program.
+         *
+         * <p>A public ID of the content which allows the application to apply the same operation to
+         * all the program copies in different channels.
+         *
+         * <p>Can be empty.
+         *
+         * <p>Type: TEXT
+         */
+        public static final String COLUMN_CONTENT_ID = "content_id";
+
+    }
+
     /** Column definitions for the TV channels table. */
     public static final class Channels implements BaseTvColumns {
 
@@ -1186,14 +1932,15 @@
         /**
          * The flag indicating whether this TV channel is browsable or not.
          *
+         * <p>This column can only be set by applications having proper system permission. For
+         * other applications, this is a read-only column.
+         *
          * <p>A value of 1 indicates the channel is included in the channel list that applications
          * use to browse channels, a value of 0 indicates the channel is not included in the list.
          * If not specified, this value is set to 0 (not browsable) by default.
          *
          * <p>Type: INTEGER (boolean)
-         * @hide
          */
-        @SystemApi
         public static final String COLUMN_BROWSABLE = "browsable";
 
         /**
@@ -1494,6 +2241,17 @@
         public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program";
 
         /**
+         * The ID of the TV channel that provides this TV program.
+         *
+         * <p>This is a part of the channel URI and matches to {@link BaseColumns#_ID}.
+         *
+         * <p>This is a required field.
+         *
+         * <p>Type: INTEGER (long)
+         */
+        public static final String COLUMN_CHANNEL_ID = "channel_id";
+
+        /**
          * The season number of this TV program for episodic TV shows.
          *
          * <p>Can be empty.
@@ -1797,6 +2555,17 @@
         public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/recorded_program";
 
         /**
+         * The ID of the TV channel that provides this recorded program.
+         *
+         * <p>This is a part of the channel URI and matches to {@link BaseColumns#_ID}.
+         *
+         * <p>This is a required field.
+         *
+         * <p>Type: INTEGER (long)
+         */
+        public static final String COLUMN_CHANNEL_ID = "channel_id";
+
+        /**
          * The ID of the TV input service that is associated with this recorded program.
          *
          * <p>Use {@link #buildInputId} to build the ID.
@@ -1895,7 +2664,7 @@
     /**
      * Column definitions for the preview TV programs table.
      */
-    public static final class PreviewPrograms implements BaseProgramColumns {
+    public static final class PreviewPrograms implements BasePreviewProgramColumns {
 
         /** The content:// style URI for this table. */
         public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/"
@@ -1907,522 +2676,16 @@
         /** The MIME type of a single preview TV program. */
         public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/preview_program";
 
-        /** @hide */
-        @StringDef({
-                TYPE_MOVIE,
-                TYPE_TV_SERIES,
-                TYPE_TV_SEASON,
-                TYPE_TV_EPISODE,
-                TYPE_CLIP,
-                TYPE_EVENT,
-                TYPE_CHANNEL,
-                TYPE_TRACK,
-                TYPE_ALBUM,
-                TYPE_ARTIST,
-                TYPE_PLAYLIST,
-                TYPE_STATION,
-        })
-        @Retention(RetentionPolicy.SOURCE)
-        public @interface Type {}
-
         /**
-         * The program type for movie.
+         * The ID of the TV channel that provides this TV program.
          *
-         * @see #COLUMN_TYPE
+         * <p>This is a part of the channel URI and matches to {@link BaseColumns#_ID}.
+         *
+         * <p>This is a required field.
+         *
+         * <p>Type: INTEGER (long)
          */
-        public static final String TYPE_MOVIE = "TYPE_MOVIE";
-
-        /**
-         * The program type for TV series.
-         *
-         * @see #COLUMN_TYPE
-         */
-        public static final String TYPE_TV_SERIES = "TYPE_TV_SERIES";
-
-        /**
-         * The program type for TV season.
-         *
-         * @see #COLUMN_TYPE
-         */
-        public static final String TYPE_TV_SEASON = "TYPE_TV_SEASON";
-
-        /**
-         * The program type for TV episode.
-         *
-         * @see #COLUMN_TYPE
-         */
-        public static final String TYPE_TV_EPISODE = "TYPE_TV_EPISODE";
-
-        /**
-         * The program type for clip.
-         *
-         * @see #COLUMN_TYPE
-         */
-        public static final String TYPE_CLIP = "TYPE_CLIP";
-
-        /**
-         * The program type for event.
-         *
-         * @see #COLUMN_TYPE
-         */
-        public static final String TYPE_EVENT = "TYPE_EVENT";
-
-        /**
-         * The program type for channel.
-         *
-         * @see #COLUMN_TYPE
-         */
-        public static final String TYPE_CHANNEL = "TYPE_CHANNEL";
-
-        /**
-         * The program type for track.
-         *
-         * @see #COLUMN_TYPE
-         */
-        public static final String TYPE_TRACK = "TYPE_TRACK";
-
-        /**
-         * The program type for album.
-         *
-         * @see #COLUMN_TYPE
-         */
-        public static final String TYPE_ALBUM = "TYPE_ALBUM";
-
-        /**
-         * The program type for artist.
-         *
-         * @see #COLUMN_TYPE
-         */
-        public static final String TYPE_ARTIST = "TYPE_ARTIST";
-
-        /**
-         * The program type for playlist.
-         *
-         * @see #COLUMN_TYPE
-         */
-        public static final String TYPE_PLAYLIST = "TYPE_PLAYLIST";
-
-        /**
-         * The program type for station.
-         *
-         * @see #COLUMN_TYPE
-         */
-        public static final String TYPE_STATION = "TYPE_STATION";
-
-        /** @hide */
-        @StringDef({
-                WATCH_NEXT_TYPE_CONTINUE,
-                WATCH_NEXT_TYPE_NEXT,
-                WATCH_NEXT_TYPE_NEW,
-        })
-        @Retention(RetentionPolicy.SOURCE)
-        public @interface WatchNextType {}
-
-        /**
-         * The watch next type for CONTINUE.
-         *
-         * @see #COLUMN_WATCH_NEXT_TYPE
-         */
-        public static final String WATCH_NEXT_TYPE_CONTINUE = "WATCH_NEXT_TYPE_CONTINUE";
-
-        /**
-         * The watch next type for NEXT.
-         *
-         * @see #COLUMN_WATCH_NEXT_TYPE
-         */
-        public static final String WATCH_NEXT_TYPE_NEXT = "WATCH_NEXT_TYPE_NEXT";
-
-        /**
-         * The watch next type for NEW.
-         *
-         * @see #COLUMN_WATCH_NEXT_TYPE
-         */
-        public static final String WATCH_NEXT_TYPE_NEW = "WATCH_NEXT_TYPE_NEW";
-
-        /** @hide */
-        @StringDef({
-                ASPECT_RATIO_16_9,
-                ASPECT_RATIO_3_2,
-                ASPECT_RATIO_1_1,
-                ASPECT_RATIO_2_3,
-        })
-        @Retention(RetentionPolicy.SOURCE)
-        public @interface AspectRatio {}
-
-        /**
-         * The aspect ratio for 16:9.
-         *
-         * @see #COLUMN_POSTER_ART_ASPECT_RATIO
-         * @see #COLUMN_THUMBNAIL_ASPECT_RATIO
-         */
-        public static final String ASPECT_RATIO_16_9 = "ASPECT_RATIO_16_9";
-
-        /**
-         * The aspect ratio for 3:2.
-         *
-         * @see #COLUMN_POSTER_ART_ASPECT_RATIO
-         * @see #COLUMN_THUMBNAIL_ASPECT_RATIO
-         */
-        public static final String ASPECT_RATIO_3_2 = "ASPECT_RATIO_3_2";
-
-        /**
-         * The aspect ratio for 1:1.
-         *
-         * @see #COLUMN_POSTER_ART_ASPECT_RATIO
-         * @see #COLUMN_THUMBNAIL_ASPECT_RATIO
-         */
-        public static final String ASPECT_RATIO_1_1 = "ASPECT_RATIO_1_1";
-
-        /**
-         * The aspect ratio for 2:3.
-         *
-         * @see #COLUMN_POSTER_ART_ASPECT_RATIO
-         * @see #COLUMN_THUMBNAIL_ASPECT_RATIO
-         */
-        public static final String ASPECT_RATIO_2_3 = "ASPECT_RATIO_2_3";
-
-        /** @hide */
-        @StringDef({
-                AVAILABILITY_AVAILABLE,
-                AVAILABILITY_FREE_WITH_SUBSCRIPTION,
-                AVAILABILITY_PAID_CONTENT,
-        })
-        @Retention(RetentionPolicy.SOURCE)
-        public @interface Availability {}
-
-        /**
-         * The availability for "available to this user".
-         *
-         * @see #COLUMN_AVAILABILITY
-         */
-        public static final String AVAILABILITY_AVAILABLE = "AVAILABILITY_AVAILABLE";
-
-        /**
-         * The availability for "free with subscription".
-         *
-         * @see #COLUMN_AVAILABILITY
-         */
-        public static final String AVAILABILITY_FREE_WITH_SUBSCRIPTION =
-                "AVAILABILITY_FREE_WITH_SUBSCRIPTION";
-
-        /**
-         * The availability for "paid content, either to-own or rental
-         * (user has not purchased/rented).
-         *
-         * @see #COLUMN_AVAILABILITY
-         */
-        public static final String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT";
-
-        /** @hide */
-        @StringDef({
-                INTERACTION_TYPE_LISTENS,
-                INTERACTION_TYPE_FOLLOWERS,
-                INTERACTION_TYPE_FANS,
-                INTERACTION_TYPE_LIKES,
-                INTERACTION_TYPE_THUMBS,
-                INTERACTION_TYPE_VIEWS,
-                INTERACTION_TYPE_VIEWERS,
-        })
-        @Retention(RetentionPolicy.SOURCE)
-        public @interface InteractionType {}
-
-        /**
-         * The interaction type for "listens".
-         *
-         * @see #COLUMN_INTERACTION_TYPE
-         */
-        public static final String INTERACTION_TYPE_LISTENS = "INTERACTION_TYPE_LISTENS";
-
-        /**
-         * The interaction type for "followers".
-         *
-         * @see #COLUMN_INTERACTION_TYPE
-         */
-        public static final String INTERACTION_TYPE_FOLLOWERS = "INTERACTION_TYPE_FOLLOWERS";
-
-        /**
-         * The interaction type for "fans".
-         *
-         * @see #COLUMN_INTERACTION_TYPE
-         */
-        public static final String INTERACTION_TYPE_FANS = "INTERACTION_TYPE_FANS";
-
-        /**
-         * The interaction type for "likes".
-         *
-         * @see #COLUMN_INTERACTION_TYPE
-         */
-        public static final String INTERACTION_TYPE_LIKES = "INTERACTION_TYPE_LIKES";
-
-        /**
-         * The interaction type for "thumbs".
-         *
-         * @see #COLUMN_INTERACTION_TYPE
-         */
-        public static final String INTERACTION_TYPE_THUMBS = "INTERACTION_TYPE_THUMBS";
-
-        /**
-         * The interaction type for "views".
-         *
-         * @see #COLUMN_INTERACTION_TYPE
-         */
-        public static final String INTERACTION_TYPE_VIEWS = "INTERACTION_TYPE_VIEWS";
-
-        /**
-         * The interaction type for "viewers".
-         *
-         * @see #COLUMN_INTERACTION_TYPE
-         */
-        public static final String INTERACTION_TYPE_VIEWERS = "INTERACTION_TYPE_VIEWERS";
-
-        /** @hide */
-        @StringDef({
-                REVIEW_RATING_STYLE_STARS,
-                REVIEW_RATING_STYLE_THUMBS_UP_DOWN,
-                REVIEW_RATING_STYLE_PERCENTAGE,
-        })
-        @Retention(RetentionPolicy.SOURCE)
-        public @interface ReviewRatingStyle {}
-
-        /**
-         * The review rating style for five star rating.
-         *
-         * @see #COLUMN_REVIEW_RATING_STYLE
-         */
-        public static final String REVIEW_RATING_STYLE_STARS = "REVIEW_RATING_STYLE_STARS";
-
-        /**
-         * The review rating style for thumbs-up and thumbs-down rating.
-         *
-         * @see #COLUMN_REVIEW_RATING_STYLE
-         */
-        public static final String REVIEW_RATING_STYLE_THUMBS_UP_DOWN =
-                "REVIEW_RATING_STYLE_THUMBS_UP_DOWN";
-
-        /**
-         * The review rating style for 0 to 100 point system.
-         *
-         * @see #COLUMN_REVIEW_RATING_STYLE
-         */
-        public static final String REVIEW_RATING_STYLE_PERCENTAGE =
-                "REVIEW_RATING_STYLE_PERCENTAGE";
-
-        /**
-         * The type of this program content.
-         *
-         * <p>The value should match one of the followings:
-         * {@link #TYPE_MOVIE},
-         * {@link #TYPE_TV_SERIES},
-         * {@link #TYPE_TV_SEASON},
-         * {@link #TYPE_TV_EPISODE},
-         * {@link #TYPE_CLIP},
-         * {@link #TYPE_EVENT},
-         * {@link #TYPE_CHANNEL},
-         * {@link #TYPE_TRACK},
-         * {@link #TYPE_ALBUM},
-         * {@link #TYPE_ARTIST},
-         * {@link #TYPE_PLAYLIST}, and
-         * {@link #TYPE_STATION}.
-         *
-         * <p>This is a required field if the program is from a {@link Channels#TYPE_PREVIEW}
-         * channel.
-         *
-         * <p>Type: TEXT
-         */
-        public static final String COLUMN_TYPE = "type";
-
-        /**
-         * The "watch next" type of this program content.
-         *
-         * <p>The value should match one of the followings:
-         * {@link #WATCH_NEXT_TYPE_CONTINUE},
-         * {@link #WATCH_NEXT_TYPE_NEXT}, and
-         * {@link #WATCH_NEXT_TYPE_NEW}.
-         *
-         * <p>Can be empty.
-         *
-         * <p>Type: TEXT
-         */
-        public static final String COLUMN_WATCH_NEXT_TYPE = "watch_next_type";
-
-        /**
-         * The aspect ratio of the poster art for this TV program.
-         *
-         * <p>The value should match one of the followings:
-         * {@link #ASPECT_RATIO_16_9},
-         * {@link #ASPECT_RATIO_3_2},
-         * {@link #ASPECT_RATIO_1_1}, and
-         * {@link #ASPECT_RATIO_2_3}.
-         *
-         * <p>Type: TEXT
-         */
-        public static final String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
-
-        /**
-         * The aspect ratio of the thumbnail for this TV program.
-         *
-         * <p>The value should match one of the followings:
-         * {@link #ASPECT_RATIO_16_9},
-         * {@link #ASPECT_RATIO_3_2},
-         * {@link #ASPECT_RATIO_1_1}, and
-         * {@link #ASPECT_RATIO_2_3}.
-         *
-         * <p>Type: TEXT
-         */
-        public static final String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
-
-        /**
-         * The URI for the logo of this TV program.
-         *
-         * <p>This is a small badge shown on top of the poster art or thumbnail representing the
-         * source of the content.
-         *
-         * <p>The data in the column must be a URL, or a URI in one of the following formats:
-         *
-         * <ul>
-         * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
-         * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})
-         * </li>
-         * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
-         * </ul>
-         *
-         * <p>Can be empty.
-         *
-         * <p>Type: TEXT
-         */
-        public static final String COLUMN_LOGO_URI = "logo_uri";
-
-        /**
-         * The availability of this TV program.
-         *
-         * <p>The value should match one of the followings:
-         * {@link #AVAILABILITY_AVAILABLE},
-         * {@link #AVAILABILITY_FREE_WITH_SUBSCRIPTION}, and
-         * {@link #AVAILABILITY_PAID_CONTENT}.
-         *
-         * <p>Type: TEXT
-         */
-        public static final String COLUMN_AVAILABILITY = "availability";
-
-        /**
-         * The starting price of this TV program.
-         *
-         * <p>This indicates the lowest regular acquisition cost of the content. It is only used
-         * if the availability of the program is {@link #AVAILABILITY_PAID_CONTENT}.
-         *
-         * <p>Type: TEXT
-         * @see #COLUMN_OFFER_PRICE
-         */
-        public static final String COLUMN_STARTING_PRICE = "starting_price";
-
-        /**
-         * The offer price of this TV program.
-         *
-         * <p>This is the promotional cost of the content. It is only used if the availability of
-         * the program is {@link #AVAILABILITY_PAID_CONTENT}.
-         *
-         * <p>Type: TEXT
-         * @see #COLUMN_STARTING_PRICE
-         */
-        public static final String COLUMN_OFFER_PRICE = "offer_price";
-
-        /**
-         * The release date of this TV program.
-         *
-         * <p>The value should be in the form of either "yyyy-MM-dd" or "yyyy".
-         *
-         * <p>Type: TEXT
-         */
-        public static final String COLUMN_RELEASE_DATE = "release_date";
-
-        /**
-         * The count of the items included in this TV program.
-         *
-         * <p>This is only relevant if the program represents a collection of items such as series,
-         * episodes, or music tracks.
-         *
-         * <p>Type: INTEGER
-         */
-        public static final String COLUMN_ITEM_COUNT = "item_count";
-
-        /**
-         * The flag indicating whether this TV program is live or not.
-         *
-         * <p>A value of 1 indicates that the content is airing and should be consumed now, a value
-         * of 0 indicates that the content is off the air and does not need to be consumed at the
-         * present time. If not specified, the value is set to 0 (not live) by default.
-         *
-         * <p>Type: INTEGER (boolean)
-         */
-        public static final String COLUMN_LIVE = "live";
-
-        /**
-         * The internal ID used by individual TV input services.
-         *
-         * <p>This is internal to the provider that inserted it, and should not be decoded by other
-         * apps.
-         *
-         * <p>Can be empty.
-         *
-         * <p>Type: TEXT
-         */
-        public static final String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
-
-        /**
-         * The URI for the preview video.
-         *
-         * <p>This is only relevant to {@link Channels#TYPE_PREVIEW}. The data in the column must be
-         * a URL, or a URI in one of the following formats:
-         *
-         * <ul>
-         * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
-         * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})
-         * </li>
-         * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
-         * </ul>
-         *
-         * <p>Can be empty.
-         *
-         * <p>Type: TEXT
-         */
-        public static final String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri";
-
-        /**
-         * The last playback position (in milliseconds) of the preview video.
-         *
-         * <p>This is only relevant to {@link Channels#TYPE_PREVIEW}.
-         *
-         * <p>Can be empty.
-         *
-         * <p>Type: INTEGER
-         */
-        public static final String COLUMN_LAST_PLAYBACK_POSITION_MILLIS =
-                "last_playback_position_millis";
-
-        /**
-         * The duration (in milliseconds) of the preview video.
-         *
-         * <p>This is only relevant to {@link Channels#TYPE_PREVIEW}.
-         *
-         * <p>Can be empty.
-         *
-         * <p>Type: INTEGER
-         */
-        public static final String COLUMN_DURATION_MILLIS = "duration_millis";
-
-        /**
-         * The intent URI which is launched when the preview video is selected.
-         *
-         * <p>The URI is created using {@link Intent#toUri} with {@link Intent#URI_INTENT_SCHEME}
-         * and converted back to the original intent with {@link Intent#parseUri}. The intent is
-         * launched when the user selects the preview video item.
-         *
-         * <p>Can be empty.
-         *
-         * <p>Type: TEXT
-         */
-        public static final String COLUMN_APP_LINK_INTENT_URI =
-                "app_link_intent_uri";
+        public static final String COLUMN_CHANNEL_ID = "channel_id";
 
         /**
          * The weight of the preview program within the channel.
@@ -2438,103 +2701,110 @@
          */
         public static final String COLUMN_WEIGHT = "weight";
 
-        /**
-         * The flag indicating whether this program is transient or not.
-         *
-         * <p>A value of 1 indicates that the channel will be automatically removed by the system on
-         * reboot, and a value of 0 indicates that the channel is persistent across reboot. If not
-         * specified, this value is set to 0 (not transient) by default.
-         *
-         * <p>Type: INTEGER (boolean)
-         * @see Channels#COLUMN_TRANSIENT
-         * @hide
-         */
-        @SystemApi
-        public static final String COLUMN_TRANSIENT = "transient";
-
-        /**
-         * The type of interaction for this TV program.
-         *
-         * <p> The value should match one of the followings:
-         * {@link #INTERACTION_TYPE_LISTENS},
-         * {@link #INTERACTION_TYPE_FOLLOWERS},
-         * {@link #INTERACTION_TYPE_FANS},
-         * {@link #INTERACTION_TYPE_LIKES},
-         * {@link #INTERACTION_TYPE_THUMBS},
-         * {@link #INTERACTION_TYPE_VIEWS}, and
-         * {@link #INTERACTION_TYPE_VIEWERS}.
-         *
-         * <p>Type: TEXT
-         * @see #COLUMN_INTERACTION_COUNT
-         */
-        public static final String COLUMN_INTERACTION_TYPE = "interaction_type";
-
-        /**
-         * The interaction count for this program.
-         *
-         * <p>This indicates the number of times interaction has happened.
-         *
-         * <p>Type: INTEGER
-         * @see #COLUMN_INTERACTION_TYPE
-         */
-        public static final String COLUMN_INTERACTION_COUNT = "interaction_count";
-
-        /**
-         * The author or artist of this content.
-         *
-         * <p>Type: TEXT
-         */
-        public static final String COLUMN_AUTHOR = "author";
-
-        /**
-         * The review rating score style used for {@link #COLUMN_REVIEW_RATING}.
-         *
-         * <p> The value should match one of the followings: {@link #REVIEW_RATING_STYLE_STARS},
-         * {@link #REVIEW_RATING_STYLE_THUMBS_UP_DOWN}, and {@link #REVIEW_RATING_STYLE_PERCENTAGE}.
-         *
-         * <p>Type: TEXT
-         * @see #COLUMN_REVIEW_RATING
-         */
-        public static final String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
-
-        /**
-         * The review rating score for this program.
-         *
-         * <p>The format of the value is dependent on {@link #COLUMN_REVIEW_RATING_STYLE}. If the
-         * style is {@link #REVIEW_RATING_STYLE_STARS}, the value should be a real number between
-         * 0.0 and 5.0. (e.g. "4.5") If the style is {@link #REVIEW_RATING_STYLE_THUMBS_UP_DOWN},
-         * the value should be two integers, one for thumbs-up count and the other for thumbs-down
-         * count, with a comma between them. (e.g. "200,40") If the style is
-         * {@link #REVIEW_RATING_STYLE_PERCENTAGE}, the value shoule be a real number between 0 and
-         * 100. (e.g. "99.9")
-         *
-         * <p>Type: TEXT
-         * @see #COLUMN_REVIEW_RATING_STYLE
-         */
-        public static final String COLUMN_REVIEW_RATING = "review_rating";
-
-        /**
-         * The flag indicating whether this TV program is browsable or not.
-         *
-         * <p>This column can only be set by system apps. For other applications, it is a read-only
-         * column. Trying to modify it may cause {@link SecurityException}.
-         *
-         * <p>A value of 1 indicates that the program is browsable and can be shown to users in
-         * the UI. A value of 0 indicates that the program should be hidden from users and the
-         * application who changes this value to 0 should send
-         * {@link TvInputManager#ACTION_PROGRAM_BROWSABLE_DISABLED} to the owner of the program
-         * to notify this change.
-         *
-         * <p>This value is set to 1 (browsable) by default.
-         *
-         * <p>Type: INTEGER (boolean)
-         */
-        public static final String COLUMN_BROWSABLE = "browsable";
-
         private PreviewPrograms() {}
     }
 
     /**
+     * Column definitions for the "watch next" TV programs table.
+     */
+    public static final class WatchNextPrograms implements BasePreviewProgramColumns {
+
+        /** The content:// style URI for this table. */
+        public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/"
+                + PATH_WATCH_NEXT_PROGRAM);
+
+        /** The MIME type of a directory of "watch next" TV programs. */
+        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/watch_next_program";
+
+        /** The MIME type of a single preview TV program. */
+        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/watch_next_program";
+
+        /** @hide */
+        @StringDef({
+                WATCH_NEXT_TYPE_CONTINUE,
+                WATCH_NEXT_TYPE_NEXT,
+                WATCH_NEXT_TYPE_NEW,
+                WATCH_NEXT_TYPE_WATCHLIST,
+        })
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface WatchNextType {}
+
+        /**
+         * The watch next type for CONTINUE. Use this type when the user has already watched more
+         * than 1 minute of this content.
+         *
+         * @see #COLUMN_WATCH_NEXT_TYPE
+         */
+        public static final String WATCH_NEXT_TYPE_CONTINUE = "WATCH_NEXT_TYPE_CONTINUE";
+
+        /**
+         * The watch next type for NEXT. Use this type when the user has watched one or more
+         * complete episodes from some episodic content, but there remains more than one episode
+         * remaining or there is one last episode remaining, but it is not “new” in that it was
+         * released before the user started watching the show.
+         *
+         * @see #COLUMN_WATCH_NEXT_TYPE
+         */
+        public static final String WATCH_NEXT_TYPE_NEXT = "WATCH_NEXT_TYPE_NEXT";
+
+        /**
+         * The watch next type for NEW. Use this type when the user had watched all of the available
+         * episodes from some episodic content, but a new episode became available since the user
+         * started watching the first episode and now there is exactly one unwatched episode. This
+         * could also work for recorded events in a series e.g. soccer matches or football games.
+         *
+         * @see #COLUMN_WATCH_NEXT_TYPE
+         */
+        public static final String WATCH_NEXT_TYPE_NEW = "WATCH_NEXT_TYPE_NEW";
+
+        /**
+         * The watch next type for WATCHLIST. Use this type when the user has elected to explicitly
+         * add a movie, event or series to a “watchlist” as a manual way of curating what they
+         * want to watch next.
+         *
+         * @see #COLUMN_WATCH_NEXT_TYPE
+         */
+        public static final String WATCH_NEXT_TYPE_WATCHLIST = "WATCH_NEXT_TYPE_WATCHLIST";
+
+        /**
+         * The "watch next" type of this program content.
+         *
+         * <p>The value should match one of the followings:
+         * {@link #WATCH_NEXT_TYPE_CONTINUE},
+         * {@link #WATCH_NEXT_TYPE_NEXT},
+         * {@link #WATCH_NEXT_TYPE_NEW}, and
+         * {@link #WATCH_NEXT_TYPE_WATCHLIST}.
+         *
+         * <p>This is a required field.
+         *
+         * <p>Type: TEXT
+         */
+        public static final String COLUMN_WATCH_NEXT_TYPE = "watch_next_type";
+
+        /**
+         * The last UTC time that the user engaged in this TV program, in milliseconds since the
+         * epoch. This is a hint for the application that is used for ordering of "watch next"
+         * programs.
+         *
+         * <p>The meaning of the value varies depending on the {@link #COLUMN_WATCH_NEXT_TYPE}:
+         * <ul>
+         *     <li>{@link #WATCH_NEXT_TYPE_CONTINUE}: the date that the user was last watching the
+         *     content.</li>
+         *     <li>{@link #WATCH_NEXT_TYPE_NEXT}: the date of the last episode watched.</li>
+         *     <li>{@link #WATCH_NEXT_TYPE_NEW}: the release date of the new episode.</li>
+         *     <li>{@link #WATCH_NEXT_TYPE_WATCHLIST}: the date the item was added to the Watchlist.
+         *     </li>
+         * </ul>
+         *
+         * <p>This is a required field.
+         *
+         * <p>Type: INTEGER (long)
+         */
+        public static final String COLUMN_LAST_ENGAGEMENT_TIME_UTC_MILLIS =
+                "last_engagement_time_utc_millis";
+    }
+
+    /**
      * Column definitions for the TV programs that the user watched. Applications do not have access
      * to this table.
      *
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index 3b74ee7..35988d4 100644
--- a/media/java/android/media/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -694,10 +694,16 @@
          *            {@link TvInputService}.
          */
         public Builder(Context context, ComponentName component) {
-            mContext = context;
+            if (context == null) {
+                throw new IllegalArgumentException("context cannot be null.");
+            }
             Intent intent = new Intent(TvInputService.SERVICE_INTERFACE).setComponent(component);
             mResolveInfo = context.getPackageManager().resolveService(intent,
                     PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
+            if (mResolveInfo == null) {
+                throw new IllegalArgumentException("Invalid component. Can't find the service.");
+            }
+            mContext = context;
         }
 
         /**
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 4c2b031..1eae8db 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -324,40 +324,6 @@
     public static final String ACTION_VIEW_RECORDING_SCHEDULES =
             "android.media.tv.action.VIEW_RECORDING_SCHEDULES";
 
-    /**
-     * Action sent by the system to tell the target TV input that one of its program's browsable
-     * state is disabled, i.e., it will no longer be shown to users, which, for example, might
-     * be a result of users' interaction with UI.
-     *
-     * <p>The intent must contain the following bundle parameter:
-     * <ul>
-     *     <li>{@link #EXTRA_PROGRAM_ID} the program ID as a long integer.
-     * </ul>
-     */
-    public static final String ACTION_PROGRAM_BROWSABLE_DISABLED =
-            "android.media.tv.action.PROGRAM_BROWSABLE_DISABLED";
-
-    /**
-     * Action sent by an application telling the system to set the given channel as browsable.
-     *
-     * <p>The intent must contain the following bundle parameters:
-     * <ul>
-     *     <li>{@link #EXTRA_CHANNEL_ID} the channel ID as a long integer.
-     *     <li>{@link #EXTRA_PACKAGE_NAME} the package name of the requesting application.
-     * </ul>
-     */
-    public static final String ACTION_MAKE_CHANNEL_BROWSABLE
-            = "android.media.tv.action.MAKE_CHANNEL_BROWSABLE";
-
-    /** The key for a bundle parameter containing a channel ID as a long integer */
-    public static final String EXTRA_CHANNEL_ID = "android.media.tv.extra.CHANNEL_ID";
-
-    /** The key for a bundle parameter containing a package name as a string. */
-    public static final String EXTRA_PACKAGE_NAME = "android.media.tv.extra.PACKAGE_NAME";
-
-    /** The key for a bundle parameter containing a program ID as a long integer */
-    public static final String EXTRA_PROGRAM_ID = "android.media.tv.extra.PROGRAM_ID";
-
     private final ITvInputManager mService;
 
     private final Object mLock = new Object();
diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java
index eaec493..d372efb 100644
--- a/media/java/android/service/media/MediaBrowserService.java
+++ b/media/java/android/service/media/MediaBrowserService.java
@@ -137,6 +137,7 @@
      *
      * @see #onLoadChildren
      * @see #onLoadItem
+     * @see #onSearch
      */
     public class Result<T> {
         private Object mDebug;
@@ -544,16 +545,16 @@
      * media browser service when connecting and retrieving the root id for browsing, or null if
      * none. The contents of this bundle may affect the information returned when browsing.
      *
-     * @throws IllegalStateException If this method is called outside of {@link #onLoadChildren}
-     *             or {@link #onLoadItem}
+     * @throws IllegalStateException If this method is called outside of {@link #onLoadChildren},
+     *             {@link #onLoadItem} or {@link #onSearch}.
      * @see MediaBrowserService.BrowserRoot#EXTRA_RECENT
      * @see MediaBrowserService.BrowserRoot#EXTRA_OFFLINE
      * @see MediaBrowserService.BrowserRoot#EXTRA_SUGGESTED
      */
     public final Bundle getBrowserRootHints() {
         if (mCurConnection == null) {
-            throw new IllegalStateException("This should be called inside of onLoadChildren or"
-                    + " onLoadItem methods");
+            throw new IllegalStateException("This should be called inside of onLoadChildren,"
+                    + " onLoadItem or onSearch methods");
         }
         return mCurConnection.rootHints == null ? null : new Bundle(mCurConnection.rootHints);
     }
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index f69313c..23bf3d6 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -8,6 +8,7 @@
     android_media_MediaCodec.cpp \
     android_media_MediaCodecList.cpp \
     android_media_MediaDataSource.cpp \
+    android_media_MediaDescrambler.cpp \
     android_media_MediaDrm.cpp \
     android_media_MediaExtractor.cpp \
     android_media_MediaHTTPConnection.cpp \
@@ -25,6 +26,7 @@
     android_mtp_MtpDatabase.cpp \
     android_mtp_MtpDevice.cpp \
     android_mtp_MtpServer.cpp \
+    midi/android_media_midi_MidiDevice.cpp \
 
 LOCAL_SHARED_LIBRARIES := \
     libandroid_runtime \
@@ -33,6 +35,7 @@
     libbinder \
     libmedia \
     libmediadrm \
+    libmidi \
     libskia \
     libui \
     liblog \
@@ -54,6 +57,7 @@
     external/tremor/Tremor \
     frameworks/base/core/jni \
     frameworks/base/libs/hwui \
+    frameworks/base/media/native \
     frameworks/av/media/libmedia \
     frameworks/av/media/libstagefright \
     frameworks/av/media/mtp \
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index 724fc02..b00f5a5 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -17,6 +17,7 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "ImageReader_JNI"
 #include "android_media_Utils.h"
+#include <cutils/atomic.h>
 #include <utils/Log.h>
 #include <utils/misc.h>
 #include <utils/List.h>
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 6f9883c..293e5dd 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -25,9 +25,12 @@
 #include "android_media_Utils.h"
 #include "android_runtime/AndroidRuntime.h"
 #include "android_runtime/android_view_Surface.h"
+#include "android_util_Binder.h"
 #include "jni.h"
 #include "JNIHelp.h"
 
+#include <android/media/IDescrambler.h>
+
 #include <cutils/compiler.h>
 
 #include <gui/Surface.h>
@@ -269,6 +272,7 @@
         const sp<AMessage> &format,
         const sp<IGraphicBufferProducer> &bufferProducer,
         const sp<ICrypto> &crypto,
+        const sp<IDescrambler> &descrambler,
         int flags) {
     sp<Surface> client;
     if (bufferProducer != NULL) {
@@ -278,7 +282,8 @@
         mSurfaceTextureClient.clear();
     }
 
-    return mCodec->configure(format, mSurfaceTextureClient, crypto, flags);
+    return mCodec->configure(
+            format, mSurfaceTextureClient, crypto, descrambler, flags);
 }
 
 status_t JMediaCodec::setSurface(
@@ -967,6 +972,7 @@
         jobjectArray keys, jobjectArray values,
         jobject jsurface,
         jobject jcrypto,
+        jobject descramblerBinderObj,
         jint flags) {
     sp<JMediaCodec> codec = getMediaCodec(env, thiz);
 
@@ -1002,7 +1008,13 @@
         crypto = JCrypto::GetCrypto(env, jcrypto);
     }
 
-    err = codec->configure(format, bufferProducer, crypto, flags);
+    sp<IDescrambler> descrambler;
+    if (descramblerBinderObj != NULL) {
+        sp<IBinder> binder = ibinderForJavaObject(env, descramblerBinderObj);
+        descrambler = interface_cast<IDescrambler>(binder);
+    }
+
+    err = codec->configure(format, bufferProducer, crypto, descrambler, flags);
 
     throwExceptionAsNecessary(env, err);
 }
@@ -1942,7 +1954,7 @@
 
     { "native_configure",
       "([Ljava/lang/String;[Ljava/lang/Object;Landroid/view/Surface;"
-      "Landroid/media/MediaCrypto;I)V",
+      "Landroid/media/MediaCrypto;Landroid/os/IBinder;I)V",
       (void *)android_media_MediaCodec_native_configure },
 
     { "native_setSurface",
diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h
index b3b1b3a..a8c76c5 100644
--- a/media/jni/android_media_MediaCodec.h
+++ b/media/jni/android_media_MediaCodec.h
@@ -35,6 +35,10 @@
 struct MediaCodec;
 struct PersistentSurface;
 class Surface;
+namespace media {
+class IDescrambler;
+};
+using namespace media;
 
 struct JMediaCodec : public AHandler {
     JMediaCodec(
@@ -54,6 +58,7 @@
             const sp<AMessage> &format,
             const sp<IGraphicBufferProducer> &bufferProducer,
             const sp<ICrypto> &crypto,
+            const sp<IDescrambler> &descrambler,
             int flags);
 
     status_t setSurface(
diff --git a/media/jni/android_media_MediaDescrambler.cpp b/media/jni/android_media_MediaDescrambler.cpp
new file mode 100644
index 0000000..7585664
--- /dev/null
+++ b/media/jni/android_media_MediaDescrambler.cpp
@@ -0,0 +1,325 @@
+/*
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MediaDescrambler-JNI"
+#include <utils/Log.h>
+
+#include "android_media_MediaDescrambler.h"
+#include "android_runtime/AndroidRuntime.h"
+#include "android_util_Binder.h"
+#include "JNIHelp.h"
+
+#include <android/media/IDescrambler.h>
+#include <binder/MemoryDealer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <nativehelper/ScopedLocalRef.h>
+
+namespace android {
+using media::MediaDescrambler::DescrambleInfo;
+
+struct fields_t {
+    jfieldID context;
+};
+
+static fields_t gFields;
+
+static sp<JDescrambler> getDescrambler(JNIEnv *env, jobject thiz) {
+    return (JDescrambler *)env->GetLongField(thiz, gFields.context);
+}
+
+static void setDescrambler(
+        JNIEnv *env, jobject thiz, const sp<JDescrambler> &descrambler) {
+    sp<JDescrambler> old = (JDescrambler *)env->GetLongField(thiz, gFields.context);
+    if (descrambler != NULL) {
+        descrambler->incStrong(thiz);
+    }
+    if (old != NULL) {
+        old->decStrong(thiz);
+    }
+    env->SetLongField(thiz, gFields.context, (jlong)descrambler.get());
+}
+
+static status_t getBufferAndSize(
+        JNIEnv *env, jobject byteBuf, jint offset, size_t length,
+        void **outPtr, jbyteArray *outByteArray) {
+    void *ptr = env->GetDirectBufferAddress(byteBuf);
+
+    size_t bufSize;
+    jbyteArray byteArray = NULL;
+
+    ScopedLocalRef<jclass> byteBufClass(env, env->FindClass("java/nio/ByteBuffer"));
+    CHECK(byteBufClass.get() != NULL);
+
+    if (ptr == NULL) {
+        jmethodID arrayID =
+            env->GetMethodID(byteBufClass.get(), "array", "()[B");
+        CHECK(arrayID != NULL);
+
+        byteArray =
+            (jbyteArray)env->CallObjectMethod(byteBuf, arrayID);
+
+        if (byteArray == NULL) {
+            return INVALID_OPERATION;
+        }
+
+        jboolean isCopy;
+        ptr = env->GetByteArrayElements(byteArray, &isCopy);
+
+        bufSize = (size_t) env->GetArrayLength(byteArray);
+    } else {
+        bufSize = (size_t) env->GetDirectBufferCapacity(byteBuf);
+    }
+
+    if (length + offset > bufSize) {
+        if (byteArray != NULL) {
+            env->ReleaseByteArrayElements(byteArray, (jbyte *)ptr, 0);
+        }
+
+        return -ERANGE;
+    }
+
+    *outPtr = ptr;
+    *outByteArray = byteArray;
+
+    return OK;
+}
+
+JDescrambler::JDescrambler(JNIEnv *env, jobject descramblerBinderObj) {
+    sp<IDescrambler> cas;
+    if (descramblerBinderObj != NULL) {
+        sp<IBinder> binder = ibinderForJavaObject(env, descramblerBinderObj);
+        mDescrambler = interface_cast<IDescrambler>(binder);
+    }
+}
+
+JDescrambler::~JDescrambler() {
+    // Don't call release() here, it's called by Java class
+    mDescrambler.clear();
+    mMem.clear();
+    mDealer.clear();
+}
+
+void JDescrambler::ensureBufferCapacity(size_t neededSize) {
+    if (mMem != NULL && mMem->size() >= neededSize) {
+        return;
+    }
+
+    ALOGV("ensureBufferCapacity: current size %zu, new size %zu",
+            mMem == NULL ? 0 : mMem->size(), neededSize);
+
+    size_t alignment = MemoryDealer::getAllocationAlignment();
+    neededSize = (neededSize + (alignment - 1)) & ~(alignment - 1);
+    // Align to multiples of 64K.
+    neededSize = (neededSize + 65535) & ~65535;
+    mDealer = new MemoryDealer(neededSize, "JDescrambler");
+    mMem = mDealer->allocate(neededSize);
+}
+
+ssize_t JDescrambler::descramble(
+        jbyte key,
+        size_t numSubSamples,
+        ssize_t totalLength,
+        DescramblerPlugin::SubSample *subSamples,
+        const void *srcPtr,
+        jint srcOffset,
+        void *dstPtr,
+        jint dstOffset) {
+    // TODO: IDescrambler::descramble() is re-entrant, however because we
+    // only have 1 shared mem buffer, we can only do 1 descramble at a time.
+    // Concurrency might be improved by allowing on-demand allocation of up
+    // to 2 shared mem buffers.
+    Mutex::Autolock autolock(mSharedMemLock);
+
+    ensureBufferCapacity(totalLength);
+
+    memcpy(mMem->pointer(),
+            (const void*)((const uint8_t*)srcPtr + srcOffset), totalLength);
+
+    DescrambleInfo info;
+    info.dstType = DescrambleInfo::kDestinationTypeVmPointer;
+    info.numSubSamples = numSubSamples;
+    info.scramblingControl = (DescramblerPlugin::ScramblingControl) key;
+    info.subSamples = subSamples;
+    info.srcMem = mMem;
+    info.srcOffset = 0;
+    info.dstPtr = NULL;
+    info.dstOffset = 0;
+
+    int32_t result;
+    binder::Status status = mDescrambler->descramble(info, &result);
+
+    if (!status.isOk() || result > totalLength) {
+        return -1;
+    }
+    if (result > 0) {
+        memcpy((void*)((uint8_t*)dstPtr + dstOffset), mMem->pointer(), result);
+    }
+    return result;
+}
+
+}  // namespace android
+
+using namespace android;
+
+static void android_media_MediaDescrambler_native_release(JNIEnv *env, jobject thiz) {
+    setDescrambler(env, thiz, NULL);
+}
+
+static void android_media_MediaDescrambler_native_init(JNIEnv *env) {
+    ScopedLocalRef<jclass> clazz(
+            env, env->FindClass("android/media/MediaDescrambler"));
+    CHECK(clazz.get() != NULL);
+
+    gFields.context = env->GetFieldID(clazz.get(), "mNativeContext", "J");
+    CHECK(gFields.context != NULL);
+}
+
+static void android_media_MediaDescrambler_native_setup(
+        JNIEnv *env, jobject thiz, jobject descramblerBinderObj) {
+    setDescrambler(env, thiz, new JDescrambler(env, descramblerBinderObj));
+}
+
+static ssize_t getSubSampleInfo(JNIEnv *env, jint numSubSamples,
+        jintArray numBytesOfClearDataObj, jintArray numBytesOfEncryptedDataObj,
+        DescramblerPlugin::SubSample **outSubSamples) {
+
+    if (numSubSamples <= 0 || numSubSamples >=
+            (signed)(INT32_MAX / sizeof(DescramblerPlugin::SubSample)) ) {
+        // subSamples array may silently overflow if number of samples are
+        // too large.  Use INT32_MAX as maximum allocation size may be less
+        // than SIZE_MAX on some platforms.
+        ALOGE("numSubSamples is invalid!");
+        return -1;
+    }
+
+    jboolean isCopy;
+    ssize_t totalSize = 0;
+
+    jint *numBytesOfClearData =
+        (numBytesOfClearDataObj == NULL)
+            ? NULL
+            : env->GetIntArrayElements(numBytesOfClearDataObj, &isCopy);
+
+    jint *numBytesOfEncryptedData =
+        (numBytesOfEncryptedDataObj == NULL)
+            ? NULL
+            : env->GetIntArrayElements(numBytesOfEncryptedDataObj, &isCopy);
+
+    DescramblerPlugin::SubSample *subSamples =
+            new(std::nothrow) DescramblerPlugin::SubSample[numSubSamples];
+
+    if (subSamples == NULL) {
+        ALOGE("Failed to allocate SubSample array!");
+        return -1;
+    }
+
+    for (jint i = 0; i < numSubSamples; ++i) {
+        subSamples[i].mNumBytesOfClearData =
+            (numBytesOfClearData == NULL) ? 0 : numBytesOfClearData[i];
+
+        subSamples[i].mNumBytesOfEncryptedData =
+            (numBytesOfEncryptedData == NULL)
+                ? 0 : numBytesOfEncryptedData[i];
+
+        totalSize += subSamples[i].mNumBytesOfClearData +
+                subSamples[i].mNumBytesOfEncryptedData;
+    }
+
+    if (numBytesOfEncryptedData != NULL) {
+        env->ReleaseIntArrayElements(
+                numBytesOfEncryptedDataObj, numBytesOfEncryptedData, 0);
+        numBytesOfEncryptedData = NULL;
+    }
+
+    if (numBytesOfClearData != NULL) {
+        env->ReleaseIntArrayElements(
+                numBytesOfClearDataObj, numBytesOfClearData, 0);
+        numBytesOfClearData = NULL;
+    }
+
+    *outSubSamples = subSamples;
+
+    return totalSize;
+}
+
+static jint android_media_MediaDescrambler_native_descramble(
+        JNIEnv *env, jobject thiz, jbyte key, jint numSubSamples,
+        jintArray numBytesOfClearDataObj, jintArray numBytesOfEncryptedDataObj,
+        jobject srcBuf, jint srcOffset, jobject dstBuf, jint dstOffset) {
+    sp<JDescrambler> descrambler = getDescrambler(env, thiz);
+    if (descrambler == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return -1;
+    }
+
+    DescramblerPlugin::SubSample *subSamples = NULL;
+    ssize_t totalLength = getSubSampleInfo(
+            env, numSubSamples, numBytesOfClearDataObj,
+            numBytesOfEncryptedDataObj, &subSamples);
+    if (totalLength < 0) {
+        jniThrowException(env, "java/lang/IllegalArgumentException",
+                "Invalid sub sample info!");
+        return -1;
+    }
+
+    ssize_t result = -1;
+    void *srcPtr = NULL, *dstPtr = NULL;
+    jbyteArray srcArray = NULL, dstArray = NULL;
+    status_t err = getBufferAndSize(
+            env, srcBuf, srcOffset, totalLength, &srcPtr, &srcArray);
+
+    if (err == OK) {
+        if (dstBuf == NULL) {
+            dstPtr = srcPtr;
+        } else {
+            err = getBufferAndSize(
+                    env, dstBuf, dstOffset, totalLength, &dstPtr, &dstArray);
+        }
+    }
+
+    if (err == OK) {
+        result = descrambler->descramble(
+                key, numSubSamples, totalLength, subSamples,
+                srcPtr, srcOffset, dstPtr, dstOffset);
+    }
+
+    delete[] subSamples;
+    if (srcArray != NULL) {
+        env->ReleaseByteArrayElements(srcArray, (jbyte *)srcPtr, 0);
+    }
+    if (dstArray != NULL) {
+        env->ReleaseByteArrayElements(dstArray, (jbyte *)dstPtr, 0);
+    }
+    return result;
+}
+
+static const JNINativeMethod gMethods[] = {
+    { "native_release", "()V",
+            (void *)android_media_MediaDescrambler_native_release },
+    { "native_init", "()V",
+            (void *)android_media_MediaDescrambler_native_init },
+    { "native_setup", "(Landroid/os/IBinder;)V",
+            (void *)android_media_MediaDescrambler_native_setup },
+    { "native_descramble", "(BI[I[ILjava/nio/ByteBuffer;ILjava/nio/ByteBuffer;I)I",
+            (void *)android_media_MediaDescrambler_native_descramble },
+};
+
+int register_android_media_Descrambler(JNIEnv *env) {
+    return AndroidRuntime::registerNativeMethods(env,
+                "android/media/MediaDescrambler", gMethods, NELEM(gMethods));
+}
+
diff --git a/media/jni/android_media_MediaDescrambler.h b/media/jni/android_media_MediaDescrambler.h
new file mode 100644
index 0000000..e944a90
--- /dev/null
+++ b/media/jni/android_media_MediaDescrambler.h
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+#ifndef _ANDROID_MEDIA_DESCRAMBLER_H_
+#define _ANDROID_MEDIA_DESCRAMBLER_H_
+
+#include "jni.h"
+
+#include <media/cas/DescramblerAPI.h>
+#include <media/stagefright/foundation/ABase.h>
+#include <utils/Mutex.h>
+#include <utils/RefBase.h>
+
+namespace android {
+class IMemory;
+class MemoryDealer;
+namespace media {
+class IDescrambler;
+};
+using namespace media;
+
+struct JDescrambler : public RefBase {
+    JDescrambler(JNIEnv *env, jobject descramberBinderObj);
+
+    ssize_t descramble(
+            jbyte key,
+            size_t numSubSamples,
+            ssize_t totalLength,
+            DescramblerPlugin::SubSample *subSamples,
+            const void *srcPtr,
+            jint srcOffset,
+            void *dstPtr,
+            jint dstOffset);
+
+protected:
+    virtual ~JDescrambler();
+
+private:
+    sp<IDescrambler> mDescrambler;
+    sp<IMemory> mMem;
+    sp<MemoryDealer> mDealer;
+    Mutex mSharedMemLock;
+
+    void ensureBufferCapacity(size_t neededSize);
+
+    DISALLOW_EVIL_CONSTRUCTORS(JDescrambler);
+};
+
+}  // namespace android
+
+#endif  // _ANDROID_MEDIA_DESCRAMBLER_H_
diff --git a/media/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp
index 2008f8d..3c33493 100644
--- a/media/jni/android_media_MediaExtractor.cpp
+++ b/media/jni/android_media_MediaExtractor.cpp
@@ -37,6 +37,7 @@
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/NuMediaExtractor.h>
+#include <android/media/ICas.h>
 
 #include <nativehelper/ScopedLocalRef.h>
 
@@ -88,6 +89,10 @@
     return mImpl->setDataSource(datasource);
 }
 
+status_t JMediaExtractor::setMediaCas(const sp<ICas> &cas) {
+    return mImpl->setMediaCas(cas);
+}
+
 size_t JMediaExtractor::countTracks() const {
     return mImpl->countTracks();
 }
@@ -734,6 +739,36 @@
     }
 }
 
+static void android_media_MediaExtractor_setMediaCas(
+        JNIEnv *env, jobject thiz, jobject casBinderObj) {
+    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
+
+    if (extractor == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return;
+    }
+
+    if (casBinderObj == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+        return;
+    }
+
+    sp<ICas> cas;
+    if (casBinderObj != NULL) {
+        sp<IBinder> binder = ibinderForJavaObject(env, casBinderObj);
+        cas = interface_cast<ICas>(binder);
+    }
+    status_t err = extractor->setMediaCas(cas);
+
+    if (err != OK) {
+        cas.clear();
+        jniThrowException(
+                env,
+                "java/io/IllegalArgumentException",
+                "Failed to set MediaCas on extractor.");
+    }
+}
+
 static jlong android_media_MediaExtractor_getCachedDurationUs(
         JNIEnv *env, jobject thiz) {
     sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
@@ -861,6 +896,9 @@
     { "setDataSource", "(Landroid/media/MediaDataSource;)V",
       (void *)android_media_MediaExtractor_setDataSourceCallback },
 
+    { "nativeSetMediaCas", "(Landroid/os/IBinder;)V",
+      (void *)android_media_MediaExtractor_setMediaCas },
+
     { "getCachedDuration", "()J",
       (void *)android_media_MediaExtractor_getCachedDurationUs },
 
diff --git a/media/jni/android_media_MediaExtractor.h b/media/jni/android_media_MediaExtractor.h
index c747ef5..3d8c50b 100644
--- a/media/jni/android_media_MediaExtractor.h
+++ b/media/jni/android_media_MediaExtractor.h
@@ -28,6 +28,10 @@
 #include "jni.h"
 
 namespace android {
+namespace media {
+class ICas;
+};
+using namespace media;
 
 struct IMediaHTTPService;
 class MetaData;
@@ -44,6 +48,8 @@
     status_t setDataSource(int fd, off64_t offset, off64_t size);
     status_t setDataSource(const sp<DataSource> &source);
 
+    status_t setMediaCas(const sp<ICas> &cas);
+
     size_t countTracks() const;
     status_t getTrackFormat(size_t index, jobject *format) const;
 
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 636727e..27724a1 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -1445,6 +1445,7 @@
 extern int register_android_media_ImageWriter(JNIEnv *env);
 extern int register_android_media_Crypto(JNIEnv *env);
 extern int register_android_media_Drm(JNIEnv *env);
+extern int register_android_media_Descrambler(JNIEnv *env);
 extern int register_android_media_MediaCodec(JNIEnv *env);
 extern int register_android_media_MediaExtractor(JNIEnv *env);
 extern int register_android_media_MediaCodecList(JNIEnv *env);
@@ -1561,6 +1562,11 @@
         goto bail;
     }
 
+    if (register_android_media_Descrambler(env) < 0) {
+        ALOGE("ERROR: MediaDescrambler native registration failed");
+        goto bail;
+    }
+
     if (register_android_media_MediaHTTPConnection(env) < 0) {
         ALOGE("ERROR: MediaHTTPConnection native registration failed");
         goto bail;
diff --git a/media/jni/android_media_VolumeShaper.h b/media/jni/android_media_VolumeShaper.h
index dbbc478..73498a2 100644
--- a/media/jni/android_media_VolumeShaper.h
+++ b/media/jni/android_media_VolumeShaper.h
@@ -29,9 +29,9 @@
         jmethodID coConstructId;
         jfieldID  coTypeId;
         jfieldID  coIdId;
-        jfieldID  coInterpolatorTypeId;
         jfieldID  coOptionFlagsId;
         jfieldID  coDurationMsId;
+        jfieldID  coInterpolatorTypeId;
         jfieldID  coTimesId;
         jfieldID  coVolumesId;
 
@@ -56,12 +56,12 @@
             if (coClazz == nullptr) {
                 return;
             }
-            coConstructId = env->GetMethodID(coClazz, "<init>", "(IIIID[F[F)V");
+            coConstructId = env->GetMethodID(coClazz, "<init>", "(IIIDI[F[F)V");
             coTypeId = env->GetFieldID(coClazz, "mType", "I");
             coIdId = env->GetFieldID(coClazz, "mId", "I");
-            coInterpolatorTypeId = env->GetFieldID(coClazz, "mInterpolatorType", "I");
             coOptionFlagsId = env->GetFieldID(coClazz, "mOptionFlags", "I");
             coDurationMsId = env->GetFieldID(coClazz, "mDurationMs", "D");
+            coInterpolatorTypeId = env->GetFieldID(coClazz, "mInterpolatorType", "I");
             coTimesId = env->GetFieldID(coClazz, "mTimes", "[F");
             coVolumesId = env->GetFieldID(coClazz, "mVolumes", "[F");
             env->DeleteLocalRef(lclazz);
@@ -108,14 +108,14 @@
         configuration->setId(
             (int)env->GetIntField(jshaper, fields.coIdId));
         if (configuration->getType() == VolumeShaper::Configuration::TYPE_SCALE) {
-            configuration->setInterpolatorType(
-                (VolumeShaper::Configuration::InterpolatorType)
-                env->GetIntField(jshaper, fields.coInterpolatorTypeId));
             configuration->setOptionFlags(
                 (VolumeShaper::Configuration::OptionFlag)
                 env->GetIntField(jshaper, fields.coOptionFlagsId));
             configuration->setDurationMs(
                     (double)env->GetDoubleField(jshaper, fields.coDurationMsId));
+            configuration->setInterpolatorType(
+                (VolumeShaper::Configuration::InterpolatorType)
+                env->GetIntField(jshaper, fields.coInterpolatorTypeId));
 
             // convert point arrays
             jobject xobj = env->GetObjectField(jshaper, fields.coTimesId);
@@ -165,9 +165,9 @@
         jvalue args[7];
         args[0].i = (jint)configuration->getType();
         args[1].i = (jint)configuration->getId();
-        args[2].i = (jint)configuration->getInterpolatorType();
-        args[3].i = (jint)configuration->getOptionFlags();
-        args[4].d = (jdouble)configuration->getDurationMs();
+        args[2].i = (jint)configuration->getOptionFlags();
+        args[3].d = (jdouble)configuration->getDurationMs();
+        args[4].i = (jint)configuration->getInterpolatorType();
         args[5].l = xarray;
         args[6].l = yarray;
         jobject jshaper = env->NewObjectA(fields.coClazz, fields.coConstructId, args);
diff --git a/media/jni/midi/android_media_midi_MidiDevice.cpp b/media/jni/midi/android_media_midi_MidiDevice.cpp
new file mode 100644
index 0000000..1e54bac
--- /dev/null
+++ b/media/jni/midi/android_media_midi_MidiDevice.cpp
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Midi-JNI"
+
+#include <android_util_Binder.h>
+#include <midi/MidiDeviceRegistry.h>
+#include <nativehelper/jni.h>
+#include <utils/Log.h>
+
+using namespace android;
+using namespace android::media::midi;
+
+extern "C" jint Java_android_media_midi_MidiDevice_mirrorToNative(
+        JNIEnv *env, jobject thiz, jobject midiDeviceServer, jint id)
+{
+    (void)thiz;
+    sp<IBinder> serverBinder = ibinderForJavaObject(env, midiDeviceServer);
+    if (serverBinder.get() == NULL) {
+        ALOGE("Could not obtain IBinder from passed jobject");
+        return -EINVAL;
+    }
+    // return MidiDeviceManager::getInstance().addDevice(serverBinder, uid);
+    return MidiDeviceRegistry::getInstance().addDevice(
+               new BpMidiDeviceServer(serverBinder), id);
+}
+
+extern "C" jint Java_android_media_midi_MidiDevice_removeFromNative(
+        JNIEnv *env, jobject thiz, jint uid)
+{
+    (void)env;
+    (void)thiz;
+    // return MidiDeviceManager::getInstance().removeDevice(uid);
+    return MidiDeviceRegistry::getInstance().removeDevice(uid);
+}
diff --git a/media/native/midi/Android.bp b/media/native/midi/Android.bp
new file mode 100644
index 0000000..3500805
--- /dev/null
+++ b/media/native/midi/Android.bp
@@ -0,0 +1,21 @@
+// 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.
+
+// The headers module is in frameworks/media/native/midi/Android.bp.
+ndk_library {
+    name: "libmidi.ndk",
+    symbol_file: "libmidi.map.txt",
+    first_version: "26",
+//    unversioned_until: "current",
+}
diff --git a/media/native/midi/Android.mk b/media/native/midi/Android.mk
new file mode 100644
index 0000000..b91c430
--- /dev/null
+++ b/media/native/midi/Android.mk
@@ -0,0 +1,22 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+	../../java/android/media/midi/IMidiDeviceServer.aidl \
+	midi.cpp \
+	MidiDeviceRegistry.cpp \
+	MidiPortRegistry.cpp
+
+LOCAL_AIDL_INCLUDES := \
+	$(FRAMEWORKS_BASE_JAVA_SRC_DIRS) \
+	frameworks/native/aidl/binder
+
+LOCAL_CFLAGS += -Wall -Werror -O0
+
+LOCAL_MODULE := libmidi
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SHARED_LIBRARIES := liblog libbinder libutils libmedia
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/native/midi/MidiDeviceRegistry.cpp b/media/native/midi/MidiDeviceRegistry.cpp
new file mode 100644
index 0000000..8854a08
--- /dev/null
+++ b/media/native/midi/MidiDeviceRegistry.cpp
@@ -0,0 +1,106 @@
+/*
+ * 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.
+ */
+
+#include "MidiDeviceRegistry.h"
+
+namespace android {
+
+ANDROID_SINGLETON_STATIC_INSTANCE(media::midi::MidiDeviceRegistry);
+
+namespace media {
+namespace midi {
+
+MidiDeviceRegistry::MidiDeviceRegistry() : mNextDeviceToken(1) {
+}
+
+status_t MidiDeviceRegistry::addDevice(sp<BpMidiDeviceServer> server, int32_t deviceId) {
+    if (server.get() == nullptr) {
+        return -EINVAL;
+    }
+
+    std::lock_guard<std::mutex> guard(mMapsLock);
+    mServers[deviceId] = server;
+    return OK;
+}
+
+status_t MidiDeviceRegistry::removeDevice(int32_t deviceId) {
+    std::lock_guard<std::mutex> guard(mMapsLock);
+    mServers.erase(deviceId);
+    const auto& iter = mUidToToken.find(deviceId);
+    if (iter != mUidToToken.end()) {
+        mTokenToUid.erase(iter->second);
+        mUidToToken.erase(iter);
+    }
+    return OK;
+}
+
+//NOTE: This creates an entry if not found, or returns an existing one.
+status_t MidiDeviceRegistry::obtainDeviceToken(int32_t deviceId, AMIDI_Device *deviceTokenPtr) {
+    std::lock_guard<std::mutex> guard(mMapsLock);
+    const auto& serversIter = mServers.find(deviceId);
+    if (serversIter == mServers.end()) {
+        // Not found.
+        return -EINVAL;
+    }
+
+    const auto& iter = mUidToToken.find(deviceId);
+    if (iter != mUidToToken.end()) {
+        *deviceTokenPtr = iter->second;
+    } else {
+        *deviceTokenPtr = mNextDeviceToken++;
+        mTokenToUid[*deviceTokenPtr] = deviceId;
+        mUidToToken[deviceId] = *deviceTokenPtr;
+    }
+    return OK;
+}
+
+status_t MidiDeviceRegistry::releaseDevice(AMIDI_Device deviceToken) {
+    std::lock_guard<std::mutex> guard(mMapsLock);
+    const auto& iter = mTokenToUid.find(deviceToken);
+    if (iter == mTokenToUid.end()) {
+        // Not found
+        return -EINVAL;
+    }
+
+    mServers.erase(iter->second);
+    mUidToToken.erase(iter->second);
+    mTokenToUid.erase(iter);
+    return OK;
+}
+
+status_t MidiDeviceRegistry::getDeviceByToken(
+        AMIDI_Device deviceToken, sp<BpMidiDeviceServer> *devicePtr) {
+    std::lock_guard<std::mutex> guard(mMapsLock);
+    int32_t id = -1;
+    {
+        const auto& iter = mTokenToUid.find(deviceToken);
+        if (iter == mTokenToUid.end()) {
+            return -EINVAL;
+        }
+        id = iter->second;
+    }
+    const auto& iter = mServers.find(id);
+    if (iter == mServers.end()) {
+        return -EINVAL;
+    }
+
+    *devicePtr = iter->second;
+    return OK;
+}
+
+} // namespace midi
+} // namespace media
+} // namespace android
diff --git a/media/native/midi/MidiDeviceRegistry.h b/media/native/midi/MidiDeviceRegistry.h
new file mode 100644
index 0000000..93be733
--- /dev/null
+++ b/media/native/midi/MidiDeviceRegistry.h
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_MEDIA_MIDI_DEVICE_REGISTRY_H_
+#define ANDROID_MEDIA_MIDI_DEVICE_REGISTRY_H_
+
+#include <map>
+#include <mutex>
+
+#include <binder/IBinder.h>
+#include <utils/Errors.h>
+#include <utils/Singleton.h>
+
+#include "android/media/midi/BpMidiDeviceServer.h"
+#include "midi.h"
+
+namespace android {
+namespace media {
+namespace midi {
+
+/*
+ * Maintains a thread-safe, (singleton) list of MIDI devices with associated Binder interfaces,
+ * which are exposed to the Native API via (Java) MidiDevice.mirrorToNative() &
+ * MidiDevice.removeFromNative().
+ * (Called via MidiDeviceManager::addDevice() MidiManager::removeDevice()).
+ */
+class MidiDeviceRegistry : public Singleton<MidiDeviceRegistry> {
+  public:
+    /* Add a MIDI Device to the registry.
+     *
+     * server       The Binder interface to the MIDI device server.
+     * deviceUId    The unique ID of the device obtained from
+     *              the Java API via MidiDeviceInfo.getId().
+     */
+    status_t addDevice(sp<BpMidiDeviceServer> server, int32_t deviceId);
+
+    /* Remove the device (and associated server) from the Device registry.
+     *
+     * deviceUid    The ID of the device which was used in the call to addDevice().
+     */
+    status_t removeDevice(int32_t deviceId);
+
+    /* Gets a device token associated with the device ID. This is used by the
+     * native API to identify/access the device.
+     * Multiple calls without releasing the token will return the same value.
+     *
+     * deviceUid    The ID of the device.
+     * deviceTokenPtr Receives the device (native) token associated with the device ID.
+     * returns: OK on success, error code otherwise.
+     */
+    status_t obtainDeviceToken(int32_t deviceId, AMIDI_Device *deviceTokenPtr);
+
+    /*
+     * Releases the native API device token associated with a MIDI device.
+     *
+     * deviceToken The device (native) token associated with the device ID.
+     */
+    status_t releaseDevice(AMIDI_Device deviceToken);
+
+    /*
+     * Gets the Device server binder interface associated with the device token.
+     *
+     * deviceToken The device (native) token associated with the device ID.
+     */
+    status_t getDeviceByToken(AMIDI_Device deviceToken, sp<BpMidiDeviceServer> *devicePtr);
+
+  private:
+    friend class Singleton<MidiDeviceRegistry>;
+    MidiDeviceRegistry();
+
+    // Access Mutex
+    std::mutex                              mMapsLock;
+
+    // maps device IDs to servers
+    std::map<int32_t, sp<BpMidiDeviceServer>>   mServers;
+
+    // maps device tokens to device ID
+    std::map<AMIDI_Device, int32_t>         mTokenToUid;
+
+    // maps device IDs to device tokens
+    std::map<int32_t, AMIDI_Device>         mUidToToken;
+
+    // Value of next device token to dole out.
+    AMIDI_Device                            mNextDeviceToken;
+};
+
+} // namespace midi
+} // namespace media
+} // namespace android
+
+#endif // ANDROID_MEDIA_MIDI_DEVICE_REGISTRY_H_
diff --git a/media/native/midi/MidiPortRegistry.cpp b/media/native/midi/MidiPortRegistry.cpp
new file mode 100644
index 0000000..fa70af8
--- /dev/null
+++ b/media/native/midi/MidiPortRegistry.cpp
@@ -0,0 +1,200 @@
+/*
+ * 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.
+ */
+
+#include "MidiPortRegistry.h"
+
+namespace android {
+
+ANDROID_SINGLETON_STATIC_INSTANCE(media::midi::MidiPortRegistry);
+
+namespace media {
+namespace midi {
+
+//TODO Note that these 2 are identical
+struct MidiPortRegistry::OutputPort {
+    AMIDI_Device device;
+    sp<IBinder> binderToken;
+    base::unique_fd ufd;
+};
+
+struct MidiPortRegistry::InputPort {
+    AMIDI_Device device;
+    sp<IBinder> binderToken;
+    base::unique_fd ufd;
+};
+
+MidiPortRegistry::MidiPortRegistry() : mNextOutputPortToken(0), mNextInputPortToken(0) {
+}
+
+status_t MidiPortRegistry::addOutputPort(
+        AMIDI_Device device,
+        sp<IBinder> portToken,
+        base::unique_fd &&ufd,
+        AMIDI_OutputPort *portPtr) {
+    *portPtr = mNextOutputPortToken++;
+
+    OutputPortEntry* portEntry = new OutputPortEntry;
+    portEntry->port = new OutputPort;
+    portEntry->state = MIDI_OUTPUT_PORT_STATE_OPEN_IDLE;
+    portEntry->port = new OutputPort;
+    portEntry->port->device = device;
+    portEntry->port->binderToken = portToken;
+    portEntry->port->ufd = std::move(ufd);
+
+    mOutputPortMap[*portPtr] = portEntry;
+
+    return OK;
+}
+
+status_t MidiPortRegistry::removeOutputPort(
+        AMIDI_OutputPort port,
+        AMIDI_Device *devicePtr,
+        sp<IBinder> *portTokenPtr) {
+    OutputPortMap::iterator itr = mOutputPortMap.find(port);
+    if (itr == mOutputPortMap.end()) {
+        return -EINVAL;
+    }
+
+    OutputPortEntry *entry = mOutputPortMap[port];
+    int portState = MIDI_OUTPUT_PORT_STATE_OPEN_IDLE;
+    while (!entry->state.compare_exchange_weak(portState, MIDI_OUTPUT_PORT_STATE_CLOSED)) {
+        if (portState == MIDI_OUTPUT_PORT_STATE_CLOSED) {
+            return -EINVAL; // Already closed
+        }
+    }
+    *devicePtr = entry->port->device;
+    *portTokenPtr = entry->port->binderToken;
+    delete entry->port;
+    entry->port = nullptr;
+
+    mOutputPortMap.erase(itr);
+
+    return OK;
+}
+
+status_t MidiPortRegistry::getOutputPortFdAndLock(
+        AMIDI_OutputPort port, base::unique_fd **ufdPtr) {
+    if (mOutputPortMap.find(port) == mOutputPortMap.end()) {
+        return -EINVAL;
+    }
+
+    OutputPortEntry *entry = mOutputPortMap[port];
+    int portState = MIDI_OUTPUT_PORT_STATE_OPEN_IDLE;
+    if (!entry->state.compare_exchange_strong(portState, MIDI_OUTPUT_PORT_STATE_OPEN_ACTIVE)) {
+        // The port has been closed.
+        return -EPIPE;
+    }
+    *ufdPtr = &entry->port->ufd;
+
+    return OK;
+}
+
+status_t MidiPortRegistry::unlockOutputPort(AMIDI_OutputPort port) {
+    if (mOutputPortMap.find(port) == mOutputPortMap.end()) {
+        return -EINVAL;
+    }
+
+    OutputPortEntry *entry = mOutputPortMap[port];
+    entry->state.store(MIDI_OUTPUT_PORT_STATE_OPEN_IDLE);
+    return OK;
+}
+
+status_t MidiPortRegistry::addInputPort(
+        AMIDI_Device device,
+        sp<IBinder> portToken,
+        base::unique_fd &&ufd,
+        AMIDI_InputPort *portPtr) {
+    *portPtr = mNextInputPortToken++;
+
+    InputPortEntry *entry = new InputPortEntry;
+
+    entry->state = MIDI_INPUT_PORT_STATE_OPEN_IDLE;
+    entry->port = new InputPort;
+    entry->port->device = device;
+    entry->port->binderToken = portToken;
+    entry->port->ufd = std::move(ufd);
+
+    mInputPortMap[*portPtr] = entry;
+
+    return OK;
+}
+
+status_t MidiPortRegistry::removeInputPort(
+        AMIDI_InputPort port,
+        AMIDI_Device *devicePtr,
+        sp<IBinder> *portTokenPtr) {
+    InputPortMap::iterator itr = mInputPortMap.find(port);
+    if (itr == mInputPortMap.end()) {
+        return -EINVAL;
+    }
+
+    InputPortEntry *entry = mInputPortMap[port];
+    int portState = MIDI_INPUT_PORT_STATE_OPEN_IDLE;
+    while (!entry->state.compare_exchange_weak(portState, MIDI_INPUT_PORT_STATE_CLOSED)) {
+        if (portState == MIDI_INPUT_PORT_STATE_CLOSED) return -EINVAL; // Already closed
+    }
+
+    *devicePtr = entry->port->device;
+    *portTokenPtr = entry->port->binderToken;
+    delete entry->port;
+    entry->port = nullptr;
+
+    mInputPortMap.erase(itr);
+
+    return OK;
+}
+
+status_t MidiPortRegistry::getInputPortFd(AMIDI_InputPort port, base::unique_fd **ufdPtr) {
+    if (mInputPortMap.find(port) == mInputPortMap.end()) {
+        return -EINVAL;
+    }
+
+    InputPortEntry *entry = mInputPortMap[port];
+
+    *ufdPtr = &entry->port->ufd;
+
+    return OK;
+}
+
+status_t MidiPortRegistry::getInputPortFdAndLock(AMIDI_InputPort port, base::unique_fd **ufdPtr) {
+    if (mInputPortMap.find(port) == mInputPortMap.end()) {
+        return -EINVAL;
+    }
+
+    InputPortEntry *entry = mInputPortMap[port];
+
+    int portState = MIDI_INPUT_PORT_STATE_OPEN_IDLE;
+    if (!entry->state.compare_exchange_strong(portState, MIDI_INPUT_PORT_STATE_OPEN_ACTIVE)) {
+        // The port has been closed.
+        return -EPIPE;
+    }
+    *ufdPtr = &entry->port->ufd;
+    return OK;
+}
+
+status_t MidiPortRegistry::MidiPortRegistry::unlockInputPort(AMIDI_InputPort port) {
+    if (mInputPortMap.find(port) == mInputPortMap.end()) {
+        return -EINVAL;
+    }
+
+    InputPortEntry *entry = mInputPortMap[port];
+    entry->state.store(MIDI_INPUT_PORT_STATE_OPEN_IDLE);
+    return OK;
+}
+
+} // namespace midi
+} // namespace media
+} // namespace android
diff --git a/media/native/midi/MidiPortRegistry.h b/media/native/midi/MidiPortRegistry.h
new file mode 100644
index 0000000..f1ffb78
--- /dev/null
+++ b/media/native/midi/MidiPortRegistry.h
@@ -0,0 +1,192 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_MEDIA_MIDI_PORT_REGISTRY_H_
+#define ANDROID_MEDIA_MIDI_PORT_REGISTRY_H_
+
+#include <atomic>
+#include <map>
+
+#include <android-base/unique_fd.h>
+#include <binder/IBinder.h>
+#include <utils/Errors.h>
+#include <utils/Singleton.h>
+
+#include "midi.h"
+
+namespace android {
+namespace media {
+namespace midi {
+
+/*
+ * Maintains lists of all active input and output MIDI ports and controls access to them. Provides
+ * exclusive access to specific MIDI ports.
+ */
+class MidiPortRegistry : public Singleton<MidiPortRegistry> {
+  public:
+    /*
+     * Creates an output port entry and associates it with the specified MIDI device.
+     * Called by AMIDI_openOutputPort();
+     *
+     * device       The native API device ID.
+     * portToken    The port token (returned from the device server).
+     * udf          File descriptor for the data port associated with the MIDI output port.
+     * portPtr      Receives the native API port ID of the port being opened.
+     */
+    status_t addOutputPort(
+            AMIDI_Device device,
+            sp<IBinder> portToken,
+            base::unique_fd &&ufd,
+            AMIDI_OutputPort *portPtr);
+
+    /*
+     * Removes for the output port list a previously added output port.
+     * Called by AMIDI_closeOutputPort();
+     *
+     * port         The native API port ID of the port being closed.
+     * devicePtr    Receives the native API device ID associated with the port.
+     * portTokenPtr Receives the binder token associated with the port.
+     */
+    status_t removeOutputPort(
+            AMIDI_OutputPort port,
+            AMIDI_Device *devicePtr,
+            sp<IBinder> *portTokenPtr);
+
+    /*
+     * Creates an input port entry and associates it with the specified MIDI device.
+     * Called by AMIDI_openInputPort();
+     *
+     * device       The native API device ID.
+     * portToken    The port token (returned from the device server).
+     * udf          File descriptor for the data port associated with the MIDI input port.
+     * portPtr      Receives the native API port ID of the port being opened.
+     */
+    status_t addInputPort(
+            AMIDI_Device device,
+            sp<IBinder> portToken,
+            base::unique_fd &&ufd,
+            AMIDI_InputPort *portPtr);
+
+    /*
+     * Removes for the input port list a previously added input port.
+     * Called by AMIDI_closeINputPort();
+     *
+     * port         The native API port ID of the port being closed.
+     * devicePtr    Receives the native API device ID associated with the port.
+     * portTokenPtr Receives the binder token associated with the port.
+     */
+    status_t removeInputPort(
+            AMIDI_InputPort port,
+            AMIDI_Device *devicePtr,
+            sp<IBinder> *portTokenPtr);
+
+    /*
+     * Retrieves an exclusive-access file descriptor for an output port.
+     * Called from AMIDI_receive().
+     *
+     * port     The native API id of the output port.
+     * ufdPtr   Receives the exclusive-access file descriptor for the output port.
+     */
+    status_t getOutputPortFdAndLock(AMIDI_OutputPort port, base::unique_fd **ufdPtr);
+
+    /*
+     * Releases exclusive-access to the port and invalidates the previously received file
+     * descriptor.
+     * Called from AMIDI_receive().
+     *
+     * port The native API id of the output port.
+     */
+    status_t unlockOutputPort(AMIDI_OutputPort port);
+
+    /*
+     * Retrieves an exclusive-access file descriptor for an input port.
+     * (Not being used as (perhaps) AMIDI_sendWithTimestamp() doesn't need exclusive access
+     * to the port).
+     *
+     * port     The native API id of the input port.
+     * ufdPtr   Receives the exclusive-access file descriptor for the input port.
+     */
+    status_t getInputPortFdAndLock(AMIDI_InputPort port, base::unique_fd **ufdPtr);
+
+    /*
+     * Releases exclusive-access to the port and invalidates the previously received file
+     * descriptor.
+     * (Not used. See above).
+     *
+     * port The native API id of the input port.
+     */
+    status_t unlockInputPort(AMIDI_InputPort port);
+
+    /*
+     * Retrieves an unlocked (multi-access) file descriptor for an input port.
+     * Used by AMIDI_sendWith(), AMIDI_sendWithTimestamp & AMIDI_flush.
+     *
+     * port     The native API id of the input port.
+     * ufdPtr   Receives the multi-access file descriptor for the input port.
+     */
+    status_t getInputPortFd(AMIDI_InputPort port, base::unique_fd **ufdPtr);
+
+  private:
+    friend class Singleton<MidiPortRegistry>;
+    MidiPortRegistry();
+
+    /*
+     * Output (data receiving) ports.
+     */
+    struct OutputPort;
+    enum {
+        MIDI_OUTPUT_PORT_STATE_CLOSED = 0,
+        MIDI_OUTPUT_PORT_STATE_OPEN_IDLE,
+        MIDI_OUTPUT_PORT_STATE_OPEN_ACTIVE
+    };
+
+    struct OutputPortEntry {
+        std::atomic_int state;
+        OutputPort *port;
+    };
+
+    typedef std::map<AMIDI_OutputPort, OutputPortEntry*> OutputPortMap;
+    // Access is synchronized per record via 'state' field.
+    std::atomic<AMIDI_OutputPort> mNextOutputPortToken;
+    OutputPortMap  mOutputPortMap;
+
+    /*
+     * Input (data sending) ports.
+     */
+    struct InputPort;
+    enum {
+        MIDI_INPUT_PORT_STATE_CLOSED = 0,
+        MIDI_INPUT_PORT_STATE_OPEN_IDLE,
+        MIDI_INPUT_PORT_STATE_OPEN_ACTIVE
+    };
+
+    struct InputPortEntry {
+        std::atomic_int state;
+        InputPort *port;
+    };
+
+    typedef std::map<AMIDI_OutputPort, InputPortEntry*> InputPortMap;
+    // Access is synchronized per record via 'state' field.
+    std::atomic<AMIDI_InputPort> mNextInputPortToken;
+    InputPortMap  mInputPortMap;
+
+};
+
+} // namespace midi
+} // namespace media
+} // namespace android
+
+#endif // ANDROID_MEDIA_MIDI_PORT_REGISTRY_H_
diff --git a/media/native/midi/midi.cpp b/media/native/midi/midi.cpp
new file mode 100644
index 0000000..1bf0bd0
--- /dev/null
+++ b/media/native/midi/midi.cpp
@@ -0,0 +1,317 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "NativeMIDI"
+
+#include <poll.h>
+#include <unistd.h>
+
+#include <binder/Binder.h>
+#include <utils/Errors.h>
+#include <utils/Log.h>
+
+#include "android/media/midi/BpMidiDeviceServer.h"
+#include "media/MidiDeviceInfo.h"
+#include "MidiDeviceRegistry.h"
+#include "MidiPortRegistry.h"
+
+#include "midi.h"
+
+using android::IBinder;
+using android::BBinder;
+using android::OK;
+using android::sp;
+using android::status_t;
+using android::base::unique_fd;
+using android::binder::Status;
+using android::media::midi::BpMidiDeviceServer;
+using android::media::midi::MidiDeviceInfo;
+using android::media::midi::MidiDeviceRegistry;
+using android::media::midi::MidiPortRegistry;
+
+#define SIZE_MIDIRECEIVEBUFFER AMIDI_BUFFER_SIZE
+
+/* TRANSFER PACKET FORMAT (as defined in MidiPortImpl.java)
+ *
+ * Transfer packet format is as follows (see MidiOutputPort.mThread.run() to see decomposition):
+ * |oc|md|md| ......... |md|ts|ts|ts|ts|ts|ts|ts|ts|
+ *  ^ +--------------------+-----------------------+
+ *  |  ^                    ^
+ *  |  |                    |
+ *  |  |                    + timestamp (8 bytes)
+ *  |  |
+ *  |  + MIDI data bytes (numBytes bytes)
+ *  |
+ *  + OpCode (AMIDI_OPCODE_DATA)
+ *
+ *  NOTE: The socket pair is configured to use SOCK_SEQPACKET mode.
+ *  SOCK_SEQPACKET, for a sequenced-packet socket that is connection-oriented, preserves message
+ *  boundaries, and delivers messages in the order that they were sent.
+ *  So 'read()' always returns a whole message.
+ */
+
+status_t AMIDI_getDeviceById(int32_t id, AMIDI_Device *devicePtr) {
+    return MidiDeviceRegistry::getInstance().obtainDeviceToken(id, devicePtr);
+}
+
+status_t AMIDI_getDeviceInfo(AMIDI_Device device, AMIDI_DeviceInfo *deviceInfoPtr) {
+    sp<BpMidiDeviceServer> deviceServer;
+    status_t result = MidiDeviceRegistry::getInstance().getDeviceByToken(device, &deviceServer);
+    if (result != OK) {
+        ALOGE("AMIDI_getDeviceInfo bad device token %d: %d", device, result);
+        return result;
+    }
+
+    MidiDeviceInfo deviceInfo;
+    Status txResult = deviceServer->getDeviceInfo(&deviceInfo);
+    if (!txResult.isOk()) {
+        ALOGE("AMIDI_getDeviceInfo transaction error: %d", txResult.transactionError());
+        return txResult.transactionError();
+    }
+
+    deviceInfoPtr->type = deviceInfo.getType();
+    deviceInfoPtr->uid = deviceInfo.getUid();
+    deviceInfoPtr->isPrivate = deviceInfo.isPrivate();
+    deviceInfoPtr->inputPortCount = deviceInfo.getInputPortNames().size();
+    deviceInfoPtr->outputPortCount = deviceInfo.getOutputPortNames().size();
+    return OK;
+}
+
+/*
+ * Output (receiving) API
+ */
+status_t AMIDI_openOutputPort(AMIDI_Device device, int portNumber, AMIDI_OutputPort *outputPortPtr) {
+    sp<BpMidiDeviceServer> deviceServer;
+    status_t result = MidiDeviceRegistry::getInstance().getDeviceByToken(device, &deviceServer);
+    if (result != OK) {
+        ALOGE("AMIDI_openOutputPort bad device token %d: %d", device, result);
+        return result;
+    }
+
+    sp<BBinder> portToken(new BBinder());
+    unique_fd ufd;
+    Status txResult = deviceServer->openOutputPort(portToken, portNumber, &ufd);
+    if (!txResult.isOk()) {
+        ALOGE("AMIDI_openOutputPort transaction error: %d", txResult.transactionError());
+        return txResult.transactionError();
+    }
+
+    result = MidiPortRegistry::getInstance().addOutputPort(
+            device, portToken, std::move(ufd), outputPortPtr);
+    if (result != OK) {
+        ALOGE("AMIDI_openOutputPort port registration error: %d", result);
+        // Close port
+        return result;
+    }
+    return OK;
+}
+
+ssize_t AMIDI_receive(AMIDI_OutputPort outputPort, AMIDI_Message *messages, ssize_t maxMessages) {
+    unique_fd *ufd;
+    // TODO: May return a nicer self-unlocking object
+    status_t result = MidiPortRegistry::getInstance().getOutputPortFdAndLock(outputPort, &ufd);
+    if (result != OK) {
+        return result;
+    }
+
+    ssize_t messagesRead = 0;
+    while (messagesRead < maxMessages) {
+        struct pollfd checkFds[1] = { { *ufd, POLLIN, 0 } };
+        int pollResult = poll(checkFds, 1, 0);
+        if (pollResult < 1) {
+            result = android::INVALID_OPERATION;
+            break;
+        }
+
+        AMIDI_Message *message = &messages[messagesRead];
+        uint8_t readBuffer[AMIDI_PACKET_SIZE];
+        memset(readBuffer, 0, sizeof(readBuffer));
+        ssize_t readCount = read(*ufd, readBuffer, sizeof(readBuffer));
+        if (readCount == EINTR) {
+            continue;
+        }
+        if (readCount < 1) {
+            result = android::NOT_ENOUGH_DATA;
+            break;
+        }
+
+        // set Packet Format definition at the top of this file.
+        size_t dataSize = 0;
+        message->opcode = readBuffer[0];
+        message->timestamp = 0;
+        if (message->opcode == AMIDI_OPCODE_DATA && readCount >= AMIDI_PACKET_OVERHEAD) {
+            dataSize = readCount - AMIDI_PACKET_OVERHEAD;
+            if (dataSize) {
+                memcpy(message->buffer, readBuffer + 1, dataSize);
+            }
+            message->timestamp = *(uint64_t*) (readBuffer + readCount - sizeof(uint64_t));
+        }
+        message->len = dataSize;
+        ++messagesRead;
+    }
+
+    MidiPortRegistry::getInstance().unlockOutputPort(outputPort);
+    return result == OK ? messagesRead : result;
+}
+
+status_t AMIDI_closeOutputPort(AMIDI_OutputPort outputPort) {
+    AMIDI_Device device;
+    sp<IBinder> portToken;
+    status_t result =
+        MidiPortRegistry::getInstance().removeOutputPort(outputPort, &device, &portToken);
+    if (result != OK) {
+        return result;
+    }
+
+    sp<BpMidiDeviceServer> deviceServer;
+    result = MidiDeviceRegistry::getInstance().getDeviceByToken(device, &deviceServer);
+    if (result != OK) {
+        return result;
+    }
+
+    Status txResult = deviceServer->closePort(portToken);
+    if (!txResult.isOk()) {
+        return txResult.transactionError();
+    }
+    return OK;
+}
+
+/*
+ * Input (sending) API
+ */
+status_t AMIDI_openInputPort(AMIDI_Device device, int portNumber, AMIDI_InputPort *inputPortPtr) {
+    sp<BpMidiDeviceServer> deviceServer;
+    status_t result = MidiDeviceRegistry::getInstance().getDeviceByToken(device, &deviceServer);
+    if (result != OK) {
+        ALOGE("AMIDI_openInputPort bad device token %d: %d", device, result);
+        return result;
+    }
+
+    sp<BBinder> portToken(new BBinder());
+    unique_fd ufd; // this is the file descriptor of the "receive" port s
+    Status txResult = deviceServer->openInputPort(portToken, portNumber, &ufd);
+    if (!txResult.isOk()) {
+        ALOGE("AMIDI_openInputPort transaction error: %d", txResult.transactionError());
+        return txResult.transactionError();
+    }
+
+    result = MidiPortRegistry::getInstance().addInputPort(
+            device, portToken, std::move(ufd), inputPortPtr);
+    if (result != OK) {
+        ALOGE("AMIDI_openInputPort port registration error: %d", result);
+        // Close port
+        return result;
+    }
+
+    return OK;
+}
+
+status_t AMIDI_closeInputPort(AMIDI_InputPort inputPort) {
+    AMIDI_Device device;
+    sp<IBinder> portToken;
+    status_t result = MidiPortRegistry::getInstance().removeInputPort(
+            inputPort, &device, &portToken);
+    if (result != OK) {
+        ALOGE("AMIDI_closeInputPort remove port error: %d", result);
+        return result;
+    }
+
+    sp<BpMidiDeviceServer> deviceServer;
+    result = MidiDeviceRegistry::getInstance().getDeviceByToken(device, &deviceServer);
+    if (result != OK) {
+        ALOGE("AMIDI_closeInputPort can't find device error: %d", result);
+        return result;
+    }
+
+    Status txResult = deviceServer->closePort(portToken);
+    if (!txResult.isOk()) {
+        result = txResult.transactionError();
+        ALOGE("AMIDI_closeInputPort transaction error: %d", result);
+        return result;
+    }
+
+    return OK;
+}
+
+ssize_t AMIDI_getMaxMessageSizeInBytes(AMIDI_InputPort /*inputPort*/) {
+    return SIZE_MIDIRECEIVEBUFFER;
+}
+
+static ssize_t AMIDI_makeSendBuffer(uint8_t *buffer, uint8_t *data, ssize_t numBytes, uint64_t timestamp) {
+    buffer[0] = AMIDI_OPCODE_DATA;
+    memcpy(buffer + 1, data, numBytes);
+    memcpy(buffer + 1 + numBytes, &timestamp, sizeof(timestamp));
+    return numBytes + AMIDI_PACKET_OVERHEAD;
+}
+
+// Handy debugging function.
+//static void AMIDI_logBuffer(uint8_t *data, size_t numBytes) {
+//    for (size_t index = 0; index < numBytes; index++) {
+//      ALOGI("  data @%zu [0x%X]", index, data[index]);
+//    }
+//}
+
+ssize_t AMIDI_send(AMIDI_InputPort inputPort, uint8_t *buffer, ssize_t numBytes) {
+    return AMIDI_sendWithTimestamp(inputPort, buffer, numBytes, 0);
+}
+
+ssize_t AMIDI_sendWithTimestamp(AMIDI_InputPort inputPort, uint8_t *data,
+        ssize_t numBytes, int64_t timestamp) {
+
+    if (numBytes > SIZE_MIDIRECEIVEBUFFER) {
+        return android::BAD_VALUE;
+    }
+
+    // AMIDI_logBuffer(data, numBytes);
+
+    unique_fd *ufd = NULL;
+    status_t result = MidiPortRegistry::getInstance().getInputPortFd(inputPort, &ufd);
+    if (result != OK) {
+        return result;
+    }
+
+    uint8_t writeBuffer[SIZE_MIDIRECEIVEBUFFER + AMIDI_PACKET_OVERHEAD];
+    ssize_t numTransferBytes = AMIDI_makeSendBuffer(writeBuffer, data, numBytes, timestamp);
+    ssize_t numWritten = write(*ufd, writeBuffer, numTransferBytes);
+
+    if (numWritten < numTransferBytes) {
+        ALOGE("AMIDI_sendWithTimestamp Couldn't write MIDI data buffer. requested:%zu, written%zu",
+                numTransferBytes, numWritten);
+    }
+
+    return numWritten - AMIDI_PACKET_OVERHEAD;
+}
+
+status_t AMIDI_flush(AMIDI_InputPort inputPort) {
+    unique_fd *ufd = NULL;
+    status_t result = MidiPortRegistry::getInstance().getInputPortFd(inputPort, &ufd);
+    if (result != OK) {
+        return result;
+    }
+
+    uint8_t opCode = AMIDI_OPCODE_FLUSH;
+    ssize_t numTransferBytes = 1;
+    ssize_t numWritten = write(*ufd, &opCode, numTransferBytes);
+
+    if (numWritten < numTransferBytes) {
+        ALOGE("AMIDI_flush Couldn't write MIDI flush. requested:%zu, written%zu",
+                numTransferBytes, numWritten);
+        return android::INVALID_OPERATION;
+    }
+
+    return OK;
+}
+
diff --git a/media/native/midi/midi.h b/media/native/midi/midi.h
new file mode 100644
index 0000000..717bc66
--- /dev/null
+++ b/media/native/midi/midi.h
@@ -0,0 +1,202 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_MEDIA_MIDI_H_
+#define ANDROID_MEDIA_MIDI_H_
+
+#include <stdarg.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+
+using android::status_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//typedef struct _AMIDI_Device;
+//typedef struct _AMIDI_InputPort;
+//typedef struct _AMIDI_OutputPort;
+//typedef _AMIDI_Device*      AMIDI_Device;
+//typedef _AMIDI_InputPort*   AMIDI_InputPort;
+//typedef _AMIDI_OutputPort*  AMIDI_OutputPort;
+
+typedef int32_t AMIDI_Device;
+typedef int32_t AMIDI_InputPort;
+typedef int32_t  AMIDI_OutputPort;
+
+//TODO - Do we want to wrap this stuff in namespace android { namespace media { namespace midi {?
+
+enum {
+    AMIDI_INVALID_HANDLE = -1
+};
+
+enum {
+    AMIDI_OPCODE_DATA = 1,
+    AMIDI_OPCODE_FLUSH = 2,
+    AMIDI_PACKET_SIZE = 1024,  /* !!! Currently MidiPortImpl.MAX_PACKET_SIZE !!! */
+    AMIDI_PACKET_OVERHEAD = 9,
+    AMIDI_BUFFER_SIZE = AMIDI_PACKET_SIZE - AMIDI_PACKET_OVERHEAD
+            /* !!! TBD, currently MidiPortImpl.MAX_PACKET_DATA_SIZE !!! */
+};
+
+typedef struct {
+    uint32_t opcode;
+    uint8_t buffer[AMIDI_BUFFER_SIZE];
+    size_t len;
+    int64_t timestamp;
+} AMIDI_Message;
+
+enum {
+    AMIDI_DEVICE_TYPE_USB = 1,
+    AMIDI_DEVICE_TYPE_VIRTUAL = 2,
+    AMIDI_DEVICE_TYPE_BLUETOOTH = 3
+};
+
+typedef struct {
+    int32_t type;
+    int32_t uid;
+    int32_t isPrivate;
+    int32_t inputPortCount;
+    int32_t outputPortCount;
+} AMIDI_DeviceInfo;
+
+/*
+ * Device API
+ */
+/*
+ * Retrieves the native API device token for the specified Java API device ID.
+ *
+ * uid          The Java API id of the device.
+ * devicePtr    Receives the associated native API token for the device.
+ *
+ * Returns OK or a (negative) error code.
+ */
+status_t AMIDI_getDeviceById(int32_t id, AMIDI_Device *devicePtr);
+
+/*
+ * Retrieves information for the native MIDI device.
+ *
+ * device           The Native API token for the device.
+ * deviceInfoPtr    Receives the associated device info.
+ *
+ * Returns OK or a (negative) error code.
+ */
+status_t AMIDI_getDeviceInfo(AMIDI_Device device, AMIDI_DeviceInfo *deviceInfoPtr);
+
+/*
+ * API for receiving data from the Output port of a device.
+ */
+/*
+ * Opens the output port.
+ *
+ * device           Identifies the device.
+ * portNumber       Specifies the zero-based port index on the device to open.
+ * outputPortPtr    Receives the native API port identifier of the opened port.
+ *
+ * Returns OK, or a (negative) error code.
+ */
+status_t AMIDI_openOutputPort(AMIDI_Device device, int portNumber, AMIDI_OutputPort *outputPortPtr);
+
+/*
+ * Receives any pending MIDI messages (up to the specified maximum number of messages).
+ *
+ * outputPort   Identifies the port to receive messages from.
+ * messages     Points to an array (size maxMessages) to receive the MIDI messages.
+ * maxMessages  The number of messages allocated in the messages array.
+ *
+ * Returns the number of messages received, or a (negative) error code.
+ */
+ssize_t AMIDI_receive(AMIDI_OutputPort outputPort, AMIDI_Message *messages, ssize_t maxMessages);
+
+/*
+ * Closes the output port.
+ *
+ * outputPort   The native API port identifier of the port.
+ *
+ * Returns OK, or a (negative) error code.
+ */
+status_t AMIDI_closeOutputPort(AMIDI_OutputPort outputPort);
+
+/*
+ * API for sending data to the Input port of a device.
+ */
+/*
+ * Opens the input port.
+ *
+ * device           Identifies the device.
+ * portNumber       Specifies the zero-based port index on the device to open.
+ * inputPortPtr     Receives the native API port identifier of the opened port.
+ *
+ * Returns OK, or a (negative) error code.
+ */
+status_t AMIDI_openInputPort(AMIDI_Device device, int portNumber, AMIDI_InputPort *inputPortPtr);
+
+/*
+ * Returns the maximum number of bytes that can be received in a single MIDI message.
+ */
+ssize_t AMIDI_getMaxMessageSizeInBytes(AMIDI_InputPort inputPort);
+
+/*
+ * Sends data to the specified input port.
+ *
+ * inputPort    The native API identifier of the port to send data to.
+ * buffer       Points to the array of bytes containing the data to send.
+ * numBytes     Specifies the number of bytes to write.
+ *
+ * Returns  The number of bytes sent or a (negative) error code.
+ */
+ssize_t AMIDI_send(AMIDI_InputPort inputPort, uint8_t *buffer, ssize_t numBytes);
+
+/*
+ * Sends data to the specified input port with a timestamp.
+ *
+ * inputPort    The native API identifier of the port to send data to.
+ * buffer       Points to the array of bytes containing the data to send.
+ * numBytes     Specifies the number of bytes to write.
+ * timestamp    The time stamp to associate with the sent data.
+ *
+ * Returns  The number of bytes sent or a (negative) error code.
+ */
+ssize_t AMIDI_sendWithTimestamp(AMIDI_InputPort inputPort, uint8_t *buffer,
+        ssize_t numBytes, int64_t timestamp);
+
+/*
+ * Sends a message with a 'MIDI flush command code' to the specified port.
+ *
+ * inputPort    The native API identifier of the port to send the flush message to.
+ *
+ * Returns OK, or a (negative) error code.
+ */
+status_t AMIDI_flush(AMIDI_InputPort inputPort);
+
+/*
+ * Closes the input port.
+ *
+ * inputPort   The native API port identifier of the port.
+ *
+ *
+ * Returns OK, or a (negative) error code.
+ */
+status_t AMIDI_closeInputPort(AMIDI_InputPort inputPort);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ANDROID_MEDIA_MIDI_H_ */
diff --git a/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothPacketEncoder.java b/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothPacketEncoder.java
index 5fb162c..8ac6b56 100644
--- a/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothPacketEncoder.java
+++ b/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothPacketEncoder.java
@@ -48,7 +48,7 @@
 
     private boolean mWritePending;
 
-        private final Object mLock = new Object();
+    private final Object mLock = new Object();
 
     // This receives normalized data from mMidiFramer and accumulates it into a packet buffer
     private final MidiReceiver mFramedDataReceiver = new MidiReceiver() {
@@ -60,6 +60,8 @@
                 int milliTimestamp = (int)(timestamp / MILLISECOND_NANOS) & MILLISECOND_MASK;
                 byte status = msg[offset];
                 boolean isSysExStart = (status == MidiConstants.STATUS_SYSTEM_EXCLUSIVE);
+                // Because of the MidiFramer, if it is not a status byte then it
+                // must be a continuation.
                 boolean isSysExContinuation = ((status & 0x80) == 0);
 
                 int bytesNeeded;
@@ -70,7 +72,9 @@
                     bytesNeeded = count;
                 }
 
-                boolean needsTimestamp = (milliTimestamp != mPacketTimestamp);
+                // Status bytes must be preceded by a timestamp
+                boolean needsTimestamp = (status != mRunningStatus)
+                        || (milliTimestamp != mPacketTimestamp);
                 if (isSysExStart) {
                     // SysEx start byte must be preceded by a timestamp
                     needsTimestamp = true;
@@ -78,6 +82,7 @@
                     // SysEx continuation packets must not have timestamp byte
                     needsTimestamp = false;
                 }
+
                 if (needsTimestamp) bytesNeeded++;  // add one for timestamp byte
                 if (status == mRunningStatus) bytesNeeded--;    // subtract one for status byte
 
diff --git a/media/tests/NativeMidiDemo/Android.mk b/media/tests/NativeMidiDemo/Android.mk
new file mode 100644
index 0000000..6b08f6b
--- /dev/null
+++ b/media/tests/NativeMidiDemo/Android.mk
@@ -0,0 +1,30 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_PACKAGE_NAME := NativeMidiDemo
+
+#LOCAL_SDK_VERSION := current
+LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_SRC_FILES := $(call all-java-files-under, java)
+
+LOCAL_JNI_SHARED_LIBRARIES := libnativemidi_jni
+
+include $(BUILD_PACKAGE)
+
+# Include packages in subdirectories
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/media/tests/NativeMidiDemo/AndroidManifest.xml b/media/tests/NativeMidiDemo/AndroidManifest.xml
new file mode 100644
index 0000000..322873f
--- /dev/null
+++ b/media/tests/NativeMidiDemo/AndroidManifest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.example.android.nativemididemo"
+          android:versionCode="1"
+          android:versionName="1.0">
+  <application
+      android:allowBackup="false"
+      android:fullBackupContent="false"
+      android:icon="@mipmap/ic_launcher"
+      android:label="@string/app_name">
+    <uses-feature android:name="android.software.midi" android:required="true"/>
+    <activity android:name=".NativeMidi"
+              android:label="@string/app_name">
+      <intent-filter>
+        <action android:name="android.intent.action.MAIN" />
+        <category android:name="android.intent.category.LAUNCHER" />
+      </intent-filter>
+    </activity>
+  </application>
+</manifest>
diff --git a/media/tests/NativeMidiDemo/java/com/example/android/nativemididemo/NativeMidi.java b/media/tests/NativeMidiDemo/java/com/example/android/nativemididemo/NativeMidi.java
new file mode 100644
index 0000000..0969b10
--- /dev/null
+++ b/media/tests/NativeMidiDemo/java/com/example/android/nativemididemo/NativeMidi.java
@@ -0,0 +1,354 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.example.android.nativemididemo;
+
+import android.app.Activity;
+import android.content.Context;
+import android.media.midi.MidiDevice;
+import android.media.midi.MidiDeviceInfo;
+import android.media.midi.MidiManager;
+import android.media.midi.MidiOutputPort;
+import android.media.midi.MidiReceiver;
+import android.media.AudioManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.RadioButton;
+import android.widget.RadioGroup;
+import android.widget.TextView;
+
+import java.io.IOException;
+
+public class NativeMidi extends Activity
+{
+    private TextView mCallbackStatusTextView;
+    private TextView mJavaMidiStatusTextView;
+    private TextView mMessagesTextView;
+    private RadioGroup mMidiDevicesRadioGroup;
+    private Handler mTimerHandler = new Handler();
+    private boolean mAudioWorks;
+    private final int mMinFramesPerBuffer = 32;   // See {min|max}PlaySamples in nativemidi-jni.cpp
+    private final int mMaxFramesPerBuffer = 1000;
+    private int mFramesPerBuffer;
+
+    private TouchableScrollView mMessagesContainer;
+    private MidiManager mMidiManager;
+    private MidiOutputPortSelector mActivePortSelector;
+
+    private Runnable mTimerRunnable = new Runnable() {
+        private long mLastTime;
+        private long mLastPlaybackCounter;
+        private int mLastCallbackRate;
+        private long mLastUntouchedTime;
+
+        @Override
+        public void run() {
+            final long checkIntervalMs = 1000;
+            long currentTime = System.currentTimeMillis();
+            long currentPlaybackCounter = getPlaybackCounter();
+            if (currentTime - mLastTime >= checkIntervalMs) {
+                int callbackRate = Math.round(
+                        (float)(currentPlaybackCounter - mLastPlaybackCounter) /
+                        ((float)(currentTime - mLastTime) / (float)1000));
+                if (mLastCallbackRate != callbackRate) {
+                    mCallbackStatusTextView.setText(
+                           "CB: " + callbackRate + " Hz");
+                    mLastCallbackRate = callbackRate;
+                }
+                mLastTime = currentTime;
+                mLastPlaybackCounter = currentPlaybackCounter;
+            }
+
+            String[] newMessages = getRecentMessages();
+            if (newMessages != null) {
+                for (String message : newMessages) {
+                    mMessagesTextView.append(message);
+                    mMessagesTextView.append("\n");
+                }
+                if (!mMessagesContainer.isTouched) {
+                    if (mLastUntouchedTime == 0) mLastUntouchedTime = currentTime;
+                    if (currentTime - mLastUntouchedTime > 3000) {
+                        mMessagesContainer.fullScroll(View.FOCUS_DOWN);
+                    }
+                } else {
+                    mLastUntouchedTime = 0;
+                }
+            }
+
+            mTimerHandler.postDelayed(this, checkIntervalMs / 4);
+        }
+    };
+
+    private void addMessage(final String message) {
+        mTimerHandler.postDelayed(new Runnable() {
+            @Override
+            public void run() {
+                mMessagesTextView.append(message);
+            }
+        }, 0);
+    }
+
+    private class MidiOutputPortSelector implements View.OnClickListener {
+        private final MidiDeviceInfo mDeviceInfo;
+        private final int mPortNumber;
+        private MidiDevice mDevice;
+        private MidiOutputPort mOutputPort;
+
+        MidiOutputPortSelector() {
+            mDeviceInfo = null;
+            mPortNumber = -1;
+        }
+
+        MidiOutputPortSelector(MidiDeviceInfo info, int portNumber) {
+            mDeviceInfo = info;
+            mPortNumber = portNumber;
+        }
+
+        MidiDeviceInfo getDeviceInfo() { return mDeviceInfo; }
+
+        @Override
+        public void onClick(View v) {
+            if (mActivePortSelector != null) {
+                mActivePortSelector.close();
+                mActivePortSelector = null;
+            }
+            if (mDeviceInfo == null) {
+                mActivePortSelector = this;
+                return;
+            }
+            mMidiManager.openDevice(mDeviceInfo, new MidiManager.OnDeviceOpenedListener() {
+                @Override
+                public void onDeviceOpened(MidiDevice device) {
+                    if (device == null) {
+                        addMessage("! Failed to open MIDI device !\n");
+                    } else {
+                        mDevice = device;
+                        try {
+                            mDevice.mirrorToNative();
+                            startReadingMidi(mDevice.getInfo().getId(), mPortNumber);
+                        } catch (IOException e) {
+                            addMessage("! Failed to mirror to native !\n" + e.getMessage() + "\n");
+                        }
+
+                        mActivePortSelector = MidiOutputPortSelector.this;
+
+                        mOutputPort = device.openOutputPort(mPortNumber);
+                        mOutputPort.connect(mMidiReceiver);
+                    }
+                }
+            }, null);
+        }
+
+        void closePortOnly() {
+            stopReadingMidi();
+        }
+
+        void close() {
+            closePortOnly();
+            try {
+                if (mOutputPort != null) {
+                    mOutputPort.close();
+                }
+            } catch (IOException e) {
+                mMessagesTextView.append("! Port close error: " + e + "\n");
+            } finally {
+                mOutputPort = null;
+            }
+            try {
+                if (mDevice != null) {
+                    mDevice.close();
+                }
+            } catch (IOException e) {
+                mMessagesTextView.append("! Device close error: " + e + "\n");
+            } finally {
+                mDevice = null;
+            }
+        }
+    }
+
+    private MidiManager.DeviceCallback mMidiDeviceCallback = new MidiManager.DeviceCallback() {
+        @Override
+        public void onDeviceAdded(MidiDeviceInfo info) {
+            Bundle deviceProps = info.getProperties();
+            String deviceName = deviceProps.getString(MidiDeviceInfo.PROPERTY_NAME);
+            if (deviceName == null) {
+                deviceName = deviceProps.getString(MidiDeviceInfo.PROPERTY_MANUFACTURER);
+            }
+
+            for (MidiDeviceInfo.PortInfo port : info.getPorts()) {
+                if (port.getType() != MidiDeviceInfo.PortInfo.TYPE_OUTPUT) continue;
+                String portName = port.getName();
+                int portNumber = port.getPortNumber();
+                if (portName.length() == 0) portName = "[" + portNumber + "]";
+                portName += "@" + deviceName;
+                RadioButton outputDevice = new RadioButton(NativeMidi.this);
+                outputDevice.setText(portName);
+                outputDevice.setTag(info);
+                outputDevice.setOnClickListener(new MidiOutputPortSelector(info, portNumber));
+                mMidiDevicesRadioGroup.addView(outputDevice);
+            }
+
+            NativeMidi.this.updateKeepScreenOn();
+        }
+
+        @Override
+        public void onDeviceRemoved(MidiDeviceInfo info) {
+            if (mActivePortSelector != null && info.equals(mActivePortSelector.getDeviceInfo())) {
+                mActivePortSelector.close();
+                mActivePortSelector = null;
+            }
+            int removeButtonStart = -1, removeButtonCount = 0;
+            final int buttonCount = mMidiDevicesRadioGroup.getChildCount();
+            boolean checked = false;
+            for (int i = 0; i < buttonCount; ++i) {
+                RadioButton button = (RadioButton) mMidiDevicesRadioGroup.getChildAt(i);
+                if (!info.equals(button.getTag())) continue;
+                if (removeButtonStart == -1) removeButtonStart = i;
+                ++removeButtonCount;
+                if (button.isChecked()) checked = true;
+            }
+            if (removeButtonStart != -1) {
+                mMidiDevicesRadioGroup.removeViews(removeButtonStart, removeButtonCount);
+                if (checked) {
+                    mMidiDevicesRadioGroup.check(R.id.device_none);
+                }
+            }
+
+            NativeMidi.this.updateKeepScreenOn();
+        }
+    };
+
+    private class JavaMidiReceiver extends MidiReceiver implements Runnable {
+        @Override
+        public void onSend(byte[] data, int offset,
+                int count, long timestamp) throws IOException {
+            mTimerHandler.removeCallbacks(this);
+            mTimerHandler.postDelayed(new Runnable() {
+                @Override
+                public void run() {
+                    mJavaMidiStatusTextView.setText("Java: MSG");
+                }
+            }, 0);
+            mTimerHandler.postDelayed(this, 100);
+        }
+
+        @Override
+        public void run() {
+            mJavaMidiStatusTextView.setText("Java: ---");
+        }
+    }
+
+    private JavaMidiReceiver mMidiReceiver = new JavaMidiReceiver();
+
+    private void updateKeepScreenOn() {
+        if (mMidiDevicesRadioGroup.getChildCount() > 1) {
+            getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+        } else {
+            getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+        }
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+
+        mCallbackStatusTextView = (TextView) findViewById(R.id.callback_status);
+        mJavaMidiStatusTextView = (TextView) findViewById(R.id.java_midi_status);
+        mMessagesTextView = (TextView) findViewById(R.id.messages);
+        mMessagesContainer = (TouchableScrollView) findViewById(R.id.messages_scroll);
+        mMidiDevicesRadioGroup = (RadioGroup) findViewById(R.id.devices);
+        RadioButton deviceNone = (RadioButton) findViewById(R.id.device_none);
+        deviceNone.setOnClickListener(new MidiOutputPortSelector());
+
+        AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
+        String sampleRate = am.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
+        if (sampleRate == null) sampleRate = "48000";
+        String framesPerBuffer = am.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER);
+        if (framesPerBuffer == null) framesPerBuffer = Integer.toString(mMaxFramesPerBuffer);
+        mFramesPerBuffer = Integer.parseInt(framesPerBuffer);
+        String audioInitResult = initAudio(Integer.parseInt(sampleRate), mFramesPerBuffer);
+        mMessagesTextView.append("Open SL ES init: " + audioInitResult + "\n");
+
+        if (audioInitResult.startsWith("Success")) {
+            mAudioWorks = true;
+            mTimerHandler.postDelayed(mTimerRunnable, 0);
+            mTimerHandler.postDelayed(mMidiReceiver, 0);
+        }
+
+        mMidiManager = (MidiManager) getSystemService(Context.MIDI_SERVICE);
+        mMidiManager.registerDeviceCallback(mMidiDeviceCallback, new Handler());
+        for (MidiDeviceInfo info : mMidiManager.getDevices()) {
+            mMidiDeviceCallback.onDeviceAdded(info);
+        }
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        if (mAudioWorks) {
+            mTimerHandler.removeCallbacks(mTimerRunnable);
+            pauseAudio();
+        }
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        if (mAudioWorks) {
+            mTimerHandler.postDelayed(mTimerRunnable, 0);
+            resumeAudio();
+        }
+    }
+
+    @Override
+    protected void onDestroy() {
+        if (mActivePortSelector != null) {
+            mActivePortSelector.close();
+            mActivePortSelector = null;
+        }
+        shutdownAudio();
+        super.onDestroy();
+    }
+
+    public void onClearMessages(View v) {
+        mMessagesTextView.setText("");
+    }
+
+    public void onClosePort(View v) {
+        if (mActivePortSelector != null) {
+            mActivePortSelector.closePortOnly();
+        }
+    }
+
+    private native String initAudio(int sampleRate, int playSamples);
+    private native void pauseAudio();
+    private native void resumeAudio();
+    private native void shutdownAudio();
+
+    private native long getPlaybackCounter();
+    private native String[] getRecentMessages();
+
+    private native void startReadingMidi(int deviceId, int portNumber);
+    private native void stopReadingMidi();
+
+    static {
+        System.loadLibrary("nativemidi_jni");
+    }
+}
diff --git a/media/tests/NativeMidiDemo/java/com/example/android/nativemididemo/TouchableScrollView.java b/media/tests/NativeMidiDemo/java/com/example/android/nativemididemo/TouchableScrollView.java
new file mode 100644
index 0000000..645aafa
--- /dev/null
+++ b/media/tests/NativeMidiDemo/java/com/example/android/nativemididemo/TouchableScrollView.java
@@ -0,0 +1,32 @@
+package com.example.android.nativemididemo;
+
+import android.content.Context;
+import android.view.MotionEvent;
+import android.util.AttributeSet;
+import android.widget.ScrollView;
+
+public class TouchableScrollView extends ScrollView {
+    public boolean isTouched;
+
+    public TouchableScrollView(Context context) {
+        super(context);
+    }
+
+    public TouchableScrollView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        switch (event.getAction()) {
+            case MotionEvent.ACTION_DOWN:
+                isTouched = true;
+                break;
+            case MotionEvent.ACTION_CANCEL:
+            case MotionEvent.ACTION_UP:
+                isTouched = false;
+                break;
+        }
+        return super.onTouchEvent(event);
+    }
+}
diff --git a/media/tests/NativeMidiDemo/jni/Android.mk b/media/tests/NativeMidiDemo/jni/Android.mk
new file mode 100644
index 0000000..69a64bd
--- /dev/null
+++ b/media/tests/NativeMidiDemo/jni/Android.mk
@@ -0,0 +1,35 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_MODULE := libnativemidi_jni
+
+LOCAL_SRC_FILES := \
+	nativemidi-jni.cpp \
+	messagequeue.cpp
+
+LOCAL_CFLAGS += -Wall -Wextra -Werror -O0
+
+LOCAL_C_INCLUDES += \
+    frameworks/base/media/native
+
+LOCAL_CXX_STL := libc++_static
+
+LOCAL_SHARED_LIBRARIES := libOpenSLES libmidi
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/tests/NativeMidiDemo/jni/messagequeue.cpp b/media/tests/NativeMidiDemo/jni/messagequeue.cpp
new file mode 100644
index 0000000..ffaef38
--- /dev/null
+++ b/media/tests/NativeMidiDemo/jni/messagequeue.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <atomic>
+#include <stdio.h>
+#include <string.h>
+
+#include "messagequeue.h"
+
+namespace nativemididemo {
+
+static const int messageBufferSize = 64 * 1024;
+static char messageBuffer[messageBufferSize];
+static std::atomic_ullong messagesLastWritePosition;
+
+void writeMessage(const char* message)
+{
+    static unsigned long long lastWritePos = 0;
+    size_t messageLen = strlen(message);
+    if (messageLen == 0) return;
+
+    messageLen += 1; // Also count in the null terminator.
+    char buffer[1024];
+    if (messageLen >= messageBufferSize) {
+        snprintf(buffer, sizeof(buffer), "!!! Message too long: %zu bytes !!!", messageLen);
+        message = buffer;
+        messageLen = strlen(message);
+    }
+
+    size_t wrappedWritePos = lastWritePos % messageBufferSize;
+    if (wrappedWritePos + messageLen >= messageBufferSize) {
+        size_t tailLen = messageBufferSize - wrappedWritePos;
+        memset(messageBuffer + wrappedWritePos, 0, tailLen);
+        lastWritePos += tailLen;
+        wrappedWritePos = 0;
+    }
+
+    memcpy(messageBuffer + wrappedWritePos, message, messageLen);
+    lastWritePos += messageLen;
+    messagesLastWritePosition.store(lastWritePos);
+}
+
+static char messageBufferCopy[messageBufferSize];
+
+jobjectArray getRecentMessagesForJava(JNIEnv* env, jobject)
+{
+    static unsigned long long lastReadPos = 0;
+    const char* overrunMessage = "";
+    size_t messagesCount = 0;
+    jobjectArray result = NULL;
+
+    // First we copy the portion of the message buffer into messageBufferCopy.  If after finishing
+    // the copy we notice that the writer has mutated the portion of the buffer that we were
+    // copying, we report an overrun. Afterwards we can safely read messages from the copy.
+    memset(messageBufferCopy, 0, sizeof(messageBufferCopy));
+    unsigned long long lastWritePos = messagesLastWritePosition.load();
+    if (lastWritePos - lastReadPos > messageBufferSize) {
+        overrunMessage = "!!! Message buffer overrun !!!";
+        messagesCount = 1;
+        lastReadPos = lastWritePos;
+        goto create_array;
+    }
+    if (lastWritePos == lastReadPos) return result;
+    if (lastWritePos / messageBufferSize == lastReadPos / messageBufferSize) {
+        size_t wrappedReadPos = lastReadPos % messageBufferSize;
+        memcpy(messageBufferCopy + wrappedReadPos,
+                messageBuffer + wrappedReadPos,
+                lastWritePos % messageBufferSize - wrappedReadPos);
+    } else {
+        size_t wrappedReadPos = lastReadPos % messageBufferSize;
+        memcpy(messageBufferCopy, messageBuffer, lastWritePos % messageBufferSize);
+        memcpy(messageBufferCopy + wrappedReadPos,
+                messageBuffer + wrappedReadPos,
+                messageBufferSize - wrappedReadPos);
+    }
+    {
+    unsigned long long newLastWritePos = messagesLastWritePosition.load();
+    if (newLastWritePos - lastReadPos > messageBufferSize) {
+        overrunMessage = "!!! Message buffer overrun !!!";
+        messagesCount = 1;
+        lastReadPos = lastWritePos = newLastWritePos;
+        goto create_array;
+    }
+    }
+    // Otherwise we ignore newLastWritePos, since we only have a copy of the buffer
+    // up to lastWritePos.
+
+    for (unsigned long long readPos = lastReadPos; readPos < lastWritePos; ) {
+        size_t messageLen = strlen(messageBufferCopy + (readPos % messageBufferSize));
+        if (messageLen != 0) {
+            readPos += messageLen + 1;
+            messagesCount++;
+        } else {
+            // Skip to the beginning of the buffer.
+            readPos = (readPos / messageBufferSize + 1) * messageBufferSize;
+        }
+    }
+    if (messagesCount == 0) {
+        lastReadPos = lastWritePos;
+        return result;
+    }
+
+create_array:
+    result = env->NewObjectArray(
+            messagesCount, env->FindClass("java/lang/String"), env->NewStringUTF(overrunMessage));
+    if (lastWritePos == lastReadPos) return result;
+
+    jsize arrayIndex = 0;
+    while (lastReadPos < lastWritePos) {
+        size_t wrappedReadPos = lastReadPos % messageBufferSize;
+        if (messageBufferCopy[wrappedReadPos] != '\0') {
+            jstring message = env->NewStringUTF(messageBufferCopy + wrappedReadPos);
+            env->SetObjectArrayElement(result, arrayIndex++, message);
+            lastReadPos += env->GetStringLength(message) + 1;
+            env->DeleteLocalRef(message);
+        } else {
+            // Skip to the beginning of the buffer.
+            lastReadPos = (lastReadPos / messageBufferSize + 1) * messageBufferSize;
+        }
+    }
+    return result;
+}
+
+} // namespace nativemididemo
diff --git a/core/java/com/android/internal/logging/legacy/Util.java b/media/tests/NativeMidiDemo/jni/messagequeue.h
similarity index 60%
copy from core/java/com/android/internal/logging/legacy/Util.java
copy to media/tests/NativeMidiDemo/jni/messagequeue.h
index 99f71ca..20aa9e8 100644
--- a/core/java/com/android/internal/logging/legacy/Util.java
+++ b/media/tests/NativeMidiDemo/jni/messagequeue.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -12,14 +12,19 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
+ *
  */
-package com.android.internal.logging.legacy;
 
-/**
- * Created by cwren on 11/21/16.
- */
-public class Util {
-    public static boolean debug() {
-        return false;
-    }
-}
+#ifndef NATIVEMIDIDEMO_MESSAGEQUEUE_H
+#define NATIVEMIDIDEMO_MESSAGEQUEUE_H
+
+#include <jni.h>
+
+namespace nativemididemo {
+
+void writeMessage(const char* message);
+jobjectArray getRecentMessagesForJava(JNIEnv* env, jobject thiz);
+
+} // namespace nativemididemo
+
+#endif // NATIVEMIDIDEMO_MESSAGEQUEUE_H
diff --git a/media/tests/NativeMidiDemo/jni/nativemidi-jni.cpp b/media/tests/NativeMidiDemo/jni/nativemidi-jni.cpp
new file mode 100644
index 0000000..8aa874a
--- /dev/null
+++ b/media/tests/NativeMidiDemo/jni/nativemidi-jni.cpp
@@ -0,0 +1,285 @@
+#include <atomic>
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <jni.h>
+
+#include <midi/midi.h>
+#include <SLES/OpenSLES.h>
+#include <SLES/OpenSLES_Android.h>
+
+#include "messagequeue.h"
+
+extern "C" {
+JNIEXPORT jstring JNICALL Java_com_example_android_nativemididemo_NativeMidi_initAudio(
+        JNIEnv* env, jobject thiz, jint sampleRate, jint playSamples);
+JNIEXPORT void JNICALL Java_com_example_android_nativemididemo_NativeMidi_pauseAudio(
+        JNIEnv* env, jobject thiz);
+JNIEXPORT void JNICALL Java_com_example_android_nativemididemo_NativeMidi_resumeAudio(
+        JNIEnv* env, jobject thiz);
+JNIEXPORT void JNICALL Java_com_example_android_nativemididemo_NativeMidi_shutdownAudio(
+        JNIEnv* env, jobject thiz);
+JNIEXPORT jlong JNICALL Java_com_example_android_nativemididemo_NativeMidi_getPlaybackCounter(
+        JNIEnv* env, jobject thiz);
+JNIEXPORT jobjectArray JNICALL Java_com_example_android_nativemididemo_NativeMidi_getRecentMessages(
+        JNIEnv* env, jobject thiz);
+JNIEXPORT void JNICALL Java_com_example_android_nativemididemo_NativeMidi_startReadingMidi(
+        JNIEnv* env, jobject thiz, jint deviceId, jint portNumber);
+JNIEXPORT void JNICALL Java_com_example_android_nativemididemo_NativeMidi_stopReadingMidi(
+        JNIEnv* env, jobject thiz);
+}
+
+static const char* errStrings[] = {
+    "SL_RESULT_SUCCESS",                    // 0
+    "SL_RESULT_PRECONDITIONS_VIOLATED",     // 1
+    "SL_RESULT_PARAMETER_INVALID",          // 2
+    "SL_RESULT_MEMORY_FAILURE",             // 3
+    "SL_RESULT_RESOURCE_ERROR",             // 4
+    "SL_RESULT_RESOURCE_LOST",              // 5
+    "SL_RESULT_IO_ERROR",                   // 6
+    "SL_RESULT_BUFFER_INSUFFICIENT",        // 7
+    "SL_RESULT_CONTENT_CORRUPTED",          // 8
+    "SL_RESULT_CONTENT_UNSUPPORTED",        // 9
+    "SL_RESULT_CONTENT_NOT_FOUND",          // 10
+    "SL_RESULT_PERMISSION_DENIED",          // 11
+    "SL_RESULT_FEATURE_UNSUPPORTED",        // 12
+    "SL_RESULT_INTERNAL_ERROR",             // 13
+    "SL_RESULT_UNKNOWN_ERROR",              // 14
+    "SL_RESULT_OPERATION_ABORTED",          // 15
+    "SL_RESULT_CONTROL_LOST" };             // 16
+static const char* getSLErrStr(int code) {
+    return errStrings[code];
+}
+
+static SLObjectItf engineObject;
+static SLEngineItf engineEngine;
+static SLObjectItf outputMixObject;
+static SLObjectItf playerObject;
+static SLPlayItf playerPlay;
+static SLAndroidSimpleBufferQueueItf playerBufferQueue;
+
+static const int minPlaySamples = 32;
+static const int maxPlaySamples = 1000;
+static std::atomic_int playSamples(maxPlaySamples);
+static short playBuffer[maxPlaySamples];
+
+static std::atomic_ullong sharedCounter;
+
+static AMIDI_Device midiDevice = AMIDI_INVALID_HANDLE;
+static std::atomic<AMIDI_OutputPort> midiOutputPort(AMIDI_INVALID_HANDLE);
+
+static int setPlaySamples(int newPlaySamples)
+{
+    if (newPlaySamples < minPlaySamples) newPlaySamples = minPlaySamples;
+    if (newPlaySamples > maxPlaySamples) newPlaySamples = maxPlaySamples;
+    playSamples.store(newPlaySamples);
+    return newPlaySamples;
+}
+
+// Amount of messages we are ready to handle during one callback cycle.
+static const size_t MAX_INCOMING_MIDI_MESSAGES = 20;
+// Static allocation to save time in the callback.
+static AMIDI_Message incomingMidiMessages[MAX_INCOMING_MIDI_MESSAGES];
+
+static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void */*context*/)
+{
+    sharedCounter++;
+
+    AMIDI_OutputPort outputPort = midiOutputPort.load();
+    if (outputPort != AMIDI_INVALID_HANDLE) {
+        char midiDumpBuffer[1024];
+        ssize_t midiReceived = AMIDI_receive(
+                outputPort, incomingMidiMessages, MAX_INCOMING_MIDI_MESSAGES);
+        if (midiReceived >= 0) {
+            for (ssize_t i = 0; i < midiReceived; ++i) {
+                AMIDI_Message* msg = &incomingMidiMessages[i];
+                if (msg->opcode == AMIDI_OPCODE_DATA) {
+                    memset(midiDumpBuffer, 0, sizeof(midiDumpBuffer));
+                    int pos = snprintf(midiDumpBuffer, sizeof(midiDumpBuffer),
+                            "%" PRIx64 " ", msg->timestamp);
+                    for (uint8_t *b = msg->buffer, *e = b + msg->len; b < e; ++b) {
+                        pos += snprintf(midiDumpBuffer + pos, sizeof(midiDumpBuffer) - pos,
+                                "%02x ", *b);
+                    }
+                    nativemididemo::writeMessage(midiDumpBuffer);
+                } else if (msg->opcode == AMIDI_OPCODE_FLUSH) {
+                    nativemididemo::writeMessage("MIDI flush");
+                }
+            }
+        } else {
+            snprintf(midiDumpBuffer, sizeof(midiDumpBuffer),
+                    "! MIDI Receive error: %s !", strerror(-midiReceived));
+            nativemididemo::writeMessage(midiDumpBuffer);
+        }
+    }
+
+    size_t usedBufferSize = playSamples.load() * sizeof(playBuffer[0]);
+    if (usedBufferSize > sizeof(playBuffer)) {
+        usedBufferSize = sizeof(playBuffer);
+    }
+    (*bq)->Enqueue(bq, playBuffer, usedBufferSize);
+}
+
+jstring Java_com_example_android_nativemididemo_NativeMidi_initAudio(
+        JNIEnv* env, jobject, jint sampleRate, jint playSamples) {
+    const char* stage;
+    SLresult result;
+    char printBuffer[1024];
+
+    playSamples = setPlaySamples(playSamples);
+
+    result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
+    if (SL_RESULT_SUCCESS != result) { stage = "slCreateEngine"; goto handle_error; }
+
+    result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
+    if (SL_RESULT_SUCCESS != result) { stage = "realize Engine object"; goto handle_error; }
+
+    result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
+    if (SL_RESULT_SUCCESS != result) { stage = "get Engine interface"; goto handle_error; }
+
+    result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, NULL, NULL);
+    if (SL_RESULT_SUCCESS != result) { stage = "CreateOutputMix"; goto handle_error; }
+
+    result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
+    if (SL_RESULT_SUCCESS != result) { stage = "realize OutputMix object"; goto handle_error; }
+
+    {
+    SLDataFormat_PCM format_pcm = { SL_DATAFORMAT_PCM, 1, (SLuint32)sampleRate * 1000,
+                                    SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16,
+                                    SL_SPEAKER_FRONT_LEFT, SL_BYTEORDER_LITTLEENDIAN };
+    SLDataLocator_AndroidSimpleBufferQueue loc_bufq =
+            { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 1 };
+    SLDataSource audioSrc = { &loc_bufq, &format_pcm };
+    SLDataLocator_OutputMix loc_outmix = { SL_DATALOCATOR_OUTPUTMIX, outputMixObject };
+    SLDataSink audioSnk = { &loc_outmix, NULL };
+    const SLInterfaceID ids[1] = { SL_IID_BUFFERQUEUE };
+    const SLboolean req[1] = { SL_BOOLEAN_TRUE };
+    result = (*engineEngine)->CreateAudioPlayer(
+            engineEngine, &playerObject, &audioSrc, &audioSnk, 1, ids, req);
+    if (SL_RESULT_SUCCESS != result) { stage = "CreateAudioPlayer"; goto handle_error; }
+
+    result = (*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE);
+    if (SL_RESULT_SUCCESS != result) { stage = "realize Player object"; goto handle_error; }
+    }
+
+    result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playerPlay);
+    if (SL_RESULT_SUCCESS != result) { stage = "get Play interface"; goto handle_error; }
+
+    result = (*playerObject)->GetInterface(playerObject, SL_IID_BUFFERQUEUE, &playerBufferQueue);
+    if (SL_RESULT_SUCCESS != result) { stage = "get BufferQueue interface"; goto handle_error; }
+
+    result = (*playerBufferQueue)->RegisterCallback(playerBufferQueue, bqPlayerCallback, NULL);
+    if (SL_RESULT_SUCCESS != result) { stage = "register BufferQueue callback"; goto handle_error; }
+
+    result = (*playerBufferQueue)->Enqueue(playerBufferQueue, playBuffer, sizeof(playBuffer));
+    if (SL_RESULT_SUCCESS != result) {
+        stage = "enqueue into PlayerBufferQueue"; goto handle_error; }
+
+    result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING);
+    if (SL_RESULT_SUCCESS != result) {
+        stage = "SetPlayState(SL_PLAYSTATE_PLAYING)"; goto handle_error; }
+
+    snprintf(printBuffer, sizeof(printBuffer),
+            "Success, sample rate %d, buffer samples %d", sampleRate, playSamples);
+    return env->NewStringUTF(printBuffer);
+
+handle_error:
+    snprintf(printBuffer, sizeof(printBuffer), "Error at %s: %s", stage, getSLErrStr(result));
+    return env->NewStringUTF(printBuffer);
+}
+
+void Java_com_example_android_nativemididemo_NativeMidi_pauseAudio(
+        JNIEnv*, jobject) {
+    if (playerPlay != NULL) {
+        (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PAUSED);
+    }
+}
+
+void Java_com_example_android_nativemididemo_NativeMidi_resumeAudio(
+        JNIEnv*, jobject) {
+    if (playerBufferQueue != NULL && playerPlay != NULL) {
+        (*playerBufferQueue)->Enqueue(playerBufferQueue, playBuffer, sizeof(playBuffer));
+        (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING);
+    }
+}
+
+void Java_com_example_android_nativemididemo_NativeMidi_shutdownAudio(
+        JNIEnv*, jobject) {
+    if (playerObject != NULL) {
+        (*playerObject)->Destroy(playerObject);
+        playerObject = NULL;
+        playerPlay = NULL;
+        playerBufferQueue = NULL;
+    }
+
+    if (outputMixObject != NULL) {
+        (*outputMixObject)->Destroy(outputMixObject);
+        outputMixObject = NULL;
+    }
+
+    if (engineObject != NULL) {
+        (*engineObject)->Destroy(engineObject);
+        engineObject = NULL;
+        engineEngine = NULL;
+    }
+}
+
+jlong Java_com_example_android_nativemididemo_NativeMidi_getPlaybackCounter(JNIEnv*, jobject) {
+    return sharedCounter.load();
+}
+
+jobjectArray Java_com_example_android_nativemididemo_NativeMidi_getRecentMessages(
+        JNIEnv* env, jobject thiz) {
+    return nativemididemo::getRecentMessagesForJava(env, thiz);
+}
+
+void Java_com_example_android_nativemididemo_NativeMidi_startReadingMidi(
+        JNIEnv*, jobject, jint deviceId, jint portNumber) {
+    char buffer[1024];
+
+    int result = AMIDI_getDeviceById(deviceId, &midiDevice);
+    if (result == 0) {
+        snprintf(buffer, sizeof(buffer), "Obtained device token for uid %d: token %d", deviceId, midiDevice);
+    } else {
+        snprintf(buffer, sizeof(buffer), "Could not obtain device token for uid %d: %d", deviceId, result);
+    }
+    nativemididemo::writeMessage(buffer);
+    if (result) return;
+
+    AMIDI_DeviceInfo deviceInfo;
+    result = AMIDI_getDeviceInfo(midiDevice, &deviceInfo);
+    if (result == 0) {
+        snprintf(buffer, sizeof(buffer), "Device info: uid %d, type %d, priv %d, ports %d I / %d O",
+                deviceInfo.uid, deviceInfo.type, deviceInfo.isPrivate,
+                (int)deviceInfo.inputPortCount, (int)deviceInfo.outputPortCount);
+    } else {
+        snprintf(buffer, sizeof(buffer), "Could not obtain device info %d", result);
+    }
+    nativemididemo::writeMessage(buffer);
+    if (result) return;
+
+    AMIDI_OutputPort outputPort;
+    result = AMIDI_openOutputPort(midiDevice, portNumber, &outputPort);
+    if (result == 0) {
+        snprintf(buffer, sizeof(buffer), "Opened port %d: token %d", portNumber, outputPort);
+        midiOutputPort.store(outputPort);
+    } else {
+        snprintf(buffer, sizeof(buffer), "Could not open port %d: %d", deviceId, result);
+    }
+    nativemididemo::writeMessage(buffer);
+}
+
+void Java_com_example_android_nativemididemo_NativeMidi_stopReadingMidi(
+        JNIEnv*, jobject) {
+    AMIDI_OutputPort outputPort = midiOutputPort.exchange(AMIDI_INVALID_HANDLE);
+    if (outputPort == AMIDI_INVALID_HANDLE) return;
+    int result = AMIDI_closeOutputPort(outputPort);
+    char buffer[1024];
+    if (result == 0) {
+        snprintf(buffer, sizeof(buffer), "Closed port by token %d", outputPort);
+    } else {
+        snprintf(buffer, sizeof(buffer), "Could not close port by token %d: %d", outputPort, result);
+    }
+    nativemididemo::writeMessage(buffer);
+}
diff --git a/media/tests/NativeMidiDemo/res/layout/main.xml b/media/tests/NativeMidiDemo/res/layout/main.xml
new file mode 100644
index 0000000..465d471
--- /dev/null
+++ b/media/tests/NativeMidiDemo/res/layout/main.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    >
+  <LinearLayout
+      android:orientation="horizontal"
+      android:layout_width="match_parent"
+      android:layout_height="wrap_content"
+      >
+    <TextView
+        android:id="@+id/callback_status"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textSize="13sp"
+        android:typeface="monospace"
+        />
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textSize="13sp"
+        android:typeface="monospace"
+        android:text=" | "
+        />
+    <TextView
+        android:id="@+id/java_midi_status"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textSize="13sp"
+        android:typeface="monospace"
+        />
+    <TextView
+        android:layout_width="0px"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:textSize="13sp"
+        android:typeface="monospace"
+        android:text=" "
+        />
+  </LinearLayout>
+  <HorizontalScrollView
+      android:layout_width="fill_parent"
+      android:layout_height="wrap_content"
+      android:paddingTop="6sp"
+      android:paddingBottom="6sp"
+      >
+    <RadioGroup
+        android:id="@+id/devices"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal"
+        android:checkedButton="@+id/device_none"
+        >
+      <RadioButton
+          android:id="@+id/device_none"
+          android:text="None" 
+          />
+    </RadioGroup>
+  </HorizontalScrollView>
+  <com.example.android.nativemididemo.TouchableScrollView android:id="@+id/messages_scroll"
+              android:layout_width="match_parent"
+              android:layout_height="0px"
+              android:layout_weight="1"
+              >
+    <TextView android:id="@+id/messages"
+              android:layout_width="match_parent"
+              android:layout_height="wrap_content"
+              android:textSize="13sp"
+              android:typeface="monospace"
+              />
+  </com.example.android.nativemididemo.TouchableScrollView>
+  <LinearLayout
+      android:orientation="horizontal"
+      android:layout_width="match_parent"
+      android:layout_height="wrap_content"
+      >
+    <Button android:id="@+id/clear_messages"
+          android:layout_width="0px"
+          android:layout_height="wrap_content"
+          android:layout_weight="1"
+          android:text="@string/clear_messages"
+          android:onClick="onClearMessages"
+          />
+    <Button android:id="@+id/close_port"
+          android:layout_width="0px"
+          android:layout_height="wrap_content"
+          android:layout_weight="1"
+          android:text="@string/close_port"
+          android:onClick="onClosePort"
+          />
+  </LinearLayout>
+</LinearLayout>
diff --git a/core/res/res/drawable-hdpi/sym_def_app_icon.png b/media/tests/NativeMidiDemo/res/mipmap-hdpi/ic_launcher.png
similarity index 100%
rename from core/res/res/drawable-hdpi/sym_def_app_icon.png
rename to media/tests/NativeMidiDemo/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sym_def_app_icon.png b/media/tests/NativeMidiDemo/res/mipmap-mdpi/ic_launcher.png
similarity index 100%
rename from core/res/res/drawable-mdpi/sym_def_app_icon.png
rename to media/tests/NativeMidiDemo/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/sym_def_app_icon.png b/media/tests/NativeMidiDemo/res/mipmap-xhdpi/ic_launcher.png
similarity index 100%
rename from core/res/res/drawable-xhdpi/sym_def_app_icon.png
rename to media/tests/NativeMidiDemo/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/sym_def_app_icon.png b/media/tests/NativeMidiDemo/res/mipmap-xxhdpi/ic_launcher.png
similarity index 100%
rename from core/res/res/drawable-xxhdpi/sym_def_app_icon.png
rename to media/tests/NativeMidiDemo/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/media/tests/NativeMidiDemo/res/values/strings.xml b/media/tests/NativeMidiDemo/res/values/strings.xml
new file mode 100644
index 0000000..5b69b52
--- /dev/null
+++ b/media/tests/NativeMidiDemo/res/values/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+  <string name="app_name">NativeMidiDemo</string>
+  <string name="clear_messages">Clear Messages</string>
+  <string name="close_port">Close Port</string>
+</resources>
diff --git a/native/android/Android.mk b/native/android/Android.mk
index 69544f5..6e15331 100644
--- a/native/android/Android.mk
+++ b/native/android/Android.mk
@@ -11,16 +11,15 @@
     asset_manager.cpp \
     choreographer.cpp \
     configuration.cpp \
-    hardware_buffer.cpp \
     hardware_buffer_jni.cpp \
     input.cpp \
     looper.cpp \
     native_activity.cpp \
-    native_window.cpp \
     native_window_jni.cpp \
     net.c \
     obb.cpp \
     sensor.cpp \
+    sharedmem.cpp \
     storage_manager.cpp \
     trace.cpp \
 
@@ -33,12 +32,16 @@
     libbinder \
     libui \
     libgui \
+    libsensor \
     libandroid_runtime \
     libnetd_client \
 
 LOCAL_STATIC_LIBRARIES := \
     libstorage \
-    libarect
+    libarect \
+
+LOCAL_WHOLE_STATIC_LIBRARIES := \
+    libnativewindow
 
 LOCAL_C_INCLUDES += \
     frameworks/base/native/include \
@@ -46,7 +49,9 @@
     bionic/libc/dns/include \
     system/netd/include \
 
-LOCAL_EXPORT_STATIC_LIBRARY_HEADERS := libarect
+LOCAL_EXPORT_STATIC_LIBRARY_HEADERS := \
+    libarect \
+    libnativewindow \
 
 LOCAL_MODULE := libandroid
 
diff --git a/native/android/hardware_buffer.cpp b/native/android/hardware_buffer.cpp
deleted file mode 100644
index 77ebd52..0000000
--- a/native/android/hardware_buffer.cpp
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * 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.
- */
-
-#define LOG_TAG "AHardwareBuffer"
-
-#include <android/hardware_buffer.h>
-
-#include <errno.h>
-#include <sys/socket.h>
-
-#include <memory>
-
-#include <cutils/native_handle.h>
-
-#include <utils/Log.h>
-
-#include <ui/GraphicBuffer.h>
-
-#include <binder/IServiceManager.h>
-#include <gui/ISurfaceComposer.h>
-#include <gui/IGraphicBufferAlloc.h>
-
-#include <android_runtime/android_hardware_HardwareBuffer.h>
-
-
-static constexpr int kDataBufferSize = 64 * sizeof(int);  // 64 ints
-
-using namespace android;
-
-static inline const GraphicBuffer* AHardwareBuffer_to_GraphicBuffer(
-        const AHardwareBuffer* buffer) {
-    return reinterpret_cast<const GraphicBuffer*>(buffer);
-}
-
-static inline GraphicBuffer* AHardwareBuffer_to_GraphicBuffer(
-        AHardwareBuffer* buffer) {
-    return reinterpret_cast<GraphicBuffer*>(buffer);
-}
-
-static inline AHardwareBuffer* GraphicBuffer_to_AHardwareBuffer(
-        GraphicBuffer* buffer) {
-    return reinterpret_cast<AHardwareBuffer*>(buffer);
-}
-
-// ----------------------------------------------------------------------------
-// Public functions
-// ----------------------------------------------------------------------------
-
-int AHardwareBuffer_allocate(const AHardwareBuffer_Desc* desc,
-        AHardwareBuffer** outBuffer) {
-    if (!outBuffer || !desc) return BAD_VALUE;
-
-    // The holder is used to destroy the buffer if an error occurs.
-    sp<IServiceManager> sm = defaultServiceManager();
-    if (sm == nullptr) {
-        ALOGE("Unable to connect to ServiceManager");
-        return PERMISSION_DENIED;
-    }
-
-    // Get the SurfaceFlingerService.
-    sp<ISurfaceComposer> composer = interface_cast<ISurfaceComposer>(
-            sm->getService(String16("SurfaceFlinger")));
-    if (composer == nullptr) {
-        ALOGE("Unable to connect to surface composer");
-        return PERMISSION_DENIED;
-    }
-    // Get an IGraphicBufferAlloc to create the buffer.
-    sp<IGraphicBufferAlloc> allocator = composer->createGraphicBufferAlloc();
-    if (allocator == nullptr) {
-        ALOGE("Unable to obtain a buffer allocator");
-        return PERMISSION_DENIED;
-    }
-
-    int format = android_hardware_HardwareBuffer_convertToPixelFormat(
-            desc->format);
-    if (format == 0) {
-        ALOGE("Invalid pixel format");
-        return BAD_VALUE;
-    }
-
-    if (desc->format == AHARDWAREBUFFER_FORMAT_BLOB && desc->height != 1) {
-        ALOGE("Height must be 1 when using the AHARDWAREBUFFER_FORMAT_BLOB "
-                "format");
-        return BAD_VALUE;
-    }
-
-    status_t err;
-    uint64_t producerUsage = 0;
-    uint64_t consumerUsage = 0;
-    android_hardware_HardwareBuffer_convertToGrallocUsageBits(desc->usage0,
-            desc->usage1, &producerUsage, &consumerUsage);
-    sp<GraphicBuffer> gbuffer = allocator->createGraphicBuffer(desc->width,
-            desc->height, format, desc->layers, producerUsage, consumerUsage,
-            std::string("AHardwareBuffer pid [") + std::to_string(getpid()) +
-            "]", &err);
-    if (err != NO_ERROR) {
-        return err;
-    }
-
-    *outBuffer = GraphicBuffer_to_AHardwareBuffer(gbuffer.get());
-    // Ensure the buffer doesn't get destroyed with the sp<> goes away.
-    AHardwareBuffer_acquire(*outBuffer);
-    return NO_ERROR;
-}
-
-void AHardwareBuffer_acquire(AHardwareBuffer* buffer) {
-    AHardwareBuffer_to_GraphicBuffer(buffer)->incStrong(
-            (void*)AHardwareBuffer_acquire);
-}
-
-void AHardwareBuffer_release(AHardwareBuffer* buffer) {
-    AHardwareBuffer_to_GraphicBuffer(buffer)->decStrong(
-            (void*)AHardwareBuffer_acquire);
-}
-
-void AHardwareBuffer_describe(const AHardwareBuffer* buffer,
-        AHardwareBuffer_Desc* outDesc) {
-    if (!buffer || !outDesc) return;
-
-    const GraphicBuffer* gbuffer = AHardwareBuffer_to_GraphicBuffer(buffer);
-
-    outDesc->width = gbuffer->getWidth();
-    outDesc->height = gbuffer->getHeight();
-    outDesc->layers = gbuffer->getLayerCount();
-    outDesc->usage0 =
-            android_hardware_HardwareBuffer_convertFromGrallocUsageBits(
-                    gbuffer->getUsage(), gbuffer->getUsage());
-    outDesc->usage1 = 0;
-    outDesc->format = android_hardware_HardwareBuffer_convertFromPixelFormat(
-            static_cast<uint32_t>(gbuffer->getPixelFormat()));
-}
-
-int AHardwareBuffer_lock(AHardwareBuffer* buffer, uint64_t usage0,
-        int32_t fence, const ARect* rect, void** outVirtualAddress) {
-    if (!buffer) return BAD_VALUE;
-
-    if (usage0 & ~(AHARDWAREBUFFER_USAGE0_CPU_READ_OFTEN |
-            AHARDWAREBUFFER_USAGE0_CPU_WRITE_OFTEN)) {
-        ALOGE("Invalid usage flags passed to AHardwareBuffer_lock; only "
-                " AHARDWAREBUFFER_USAGE0_CPU_* flags are allowed");
-        return BAD_VALUE;
-    }
-
-    uint64_t producerUsage = 0;
-    uint64_t consumerUsage = 0;
-    android_hardware_HardwareBuffer_convertToGrallocUsageBits(usage0, 0,
-            &producerUsage, &consumerUsage);
-    GraphicBuffer* gBuffer = AHardwareBuffer_to_GraphicBuffer(buffer);
-    Rect bounds;
-    if (!rect) {
-        bounds.set(Rect(gBuffer->getWidth(), gBuffer->getHeight()));
-    } else {
-        bounds.set(Rect(rect->left, rect->top, rect->right, rect->bottom));
-    }
-    return gBuffer->lockAsync(producerUsage, consumerUsage, bounds,
-            outVirtualAddress, fence);
-}
-
-int AHardwareBuffer_unlock(AHardwareBuffer* buffer, int32_t* fence) {
-    if (!buffer) return BAD_VALUE;
-
-    GraphicBuffer* gBuffer = AHardwareBuffer_to_GraphicBuffer(buffer);
-    return gBuffer->unlockAsync(fence);
-}
-
-int AHardwareBuffer_sendHandleToUnixSocket(const AHardwareBuffer* buffer,
-        int socketFd) {
-    if (!buffer) return BAD_VALUE;
-    const GraphicBuffer* gBuffer = AHardwareBuffer_to_GraphicBuffer(buffer);
-
-    size_t flattenedSize = gBuffer->getFlattenedSize();
-    size_t fdCount = gBuffer->getFdCount();
-
-    std::unique_ptr<uint8_t[]> data(new uint8_t[flattenedSize]);
-    std::unique_ptr<int[]> fds(new int[fdCount]);
-
-    // Make copies of needed items since flatten modifies them, and we don't
-    // want to send anything if there's an error during flatten.
-    size_t flattenedSizeCopy = flattenedSize;
-    size_t fdCountCopy = fdCount;
-    void* dataStart = data.get();
-    int* fdsStart = fds.get();
-    status_t err = gBuffer->flatten(dataStart, flattenedSizeCopy, fdsStart,
-                fdCountCopy);
-    if (err != NO_ERROR) {
-        return err;
-    }
-
-    struct iovec iov[1];
-    iov[0].iov_base = data.get();
-    iov[0].iov_len = flattenedSize;
-
-    char buf[CMSG_SPACE(kDataBufferSize)];
-    struct msghdr msg = {
-        .msg_control = buf,
-        .msg_controllen = sizeof(buf),
-        .msg_iov = &iov[0],
-        .msg_iovlen = 1,
-    };
-
-    struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
-    cmsg->cmsg_level = SOL_SOCKET;
-    cmsg->cmsg_type = SCM_RIGHTS;
-    cmsg->cmsg_len = CMSG_LEN(sizeof(int) * fdCount);
-    int* fdData = reinterpret_cast<int*>(CMSG_DATA(cmsg));
-    memcpy(fdData, fds.get(), sizeof(int) * fdCount);
-    msg.msg_controllen = cmsg->cmsg_len;
-
-    int result = sendmsg(socketFd, &msg, 0);
-    if (result <= 0) {
-        ALOGE("Error writing AHardwareBuffer to socket: error %#x (%s)",
-                result, strerror(errno));
-        return result;
-    }
-    return NO_ERROR;
-}
-
-int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd,
-        AHardwareBuffer** outBuffer) {
-    if (!outBuffer) return BAD_VALUE;
-
-    char dataBuf[CMSG_SPACE(kDataBufferSize)];
-    char fdBuf[CMSG_SPACE(kDataBufferSize)];
-    struct iovec iov[1];
-    iov[0].iov_base = dataBuf;
-    iov[0].iov_len = sizeof(dataBuf);
-
-    struct msghdr msg = {
-        .msg_control = fdBuf,
-        .msg_controllen = sizeof(fdBuf),
-        .msg_iov = &iov[0],
-        .msg_iovlen = 1,
-    };
-
-    int result = recvmsg(socketFd, &msg, 0);
-    if (result <= 0) {
-        ALOGE("Error reading AHardwareBuffer from socket: error %#x (%s)",
-                result, strerror(errno));
-        return result;
-    }
-
-    if (msg.msg_iovlen != 1) {
-        ALOGE("Error reading AHardwareBuffer from socket: bad data length");
-        return INVALID_OPERATION;
-    }
-
-    if (msg.msg_controllen % sizeof(int) != 0) {
-        ALOGE("Error reading AHardwareBuffer from socket: bad fd length");
-        return INVALID_OPERATION;
-    }
-
-    size_t dataLen = msg.msg_iov[0].iov_len;
-    const void* data = static_cast<const void*>(msg.msg_iov[0].iov_base);
-    if (!data) {
-        ALOGE("Error reading AHardwareBuffer from socket: no buffer data");
-        return INVALID_OPERATION;
-    }
-
-    struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
-    if (!cmsg) {
-        ALOGE("Error reading AHardwareBuffer from socket: no fd header");
-        return INVALID_OPERATION;
-    }
-
-    size_t fdCount = msg.msg_controllen >> 2;
-    const int* fdData = reinterpret_cast<const int*>(CMSG_DATA(cmsg));
-    if (!fdData) {
-        ALOGE("Error reading AHardwareBuffer from socket: no fd data");
-        return INVALID_OPERATION;
-    }
-
-    GraphicBuffer* gBuffer = new GraphicBuffer();
-    status_t err = gBuffer->unflatten(data, dataLen, fdData, fdCount);
-    if (err != NO_ERROR) {
-        return err;
-    }
-    *outBuffer = GraphicBuffer_to_AHardwareBuffer(gBuffer);
-    // Ensure the buffer has a positive ref-count.
-    AHardwareBuffer_acquire(*outBuffer);
-
-    return NO_ERROR;
-}
-
-const struct native_handle* AHardwareBuffer_getNativeHandle(
-        const AHardwareBuffer* buffer) {
-    if (!buffer) return nullptr;
-    const GraphicBuffer* gbuffer = AHardwareBuffer_to_GraphicBuffer(buffer);
-    return gbuffer->handle;
-}
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index f9e8fda..c7bed9b 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -169,15 +169,22 @@
     ASensorEventQueue_enableSensor;
     ASensorEventQueue_getEvents;
     ASensorEventQueue_hasEvents;
+    ASensorEventQueue_registerSensor; # introduced=26
     ASensorEventQueue_setEventRate;
+    ASensorManager_configureDirectReport; # introduced=26
     ASensorManager_createEventQueue;
+    ASensorManager_createHardwareBufferDirectChannel; # introduced=26
+    ASensorManager_createSharedMemoryDirectChannel; # introduced=26
+    ASensorManager_destroyDirectChannel; # introduced=26
     ASensorManager_destroyEventQueue;
     ASensorManager_getDefaultSensor;
     ASensorManager_getDefaultSensorEx; # introduced=21
     ASensorManager_getInstance;
+    ASensorManager_getInstanceForPackage; # introduced=26
     ASensorManager_getSensorList;
     ASensor_getFifoMaxEventCount; # introduced=21
     ASensor_getFifoReservedEventCount; # introduced=21
+    ASensor_getHighestDirectReportRateLevel; # introduced=26
     ASensor_getMinDelay;
     ASensor_getName;
     ASensor_getReportingMode; # introduced=21
@@ -185,7 +192,11 @@
     ASensor_getStringType; # introduced=21
     ASensor_getType;
     ASensor_getVendor;
+    ASensor_isDirectChannelTypeSupported; # introduced=26
     ASensor_isWakeUpSensor; # introduced=21
+    ASharedMemory_create; # introduced=26
+    ASharedMemory_getSize; # introduced=26
+    ASharedMemory_setProt; # introduced=26
     AStorageManager_delete;
     AStorageManager_getMountedObbPath;
     AStorageManager_isObbMounted;
diff --git a/native/android/native_window.cpp b/native/android/native_window.cpp
deleted file mode 100644
index 8c080d7..0000000
--- a/native/android/native_window.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "Surface"
-
-#include <android/native_window.h>
-#include <system/window.h>
-
-void ANativeWindow_acquire(ANativeWindow* window) {
-    window->incStrong((void*)ANativeWindow_acquire);
-}
-
-void ANativeWindow_release(ANativeWindow* window) {
-    window->decStrong((void*)ANativeWindow_acquire);
-}
-
-static int32_t getWindowProp(ANativeWindow* window, int what) {
-    int value;
-    int res = window->query(window, what, &value);
-    return res < 0 ? res : value;
-}
-
-int32_t ANativeWindow_getWidth(ANativeWindow* window) {
-    return getWindowProp(window, NATIVE_WINDOW_WIDTH);
-}
-
-int32_t ANativeWindow_getHeight(ANativeWindow* window) {
-    return getWindowProp(window, NATIVE_WINDOW_HEIGHT);
-}
-
-int32_t ANativeWindow_getFormat(ANativeWindow* window) {
-    return getWindowProp(window, NATIVE_WINDOW_FORMAT);
-}
-
-int32_t ANativeWindow_setBuffersGeometry(ANativeWindow* window, int32_t width,
-        int32_t height, int32_t format) {
-    int32_t err = native_window_set_buffers_format(window, format);
-    if (!err) {
-        err = native_window_set_buffers_user_dimensions(window, width, height);
-        if (!err) {
-            int mode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
-            if (width && height) {
-                mode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW;
-            }
-            err = native_window_set_scaling_mode(window, mode);
-         }
-    }
-    return err;
-}
-
-int32_t ANativeWindow_lock(ANativeWindow* window, ANativeWindow_Buffer* outBuffer,
-        ARect* inOutDirtyBounds) {
-    return window->perform(window, NATIVE_WINDOW_LOCK, outBuffer, inOutDirtyBounds);
-}
-
-int32_t ANativeWindow_unlockAndPost(ANativeWindow* window) {
-    return window->perform(window, NATIVE_WINDOW_UNLOCK_AND_POST);
-}
diff --git a/native/android/sensor.cpp b/native/android/sensor.cpp
index 5cfe300..ae16949 100644
--- a/native/android/sensor.cpp
+++ b/native/android/sensor.cpp
@@ -17,17 +17,18 @@
 #define LOG_TAG "sensor"
 #include <utils/Log.h>
 
+#include <android/hardware_buffer.h>
 #include <android/looper.h>
 #include <android/sensor.h>
-
-#include <utils/RefBase.h>
+#include <android/sharedmem.h>
+#include <cutils/native_handle.h>
+#include <sensor/Sensor.h>
+#include <sensor/SensorManager.h>
+#include <sensor/SensorEventQueue.h>
 #include <utils/Looper.h>
+#include <utils/RefBase.h>
 #include <utils/Timers.h>
 
-#include <gui/Sensor.h>
-#include <gui/SensorManager.h>
-#include <gui/SensorEventQueue.h>
-
 #include <poll.h>
 
 using android::sp;
@@ -38,13 +39,33 @@
 using android::String16;
 
 /*****************************************************************************/
-ASensorManager* ASensorManager_getInstance()
-{
-    return ASensorManager_getInstanceForPackage(NULL);
+#define ERROR_INVALID_PARAMETER(message) ALOGE("%s: " message, __func__)
+
+// frequently used checks
+#define RETURN_IF_MANAGER_IS_NULL(retval) do {\
+        if (manager == nullptr) { \
+            ERROR_INVALID_PARAMETER("manager cannot be NULL"); \
+            return retval; \
+        } \
+    } while (false)
+#define RETURN_IF_SENSOR_IS_NULL(retval) do {\
+        if (sensor == nullptr) { \
+            ERROR_INVALID_PARAMETER("sensor cannot be NULL"); \
+            return retval; \
+        } \
+    } while (false)
+#define RETURN_IF_QUEUE_IS_NULL(retval) do {\
+        if (queue == nullptr) { \
+            ERROR_INVALID_PARAMETER("queue cannot be NULL"); \
+            return retval; \
+        } \
+    } while (false)
+
+ASensorManager* ASensorManager_getInstance() {
+    return ASensorManager_getInstanceForPackage(nullptr);
 }
 
-ASensorManager* ASensorManager_getInstanceForPackage(const char* packageName)
-{
+ASensorManager* ASensorManager_getInstanceForPackage(const char* packageName) {
     if (packageName) {
         return &SensorManager::getInstanceForPackage(String16(packageName));
     } else {
@@ -52,9 +73,8 @@
     }
 }
 
-int ASensorManager_getSensorList(ASensorManager* manager,
-        ASensorList* list)
-{
+int ASensorManager_getSensorList(ASensorManager* manager, ASensorList* list) {
+    RETURN_IF_MANAGER_IS_NULL(android::BAD_VALUE);
     Sensor const* const* l;
     int c = static_cast<SensorManager*>(manager)->getSensorList(&l);
     if (list) {
@@ -63,13 +83,13 @@
     return c;
 }
 
-ASensor const* ASensorManager_getDefaultSensor(ASensorManager* manager, int type)
-{
+ASensor const* ASensorManager_getDefaultSensor(ASensorManager* manager, int type) {
+    RETURN_IF_MANAGER_IS_NULL(nullptr);
     return static_cast<SensorManager*>(manager)->getDefaultSensor(type);
 }
 
-ASensor const* ASensorManager_getDefaultSensorEx(ASensorManager* manager,
-        int type, bool wakeUp) {
+ASensor const* ASensorManager_getDefaultSensorEx(ASensorManager* manager, int type, bool wakeUp) {
+    RETURN_IF_MANAGER_IS_NULL(nullptr);
     Sensor const* const* sensorList;
     size_t size = static_cast<SensorManager*>(manager)->getSensorList(&sensorList);
     for (size_t i = 0; i < size; ++i) {
@@ -78,12 +98,18 @@
             return reinterpret_cast<ASensor const *>(sensorList[i]);
        }
     }
-    return NULL;
+    return nullptr;
 }
 
 ASensorEventQueue* ASensorManager_createEventQueue(ASensorManager* manager,
-        ALooper* looper, int ident, ALooper_callbackFunc callback, void* data)
-{
+        ALooper* looper, int ident, ALooper_callbackFunc callback, void* data) {
+    RETURN_IF_MANAGER_IS_NULL(nullptr);
+
+    if (looper == nullptr) {
+        ERROR_INVALID_PARAMETER("looper cannot be NULL");
+        return nullptr;
+    }
+
     sp<SensorEventQueue> queue =
             static_cast<SensorManager*>(manager)->createEventQueue();
     if (queue != 0) {
@@ -94,46 +120,137 @@
     return static_cast<ASensorEventQueue*>(queue.get());
 }
 
-int ASensorManager_destroyEventQueue(ASensorManager* manager,
-        ASensorEventQueue* inQueue)
-{
-    sp<SensorEventQueue> queue = static_cast<SensorEventQueue*>(inQueue);
-    ALooper_removeFd(queue->looper, queue->getFd());
-    queue->decStrong(manager);
+int ASensorManager_destroyEventQueue(ASensorManager* manager, ASensorEventQueue* queue) {
+    RETURN_IF_MANAGER_IS_NULL(android::BAD_VALUE);
+    RETURN_IF_QUEUE_IS_NULL(android::BAD_VALUE);
+
+    sp<SensorEventQueue> q = static_cast<SensorEventQueue*>(queue);
+    ALooper_removeFd(q->looper, q->getFd());
+    q->decStrong(manager);
     return 0;
 }
 
+int ASensorManager_createSharedMemoryDirectChannel(ASensorManager *manager, int fd, size_t size) {
+    RETURN_IF_MANAGER_IS_NULL(android::BAD_VALUE);
+
+    if (fd < 0) {
+        ERROR_INVALID_PARAMETER("fd is invalid.");
+        return android::BAD_VALUE;
+    }
+
+    if (size < sizeof(ASensorEvent)) {
+        ERROR_INVALID_PARAMETER("size has to be greater or equal to sizeof(ASensorEvent).");
+        return android::BAD_VALUE;
+    }
+
+    native_handle_t *resourceHandle = native_handle_create(1 /* nFd */, 0 /* nInt */);
+    if (!resourceHandle) {
+        return android::NO_MEMORY;
+    }
+
+    resourceHandle->data[0] = fd;
+    int ret = static_cast<SensorManager *>(manager)->createDirectChannel(
+            size, ASENSOR_DIRECT_CHANNEL_TYPE_SHARED_MEMORY, resourceHandle);
+    native_handle_delete(resourceHandle);
+    return ret;
+}
+
+int ASensorManager_createHardwareBufferDirectChannel(
+        ASensorManager *manager, AHardwareBuffer const *buffer, size_t size) {
+    RETURN_IF_MANAGER_IS_NULL(android::BAD_VALUE);
+
+    if (buffer == nullptr) {
+        ERROR_INVALID_PARAMETER("buffer cannot be NULL");
+        return android::BAD_VALUE;
+    }
+
+    if (size < sizeof(ASensorEvent)) {
+        ERROR_INVALID_PARAMETER("size has to be greater or equal to sizeof(ASensorEvent).");
+        return android::BAD_VALUE;
+    }
+
+    const native_handle_t *resourceHandle = AHardwareBuffer_getNativeHandle(buffer);
+    if (!resourceHandle) {
+        return android::NO_MEMORY;
+    }
+
+    return static_cast<SensorManager *>(manager)->createDirectChannel(
+            size, ASENSOR_DIRECT_CHANNEL_TYPE_HARDWARE_BUFFER, resourceHandle);
+}
+
+void ASensorManager_destroyDirectChannel(ASensorManager *manager, int channelId) {
+    RETURN_IF_MANAGER_IS_NULL(void());
+
+    static_cast<SensorManager *>(manager)->destroyDirectChannel(channelId);
+}
+
+int ASensorManager_configureDirectReport(
+        ASensorManager *manager, ASensor const *sensor, int channelId, int rate) {
+    RETURN_IF_MANAGER_IS_NULL(android::BAD_VALUE);
+
+    int sensorHandle;
+    if (sensor == nullptr) {
+        if (rate != ASENSOR_DIRECT_RATE_STOP) {
+            ERROR_INVALID_PARAMETER(
+                "sensor cannot be null when rate is not ASENSOR_DIRECT_RATE_STOP");
+            return android::BAD_VALUE;
+        }
+        sensorHandle = -1;
+    } else {
+        sensorHandle = static_cast<Sensor const *>(sensor)->getHandle();
+    }
+    return static_cast<SensorManager *>(manager)->configureDirectChannel(
+            channelId, sensorHandle, rate);
+}
+
 /*****************************************************************************/
 
 int ASensorEventQueue_registerSensor(ASensorEventQueue* queue, ASensor const* sensor,
-        int32_t samplingPeriodUs, int maxBatchReportLatencyUs)
-{
+        int32_t samplingPeriodUs, int64_t maxBatchReportLatencyUs) {
+    RETURN_IF_QUEUE_IS_NULL(android::BAD_VALUE);
+    RETURN_IF_SENSOR_IS_NULL(android::BAD_VALUE);
+    if (samplingPeriodUs < 0 || maxBatchReportLatencyUs < 0) {
+        ERROR_INVALID_PARAMETER("samplingPeriodUs and maxBatchReportLatencyUs cannot be negative");
+        return android::BAD_VALUE;
+    }
+
     return static_cast<SensorEventQueue*>(queue)->enableSensor(
             static_cast<Sensor const*>(sensor)->getHandle(), samplingPeriodUs,
                     maxBatchReportLatencyUs, 0);
 }
 
-int ASensorEventQueue_enableSensor(ASensorEventQueue* queue, ASensor const* sensor)
-{
+int ASensorEventQueue_enableSensor(ASensorEventQueue* queue, ASensor const* sensor) {
+    RETURN_IF_QUEUE_IS_NULL(android::BAD_VALUE);
+    RETURN_IF_SENSOR_IS_NULL(android::BAD_VALUE);
+
     return static_cast<SensorEventQueue*>(queue)->enableSensor(
             static_cast<Sensor const*>(sensor));
 }
 
-int ASensorEventQueue_disableSensor(ASensorEventQueue* queue, ASensor const* sensor)
-{
+int ASensorEventQueue_disableSensor(ASensorEventQueue* queue, ASensor const* sensor) {
+    RETURN_IF_QUEUE_IS_NULL(android::BAD_VALUE);
+    RETURN_IF_SENSOR_IS_NULL(android::BAD_VALUE);
+
     return static_cast<SensorEventQueue*>(queue)->disableSensor(
             static_cast<Sensor const*>(sensor));
 }
 
-int ASensorEventQueue_setEventRate(ASensorEventQueue* queue, ASensor const* sensor,
-        int32_t usec)
-{
+int ASensorEventQueue_setEventRate(ASensorEventQueue* queue, ASensor const* sensor, int32_t usec) {
+    RETURN_IF_QUEUE_IS_NULL(android::BAD_VALUE);
+    RETURN_IF_SENSOR_IS_NULL(android::BAD_VALUE);
+
+    if (usec < 0) {
+        ERROR_INVALID_PARAMETER("usec cannot be negative");
+        return android::BAD_VALUE;
+    }
+
     return static_cast<SensorEventQueue*>(queue)->setEventRate(
             static_cast<Sensor const*>(sensor), us2ns(usec));
 }
 
-int ASensorEventQueue_hasEvents(ASensorEventQueue* queue)
-{
+int ASensorEventQueue_hasEvents(ASensorEventQueue* queue) {
+    RETURN_IF_QUEUE_IS_NULL(android::BAD_VALUE);
+
     struct pollfd pfd;
     pfd.fd = static_cast<SensorEventQueue*>(queue)->getFd();
     pfd.events = POLLIN;
@@ -150,9 +267,13 @@
     return (nfd == 0) ? 0 : 1;
 }
 
-ssize_t ASensorEventQueue_getEvents(ASensorEventQueue* queue,
-                ASensorEvent* events, size_t count)
-{
+ssize_t ASensorEventQueue_getEvents(ASensorEventQueue* queue, ASensorEvent* events, size_t count) {
+    RETURN_IF_QUEUE_IS_NULL(android::BAD_VALUE);
+    if (events == nullptr) {
+        ERROR_INVALID_PARAMETER("events cannot be NULL");
+        return android::BAD_VALUE;
+    }
+
     ssize_t actual = static_cast<SensorEventQueue*>(queue)->read(events, count);
     if (actual > 0) {
         static_cast<SensorEventQueue*>(queue)->sendAck(events, actual);
@@ -162,52 +283,62 @@
 
 /*****************************************************************************/
 
-const char* ASensor_getName(ASensor const* sensor)
-{
+const char* ASensor_getName(ASensor const* sensor) {
+    RETURN_IF_SENSOR_IS_NULL(nullptr);
     return static_cast<Sensor const*>(sensor)->getName().string();
 }
 
-const char* ASensor_getVendor(ASensor const* sensor)
-{
+const char* ASensor_getVendor(ASensor const* sensor) {
+    RETURN_IF_SENSOR_IS_NULL(nullptr);
     return static_cast<Sensor const*>(sensor)->getVendor().string();
 }
 
-int ASensor_getType(ASensor const* sensor)
-{
+int ASensor_getType(ASensor const* sensor) {
+    RETURN_IF_SENSOR_IS_NULL(ASENSOR_TYPE_INVALID);
     return static_cast<Sensor const*>(sensor)->getType();
 }
 
-float ASensor_getResolution(ASensor const* sensor)
-{
+float ASensor_getResolution(ASensor const* sensor) {
+    RETURN_IF_SENSOR_IS_NULL(ASENSOR_RESOLUTION_INVALID);
     return static_cast<Sensor const*>(sensor)->getResolution();
 }
 
-int ASensor_getMinDelay(ASensor const* sensor)
-{
+int ASensor_getMinDelay(ASensor const* sensor) {
+    RETURN_IF_SENSOR_IS_NULL(ASENSOR_DELAY_INVALID);
     return static_cast<Sensor const*>(sensor)->getMinDelay();
 }
 
-int ASensor_getFifoMaxEventCount(ASensor const* sensor)
-{
+int ASensor_getFifoMaxEventCount(ASensor const* sensor) {
+    RETURN_IF_SENSOR_IS_NULL(ASENSOR_FIFO_COUNT_INVALID);
     return static_cast<Sensor const*>(sensor)->getFifoMaxEventCount();
 }
 
-int ASensor_getFifoReservedEventCount(ASensor const* sensor)
-{
+int ASensor_getFifoReservedEventCount(ASensor const* sensor) {
+    RETURN_IF_SENSOR_IS_NULL(ASENSOR_FIFO_COUNT_INVALID);
     return static_cast<Sensor const*>(sensor)->getFifoReservedEventCount();
 }
 
-const char* ASensor_getStringType(ASensor const* sensor)
-{
+const char* ASensor_getStringType(ASensor const* sensor) {
+    RETURN_IF_SENSOR_IS_NULL(nullptr);
     return static_cast<Sensor const*>(sensor)->getStringType().string();
 }
 
-int ASensor_getReportingMode(ASensor const* sensor)
-{
+int ASensor_getReportingMode(ASensor const* sensor) {
+    RETURN_IF_SENSOR_IS_NULL(AREPORTING_MODE_INVALID);
     return static_cast<Sensor const*>(sensor)->getReportingMode();
 }
 
-bool ASensor_isWakeUpSensor(ASensor const* sensor)
-{
+bool ASensor_isWakeUpSensor(ASensor const* sensor) {
+    RETURN_IF_SENSOR_IS_NULL(false);
     return static_cast<Sensor const*>(sensor)->isWakeUpSensor();
 }
+
+bool ASensor_isDirectChannelTypeSupported(ASensor const *sensor, int channelType) {
+    RETURN_IF_SENSOR_IS_NULL(false);
+    return static_cast<Sensor const *>(sensor)->isDirectChannelTypeSupported(channelType);
+}
+
+int ASensor_getHighestDirectReportRateLevel(ASensor const *sensor) {
+    RETURN_IF_SENSOR_IS_NULL(ASENSOR_DIRECT_RATE_STOP);
+    return static_cast<Sensor const *>(sensor)->getHighestDirectReportRateLevel();
+}
diff --git a/native/android/sharedmem.cpp b/native/android/sharedmem.cpp
new file mode 100644
index 0000000..9d029df
--- /dev/null
+++ b/native/android/sharedmem.cpp
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+#include <android/sharedmem.h>
+#include <cutils/ashmem.h>
+#include <utils/Errors.h>
+
+int ASharedMemory_create(const char *name, size_t size) {
+    if (size == 0) {
+        return android::BAD_VALUE;
+    }
+    return ashmem_create_region(name, size);
+}
+
+size_t ASharedMemory_getSize(int fd) {
+    return ashmem_valid(fd) ? ashmem_get_size_region(fd) : 0;
+}
+
+int ASharedMemory_setProt(int fd, int prot) {
+    return ashmem_set_prot_region(fd, prot);
+}
diff --git a/native/graphics/jni/bitmap.cpp b/native/graphics/jni/bitmap.cpp
index 6d2de98..bf5cabb 100644
--- a/native/graphics/jni/bitmap.cpp
+++ b/native/graphics/jni/bitmap.cpp
@@ -15,11 +15,7 @@
  */
 
 #include <android/bitmap.h>
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-parameter"
-#include <GraphicsJNI.h>
-#pragma GCC diagnostic pop
+#include <Bitmap.h>
 
 int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap,
                           AndroidBitmapInfo* info) {
@@ -27,32 +23,8 @@
         return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
     }
 
-    SkBitmap bm;
-    GraphicsJNI::getSkBitmap(env, jbitmap, &bm);
-
     if (info) {
-        info->width     = bm.width();
-        info->height    = bm.height();
-        info->stride    = bm.rowBytes();
-        info->flags     = 0;
-
-        switch (bm.colorType()) {
-            case kN32_SkColorType:
-                info->format = ANDROID_BITMAP_FORMAT_RGBA_8888;
-                break;
-            case kRGB_565_SkColorType:
-                info->format = ANDROID_BITMAP_FORMAT_RGB_565;
-                break;
-            case kARGB_4444_SkColorType:
-                info->format = ANDROID_BITMAP_FORMAT_RGBA_4444;
-                break;
-            case kAlpha_8_SkColorType:
-                info->format = ANDROID_BITMAP_FORMAT_A_8;
-                break;
-            default:
-                info->format = ANDROID_BITMAP_FORMAT_NONE;
-                break;
-        }
+        android::bitmap::imageInfo(env, jbitmap, info);
     }
     return ANDROID_BITMAP_RESULT_SUCCESS;
 }
@@ -62,19 +34,11 @@
         return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
     }
 
-    SkPixelRef* pixelRef = GraphicsJNI::refSkPixelRef(env, jbitmap);
-    if (!pixelRef) {
+    void* addr = android::bitmap::lockPixels(env, jbitmap);
+    if (!addr) {
         return ANDROID_BITMAP_RESULT_JNI_EXCEPTION;
     }
 
-    pixelRef->lockPixels();
-    void* addr = pixelRef->pixels();
-    if (NULL == addr) {
-        pixelRef->unlockPixels();
-        pixelRef->unref();
-        return ANDROID_BITMAP_RESULT_ALLOCATION_FAILED;
-    }
-
     if (addrPtr) {
         *addrPtr = addr;
     }
@@ -86,26 +50,10 @@
         return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
     }
 
-    SkPixelRef* pixelRef = GraphicsJNI::refSkPixelRef(env, jbitmap);
-    if (!pixelRef) {
+    bool unlocked = android::bitmap::unlockPixels(env, jbitmap);
+    if (!unlocked) {
         return ANDROID_BITMAP_RESULT_JNI_EXCEPTION;
     }
-
-    // notifyPixelsChanged() needs be called to apply writes to GL-backed
-    // bitmaps.  Note that this will slow down read-only accesses to the
-    // bitmaps, but the NDK methods are primarily intended to be used for
-    // writes.
-    pixelRef->notifyPixelsChanged();
-
-    pixelRef->unlockPixels();
-    // Awkward in that we need to double-unref as the call to get the SkPixelRef
-    // did a ref(), so we need to unref() for the local ref and for the previous
-    // AndroidBitmap_lockPixels(). However this keeps GraphicsJNI a bit safer
-    // if others start using it without knowing about android::Bitmap's "fun"
-    // ref counting mechanism(s).
-    pixelRef->unref();
-    pixelRef->unref();
-
     return ANDROID_BITMAP_RESULT_SUCCESS;
 }
 
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index 23a8655..6394c64 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -77,8 +77,8 @@
         mCm = ConnectivityManager.from(this);
         mNetwork = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_NETWORK);
         mCaptivePortal = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL);
-        mUserAgent = getIntent().getParcelableExtra(
-                ConnectivityManager.EXTRA_CAPTIVE_PORTAL_USER_AGENT);
+        mUserAgent =
+                getIntent().getStringExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_USER_AGENT);
         mUrl = getUrl();
         if (mUrl == null) {
             // getUrl() failed to parse the url provided in the intent: bail out in a way that
@@ -274,8 +274,17 @@
                     if (mUserAgent != null) {
                        urlConnection.setRequestProperty("User-Agent", mUserAgent);
                     }
+                    // cannot read request header after connection
+                    String requestHeader = urlConnection.getRequestProperties().toString();
+
                     urlConnection.getInputStream();
                     httpResponseCode = urlConnection.getResponseCode();
+                    if (DBG) {
+                        Log.d(TAG, "probe at " + mUrl +
+                                " ret=" + httpResponseCode +
+                                " request=" + requestHeader +
+                                " headers=" + urlConnection.getHeaderFields());
+                    }
                 } catch (IOException e) {
                 } finally {
                     if (urlConnection != null) urlConnection.disconnect();
diff --git a/packages/CarrierDefaultApp/AndroidManifest.xml b/packages/CarrierDefaultApp/AndroidManifest.xml
index e2080b0..d910920 100644
--- a/packages/CarrierDefaultApp/AndroidManifest.xml
+++ b/packages/CarrierDefaultApp/AndroidManifest.xml
@@ -31,7 +31,7 @@
     <application android:label="@string/app_name" >
         <receiver android:name="com.android.carrierdefaultapp.CarrierDefaultBroadcastReceiver">
             <intent-filter>
-                <action android:name="android.intent.action.CARRIER_SIGNAL_REDIRECTED" />
+                <action android:name="com.android.internal.telephony.CARRIER_SIGNAL_REDIRECTED" />
             </intent-filter>
         </receiver>
         <activity android:name="com.android.carrierdefaultapp.CaptivePortalLaunchActivity"
diff --git a/packages/CarrierDefaultApp/res/values-zh-rTW/strings.xml b/packages/CarrierDefaultApp/res/values-zh-rTW/strings.xml
index ad0ea6b..cbe677d 100644
--- a/packages/CarrierDefaultApp/res/values-zh-rTW/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-zh-rTW/strings.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="5247871339820894594">"行動通訊業者預設應用程式"</string>
+    <string name="app_name" msgid="5247871339820894594">"電信業者預設應用程式"</string>
     <string name="portal_notification_id" msgid="267536768510843288">"啟用服務"</string>
     <string name="no_data_notification_id" msgid="5216950045164991172">"沒有數據服務"</string>
     <string name="portal_notification_detail" msgid="2860620550281695686">"輕觸即可啟用服務"</string>
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLaunchActivity.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLaunchActivity.java
index b7fde12..28251cb 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLaunchActivity.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLaunchActivity.java
@@ -79,7 +79,7 @@
     private void showConnectingProgressDialog() {
         mProgressDialog = new ProgressDialog(getApplicationContext());
         mProgressDialog.setMessage(getString(R.string.progress_dialogue_network_connection));
-        mProgressDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+        mProgressDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
         mProgressDialog.show();
     }
 
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
index 25127ef..12bab18 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
@@ -92,7 +92,7 @@
         try {
             final PackageManager packageManager = getPackageManager();
             return packageManager.getApplicationLabel(
-                    packageManager.getApplicationInfo(getService().mCallingPackage, 0));
+                    packageManager.getApplicationInfo(getCallingPackage(), 0));
         } catch (PackageManager.NameNotFoundException e) {
             throw new RuntimeException(e);
         }
@@ -128,7 +128,7 @@
     }
 
     protected void onPairTapped(BluetoothDevice selectedDevice) {
-        getService().onDeviceSelected();
+        getService().onDeviceSelected(getCallingPackage(), selectedDevice.getAddress());
         setResult(RESULT_OK,
                 new Intent().putExtra(CompanionDeviceManager.EXTRA_DEVICE, selectedDevice));
         finish();
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
index 11c722d..f0f9108 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
@@ -33,6 +33,7 @@
 import android.bluetooth.le.ScanSettings;
 import android.companion.AssociationRequest;
 import android.companion.BluetoothLEDeviceFilter;
+import android.companion.CompanionDeviceManager;
 import android.companion.ICompanionDeviceDiscoveryService;
 import android.companion.ICompanionDeviceDiscoveryServiceCallback;
 import android.companion.IFindDeviceCallback;
@@ -71,7 +72,6 @@
     DevicesAdapter mDevicesAdapter;
     IFindDeviceCallback mFindCallback;
     ICompanionDeviceDiscoveryServiceCallback mServiceCallback;
-    String mCallingPackage;
 
     private final ICompanionDeviceDiscoveryService mBinder =
             new ICompanionDeviceDiscoveryService.Stub() {
@@ -88,7 +88,6 @@
             }
             mFindCallback = findCallback;
             mServiceCallback = serviceCallback;
-            mCallingPackage = callingPackage;
             DeviceDiscoveryService.this.startDiscovery(request);
         }
     };
@@ -174,14 +173,6 @@
         return super.onUnbind(intent);
     }
 
-    public void onDeviceSelected() {
-        try {
-            mServiceCallback.onDeviceSelected(mCallingPackage, getUserId());
-        } catch (RemoteException e) {
-            Log.e(LOG_TAG, "Error reporting selected device");
-        }
-    }
-
     private void stopScan() {
         if (DEBUG) Log.i(LOG_TAG, "stopScan() called");
         mBluetoothAdapter.cancelDiscovery();
@@ -234,6 +225,17 @@
         }
     }
 
+    void onDeviceSelected(String callingPackage, String deviceAddress) {
+        try {
+            mServiceCallback.onDeviceSelected(
+                    //TODO is this the right userId?
+                    callingPackage, getUserId(), deviceAddress);
+        } catch (RemoteException e) {
+            Log.e(LOG_TAG, "Failed to record association: "
+                    + callingPackage + " <-> " + deviceAddress);
+        }
+    }
+
     class DevicesAdapter extends ArrayAdapter<BluetoothDevice> {
         private Drawable BLUETOOTH_ICON = icon(android.R.drawable.stat_sys_data_bluetooth);
 
diff --git a/packages/ExtServices/Android.mk b/packages/ExtServices/Android.mk
index e8a4007..d0c2b9f 100644
--- a/packages/ExtServices/Android.mk
+++ b/packages/ExtServices/Android.mk
@@ -34,7 +34,8 @@
 
 include $(BUILD_PACKAGE)
 
-
-
-
+# Use the following include to make our test apk.
+ifeq ($(strip $(LOCAL_PACKAGE_OVERRIDES)),)
+include $(call all-makefiles-under, $(LOCAL_PATH))
+endif
 
diff --git a/packages/ExtServices/AndroidManifest.xml b/packages/ExtServices/AndroidManifest.xml
index f442219..f3d8983 100644
--- a/packages/ExtServices/AndroidManifest.xml
+++ b/packages/ExtServices/AndroidManifest.xml
@@ -25,6 +25,13 @@
         android:defaultToDeviceProtectedStorage="true"
         android:directBootAware="true">
 
+        <service android:name=".storage.CacheQuotaServiceImpl"
+             android:permission="android.permission.BIND_CACHE_QUOTA_SERVICE">
+            <intent-filter>
+                <action android:name="android.app.usage.CacheQuotaService" />
+            </intent-filter>
+        </service>
+
         <library android:name="android.ext.services"/>
     </application>
 
diff --git a/packages/ExtServices/src/android/ext/services/storage/CacheQuotaServiceImpl.java b/packages/ExtServices/src/android/ext/services/storage/CacheQuotaServiceImpl.java
new file mode 100644
index 0000000..18863ca
--- /dev/null
+++ b/packages/ExtServices/src/android/ext/services/storage/CacheQuotaServiceImpl.java
@@ -0,0 +1,144 @@
+
+/*
+ * 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 android.ext.services.storage;
+
+import android.app.usage.CacheQuotaHint;
+import android.app.usage.CacheQuotaService;
+import android.os.Environment;
+import android.os.storage.StorageManager;
+import android.os.storage.VolumeInfo;
+import android.util.ArrayMap;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * CacheQuotaServiceImpl implements the CacheQuotaService with a strategy for populating the quota
+ * of {@link CacheQuotaHint}.
+ */
+public class CacheQuotaServiceImpl extends CacheQuotaService {
+    private static final double CACHE_RESERVE_RATIO = 0.15;
+
+    @Override
+    public List<CacheQuotaHint> onComputeCacheQuotaHints(List<CacheQuotaHint> requests) {
+        ArrayMap<String, List<CacheQuotaHint>> byUuid = new ArrayMap<>();
+        final int requestCount = requests.size();
+        for (int i = 0; i < requestCount; i++) {
+            CacheQuotaHint request = requests.get(i);
+            String uuid = request.getVolumeUuid();
+            List<CacheQuotaHint> listForUuid = byUuid.get(uuid);
+            if (listForUuid == null) {
+                listForUuid = new ArrayList<>();
+                byUuid.put(uuid, listForUuid);
+            }
+            listForUuid.add(request);
+        }
+
+        List<CacheQuotaHint> processed = new ArrayList<>();
+        byUuid.entrySet().forEach(
+                requestListEntry -> {
+                    // Collapse all usage stats to the same uid.
+                    Map<Integer, List<CacheQuotaHint>> byUid = requestListEntry.getValue()
+                            .stream()
+                            .collect(Collectors.groupingBy(CacheQuotaHint::getUid));
+                    byUid.values().forEach(uidGroupedList -> {
+                        int size = uidGroupedList.size();
+                        if (size < 2) {
+                            return;
+                        }
+                        CacheQuotaHint first = uidGroupedList.get(0);
+                        for (int i = 1; i < size; i++) {
+                            /* Note: We can't use the UsageStats built-in addition function because
+                                     UIDs may span multiple packages and usage stats adding has
+                                     matching package names as a precondition. */
+                            first.getUsageStats().mTotalTimeInForeground +=
+                                    uidGroupedList.get(i).getUsageStats().mTotalTimeInForeground;
+                        }
+                    });
+
+                    // Because the foreground stats have been added to the first element, we need
+                    // a list of only the first values (which contain the merged foreground time).
+                    List<CacheQuotaHint> flattenedRequests =
+                            byUid.values()
+                                 .stream()
+                                 .map(entryList -> entryList.get(0))
+                                 .filter(entry -> entry.getUsageStats().mTotalTimeInForeground != 0)
+                                 .sorted(sCacheQuotaRequestComparator)
+                                 .collect(Collectors.toList());
+
+                    // Because the elements are sorted, we can use the index to also be the sorted
+                    // index for cache quota calculation.
+                    double sum = getSumOfFairShares(flattenedRequests.size());
+                    String uuid = requestListEntry.getKey();
+                    long reservedSize = getReservedCacheSize(uuid);
+                    for (int count = 0; count < flattenedRequests.size(); count++) {
+                        double share = getFairShareForPosition(count) / sum;
+                        CacheQuotaHint entry = flattenedRequests.get(count);
+                        CacheQuotaHint.Builder builder = new CacheQuotaHint.Builder(entry);
+                        builder.setQuota(Math.round(share * reservedSize));
+                        processed.add(builder.build());
+                    }
+                }
+        );
+
+        return processed.stream()
+                .filter(request -> request.getQuota() > 0).collect(Collectors.toList());
+    }
+
+    private double getFairShareForPosition(int position) {
+        double value = 1.0 / Math.log(position + 3) - 0.285;
+        return (value > 0.01) ? value : 0.01;
+    }
+
+    private double getSumOfFairShares(int size) {
+        double sum = 0;
+        for (int i = 0; i < size; i++) {
+            sum += getFairShareForPosition(i);
+        }
+        return sum;
+    }
+
+    private long getReservedCacheSize(String uuid) {
+        // TODO: Revisit the cache size after running more storage tests.
+        // TODO: Figure out how to ensure ExtServices has the permissions to call
+        //       StorageStatsManager, because this is ignoring the cache...
+        StorageManager storageManager = getSystemService(StorageManager.class);
+        long freeBytes = 0;
+        if (uuid == StorageManager.UUID_PRIVATE_INTERNAL) { // regular equals because of null
+            freeBytes = Environment.getDataDirectory().getFreeSpace();
+        } else {
+            final VolumeInfo vol = storageManager.findVolumeByUuid(uuid);
+            freeBytes = vol.getPath().getFreeSpace();
+        }
+        return Math.round(freeBytes * CACHE_RESERVE_RATIO);
+    }
+
+    // Compares based upon foreground time.
+    private static Comparator<CacheQuotaHint> sCacheQuotaRequestComparator =
+            new Comparator<CacheQuotaHint>() {
+        @Override
+        public int compare(CacheQuotaHint o, CacheQuotaHint t1) {
+            long x = t1.getUsageStats().getTotalTimeInForeground();
+            long y = o.getUsageStats().getTotalTimeInForeground();
+            return (x < y) ? -1 : ((x == y) ? 0 : 1);
+        }
+    };
+}
diff --git a/packages/ExtServices/tests/Android.mk b/packages/ExtServices/tests/Android.mk
new file mode 100644
index 0000000..cb3c352
--- /dev/null
+++ b/packages/ExtServices/tests/Android.mk
@@ -0,0 +1,24 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# We only want this apk build for tests.
+LOCAL_MODULE_TAGS := tests
+LOCAL_CERTIFICATE := platform
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android-support-test \
+    mockito-target-minus-junit4 \
+    espresso-core \
+    truth-prebuilt \
+    legacy-android-test
+
+# Include all test java files.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := ExtServicesUnitTests
+
+LOCAL_INSTRUMENTATION_FOR := ExtServices
+
+include $(BUILD_PACKAGE)
diff --git a/packages/ExtServices/tests/AndroidManifest.xml b/packages/ExtServices/tests/AndroidManifest.xml
new file mode 100644
index 0000000..e6c7b97
--- /dev/null
+++ b/packages/ExtServices/tests/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="android.ext.services.tests.unit">
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="android.ext.services"
+                     android:label="ExtServices Test Cases">
+    </instrumentation>
+
+</manifest>
\ No newline at end of file
diff --git a/packages/ExtServices/tests/src/android/ext/services/storage/CacheQuotaServiceImplTest.java b/packages/ExtServices/tests/src/android/ext/services/storage/CacheQuotaServiceImplTest.java
new file mode 100644
index 0000000..cc1699a
--- /dev/null
+++ b/packages/ExtServices/tests/src/android/ext/services/storage/CacheQuotaServiceImplTest.java
@@ -0,0 +1,150 @@
+/*
+ * 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 android.ext.services.storage;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import android.app.usage.CacheQuotaHint;
+import android.app.usage.UsageStats;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.Intent;
+import android.os.storage.StorageManager;
+import android.os.storage.VolumeInfo;
+import android.test.ServiceTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+public class CacheQuotaServiceImplTest extends ServiceTestCase<CacheQuotaServiceImpl> {
+    private static final String sTestVolUuid = "uuid";
+    private static final String sSecondTestVolUuid = "otherUuid";
+
+    @Mock private Context mContext;
+    @Mock private File mFile;
+    @Mock private VolumeInfo mVolume;
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS) private StorageManager mStorageManager;
+
+    public CacheQuotaServiceImplTest() {
+        super(CacheQuotaServiceImpl.class);
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        MockitoAnnotations.initMocks(this);
+        mContext = Mockito.spy(new ContextWrapper(getSystemContext()));
+        setContext(mContext);
+        when(mContext.getSystemService(Context.STORAGE_SERVICE)).thenReturn(mStorageManager);
+
+        when(mFile.getFreeSpace()).thenReturn(10000L);
+        when(mVolume.getPath()).thenReturn(mFile);
+        when(mStorageManager.findVolumeByUuid(sTestVolUuid)).thenReturn(mVolume);
+        when(mStorageManager.findVolumeByUuid(sSecondTestVolUuid)).thenReturn(mVolume);
+
+        Intent intent = new Intent(getContext(), CacheQuotaServiceImpl.class);
+        startService(intent);
+    }
+
+    @Test
+    public void testNoApps() {
+        CacheQuotaServiceImpl service = getService();
+        assertEquals(service.onComputeCacheQuotaHints(new ArrayList()).size(), 0);
+    }
+
+    @Test
+    public void testOneApp() throws Exception {
+        ArrayList<CacheQuotaHint> requests = new ArrayList<>();
+        CacheQuotaHint request = makeNewRequest("com.test", sTestVolUuid, 1001, 100L);
+        requests.add(request);
+
+        List<CacheQuotaHint> output = getService().onComputeCacheQuotaHints(requests);
+
+        assertThat(output).hasSize(1);
+        assertThat(output.get(0).getQuota()).isEqualTo(1500L);
+    }
+
+    @Test
+    public void testTwoAppsOneVolume() throws Exception {
+        ArrayList<CacheQuotaHint> requests = new ArrayList<>();
+        requests.add(makeNewRequest("com.test", sTestVolUuid, 1001, 100L));
+        requests.add(makeNewRequest("com.test2", sTestVolUuid, 1002, 99L));
+
+        List<CacheQuotaHint> output = getService().onComputeCacheQuotaHints(requests);
+
+        // Note that the sizes are just the cache area split up.
+        assertThat(output).hasSize(2);
+        assertThat(output.get(0).getQuota()).isEqualTo(883);
+        assertThat(output.get(1).getQuota()).isEqualTo(1500 - 883);
+    }
+
+    @Test
+    public void testTwoAppsTwoVolumes() throws Exception {
+        ArrayList<CacheQuotaHint> requests = new ArrayList<>();
+        requests.add(makeNewRequest("com.test", sTestVolUuid, 1001, 100L));
+        requests.add(makeNewRequest("com.test2", sSecondTestVolUuid, 1002, 99L));
+
+        List<CacheQuotaHint> output = getService().onComputeCacheQuotaHints(requests);
+
+        assertThat(output).hasSize(2);
+        assertThat(output.get(0).getQuota()).isEqualTo(1500);
+        assertThat(output.get(1).getQuota()).isEqualTo(1500);
+    }
+
+    @Test
+    public void testMultipleAppsPerUidIsCollated() throws Exception {
+        ArrayList<CacheQuotaHint> requests = new ArrayList<>();
+        requests.add(makeNewRequest("com.test", sTestVolUuid, 1001, 100L));
+        requests.add(makeNewRequest("com.test2", sTestVolUuid, 1001, 99L));
+
+        List<CacheQuotaHint> output = getService().onComputeCacheQuotaHints(requests);
+
+        assertThat(output).hasSize(1);
+        assertThat(output.get(0).getQuota()).isEqualTo(1500);
+    }
+
+    @Test
+    public void testTwoAppsTwoVolumesTwoUuidsShouldBESeparate() throws Exception {
+        ArrayList<CacheQuotaHint> requests = new ArrayList<>();
+        requests.add(makeNewRequest("com.test", sTestVolUuid, 1001, 100L));
+        requests.add(makeNewRequest("com.test2", sSecondTestVolUuid, 1001, 99L));
+
+        List<CacheQuotaHint> output = getService().onComputeCacheQuotaHints(requests);
+
+        assertThat(output).hasSize(2);
+        assertThat(output.get(0).getQuota()).isEqualTo(1500);
+        assertThat(output.get(1).getQuota()).isEqualTo(1500);
+    }
+
+    private CacheQuotaHint makeNewRequest(String packageName, String uuid, int uid, long foregroundTime) {
+        UsageStats stats = new UsageStats();
+        stats.mPackageName = packageName;
+        stats.mTotalTimeInForeground = foregroundTime;
+        return new CacheQuotaHint.Builder()
+                .setVolumeUuid(uuid).setUid(uid).setUsageStats(stats).setQuota(-1).build();
+    }
+}
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 22a5b7f..3cc9f65e 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -56,6 +56,7 @@
 import android.webkit.MimeTypeMap;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.content.FileSystemProvider;
 import com.android.internal.util.IndentingPrintWriter;
 
 import java.io.File;
@@ -63,15 +64,15 @@
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Objects;
 
-public class ExternalStorageProvider extends DocumentsProvider {
+public class ExternalStorageProvider extends FileSystemProvider {
     private static final String TAG = "ExternalStorage";
 
     private static final boolean DEBUG = false;
-    private static final boolean LOG_INOTIFY = false;
 
     public static final String AUTHORITY = "com.android.externalstorage.documents";
 
@@ -105,20 +106,17 @@
     private static final String ROOT_ID_HOME = "home";
 
     private StorageManager mStorageManager;
-    private Handler mHandler;
 
     private final Object mRootsLock = new Object();
 
     @GuardedBy("mRootsLock")
     private ArrayMap<String, RootInfo> mRoots = new ArrayMap<>();
 
-    @GuardedBy("mObservers")
-    private ArrayMap<File, DirectoryObserver> mObservers = new ArrayMap<>();
-
     @Override
     public boolean onCreate() {
+        super.onCreate(DEFAULT_DOCUMENT_PROJECTION);
+
         mStorageManager = (StorageManager) getContext().getSystemService(Context.STORAGE_SERVICE);
-        mHandler = new Handler();
 
         updateVolumes();
         return true;
@@ -274,11 +272,8 @@
         return projection != null ? projection : DEFAULT_ROOT_PROJECTION;
     }
 
-    private static String[] resolveDocumentProjection(String[] projection) {
-        return projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION;
-    }
-
-    private String getDocIdForFile(File file) throws FileNotFoundException {
+    @Override
+    protected String getDocIdForFile(File file) throws FileNotFoundException {
         return getDocIdForFileMaybeCreate(file, false);
     }
 
@@ -344,11 +339,8 @@
         return mostSpecificRoot;
     }
 
-    private File getFileForDocId(String docId) throws FileNotFoundException {
-        return getFileForDocId(docId, false);
-    }
-
-    private File getFileForDocId(String docId, boolean visible) throws FileNotFoundException {
+    @Override
+    protected File getFileForDocId(String docId, boolean visible) throws FileNotFoundException {
         RootInfo root = getRootFromDocId(docId);
         return buildFile(root, docId, visible);
     }
@@ -393,48 +385,9 @@
         return target;
     }
 
-    private void includeFile(MatrixCursor result, String docId, File file)
-            throws FileNotFoundException {
-        if (docId == null) {
-            docId = getDocIdForFile(file);
-        } else {
-            file = getFileForDocId(docId);
-        }
-
-        int flags = 0;
-
-        if (file.canWrite()) {
-            if (file.isDirectory()) {
-                flags |= Document.FLAG_DIR_SUPPORTS_CREATE;
-                flags |= Document.FLAG_SUPPORTS_DELETE;
-                flags |= Document.FLAG_SUPPORTS_RENAME;
-                flags |= Document.FLAG_SUPPORTS_MOVE;
-            } else {
-                flags |= Document.FLAG_SUPPORTS_WRITE;
-                flags |= Document.FLAG_SUPPORTS_DELETE;
-                flags |= Document.FLAG_SUPPORTS_RENAME;
-                flags |= Document.FLAG_SUPPORTS_MOVE;
-            }
-        }
-
-        final String mimeType = getTypeForFile(file);
-        final String displayName = file.getName();
-        if (mimeType.startsWith("image/")) {
-            flags |= Document.FLAG_SUPPORTS_THUMBNAIL;
-        }
-
-        final RowBuilder row = result.newRow();
-        row.add(Document.COLUMN_DOCUMENT_ID, docId);
-        row.add(Document.COLUMN_DISPLAY_NAME, displayName);
-        row.add(Document.COLUMN_SIZE, file.length());
-        row.add(Document.COLUMN_MIME_TYPE, mimeType);
-        row.add(Document.COLUMN_FLAGS, flags);
-
-        // Only publish dates reasonably after epoch
-        long lastModified = file.lastModified();
-        if (lastModified > 31536000000L) {
-            row.add(Document.COLUMN_LAST_MODIFIED, lastModified);
-        }
+    @Override
+    protected Uri buildNotificationUri(String docId) {
+        return DocumentsContract.buildChildDocumentsUri(AUTHORITY, docId);
     }
 
     @Override
@@ -455,22 +408,8 @@
     }
 
     @Override
-    public boolean isChildDocument(String parentDocId, String docId) {
-        try {
-            final File parent = getFileForDocId(parentDocId).getCanonicalFile();
-            final File doc = getFileForDocId(docId).getCanonicalFile();
-            return FileUtils.contains(parent, doc);
-        } catch (IOException e) {
-            throw new IllegalArgumentException(
-                    "Failed to determine if " + docId + " is child of " + parentDocId + ": " + e);
-        }
-    }
-
-    @Override
     public Path findDocumentPath(String childDocId, @Nullable String parentDocId)
             throws FileNotFoundException {
-        LinkedList<String> path = new LinkedList<>();
-
         final Pair<RootInfo, File> resolvedDocId = resolveDocId(childDocId, false);
         final RootInfo root = resolvedDocId.first;
         File child = resolvedDocId.second;
@@ -479,49 +418,7 @@
                         ? root.path
                         : getFileForDocId(parentDocId);
 
-        if (!child.exists()) {
-            throw new FileNotFoundException(childDocId + " is not found.");
-        }
-
-        if (!child.getAbsolutePath().startsWith(parent.getAbsolutePath())) {
-            throw new FileNotFoundException(childDocId + " is not found under " + parentDocId);
-        }
-
-        while (child != null && child.getAbsolutePath().startsWith(parent.getAbsolutePath())) {
-            path.addFirst(getDocIdForFile(child));
-
-            child = child.getParentFile();
-        }
-
-        return new Path(parentDocId == null ? root.rootId : null, path);
-    }
-
-    @Override
-    public String createDocument(String docId, String mimeType, String displayName)
-            throws FileNotFoundException {
-        displayName = FileUtils.buildValidFatFilename(displayName);
-
-        final File parent = getFileForDocId(docId);
-        if (!parent.isDirectory()) {
-            throw new IllegalArgumentException("Parent document isn't a directory");
-        }
-
-        final File file = FileUtils.buildUniqueFile(parent, mimeType, displayName);
-        if (Document.MIME_TYPE_DIR.equals(mimeType)) {
-            if (!file.mkdir()) {
-                throw new IllegalStateException("Failed to mkdir " + file);
-            }
-        } else {
-            try {
-                if (!file.createNewFile()) {
-                    throw new IllegalStateException("Failed to touch " + file);
-                }
-            } catch (IOException e) {
-                throw new IllegalStateException("Failed to touch " + file + ": " + e);
-            }
-        }
-
-        return getDocIdForFile(file);
+        return new Path(parentDocId == null ? root.rootId : null, findDocumentPath(parent, child));
     }
 
     private Uri getDocumentUri(String path, List<UriPermission> accessUriPermissions)
@@ -587,120 +484,14 @@
     }
 
     @Override
-    public String renameDocument(String docId, String displayName) throws FileNotFoundException {
-        // Since this provider treats renames as generating a completely new
-        // docId, we're okay with letting the MIME type change.
-        displayName = FileUtils.buildValidFatFilename(displayName);
-
-        final File before = getFileForDocId(docId);
-        final File after = FileUtils.buildUniqueFile(before.getParentFile(), displayName);
-        if (!before.renameTo(after)) {
-            throw new IllegalStateException("Failed to rename to " + after);
-        }
-        final String afterDocId = getDocIdForFile(after);
-        if (!TextUtils.equals(docId, afterDocId)) {
-            return afterDocId;
-        } else {
-            return null;
-        }
-    }
-
-    @Override
-    public void deleteDocument(String docId) throws FileNotFoundException {
-        final File file = getFileForDocId(docId);
-        final File visibleFile = getFileForDocId(docId, true);
-
-        final boolean isDirectory = file.isDirectory();
-        if (isDirectory) {
-            FileUtils.deleteContents(file);
-        }
-        if (!file.delete()) {
-            throw new IllegalStateException("Failed to delete " + file);
-        }
-
-        if (visibleFile != null) {
-            final ContentResolver resolver = getContext().getContentResolver();
-            final Uri externalUri = MediaStore.Files.getContentUri("external");
-
-            // Remove media store entries for any files inside this directory, using
-            // path prefix match. Logic borrowed from MtpDatabase.
-            if (isDirectory) {
-                final String path = visibleFile.getAbsolutePath() + "/";
-                resolver.delete(externalUri,
-                        "_data LIKE ?1 AND lower(substr(_data,1,?2))=lower(?3)",
-                        new String[] { path + "%", Integer.toString(path.length()), path });
-            }
-
-            // Remove media store entry for this exact file.
-            final String path = visibleFile.getAbsolutePath();
-            resolver.delete(externalUri,
-                    "_data LIKE ?1 AND lower(_data)=lower(?2)",
-                    new String[] { path, path });
-        }
-    }
-
-    @Override
-    public String moveDocument(String sourceDocumentId, String sourceParentDocumentId,
-            String targetParentDocumentId)
-            throws FileNotFoundException {
-        final File before = getFileForDocId(sourceDocumentId);
-        final File after = new File(getFileForDocId(targetParentDocumentId), before.getName());
-
-        if (after.exists()) {
-            throw new IllegalStateException("Already exists " + after);
-        }
-        if (!before.renameTo(after)) {
-            throw new IllegalStateException("Failed to move to " + after);
-        }
-        return getDocIdForFile(after);
-    }
-
-    @Override
-    public Cursor queryDocument(String documentId, String[] projection)
-            throws FileNotFoundException {
-        final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
-        includeFile(result, documentId, null);
-        return result;
-    }
-
-    @Override
-    public Cursor queryChildDocuments(
-            String parentDocumentId, String[] projection, String sortOrder)
-            throws FileNotFoundException {
-        final File parent = getFileForDocId(parentDocumentId);
-        final MatrixCursor result = new DirectoryCursor(
-                resolveDocumentProjection(projection), parentDocumentId, parent);
-        for (File file : parent.listFiles()) {
-            includeFile(result, null, file);
-        }
-        return result;
-    }
-
-    @Override
     public Cursor querySearchDocuments(String rootId, String query, String[] projection)
             throws FileNotFoundException {
-        final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
-
-        query = query.toLowerCase();
         final File parent;
         synchronized (mRootsLock) {
             parent = mRoots.get(rootId).path;
         }
 
-        final LinkedList<File> pending = new LinkedList<>();
-        pending.add(parent);
-        while (!pending.isEmpty() && result.getCount() < 24) {
-            final File file = pending.removeFirst();
-            if (file.isDirectory()) {
-                for (File child : file.listFiles()) {
-                    pending.add(child);
-                }
-            }
-            if (file.getName().toLowerCase().contains(query)) {
-                includeFile(result, null, file);
-            }
-        }
-        return result;
+        return querySearchDocuments(parent, query, projection, Collections.emptySet());
     }
 
     @Override
@@ -722,48 +513,6 @@
     }
 
     @Override
-    public String getDocumentType(String documentId) throws FileNotFoundException {
-        final File file = getFileForDocId(documentId);
-        return getTypeForFile(file);
-    }
-
-    @Override
-    public ParcelFileDescriptor openDocument(
-            String documentId, String mode, CancellationSignal signal)
-            throws FileNotFoundException {
-        final File file = getFileForDocId(documentId);
-        final File visibleFile = getFileForDocId(documentId, true);
-
-        final int pfdMode = ParcelFileDescriptor.parseMode(mode);
-        if (pfdMode == ParcelFileDescriptor.MODE_READ_ONLY || visibleFile == null) {
-            return ParcelFileDescriptor.open(file, pfdMode);
-        } else {
-            try {
-                // When finished writing, kick off media scanner
-                return ParcelFileDescriptor.open(file, pfdMode, mHandler, new OnCloseListener() {
-                    @Override
-                    public void onClose(IOException e) {
-                        final Intent intent = new Intent(
-                                Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
-                        intent.setData(Uri.fromFile(visibleFile));
-                        getContext().sendBroadcast(intent);
-                    }
-                });
-            } catch (IOException e) {
-                throw new FileNotFoundException("Failed to open for writing: " + e);
-            }
-        }
-    }
-
-    @Override
-    public AssetFileDescriptor openDocumentThumbnail(
-            String documentId, Point sizeHint, CancellationSignal signal)
-            throws FileNotFoundException {
-        final File file = getFileForDocId(documentId);
-        return DocumentsContract.openImageThumbnail(file);
-    }
-
-    @Override
     public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
         final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ", 160);
         synchronized (mRootsLock) {
@@ -826,107 +575,4 @@
         }
         return bundle;
     }
-
-    private static String getTypeForFile(File file) {
-        if (file.isDirectory()) {
-            return Document.MIME_TYPE_DIR;
-        } else {
-            return getTypeForName(file.getName());
-        }
-    }
-
-    private static String getTypeForName(String name) {
-        final int lastDot = name.lastIndexOf('.');
-        if (lastDot >= 0) {
-            final String extension = name.substring(lastDot + 1).toLowerCase();
-            final String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
-            if (mime != null) {
-                return mime;
-            }
-        }
-
-        return "application/octet-stream";
-    }
-
-    private void startObserving(File file, Uri notifyUri) {
-        synchronized (mObservers) {
-            DirectoryObserver observer = mObservers.get(file);
-            if (observer == null) {
-                observer = new DirectoryObserver(
-                        file, getContext().getContentResolver(), notifyUri);
-                observer.startWatching();
-                mObservers.put(file, observer);
-            }
-            observer.mRefCount++;
-
-            if (LOG_INOTIFY) Log.d(TAG, "after start: " + observer);
-        }
-    }
-
-    private void stopObserving(File file) {
-        synchronized (mObservers) {
-            DirectoryObserver observer = mObservers.get(file);
-            if (observer == null) return;
-
-            observer.mRefCount--;
-            if (observer.mRefCount == 0) {
-                mObservers.remove(file);
-                observer.stopWatching();
-            }
-
-            if (LOG_INOTIFY) Log.d(TAG, "after stop: " + observer);
-        }
-    }
-
-    private static class DirectoryObserver extends FileObserver {
-        private static final int NOTIFY_EVENTS = ATTRIB | CLOSE_WRITE | MOVED_FROM | MOVED_TO
-                | CREATE | DELETE | DELETE_SELF | MOVE_SELF;
-
-        private final File mFile;
-        private final ContentResolver mResolver;
-        private final Uri mNotifyUri;
-
-        private int mRefCount = 0;
-
-        public DirectoryObserver(File file, ContentResolver resolver, Uri notifyUri) {
-            super(file.getAbsolutePath(), NOTIFY_EVENTS);
-            mFile = file;
-            mResolver = resolver;
-            mNotifyUri = notifyUri;
-        }
-
-        @Override
-        public void onEvent(int event, String path) {
-            if ((event & NOTIFY_EVENTS) != 0) {
-                if (LOG_INOTIFY) Log.d(TAG, "onEvent() " + event + " at " + path);
-                mResolver.notifyChange(mNotifyUri, null, false);
-            }
-        }
-
-        @Override
-        public String toString() {
-            return "DirectoryObserver{file=" + mFile.getAbsolutePath() + ", ref=" + mRefCount + "}";
-        }
-    }
-
-    private class DirectoryCursor extends MatrixCursor {
-        private final File mFile;
-
-        public DirectoryCursor(String[] columnNames, String docId, File file) {
-            super(columnNames);
-
-            final Uri notifyUri = DocumentsContract.buildChildDocumentsUri(
-                    AUTHORITY, docId);
-            setNotificationUri(getContext().getContentResolver(), notifyUri);
-
-            mFile = file;
-            startObserving(mFile, notifyUri);
-        }
-
-        @Override
-        public void close() {
-            super.close();
-            stopObserving(mFile);
-        }
-    }
 }
diff --git a/packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeApp.java b/packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeApp.java
index 36ce7ce..c9e0d0a 100644
--- a/packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeApp.java
+++ b/packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeApp.java
@@ -108,14 +108,14 @@
             builder.setCancelable(false);
             builder.setPositiveButton("I understand", null);
             Dialog dialog = builder.create();
-            dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+            dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
             dialog.show();
         }
 
         // Make a fake window that is always around eating graphics resources.
         FakeView view = new FakeView(this);
         WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
-                WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
+                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                 | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
diff --git a/packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeBackgroundService.java b/packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeBackgroundService.java
index 5d1a398..ff09000 100644
--- a/packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeBackgroundService.java
+++ b/packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeBackgroundService.java
@@ -74,7 +74,7 @@
         // Make a fake window that is always around eating graphics resources.
         FakeView view = new FakeView(this);
         Dialog dialog = new Dialog(this, android.R.style.Theme_Holo_Dialog);
-        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
         dialog.getWindow().setFlags(
                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/ReceiverActivity.java b/packages/MtpDocumentsProvider/src/com/android/mtp/ReceiverActivity.java
index 84745b2..19c2c14 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/ReceiverActivity.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/ReceiverActivity.java
@@ -46,8 +46,8 @@
                 final Uri uri = DocumentsContract.buildRootUri(
                         MtpDocumentsProvider.AUTHORITY, deviceRootId);
 
-                final Intent intent = new Intent(DocumentsContract.ACTION_BROWSE);
-                intent.setData(uri);
+                final Intent intent = new Intent(Intent.ACTION_VIEW);
+                intent.setDataAndType(uri, DocumentsContract.Root.MIME_TYPE_ITEM);
                 intent.addCategory(Intent.CATEGORY_DEFAULT);
                 this.startActivity(intent);
             } catch (IOException exception) {
diff --git a/packages/PrintSpooler/res/values-hi/strings.xml b/packages/PrintSpooler/res/values-hi/strings.xml
index f36167e..36465a1 100644
--- a/packages/PrintSpooler/res/values-hi/strings.xml
+++ b/packages/PrintSpooler/res/values-hi/strings.xml
@@ -79,7 +79,7 @@
     </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> प्रिंट हो रहा है"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> रद्द हो रहा है"</string>
-    <string name="failed_notification_title_template" msgid="2256217208186530973">"प्रिंटर त्रुटि <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
+    <string name="failed_notification_title_template" msgid="2256217208186530973">"प्रिंटर गड़बड़ी <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="blocked_notification_title_template" msgid="1175435827331588646">"प्रिंटर अवरोधित <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancel" msgid="4373674107267141885">"अभी नहीं"</string>
     <string name="restart" msgid="2472034227037808749">"पुन: आरंभ करें"</string>
diff --git a/packages/SettingsLib/res/drawable/ic_help_actionbar.xml b/packages/SettingsLib/res/drawable/ic_help_actionbar.xml
new file mode 100644
index 0000000..3614625
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_help_actionbar.xml
@@ -0,0 +1,27 @@
+<?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="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0"
+        android:tint="?android:attr/colorControlNormal">
+    <path
+        android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,19h-2v-2h2v2zM15.07,11.25l-0.9,0.92C13.45,12.9 13,13.5 13,15h-2v-0.5c0,-1.1 0.45,-2.1 1.17,-2.83l1.24,-1.26c0.37,-0.36 0.59,-0.86 0.59,-1.41 0,-1.1 -0.9,-2 -2,-2s-2,0.9 -2,2L8,9c0,-2.21 1.79,-4 4,-4s4,1.79 4,4c0,0.88 -0.36,1.68 -0.93,2.25z"
+        android:fillColor="#FFFFFF"/>
+</vector>
diff --git a/packages/SettingsLib/res/layout/drawer_category.xml b/packages/SettingsLib/res/layout/drawer_category.xml
deleted file mode 100644
index 72cfddb..0000000
--- a/packages/SettingsLib/res/layout/drawer_category.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<!--
-    Copyright (C) 2015 The Android Open Source Project
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:paddingTop="8dp"
-    android:orientation="vertical">
-
-    <View
-        android:layout_width="match_parent"
-        android:layout_height="1dp"
-        android:background="?android:attr/listDivider" />
-
-    <TextView
-        style="@style/TextAppearanceSmall"
-        android:id="@android:id/title"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:minHeight="48dp"
-        android:paddingTop="16dp"
-        android:paddingBottom="16dp"
-        android:paddingStart="16dp" />
-
-</LinearLayout>
diff --git a/packages/SettingsLib/res/layout/drawer_item.xml b/packages/SettingsLib/res/layout/drawer_item.xml
deleted file mode 100644
index d492ddf..0000000
--- a/packages/SettingsLib/res/layout/drawer_item.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<!--
-    Copyright (C) 2015 The Android Open Source Project
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/tile_item"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:minHeight="48dp"
-    android:orientation="horizontal" >
-
-    <ImageView
-        android:id="@android:id/icon"
-        android:layout_width="@dimen/drawer_icon_size"
-        android:layout_height="@dimen/drawer_icon_size"
-        android:layout_marginStart="@dimen/drawer_icon_margin"
-        android:layout_marginEnd="@dimen/drawer_icon_margin"
-        android:layout_marginTop="@dimen/drawer_item_top_bottom_margin"
-        android:layout_marginBottom="@dimen/drawer_item_top_bottom_margin"
-        android:scaleType="fitCenter"
-        android:layout_gravity="center_vertical"
-        android:tint="?android:attr/colorAccent"/>
-
-    <TextView
-        android:textAppearance="@style/TextAppearanceMedium"
-        android:id="@android:id/title"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center_vertical"
-        android:textColor="?android:attr/colorControlNormal" />
-
-</LinearLayout>
diff --git a/packages/SettingsLib/res/layout/drawer_spacer.xml b/packages/SettingsLib/res/layout/drawer_spacer.xml
deleted file mode 100644
index 98120cf..0000000
--- a/packages/SettingsLib/res/layout/drawer_spacer.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<!--
-    Copyright (C) 2016 The Android Open Source Project
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<Space
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/spacer"
-    android:layout_width="match_parent"
-    android:layout_height="@dimen/drawer_spacer_height" />
diff --git a/packages/SettingsLib/res/layout/settings_with_drawer.xml b/packages/SettingsLib/res/layout/settings_with_drawer.xml
index b659cee..e9c175f 100644
--- a/packages/SettingsLib/res/layout/settings_with_drawer.xml
+++ b/packages/SettingsLib/res/layout/settings_with_drawer.xml
@@ -47,13 +47,4 @@
             android:layout_height="fill_parent"
             android:background="?android:attr/windowBackground" />
     </LinearLayout>
-    <!-- The navigation drawer -->
-    <ListView android:id="@+id/left_drawer"
-        android:layout_width="@dimen/drawer_width"
-        android:layout_height="match_parent"
-        android:layout_gravity="start"
-        android:choiceMode="singleChoice"
-        android:divider="@android:color/transparent"
-        android:dividerHeight="0dp"
-        android:background="?android:attr/colorBackground" />
 </android.support.v4.widget.DrawerLayout>
diff --git a/packages/SettingsLib/res/values-af/arrays.xml b/packages/SettingsLib/res/values-af/arrays.xml
index dbfc565..d92378a 100644
--- a/packages/SettingsLib/res/values-af/arrays.xml
+++ b/packages/SettingsLib/res/values-af/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Wys oortrekareas"</item>
     <item msgid="2290859360633824369">"Wys areas vir Deuteranomaly"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (verstek)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Standaardlimiet"</item>
     <item msgid="4071574792028999443">"Geen agtergrondprosesse"</item>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index c103b0b..9803aaa 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Gestoor"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Gedeaktiveer"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-opstelling het misluk"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Nie gekoppel nie weens laegehalte-netwerk"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi-verbinding het misluk"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Stawingsprobleem"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Nie binne ontvangs nie"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Niks"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Wag vir ontfouter"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Ontfoutde program wag vir ontfouter om te heg voordat dit uitgevoer word"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telefonie-monitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Telefonie-monitor sal loglêers insamel wanneer dit \'n probleem met telefonie-/modemfunksionaliteit bespeur en \'n kennisgewing aan die gebruiker stuur om \'n fout in te dien"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Invoer"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Skets"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Hardeware-versnelde lewering"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Wys hardewarelae se opdaterings"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Laat hardewarelae groen flits wanneer hulle opgedateer word"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Ontfout GPU-oortrek"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Stel GPU-leweraar"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Deaktiveer HW-oorleggers"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Gebruik altyd GPU vir skermsamestelling"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simuleer kleurruimte"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Voer wagwoord in om fabriekterugstelling in demonstrasiemodus uit te voer"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Volgende"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Wagwoord word benodig"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Aktiewe invoermetodes"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Gebruik stelseltale"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-am/arrays.xml b/packages/SettingsLib/res/values-am/arrays.xml
index 7fdc06a..09453f8 100644
--- a/packages/SettingsLib/res/values-am/arrays.xml
+++ b/packages/SettingsLib/res/values-am/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"ስዕሉ አልፎ የፈሰሰባቸው አካባቢዎችን አሳይ"</item>
     <item msgid="2290859360633824369">"ቀይ እና አረንጓዴ የማይለይባቸው ቦታዎች አሳይ"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (ነባሪ)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"መደበኛ ወሰኖች"</item>
     <item msgid="4071574792028999443">"ምንም የዳራ ሂደቶች የሉም"</item>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 7725827..673fd35 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"ተቀምጧል"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"ተሰናክሏል"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"የአይ.ፒ. ውቅረት መሰናከል"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"በዝቅተኛ አውታረ መረብ ምክንያት አልተገናኘም"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"የWiFi ግንኙነት መሰናከል"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"የማረጋገጫ ችግር"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"በክልል ውስጥ የለም"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"ምንም"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"ስህተት ማስወገጃውን ጠብቅ"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"ስህተቱ የተወገደለት መተግበሪያ ከመፈጸሙ በፊት የስህተት ማስወገጃው እስኪያያዝ ድረስ እየጠበቀው ነው"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"የቴሌፎኒ መከታተያ"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"TelephonyMonitor በቴሌፎኒ/ሞደም ተግባር ላይ ችግር እንዳለ ሲያገኝ የምዝግብ ማስታወሻዎችን ይሰበስብና ተጠቃሚው ሳንካ እንዲያስመዘግቡ በማሳወቂያ ይጠይቃቸዋል"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"ግብዓት"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"ስዕል"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"የተፋጠነ የሃርድዌር አሰጣጥ"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"የሃርድዌር ንብርብሮች ዝማኔዎችን አሳይ"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"የሃርድዌር ንብርብሮች ሲዘምኑ አረንጓዴ አብራ"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"የጂፒዩ አልፎ መሳል አርም"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"የGPU አሳዪ አዘጋጅ"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"የHW ተደራቢዎችን አሰናክል"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"ለማያ ገጽ ማቀናበሪያ ሁልጊዜ GPU ተጠቀም"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"የቀለም ህዋ አስመስል"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"የፋብሪካ ዳግም ማስጀመር በማሳያ ሁነታ ውስጥ ለማከናወን የይለፍ ቃል ያስገቡ"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"ቀጣይ"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"የይለፍ ቃል ያስፈልጋል"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"የገባሪ ግቤት ዘዴ"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"የሥርዓት ቋንቋዎችን ይጠቀሙ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ar/arrays.xml b/packages/SettingsLib/res/values-ar/arrays.xml
index a8976ad..dbb5d65 100644
--- a/packages/SettingsLib/res/values-ar/arrays.xml
+++ b/packages/SettingsLib/res/values-ar/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"عرض مناطق تجاوز الحد"</item>
     <item msgid="2290859360633824369">"‏عرض مناطق العرض المسرحي Deuteranomaly"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"‏OpenGL (الافتراضي)"</item>
+    <item msgid="2839130076198120436">"‏OpenGL ‏(Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"الحد القياسي"</item>
     <item msgid="4071574792028999443">"ليست هناك عمليات بالخلفية"</item>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index fa7e253..ef784ca 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"تم الحفظ"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"معطلة"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"‏أخفقت تهيئة عنوان IP"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"الجهاز غير متصل بسبب انخفاض جودة الشبكة"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"‏أخفق اتصال WiFi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"حدثت مشكلة في المصادقة"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"ليست في النطاق"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"لا شيء"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"انتظار برنامج التصحيح"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"ينتظر التطبيق قيد التصحيح انضمام برنامج التصحيح قبل التنفيذ"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"خدمة مراقبة الاتصالات الهاتفية"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"ستجمع خدمة مراقبة الاتصالات الهاتفية سجلات عند اكتشاف مشكلة متعلقة بوظائف الاتصالات الهاتفية أو المودم، وإرسال إشعار إلى المستخدم لإرسال تقرير بالخطأ"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"الإدخال"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"رسم"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"عرض تسارع الأجهزة"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"عرض تحديثات طبقات الأجهزة"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"تشغيل وميض بالأخضر لطبقات الأجهزة عند تحديثها"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"تصحيح تجاوز حد وحدة معالجة الرسومات"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"تعيين عارض معالجة الرسومات"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"تعطيل تراكبات الأجهزة"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"استخدام وحدة معالجة الرسومات دائمًا لتركيب الشاشة"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"محاكاة مسافة اللون"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"إدخال كلمة المرور لإعادة الضبط بحسب بيانات المصنع في الوضع التجريبي"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"التالي"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"يلزم توفر كلمة مرور"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"طرق الإدخال النشطة"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"استخدام لغات النظام"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-az/arrays.xml b/packages/SettingsLib/res/values-az/arrays.xml
index 7a147d5..78ac552 100644
--- a/packages/SettingsLib/res/values-az/arrays.xml
+++ b/packages/SettingsLib/res/values-az/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Böyütmə sahələrini göstər"</item>
     <item msgid="2290859360633824369">"Daltonizm üçün sahələri göstərin"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (Defolt)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Standart limit"</item>
     <item msgid="4071574792028999443">"Fon proses yoxdur"</item>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 70a8c49..0a22c62 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Yadda saxlanılan"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Deaktiv"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Konfiqurasiya Uğursuzluğu"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Şəbəkə keyfiyyəti aşağı olduğuna görə qoşulmadı"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi Bağlantı Uğursuzluğu"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Autentifikasiya problemi"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Diapazonda deyil"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Heç nə"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Sazlamanı gözləyin"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Sazlanmış tətbiq icradan əvvəl qoşulmaq üçün sazlayıcı gözləyir"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telefoniya Monitoru"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Telefoniya Monitoru telefoniya/modem funksionallığı ilə bağlı problem aşkar etdikdə qeydiyyatları toplayır və baq haqqında istifadəçiyə bildiriş göndərir"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Daxiletmə"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Təsvir"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Avadanlıq qaldırma renderi"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Avadanlıq düzənlərinin güncəlləşməsini göstərin"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Onlar güncəllənəndən sonra avadanlıq qatlarında işartı olsun"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU böyütməsini sazlayın"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU Renderi ayarlayın"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"HW overlay deaktiv edin"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Həmişə ekran kompozisiyası üçün GPU istifadə edin"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Rəng sahəsini simulyasiya edin"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Demo rejimində sıfırlamaq üçün parol daxil edin"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Növbəti"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Parol tələb olunur"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Aktiv daxiletmə üsulları"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Sistem dillərini istifadə edin"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
index 4498939..aef2691 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Prikaži oblasti preklapanja"</item>
     <item msgid="2290859360633824369">"Prikaži oblasti za deuteranomaliju"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (podrazumevano)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Standardno ograničenje"</item>
     <item msgid="4071574792028999443">"Bez pozadinskih procesa"</item>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 0aa9524..cfb691d 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Sačuvano"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Onemogućeno"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP konfiguracija je otkazala"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Nije povezano zbog lošeg kvaliteta mreže"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi veza je otkazala"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problem sa potvrdom autentičnosti"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Nije u opsegu"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Nijedna"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Sačekaj program za otklanjanje grešaka"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Aplikacija čeka program za otklanjanje grešaka da priloži pre izvršavanja"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"TelephonyMonitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"TelephonyMonitor će prikupljati evidenciju kada otkrije problem sa funkcionisanjem telefonije/modema i zatražiće od korisnika da prijavi grešku"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Unos"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Crtanje"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Hardverski ubrzano prikazivanje"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Prikaži ažuriranja hardverskih slojeva"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Hardverski slojevi trepere zeleno kada se ažuriraju"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Otkloni greške GPU preklapanja"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Podesi GPU prikazivač"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Onemog. HW post. elemente"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Uvek koristi GPU za komponovanje ekrana"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simuliraj prostor boje"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Unesite lozinku da biste obavili resetovanje na fabrička podešavanja u režimu demonstracije"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Dalje"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Potrebna je lozinka"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Metode aktivnog unosa"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Koristi jezike sistema"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-be/arrays.xml b/packages/SettingsLib/res/values-be/arrays.xml
index b2031cb..9122ffe 100644
--- a/packages/SettingsLib/res/values-be/arrays.xml
+++ b/packages/SettingsLib/res/values-be/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Паказаць вобласці з перабольшваннем"</item>
     <item msgid="2290859360633824369">"Паказаць вобласці для дэйтэранамаліі"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (стандартны)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Стандартны ліміт"</item>
     <item msgid="4071574792028999443">"Няма фонавых працэсаў"</item>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 876f125..363efa2 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Захавана"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Адключана"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Збой канфігурацыі IP"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Няма падключэння з-за нізкай якасці сеткі"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Збой падлучэння Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Праблема аўтэнтыфікацыі"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Не ў зоне дасягальнасці"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Нічога"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Пачакайце адладчык"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Адладжанае прыкладанне чакае далучэння да iнструмента для адладкi перад працай"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Сродак адсочвання тэлефаніі"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Праграма TelephonyMonitor будзе заносіць у журналы выпадкі выяўлення праблем, што датычацца фукнцый тэлефаніі/мадэма, а таксама паказваць карыстальніку адпаведнае апавяшчэнне з прапановай адпраўкі паведамлення пра памылку"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Увод"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Чарцёж"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Апаратнае паскарэнне рэндэрынгу"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Паказаць абнаўленнi апаратнага пласта"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Апаратныя пласты набываюць зялёны колер, калi абнаўляюцца"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Адладка перамалёўкі GPU"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Задаць рэндэрар графікі"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Адкл. апаратн. накладання"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Заўсёды выкарыстоўваць GPU для экраннай кампаноўкі"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Сімуляцыя каляр. прасторы"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Каб выканаць скід да заводскіх налад у дэманстрацыйным рэжыме, увядзіце пароль"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Далей"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Патрабуецца пароль"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Актыўныя метады ўводу"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Выкарыстоўваць мовы сістэмы"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-bg/arrays.xml b/packages/SettingsLib/res/values-bg/arrays.xml
index 9bc32a3..2bf660c 100644
--- a/packages/SettingsLib/res/values-bg/arrays.xml
+++ b/packages/SettingsLib/res/values-bg/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Области за преизчертаване: Показв."</item>
     <item msgid="2290859360633824369">"Показване на областите за деутеранопия"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (по подразбиране)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Стандартно ограничение"</item>
     <item msgid="4071574792028999443">"Няма процеси на заден план"</item>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 351b489..264684a 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Запазено"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Деактивирани"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Неуспешно конфигуриране на IP адреса"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Не е установена връзка поради ниското качество на мрежата"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Неуспешна връзка с Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Проблем при удостоверяването"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Извън обхват"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Няма"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Изчакване на инструмента за отстраняване на грешки"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Прил. изчаква инстр. за отстраняване на грешки да се прикачи преди изпълнение"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Наблюдение на телефонията"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Функцията за наблюдение на телефонията ще събира регистрационни файлове, когато установи проблем с функционалността на телефонията/модема, и ще изпрати на потребителя известие с подкана да подаде сигнал за програмна грешка"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Въвеждане"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Начертаване"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Хардуерно ускорено изобразяване"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Актуал. на слоевете на хардуера"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Примигв. на слоевете на хардуера в зелено при актуал."</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Отстран. на проблеми с преизчертаване от GPU"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Визуализатор на ГП: Избор"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Хардуерни наслагв.: Деактив."</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Винаги да се използва GPU за изграждане на екрана"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Цвет. простр.: Симулиране"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Въведете парола за възст. на фабр. настройки в демонстр. режим"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Напред"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Изисква се парола"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Активни методи за въвеждане"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Използване на системните езици"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-bn/arrays.xml b/packages/SettingsLib/res/values-bn/arrays.xml
index b40bfd4..5b18c25 100644
--- a/packages/SettingsLib/res/values-bn/arrays.xml
+++ b/packages/SettingsLib/res/values-bn/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"অতিবর্ণনা এলাকা দেখান"</item>
     <item msgid="2290859360633824369">"বর্ণান্ধতার জন্য এলাকা দেখান"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (ডিফল্ট)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"মানক সীমা"</item>
     <item msgid="4071574792028999443">"কোন ব্যাকগ্রাউন্ড প্রক্রিয়া নেই"</item>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 820fb40..1fc63e8 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"সংরক্ষিত"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"অক্ষম হয়েছে"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP কনফিগারেশনের ব্যর্থতা"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"খারাপ নেটওয়ার্কের কারণে সংযুক্ত নয়"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi সংযোগের ব্যর্থতা"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"প্রমাণীকরণ সমস্যা"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"পরিসরের মধ্যে নয়"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"কিছুই না"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"ডিবাগারের জন্য অপেক্ষা করুন"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"চালানোর আগে সংযুক্ত করতে জন্য ডিবাগ করা অ্যাপ্লিকেশনটি ডিবাগারের জন্য অপেক্ষা করছে"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"টেলিফোনি মনিটর"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"টেলিফোনি মনিটর টেলিফোনি/মোডেমের কার্যকারিতায় কোনো সমস্যা শনাক্ত করলে সমস্যাটি লগ করবে এবং সমস্যাটি জানাতে একটি বাগ ফাইল করার জন্য ব্যবহারকারিকে বিজ্ঞপ্তি পাঠাবে"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"ইনপুট"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"অঙ্কন"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"হার্ডওয়্যার দ্বারা চালিত রেন্ডারিং"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"হার্ডওয়্যার স্তর আপডেটগুলি প্রদর্শন করুন"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"যখন হার্ডওয়্যার স্তরগুলি আপডেট হয় তখন সেগুলিকে সবুজ রঙে ফ্ল্যাশ করুন"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"ডিবাগ GPU ওভারড্র"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU রেন্ডারার সেট করুন"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"HW আচ্ছাদনগুলি অক্ষম করুন"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"সর্বদা স্ক্রীন কম্পোসিটিংয়ের জন্য GPU ব্যবহার করুন"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"রঙ স্থান নকল করুন"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"ডেমো মোডে ফ্যাক্টরি রিসেট করতে পাসওয়ার্ড দিন"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"পরবর্তী"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"পাসওয়ার্ড আবশ্যক"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"সক্রিয় ইনপুট পদ্ধতিগুলি"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"সিস্টেমের ভাষাগুলি ব্যবহার করুন"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-bs/arrays.xml b/packages/SettingsLib/res/values-bs/arrays.xml
index 1c3d3bf..1923d8e 100644
--- a/packages/SettingsLib/res/values-bs/arrays.xml
+++ b/packages/SettingsLib/res/values-bs/arrays.xml
@@ -144,7 +144,7 @@
   </string-array>
   <string-array name="select_logpersist_titles">
     <item msgid="1744840221860799971">"Isključeno"</item>
-    <item msgid="3054662377365844197">"Svi"</item>
+    <item msgid="3054662377365844197">"Sve"</item>
     <item msgid="688870735111627832">"Svi osim radija"</item>
     <item msgid="2850427388488887328">"samo kernel"</item>
   </string-array>
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Prikaži overdraw područja"</item>
     <item msgid="2290859360633824369">"Prikaži područja za Deuteranomaly"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (Zadano)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Standardno ograničenje"</item>
     <item msgid="4071574792028999443">"Nema pozadinskih procesa"</item>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index aaf9713..56c520b 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Sačuvano"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Onemogućeno"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Greška u konfiguraciji IP-a"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Niste povezani zbog slabog kvaliteta mreže"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Greška pri povezivanju na Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problem pri provjeri vjerodostojnosti."</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Nije u dometu"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Ništa"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Pričekajte na program za otklanjanje grešaka"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Aplikacija u kojoj se otklanjaju greške čeka da se priloži program za otklanjanje grešaka prije izvršavanja"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Nadzor telefonije"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Nadzor telefonije će prikupiti zapisnike kada otkrije problem u funkcioniranju telefona/modema i obavijestiti korisnika da prijavi grešku"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Ulaz"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Crtanje"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Prikaz s hardverskom akceleracijom"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Prikaži dodatne informacije za ažuriranja za hardver"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Trepći hardverske slojeve zeleno kada se ažuriraju"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Otkl. GPU overdraw greške"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Postavite GPU renderer"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Onemog. HW preklapanja"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Uvijek koristi GPU za kompoziciju ekrana"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simuliraj prostor boje"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Unesite lozinku da izvršite vraćanje na fabričke postavke u načinu demonstracije"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Naprijed"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Potrebna je lozinka"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Aktivne metode unosa"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Koristi jezik sistema"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ca/arrays.xml b/packages/SettingsLib/res/values-ca/arrays.xml
index 1627ea6..67e3abe 100644
--- a/packages/SettingsLib/res/values-ca/arrays.xml
+++ b/packages/SettingsLib/res/values-ca/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Mostra les àrees superposades"</item>
     <item msgid="2290859360633824369">"Mostra les àrees amb deuteranomalia"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (predeterminat)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Límit estàndard"</item>
     <item msgid="4071574792028999443">"Sense processos en segon pla"</item>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 391782b..fd9fa80 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Desat"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Desactivat"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Error de configuració d\'IP"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"No s\'ha connectat a la xarxa perquè la qualitat és baixa"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Error de connexió Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problema d\'autenticació"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Fora de l\'abast"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Cap"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Espera el depurador"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Abans d\'executar-se, l\'aplicació de depuració espera que es connecti el depurador"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Monitor de telefonia"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Quan el monitor de telefonia detecta un problema amb la funció de telefonia/mòdem, recopila registres i mostra una notificació a l\'usuari perquè informi de l\'error"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Entrada"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Dibuix"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Renderització accelerada per maquinari"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Mostra actualitzacions capes"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Il·lumina capes de maquinari en verd en actualitzar-se"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Depura superposició de GPU"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Configura renderitzador GPU"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Desactiva superposicions HW"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Utilitza sempre GPU per combinar pantalles"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simula l\'espai de color"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Introdueix la contrasenya per restablir les dades de fàbrica en mode de demostració"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Següent"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Contrasenya obligatòria"</string>
+    <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>
 </resources>
diff --git a/packages/SettingsLib/res/values-cs/arrays.xml b/packages/SettingsLib/res/values-cs/arrays.xml
index b56fadc..0656c73 100644
--- a/packages/SettingsLib/res/values-cs/arrays.xml
+++ b/packages/SettingsLib/res/values-cs/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Zobrazit překreslované oblasti"</item>
     <item msgid="2290859360633824369">"Zobrazit oblasti pro deuteranomálii"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (výchozí)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Standardní limit"</item>
     <item msgid="4071574792028999443">"Procesy na pozadí deaktivovány"</item>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index dc5b36a..82a8fd1 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Uloženo"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Vypnuto"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Selhání konfigurace protokolu IP"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Nejste připojeni, protože síť je příliš slabá"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Selhání připojení Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problém s ověřením"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Mimo dosah"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Nic"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Počkat na ladicí program"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Aplikace čeká na připojení ladicího programu"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telephony Monitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Služba Telephony Monitor bude zaznamenávat protokoly problémů s funkcemi telefonu či modemu a zobrazí uživateli oznámení, že je třeba vyplnit hlášení o chybě"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Vstup"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Vykreslování"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Hardwarově urychlené vykreslování"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Zobrazit aktual. HW vrstev"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Rozblikat zeleně hardwarové vrstvy při aktualizaci"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Ladit překreslování GPU"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Nastavit modul vykreslení"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Zakázat hardwarové vrstvy"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Vždy použít GPU ke skládání obrazovky"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simulovat barevný prostor"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Chcete-li v ukázkovém režimu obnovit zařízení do továrního nastavení, zadejte heslo"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Další"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Je třeba zadat heslo"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Aktivní metody zadávání"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Použít systémové jazyky"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-da/arrays.xml b/packages/SettingsLib/res/values-da/arrays.xml
index a35f1bb..f1a8a3c 100644
--- a/packages/SettingsLib/res/values-da/arrays.xml
+++ b/packages/SettingsLib/res/values-da/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Vis områder med overlap"</item>
     <item msgid="2290859360633824369">"Vis områder for deuteranomali"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (standard)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Standardgrænse"</item>
     <item msgid="4071574792028999443">"Ingen baggrundsprocesser"</item>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 8071c83..5513956 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Gemt"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Deaktiveret"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-konfigurationsfejl"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Ingen forbindelse på grund af lav netværkskvalitet"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi-forbindelsesfejl"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problem med godkendelse"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Ikke inden for rækkevidde"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Ingen"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Vent på fejlfinder"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Fejlrettet app venter på tilknytning af fejlfinder før udførelse"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Overvågning af telefoni"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Overvågning af telefoni indsamler logfiler, når der registreres et problem med telefoni-/modemfunktioner, og sender brugeren en underretning, der beder vedkommende om at indsende en fejlrapport"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Input"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Tegning"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Hardware-accelereret gengivelse"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Se opdat. af hardwarelag"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Hardwarelag blinker grønt, når de opdateres"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Ret GPU-overlapsfejl"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Angiv GPU-gengiver"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Deaktiver HW-overlejring"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Brug altid GPU til skærmsammensætning"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simuler farverum"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Angiv adgangskode for at gendanne fabriksdata i demotilstand"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Næste"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Angiv en adgangskode"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Aktive inputmetoder"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Brug systemsprogene"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-de/arrays.xml b/packages/SettingsLib/res/values-de/arrays.xml
index 6e580d2..ae97637 100644
--- a/packages/SettingsLib/res/values-de/arrays.xml
+++ b/packages/SettingsLib/res/values-de/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Überschneidungsbereiche anzeigen"</item>
     <item msgid="2290859360633824369">"Bereiche für Deuteranomalie anzeigen"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (Standard)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Standardlimit"</item>
     <item msgid="4071574792028999443">"Keine Hintergrundprozesse"</item>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 8dd4c1db..926716b 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Gespeichert"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Deaktiviert"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-Konfigurationsfehler"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Keine Verbindung aufgrund der geringen Netzwerkqualität"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WLAN-Verbindungsfehler"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Authentifizierungsproblem"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Nicht in Reichweite"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Keine"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Auf Debugger warten"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"App wartet vor der Ausführung auf den Start des Debuggers"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telephony Monitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Mit Telephony Monitor werden Protokolle erfasst, wenn ein Problem mit der Telefon- oder der Modemfunktion entdeckt wird. Nutzer werden dazu aufgefordert, den Programmfehler zu melden."</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Eingabe"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Zeichnung"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Hardwarebeschleunigtes Rendering"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Hardwareebenen-Updates"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Hardwareebenen blinken beim Aktualisieren grün"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Debugging – GPU-Überschneidung"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU Renderer festlegen"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"HW-Overlays deaktivieren"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"GPU immer für Bildschirmaufbau verwenden"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Farbraum simulieren"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Passwort eingeben, um Gerät im Demomodus auf Werkseinstellungen zurückzusetzen"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Weiter"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Passwort erforderlich"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Aktive Eingabemethoden"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Systemsprache verwenden"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-el/arrays.xml b/packages/SettingsLib/res/values-el/arrays.xml
index 2b69f12..fdb58ff 100644
--- a/packages/SettingsLib/res/values-el/arrays.xml
+++ b/packages/SettingsLib/res/values-el/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Εμφάνιση περιοχών υπέρβασης"</item>
     <item msgid="2290859360633824369">"Εμφάνιση περιοχών για Deuteranomaly"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (προεπιλογή)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Τυπικό όριο"</item>
     <item msgid="4071574792028999443">"Δεν υπάρχουν διεργασίες παρασκηνίου"</item>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 1ee6db8..e468040 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Αποθηκευμένο"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Απενεργοποιημένο"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Αποτυχία διαμόρφωσης διεύθυνσης IP"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Δεν υπάρχει σύνδεση λόγω χαμηλής ποιότητας δικτύου"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Αποτυχία σύνδεσης Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Πρόβλημα ελέγχου ταυτότητας"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Εκτός εμβέλειας"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Καμία"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Περιμένετε το εργαλείο εντοπισμού σφαλμάτων"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Αναμονή εφαρμογής για να συνδεθεί ο εντοπισμός σφαλμάτων"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Παρακολούθηση τηλεφωνίας"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Η υπηρεσία TelephonyMonitor θα συλλέξει αρχεία καταγραφής μόλις εντοπίσει κάποιο πρόβλημα στη λειτουργία του τηλεφώνου/μόντεμ και θα εμφανίσει μια ειδοποίηση στον χρήστη για να υποβάλει αναφορά σφάλματος"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Εισαγωγή"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Σχέδιο"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Απόδοση με επιτάχυνση από υλικό εξοπλισμό"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Εμφ. ενημ. επιπ. υλικού"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Επισήμ. επιπέδων υλικού με πράσινο κατά την ενημ."</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Κατάρ.σφαλμ.υπέρβ.GPU"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Ρύθμ. λειτ. απόδοσης GPU"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Απενεργ. επικαλύψεων HW"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Να γίνεται πάντα χρήση του GPU για σύνθεση οθόνης"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Προσομοίωση χρωματικού χώρου"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Εισαγάγετε κωδικό πρόσβασης για επαναφορά εργοστασιακών ρυθμίσεων στη λειτουργία επίδειξης"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Επόμενο"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Απαιτείται κωδικός πρόσβασης"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Ενεργές μέθοδοι εισαγωγής"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Χρήση γλωσσών συστήματος"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rAU/arrays.xml b/packages/SettingsLib/res/values-en-rAU/arrays.xml
index ef4975c..0409800 100644
--- a/packages/SettingsLib/res/values-en-rAU/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rAU/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Show overdraw areas"</item>
     <item msgid="2290859360633824369">"Show areas for Deuteranomaly"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (Default)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Standard limit"</item>
     <item msgid="4071574792028999443">"No background processes"</item>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 1f641d5..f332b6e 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Saved"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Disabled"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Configuration Failure"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Not connected due to low quality network"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi Connection Failure"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Authentication problem"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Not in range"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Nothing"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Wait for debugger"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Debugged application waits for debugger to attach before executing"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telephony Monitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"TelephonyMonitor will collect logs when it detects a problem with telephony/modem functionality and prompt notification to user to file a bug"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Input"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Drawing"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Hardware accelerated rendering"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Show hardware layers updates"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Flash hardware layers green when they update"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Debug GPU overdraw"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Set GPU Renderer"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Disable HW overlays"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Always use GPU for screen compositing"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simulate colour space"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Enter password to perform factory reset in demo mode"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Next"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Password required"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Active input methods"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Use system languages"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rGB/arrays.xml b/packages/SettingsLib/res/values-en-rGB/arrays.xml
index ef4975c..0409800 100644
--- a/packages/SettingsLib/res/values-en-rGB/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rGB/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Show overdraw areas"</item>
     <item msgid="2290859360633824369">"Show areas for Deuteranomaly"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (Default)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Standard limit"</item>
     <item msgid="4071574792028999443">"No background processes"</item>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 1f641d5..f332b6e 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Saved"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Disabled"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Configuration Failure"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Not connected due to low quality network"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi Connection Failure"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Authentication problem"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Not in range"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Nothing"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Wait for debugger"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Debugged application waits for debugger to attach before executing"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telephony Monitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"TelephonyMonitor will collect logs when it detects a problem with telephony/modem functionality and prompt notification to user to file a bug"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Input"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Drawing"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Hardware accelerated rendering"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Show hardware layers updates"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Flash hardware layers green when they update"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Debug GPU overdraw"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Set GPU Renderer"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Disable HW overlays"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Always use GPU for screen compositing"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simulate colour space"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Enter password to perform factory reset in demo mode"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Next"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Password required"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Active input methods"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Use system languages"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rIN/arrays.xml b/packages/SettingsLib/res/values-en-rIN/arrays.xml
index ef4975c..0409800 100644
--- a/packages/SettingsLib/res/values-en-rIN/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rIN/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Show overdraw areas"</item>
     <item msgid="2290859360633824369">"Show areas for Deuteranomaly"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (Default)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Standard limit"</item>
     <item msgid="4071574792028999443">"No background processes"</item>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 1f641d5..f332b6e 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Saved"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Disabled"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Configuration Failure"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Not connected due to low quality network"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi Connection Failure"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Authentication problem"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Not in range"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Nothing"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Wait for debugger"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Debugged application waits for debugger to attach before executing"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telephony Monitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"TelephonyMonitor will collect logs when it detects a problem with telephony/modem functionality and prompt notification to user to file a bug"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Input"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Drawing"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Hardware accelerated rendering"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Show hardware layers updates"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Flash hardware layers green when they update"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Debug GPU overdraw"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Set GPU Renderer"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Disable HW overlays"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Always use GPU for screen compositing"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simulate colour space"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Enter password to perform factory reset in demo mode"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Next"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Password required"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Active input methods"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Use system languages"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-es-rUS/arrays.xml b/packages/SettingsLib/res/values-es-rUS/arrays.xml
index f5f67fb..760de55 100644
--- a/packages/SettingsLib/res/values-es-rUS/arrays.xml
+++ b/packages/SettingsLib/res/values-es-rUS/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Mostrar áreas superpuestas"</item>
     <item msgid="2290859360633824369">"Mostrar áreas para deuteranomalía"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (predeterminado)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Límite estándar"</item>
     <item msgid="4071574792028999443">"Sin procesos en 2.º plano"</item>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 25ee5a8..6216ea2 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Guardada"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Inhabilitada"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Error de configuración IP"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"No se estableció conexión debido a la mala calidad de la red"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Error de conexión Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problema de autenticación"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Fuera de alcance"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Ninguna"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Esperar al depurador"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Esperar que se conecte el depurador para iniciar la aplicación"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telephony Monitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Telephony Monitor recopilará registros cuando se detecte un problema con la funcionalidad de telefonía/módem y además enviará al usuario una notificación para que reporte el error"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Entrada"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Dibujo"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Representación acelerada mediante hardware"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Ver actualiz. de capas de hardware"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Luz verde en capas de hardware al actualizarse"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Depurar superpos. de GPU"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Elegir procesador de GPU"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Desactivar superpos. HW"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Usar GPU para combinar pantallas"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simular espacio de color"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Ingresa contraseña y restablece en demo"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Siguiente"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Contraseña obligatoria"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Métodos de entrada activos"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Usar idiomas del sistema"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-es/arrays.xml b/packages/SettingsLib/res/values-es/arrays.xml
index d5155c9..30414b2 100644
--- a/packages/SettingsLib/res/values-es/arrays.xml
+++ b/packages/SettingsLib/res/values-es/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Mostrar áreas sobredibujadas"</item>
     <item msgid="2290859360633824369">"Mostrar áreas para deuteranomalía"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (predeterminado)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Límite estándar"</item>
     <item msgid="4071574792028999443">"Sin procesos en segundo plano"</item>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 9d98096..9eb89b9 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Guardado"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Inhabilitado"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Error de configuración de IP"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"No conectado debido a la baja calidad de la red"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Error de conexión Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Error de autenticación"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Fuera de rango"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Ninguna"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Esperar al depurador"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"La aplicación depurada espera a que se active el depurador para ejecutarse"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Monitor de telefonía"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"TelephonyMonitor recopilará los registros al detectar un problema con la función de módem o telefonía y mostrará una notificación al usuario para registrar un error"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Entrada"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Dibujo"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Renderización acelerada por hardware"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Ver actualizaciones capas HW"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Iluminar capas de hardware en verde al actualizarse"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Depurar sobredibujos de GPU"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Elegir procesador de GPU"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Inhabilitar superposiciones HW"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Usar siempre la GPU para combinar pantallas"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simular espacio de color"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Escribe una contraseña para restablecer datos de fábrica en modo demostración"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Siguiente"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Contraseña obligatoria"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Métodos de introducción activos"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Usar idiomas del sistema"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-et/arrays.xml b/packages/SettingsLib/res/values-et/arrays.xml
index 07fe687..d846292 100644
--- a/packages/SettingsLib/res/values-et/arrays.xml
+++ b/packages/SettingsLib/res/values-et/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Kuva ülejoonistatud alad"</item>
     <item msgid="2290859360633824369">"Deuteranomaly jaoks alade kuvamine"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (vaikeseade)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Standardpiir"</item>
     <item msgid="4071574792028999443">"Taustaprotsessideta"</item>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 507bd20..dd9aeac 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Salvestatud"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Keelatud"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP seadistamise ebaõnnestumine"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Võrgu kehva kvaliteedi tõttu ei ühendatud"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi-ühenduse viga"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Autentimise probleem"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Pole vahemikus"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Mitte ühtegi"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Oodake silurit"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Silutud rakendus ootab toimimiseks siluri lisamist"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telephony Monitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Teenus Telephony Monitor kogub telefoni/modemi funktsioonide probleemide korral logisid ja esitab kasutajale märguande veaaruande esitamiseks"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Sisend"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Joonis"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Tarkvarakiirendusega renderdamine"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Kuva riistv. kiht. värsk."</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Riistvara kihid vilguvad värskendamisel roheliselt"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Silu GPU ülejoonistust"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU renderdi määramine"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Keela HW ülekatted"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Kasuta alati GPU-d kuva koostamisel"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Modelleeri värviruumi"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Sisestage parool, et demorežiimis tehaseseadetele lähtestada"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Järgmine"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Parool on kohustuslik"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Aktiivsed sisestusmeetodid"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Süsteemi keelte kasutamine"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-eu/arrays.xml b/packages/SettingsLib/res/values-eu/arrays.xml
index e4bcf482..91eb801 100644
--- a/packages/SettingsLib/res/values-eu/arrays.xml
+++ b/packages/SettingsLib/res/values-eu/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Erakutsi gainidatzi diren eremuak"</item>
     <item msgid="2290859360633824369">"Erakutsi daltonismorako eremuak"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (lehenetsia)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Muga estandarra"</item>
     <item msgid="4071574792028999443">"Ez dago atzeko planoko prozesurik"</item>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index d8b2496..a3a6841 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Gordeta"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Desgaituta"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Ezin izan da konfiguratu IP helbidea"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Ez dago konektatuta sarearen kalitate eskasagatik"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Ezin izan da konektatu Wi-Fi sarera"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Autentifikazio-arazoa"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Urrunegi"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Ezer ez"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Itxaron araztaileari"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Araztutako aplikazioa araztailea erantsi arte itxaroten ari da exekutatu aurretik"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telefono-gainbegiratzailea"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Telefono-gainbegiratzaileak erregistroak bilduko ditu telefono/modem funtzioarekin arazoren bat dagoela hautematen duenean, eta akatsaren berri emateko eskatuko dio erabiltzaileari"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Sarrera"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Marrazkia"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Hardware bidez bizkortutako errendatzea"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Hardware-geruzen eguneratzeak"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Eguneratu bitartean, hardware-geruzak berdez"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Araztu GPU gainidazketa"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Ezarri GPU errendatzailea"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Desgaitu HW gainjartzeak"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Erabili beti GPU pantaila-muntaietarako"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simulatu kolore-espazioa"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Idatzi pasahitza jatorrizko ezarpenak demo moduan berrezartzeko"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Hurrengoa"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Pasahitza behar da"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Idazketa-metodo aktiboak"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Erabili sistemaren hizkuntzak"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fa/arrays.xml b/packages/SettingsLib/res/values-fa/arrays.xml
index 3c08671..6b7486f 100644
--- a/packages/SettingsLib/res/values-fa/arrays.xml
+++ b/packages/SettingsLib/res/values-fa/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"نمایش نواحی بازنویسی"</item>
     <item msgid="2290859360633824369">"نمایش مناطق برای مبتلایان به سبزدشواربینی"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"‏OpenGL (پیش‌فرض)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"حد استاندارد"</item>
     <item msgid="4071574792028999443">"بدون پردازش در پس‌زمینه"</item>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index e529ac7..d492bde 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"ذخیره‌شده"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"غیرفعال شد"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"‏پیکربندی IP انجام نشد"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"اتصال ناموفق به دلیل شبکه با کیفیت پایین"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"‏اتصال Wi-Fi برقرار نشد"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"مشکل احراز هویت"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"در محدوده نیست"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"هیچ چیز"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"انتظار برای اشکال‌زدا"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"برنامه اشکال‌زدایی شده منتظر پیوست شدن اشکال‌زدا قبل از اجرا است"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telephony Monitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"‏TelephonyMonitor وقتی مشکلی در ارتباط با عملکرد تلفن/مودم تشخیص می‌دهد، گزارش جمع‌آوری می‌کند و با اعلانی از کاربر می‌خواهد گزارش اشکال تهیه کند"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"ورودی"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"طراحی"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"پردازش سخت‌افزاری سریع"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"نمایش به‌روزرسانی‌های لایه‌های سخت‌افزار"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"وقتی لایه‌های سخت‌افزاری به‌روزرسانی‌ می‌شوند، به رنگ سبز درآیند"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"‏اشکال‌زدایی بازنویسی GPU"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"‏تنظیم تولیدکننده تصویرGPU"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"‏غیر فعال کردن پوشش HW"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"‏همیشه از GPU در ترکیب صفحه استفاده شود"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"شبیه‌سازی فضای رنگ"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"برای انجام بازنشانی کارخانه‌ای در حالت نمایشی، گذرواژه را وارد کنید"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"بعدی"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"وارد کردن گذرواژه الزامی است"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"روش‌های ورودی فعال"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"استفاده از زبان‌های سیستم"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fi/arrays.xml b/packages/SettingsLib/res/values-fi/arrays.xml
index 00d967e..f4948c2 100644
--- a/packages/SettingsLib/res/values-fi/arrays.xml
+++ b/packages/SettingsLib/res/values-fi/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Näytä päällekkäiset alueet"</item>
     <item msgid="2290859360633824369">"Näytä alueet puna-vihersokeille näkyvinä"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (oletus)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Vakioraja"</item>
     <item msgid="4071574792028999443">"Ei taustaprosesseja"</item>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 0c28710..abed550 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Tallennettu"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Pois käytöstä"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-kokoonpanovirhe"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Ei yhteyttä – verkko huonolaatuinen"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi-yhteysvirhe"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Todennusvirhe"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Ei kantoalueella"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Ei mitään"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Odota vianetsintää"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Sovellus odottaa vianetsinnän lisäämistä, ja käynnistyy sen jälkeen."</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Puhelinpalvelujen seuranta"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Puhelinpalvelujen seuranta kerää tietoja virheistä puhelinpalvelujen tai modeemin toiminnassa ja kehottaa käyttäjää tekemään virheilmoituksen."</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Syöte"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Piirustus"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Laitteistokiihdytetty hahmonnus"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Näytä laitt.tason päiv."</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Näytä laitteistotasot vihreinä niiden päivittyessä"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU-objektien päällekkäisyys"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Grafiikan piirtäjä"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Poista HW-peittok. käyt."</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Käytä GPU:ta näytön koostamiseen"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simuloi väriavaruus"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Palauta tehdasasetukset antamalla salasana"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Seuraava"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Salasana vaaditaan"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Aktiiviset syöttötavat"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Käytä järjestelmän kieliä"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fr-rCA/arrays.xml b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
index 19f3c83..de920c2 100644
--- a/packages/SettingsLib/res/values-fr-rCA/arrays.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Afficher les zones de conflit"</item>
     <item msgid="2290859360633824369">"Afficher les zones de deutéranomalie"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (par défaut)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Limite standard"</item>
     <item msgid="4071574792028999443">"Aucun processus en arrière-plan"</item>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index ca8f462..d153efd 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Enregistré"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Désactivés"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Échec de configuration de l\'adresse IP"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Non connecté en raison de la mauvaise qualité du réseau"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Échec de connexion Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problème d\'authentification"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Hors de portée"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Aucune"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Attendre l\'intervention du débogueur"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Avant de s\'exécuter, l\'application déboguée doit attendre que le débogueur soit attaché."</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"TelephonyMonitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"TelephonyMonitor recueille des journaux lorsqu\'il détecte un problème lié à la fonctionnalité de téléphonie ou de modem, puis invite l\'utilisateur à soumettre un bogue."</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Entrée"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Dessin"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Accélération matérielle"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Mises à jour couches mat."</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Couches matérielles en vert une fois mises à jour"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Déboguer les conflits GPU"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Chois. moteur rendu vidéo"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Désact. superpos. matér."</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Toujours utiliser le GPU pour la composition écran"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simuler esp. colorimétrique"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Entrez m. passe pour réinit. en mode démo"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Suivant"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Mot de passe obligatoire"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Modes de saisie actifs"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Utiliser les langues du système"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fr/arrays.xml b/packages/SettingsLib/res/values-fr/arrays.xml
index e020328..3e63a58 100644
--- a/packages/SettingsLib/res/values-fr/arrays.xml
+++ b/packages/SettingsLib/res/values-fr/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Afficher les zones de conflit"</item>
     <item msgid="2290859360633824369">"Afficher couleurs de zones adaptées à deutéranomalie"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (valeur par défaut)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Limite standard"</item>
     <item msgid="4071574792028999443">"Aucun processus en arrière-plan"</item>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 05c9e93..5c992ea 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Enregistré"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Désactivé"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Échec de configuration de l\'adresse IP"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Non connecté en raison de la faible qualité du réseau"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Échec de la connexion Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problème d\'authentification."</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Hors de portée"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Aucune"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Attendre l\'intervention du débogueur"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Avant de s\'exécuter, l\'application déboguée doit attendre que le débogueur soit attaché."</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telephony Monitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Telephony Monitor recueille des journaux lorsqu\'il détecte un problème lié à la fonctionnalité de téléphonie ou de modem, puis invite l\'utilisateur à créer un bug"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Saisie"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Tracé"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Accélération matérielle"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Mises à jour couches matérielles"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Couches matérielles en vert une fois mises à jour"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Déboguer les conflits GPU"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Définir moteur rendu processeur graphique"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Désactiver superpos. matér."</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Toujours utiliser le GPU pour la composition écran"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simuler espace colori."</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Saisir mot de passe pour rétablir conf. d\'usine en mode démo."</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Suivant"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Veuillez saisir le mot de passe"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Modes de saisie actifs"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Utiliser les langues du système"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-gl/arrays.xml b/packages/SettingsLib/res/values-gl/arrays.xml
index c909271..32f711c 100644
--- a/packages/SettingsLib/res/values-gl/arrays.xml
+++ b/packages/SettingsLib/res/values-gl/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Mostrar áreas superpostas"</item>
     <item msgid="2290859360633824369">"Mostrar áreas de deuteranomalía"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (Predeterminado)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Límite estándar"</item>
     <item msgid="4071574792028999443">"Ningún proceso en segundo plano"</item>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 5de9407..1fe692d 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Gardada"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Desactivadas"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Erro na configuración de IP"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Non se estableceu conexión porque a rede é de baixa calidade"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Erro na conexión wifi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problema de autenticación"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Non está dentro da zona de cobertura"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Nada"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Agardar polo depurador"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"A aplicación depurada agarda a que o depurador se conecte antes de executarse"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Monitor de telefonía"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"O monitor de telefonía recompilará rexistros cando detecte un problema coa función da telefonía ou do módem e enviará unha notificación ao usuario para solicitarlle que informe dun erro"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Entrada"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Debuxo"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Procesamento acelerado mediante hardware"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Ver actualizacións capas"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Iluminar capas hardware en verde ao actualizarse"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Depurar superposición GPU"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Definir renderizador GPU"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Desact. superposicións HW"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Utilizar sempre GPU para a composición da pantalla"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simular o espazo da cor"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Insire contrasinal para restablec. en demostración"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Seguinte"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"O contrasinal é obrigatorio"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Métodos de entrada activos"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Usar idiomas do sistema"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-gu/arrays.xml b/packages/SettingsLib/res/values-gu/arrays.xml
index 6eb4321..f23fb96 100644
--- a/packages/SettingsLib/res/values-gu/arrays.xml
+++ b/packages/SettingsLib/res/values-gu/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"ઓવરડ્રો ક્ષેત્રો બતાવો"</item>
     <item msgid="2290859360633824369">"Deuteranomaly માટેના ક્ષેત્રો બતાવો"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (ડિફૉલ્ટ)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"માનક સીમા"</item>
     <item msgid="4071574792028999443">"કોઈ પૃષ્ઠભૂમિ પ્રક્રિયાઓ નથી"</item>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 2697419..30338d4 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"સાચવેલા"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"અક્ષમ કર્યો"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP કન્ફિગરેશન નિષ્ફળ"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"ઓછી ગુણવત્તાવાળા નેટવર્કના લીધે કનેક્ટ થયું નથી"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi કનેક્શન નિષ્ફળ"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"પ્રમાણીકરણ સમસ્યા"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"રેન્જમાં નથી"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"કંઈ નહીં"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"ડીબગર માટે રાહ જુઓ"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"ડીબગ કરેલ ઍપ્લિકેશનો ક્રિયાન્વિત થતા પહેલાં ડીબગર જોડાઈ તેની રાહ જુએ છે"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telephony Monitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"TelephonyMonitor ને જ્યારે ટેલિફોની/મૉડેમની કાર્યક્ષમતામાં કોઈ સમસ્યા મળે ત્યારે તે લૉગ એકત્રિત કરશે અને વપરાશકર્તાને બગની જાણ કરવાની સૂચનાનો સંકેત આપશે"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"ઇનપુટ"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"રેખાંકન"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"હાર્ડવેર પ્રવેગક રેન્ડરિંગ"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"હાર્ડવેર સ્તરોનાં અપડેટ્સ બતાવો"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"હાર્ડવેર સ્તરો અપડેટ થાય ત્યારે તેને લીલા રંગથી પ્રકાશિત કરો"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU ઓવરડ્રો ડીબગ કરો"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU રેન્ડરર સેટ કરો"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"HW ઓવરલે અક્ષમ કરો"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"સ્ક્રીન જોડવા માટે હંમેશાં GPU નો ઉપયોગ કરો"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"રંગ સ્થાનનું અનુકરણ કરો"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"ડેમો મોડમાં ફેક્ટરી રીસેટ પાસવર્ડ દાખલ કરો"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"આગલું"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"પાસવર્ડ આવશ્યક છે"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"ઇનપુટ પદ્ધતિઓ સક્રિય કરો"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"સિસ્ટમ ભાષાઓનો ઉપયોગ કરો"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hi/arrays.xml b/packages/SettingsLib/res/values-hi/arrays.xml
index d0c12c8..d841258 100644
--- a/packages/SettingsLib/res/values-hi/arrays.xml
+++ b/packages/SettingsLib/res/values-hi/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"ओवरड्रॉ क्षेत्रों को दिखाएं"</item>
     <item msgid="2290859360633824369">"हरा रंग पहचानने में कमी के क्षेत्र दिखाएं"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (डिफ़ॉल्ट)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"मानक सीमा"</item>
     <item msgid="4071574792028999443">"कोई पृष्ठभूमि प्रक्रियाएं नहीं"</item>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index f0cb2e3..b284443 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"सहेजा गया"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"अक्षम"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP कॉन्‍फ़िगरेशन की विफलता"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"खराब नेटवर्क होने के कारण कनेक्ट नहीं हुआ"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"वाईफ़ाई कनेक्‍शन विफलता"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"प्रमाणीकरण समस्या"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"रेंज में नहीं"</string>
@@ -189,8 +190,8 @@
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"प्रति लॉग बफ़र लॉगर आकार चुनें"</string>
     <string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"लॉगर सतत मेमोरी साफ़ करें?"</string>
     <string name="dev_logpersist_clear_warning_message" msgid="2256582531342994562">"जब हम सतत लॉगर के साथ निगरानी करना बंद कर देते हैं, तो हमें आपके डिवाइस पर मौजूद लॉगर डेटा को मिटाने की आवश्यकता होती है."</string>
-    <string name="select_logpersist_title" msgid="7530031344550073166">"डिवाइस पर लॉगर डेटा सतत संग्रहीत करें"</string>
-    <string name="select_logpersist_dialog_title" msgid="4003400579973269060">"डिवाइस पर सतत रूप से संग्रहीत करने के लिए लॉग बफ़र चुनें"</string>
+    <string name="select_logpersist_title" msgid="7530031344550073166">"डिवाइस पर लॉगर डेटा सतत संग्रहित करें"</string>
+    <string name="select_logpersist_dialog_title" msgid="4003400579973269060">"डिवाइस पर सतत रूप से संग्रहित करने के लिए लॉग बफ़र चुनें"</string>
     <string name="select_usb_configuration_title" msgid="2649938511506971843">"USB कॉन्फ़िगरेशन चुनें"</string>
     <string name="select_usb_configuration_dialog_title" msgid="6385564442851599963">"USB कॉन्फ़िगरेशन चुनें"</string>
     <string name="allow_mock_location" msgid="2787962564578664888">"कृत्रिम स्‍थानों को अनुमति दें"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"कुछ भी नहीं"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"डीबगर की प्रतीक्षा करें"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"डीबग किया गया ऐप्स  निष्पादन के पहले अनुलग्न करने के लिए डीबगर की प्रतीक्षा करता है"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"टेलीफ़ोनी मॉनिटर"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"टेलीफ़ोनी मॉनिटर को जब टेलीफ़ोनी/मॉडेम कार्यक्षमता में कोई समस्या मिलती है तो वह लॉग इकट्ठा करता है और उपयोगकर्ता को एक बग दर्ज करने के लिए नोटिफ़िकेशन देता है"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"हिंदी में लिखें"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"ड्रॉइंग"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"हार्डवेयर त्वरित रेंडरिंग"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"हार्डवेयर लेयर की नई जानकारी"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"हार्डवेयर लेयर की नई जानकारी मिलने पर हरा फ़्लैश होता है"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU ओवरड्रॉ डीबग करें"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU दाता सेट करें"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"HW ओवरले अक्षम करें"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"स्‍क्रीन संयोजन के लिए हमेशा GPU का उपयोग करें"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"रंग स्पेस सिम्युलेट करें"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"डेमो मोड में फ़ैक्टरी रीसेट के लिए पासवर्ड डालें"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"आगे"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"पासवर्ड आवश्यक"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"टाइप करने की सक्रीय पद्धतियां"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"सिस्टम की भाषाओं का उपयोग करें"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hr/arrays.xml b/packages/SettingsLib/res/values-hr/arrays.xml
index 9224adf..2295067 100644
--- a/packages/SettingsLib/res/values-hr/arrays.xml
+++ b/packages/SettingsLib/res/values-hr/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Pokaži područja slojnih iscrtavanja"</item>
     <item msgid="2290859360633824369">"Prikaži područja za deuteranomaliju"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (zadano)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Standardna ograničenje"</item>
     <item msgid="4071574792028999443">"Nema pozadinskih procesa"</item>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 8313ca1..c02785e 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Spremljeno"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Onemogućeno"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Konfiguracija IP-a nije uspjela"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Niste povezani jer je mreža loše kvalitete"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Povezivanje s Wi-Fi-jem nije uspjelo"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problem u autentifikaciji"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Nije u rasponu"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Ništa"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Čeka se program za otklanjanje pogrešaka"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Aplikacija čeka priključivanje programa za otklanjanje pogrešaka"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"TelephonyMonitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"TelephonyMonitor prikupljat će zapisnike kada otkrije problem s funkcioniranjem telefona/modema i obavijestiti korisnika da prijavi programsku pogrešku"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Ulaz"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Crtež"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Hardverski ubrzano renderiranje"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Prikaži ažuriranja hardverskih slojeva"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Hardverski slojevi bljeskaju zeleno pri ažuriranju."</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Rješavanje GPU preklapanja"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Postavi ispunjivač GPU-a"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Onemogući dijeljenje mem."</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Uvijek koristi GPU za slaganje zaslona"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simuliraj prostor boja"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Unesite zaporku za resetiranje u demo načinu"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Dalje"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Potrebna je zaporka"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Aktivni načini unosa"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Upotrijebi jezike sustava"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hu/arrays.xml b/packages/SettingsLib/res/values-hu/arrays.xml
index db5aae8..c36c398 100644
--- a/packages/SettingsLib/res/values-hu/arrays.xml
+++ b/packages/SettingsLib/res/values-hu/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Tartalom-felülírási területek mutatása"</item>
     <item msgid="2290859360633824369">"A deuteranomália területeinek megjelenítése"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (alapértelmezett)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Normál korlátozás"</item>
     <item msgid="4071574792028999443">"Nincsenek háttérfolyamatok"</item>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 15417d6..067e1f3 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Mentve"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Letiltva"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-konfigurációs hiba"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Nem kapcsolódik a hálózat rossz minősége miatt"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi-kapcsolati hiba"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Azonosítási probléma"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Hatókörön kívül"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Semmi"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Várjon a hibakeresőre."</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"A javított alkalmazás a hibakeresőre vár."</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telephony Monitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"A TelephonyMonitor begyűjti a naplókat, ha problémát észlel a telefonos szolgáltatások vagy a modem működésében, és javasolja a felhasználónak a hiba jelentését"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Bevitel"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Rajz"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Hardveres gyorsítású megjelenítés"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Hardverréteg-frissítések"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Frissítéskor a hardverrétegek zölden villognak"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU tartalom-felülírási hibakeresés"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU-megjelenítő megadása"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"HW fedvények letiltása"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Mindig a GPU használata képernyő-feldolgozáshoz"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Színtérszimuláció"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Írja be a jelszót a visszaállításhoz"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Következő"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Jelszó szükséges"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Aktív beviteli módok"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Rendszernyelvek használata"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hy/arrays.xml b/packages/SettingsLib/res/values-hy/arrays.xml
index 8925f32..85cda6b 100644
--- a/packages/SettingsLib/res/values-hy/arrays.xml
+++ b/packages/SettingsLib/res/values-hy/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Ցույց տալ գերազանցված հատվածները"</item>
     <item msgid="2290859360633824369">"Ցույց տալ դալտոնիզմի ոլորտները"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (կանխադրված)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Սովորական սահման"</item>
     <item msgid="4071574792028999443">"Հետնաշերտում գործողություններ չկան"</item>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index c75220f..9412bda 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Պահված է"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Անջատված"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP կարգավորման ձախողում"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Չի կապակցվել ցանցի թույլ ազդանշանի պատճառով"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi կապի ձախողում"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Նույնականացման խնդիր"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Ընդգրկույթից դուրս է"</string>
@@ -124,8 +125,8 @@
     <string name="tts_engine_settings_button" msgid="1030512042040722285">"Գործարկման շարժիչի կարգավորումներ"</string>
     <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Նախընտրած շարժիչը"</string>
     <string name="tts_general_section_title" msgid="4402572014604490502">"Ընդհանուր"</string>
-    <string name="tts_reset_speech_pitch_title" msgid="5789394019544785915">"Վերակայել արտասանման ձայնի բարձրությունը"</string>
-    <string name="tts_reset_speech_pitch_summary" msgid="8700539616245004418">"Տեքստի արտասանման ձայնի բարձրությունը վերադարձնել կանխադրված արժեքի:"</string>
+    <string name="tts_reset_speech_pitch_title" msgid="5789394019544785915">"Վերակայել արտասանման ձայնի ուժգնությունը"</string>
+    <string name="tts_reset_speech_pitch_summary" msgid="8700539616245004418">"Տեքստի արտասանման ձայնի ուժգնությունը վերադարձնել կանխադրված արժեքի:"</string>
   <string-array name="tts_rate_entries">
     <item msgid="6695494874362656215">"Շատ դանդաղ"</item>
     <item msgid="4795095314303559268">"Դանդաղ"</item>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Ոչինչ"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Սպասել վրիպազերծիչին"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Վրիպազերծված ծրագրիը սպասում է վրիպազերծիչի կցմանը մինչ կատարումը"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telephony Monitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Հեռախոսակապի/մոդեմի հետ կապված խնդիրներ հայտնաբերելու դեպքում TelephonyMonitor-ը կհավաքի մատյանները և օգտվողին կհուշի վրիպակ գրանցելու անհրաժեշտության մասին"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Մուտքագրում"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Պատկերում"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Սարքաշարի արագացված նյութավորում"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Ցույց տալ սարքաշարի ծածկույթի թարմացումները"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Թող սարքաշարի ծածկույթները կանաչ գույնով առկայծեն, երբ  թարմացվեն"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Վրիպազերծել GPU գերազանցումները"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Կարգավորել GPU Renderer"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Կասեցնել HW վերադրումները"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Միշտ օգտագործել GPU-ն` էկրանի կազմման համար"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Նմանակել գունատարածքը"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Մուտքագրեք գաղտնաբառը՝ ցուցադրական ռեժիմում գործարանային վերակայում կատարելու համար"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Հաջորդը"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Պահանջվում է գաղտնաբառ"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Մուտքագրման ակտիվ տարբերակներ"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Օգտագործել համակարգի լեզուները"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-in/arrays.xml b/packages/SettingsLib/res/values-in/arrays.xml
index fae09d0..d1c13da 100644
--- a/packages/SettingsLib/res/values-in/arrays.xml
+++ b/packages/SettingsLib/res/values-in/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Tampilkan area overdraw"</item>
     <item msgid="2290859360633824369">"Tampilkan area untuk Buta Warna"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (Default)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Batas standar"</item>
     <item msgid="4071574792028999443">"Tanpa proses latar belakang"</item>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 186b79c..fb0c29e 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Disimpan"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Nonaktif"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Kegagalan Konfigurasi IP"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Tidak tersambung karena jaringan berkualitas rendah"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Kegagalan Sambungan Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Masalah autentikasi"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Tidak dalam jangkauan"</string>
@@ -87,11 +88,11 @@
     <string name="process_kernel_label" msgid="3916858646836739323">"OS Android"</string>
     <string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Aplikasi dihapus"</string>
     <string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Aplikasi dan pengguna yang dihapus"</string>
-    <string name="tether_settings_title_usb" msgid="6688416425801386511">"Penambatan USB"</string>
+    <string name="tether_settings_title_usb" msgid="6688416425801386511">"Tethering USB"</string>
     <string name="tether_settings_title_wifi" msgid="3277144155960302049">"Hotspot portabel"</string>
-    <string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Penambatan bluetooth"</string>
+    <string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Tethering bluetooth"</string>
     <string name="tether_settings_title_usb_bluetooth" msgid="5355828977109785001">"Menambatkan"</string>
-    <string name="tether_settings_title_all" msgid="8356136101061143841">"Menambatkan &amp; hotspot portabel"</string>
+    <string name="tether_settings_title_all" msgid="8356136101061143841">"Tethering &amp; hotspot portabel"</string>
     <string name="managed_user_title" msgid="8109605045406748842">"Semua aplikasi kerja"</string>
     <string name="user_guest" msgid="8475274842845401871">"Tamu"</string>
     <string name="unknown" msgid="1592123443519355854">"Tidak diketahui"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Tidak ada"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Tunggu debugger"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Aplikasi yang di-debug menunggu debugger menempel sebelum berjalan"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Monitor Telefoni"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Monitor Telefoni akan mengumpulkan log jika mendeteksi masalah pada fungsi telefoni/modem dan mengirimkan notifikasi ke pengguna untuk melaporkan bug"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Masukan"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Gambar"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Render yang dipercepat perangkat keras"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Tunjukkan pembaruan lapisan hardware"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Lapisan hardware berkedip hijau saat memperbarui"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Debug overdraw oleh GPU"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Setel Perender GPU"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Nonaktifkan lapisan HW"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Selalu gunakan GPU untuk pengomposisian layar"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simulasikan ruang warna"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Masukkan sandi untuk mengembalikan ke setelan pabrik dalam mode demo"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Berikutnya"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Perlu sandi"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Metode masukan aktif"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Gunakan bahasa sistem"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-is/arrays.xml b/packages/SettingsLib/res/values-is/arrays.xml
index 7062632..82fa767 100644
--- a/packages/SettingsLib/res/values-is/arrays.xml
+++ b/packages/SettingsLib/res/values-is/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Sýna yfirteiknuð svæði"</item>
     <item msgid="2290859360633824369">"Sýna svæði fyrir litblinda"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (sjálfgefið)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Venjulegt hámark"</item>
     <item msgid="4071574792028999443">"Engar bakgrunnsvinnslur"</item>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 844a3b4..a3e2da4 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Vistað"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Óvirkt"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-stillingarvilla"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Tenging er ekki til staðar því nettengingin er léleg"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi-tengingarvilla"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Vandamál við auðkenningu"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Ekkert samband"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Ekkert"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Bíða eftir villuleit"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Villuleituð forrit bíða eftir að villuleit tengist fyrir keyrslu"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Fjarskiptaumsjón"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Fjarskiptaumsjón mun safna annálum þegar það skynjar vandamál með fjarskipti/virkni mótalds og veita notanda beiðni um að senda inn villutilkynningu"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Inntak"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Teikning"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Myndþýðing með vélbúnaðarhröðun"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Sýna uppfærslur vélbúnaðar"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Láta vélbúnaðarlög blikka græn við uppfærslu"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Yfirteiknun skjákorts"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Stilla skjákortsteiknun"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Slökkva á vélb.yfirlögnum"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Nota alltaf skjákort við samsetningu skjámyndar"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Herma eftir litasviði"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Sláðu inn aðgangsorð til að framkvæma núllstillingu í sýnisútgáfu"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Áfram"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Aðgangsorðs krafist"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Virkar innsláttaraðferðir"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Nota kerfistungumál"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-it/arrays.xml b/packages/SettingsLib/res/values-it/arrays.xml
index 85904b5..7bdccb9 100644
--- a/packages/SettingsLib/res/values-it/arrays.xml
+++ b/packages/SettingsLib/res/values-it/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Mostra aree overdraw"</item>
     <item msgid="2290859360633824369">"Mostra aree con deuteranomalia"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (predefinito)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Limite standard"</item>
     <item msgid="4071574792028999443">"Nessun processo in background"</item>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 7e3fd48..347dfbf 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Salvata"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Disattivata"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Errore configurazione IP"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Impossibile connettersi a causa della bassa qualità della rete"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Errore connessione Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problema di autenticazione"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Fuori portata"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Nessuna"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Attendi debugger"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"L\'app in debug attende il debugger prima dell\'esecuzione"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"TelephonyMonitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"TelephonyMonitor raccoglierà log quando rileverà un problema con la funzionalità di telefonia/del modem e avviserà tempestivamente l\'utente per segnalare il bug"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Input"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Disegno"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Rendering con accelerazione hardware"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Aggiornam. livelli hardware"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Lampeggia verde se aggiornam. livelli hardware"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Debug overdraw GPU"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Imposta renderer GPU"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Disabilita overlay HW"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Usa sempre GPU per la composizione dello schermo"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simula spazio colore"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Inserisci la password per eseguire il ripristino dei dati di fabbrica in modalità demo"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Avanti"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Password obbligatoria"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Metodi di immissione attivi"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Utilizza le lingue di sistema"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-iw/arrays.xml b/packages/SettingsLib/res/values-iw/arrays.xml
index 2cf333f..aef6e18 100644
--- a/packages/SettingsLib/res/values-iw/arrays.xml
+++ b/packages/SettingsLib/res/values-iw/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"הצגת אזורים עם חריגה"</item>
     <item msgid="2290859360633824369">"הצגת אזורים לעיוורון צבעים"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"‏OpenGL (ברירת מחדל)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)‎"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"הגבלה סטנדרטית"</item>
     <item msgid="4071574792028999443">"אין תהליכים ברקע"</item>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 3e1bfdb..309320e 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"נשמר"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"מושבת"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"‏כשל בתצורת IP"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"אין חיבור לרשת, כי איכות הרשת נמוכה"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"‏כשל בחיבור Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"בעיית אימות"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"מחוץ לטווח"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"אף אחת"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"המתן למנקה באגים"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"אפליקציה שנוקו בה הבאגים ממתינה למנקה הבאגים לצירוף לפני ביצוע"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telephony Monitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"‏TelephonyMonitor יאסוף מידע ביומנים כשיזהה בעיה בפונקציונליות של טלפוניה/מודם. הוא ישלח הודעה למשתמש כדי שיוכל להגיש דוח על באג"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"קלט"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"שרטוט"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"עיבוד מואץ של חומרה"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"הצג עדכוני שכבות חומרה"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"הצג הבהוב ירוק לשכבות חומרה כשהן מתעדכנות"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"‏חריגה בניפוי באגים ב-GPU"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"‏הגדר את כלי העיבוד ל-GPU"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"‏השבת שכבות על של HW"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"‏השתמש תמיד ב-GPU להרכבת מסך"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"צור הדמיה של מרחב צבעים"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"הזן סיסמה כדי לבצע איפוס להגדרות היצרן במצב הדגמה"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"הבא"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"דרושה סיסמה"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"שיטות קלט פעילות"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"שימוש בשפות מערכת"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ja/arrays.xml b/packages/SettingsLib/res/values-ja/arrays.xml
index 748bbab..843502f 100644
--- a/packages/SettingsLib/res/values-ja/arrays.xml
+++ b/packages/SettingsLib/res/values-ja/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"オーバードロー領域の表示"</item>
     <item msgid="2290859360633824369">"第二色弱の方向けの領域の表示"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL(デフォルト)"</item>
+    <item msgid="2839130076198120436">"OpenGL(Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"標準の上限"</item>
     <item msgid="4071574792028999443">"バックグラウンドプロセスを使用しない"</item>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 06602e3..3bfbfdd 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"保存済み"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"無効"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP設定エラー"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"ネットワークの品質が低いため、接続されていません"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi接続エラー"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"認証に問題"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"圏外"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"なし"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"デバッガを待機"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"アプリは実行前にデバッガのアタッチを待機します"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telephony Monitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Telephony Monitor は、電話やモデムの機能で問題が検出されたときにログを収集し、バグを報告するようユーザーに通知を表示します"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"入力"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"描画"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"ハードウェアアクセラレーテッドレンダリング"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"ハードウェア層情報を表示"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"ハードウェア層が更新されると緑を表示する"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPUオーバードローをデバッグ"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU レンダラの設定"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"HWオーバーレイを無効"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"画面合成に常にGPUを使用する"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"色空間シミュレート"</string>
@@ -358,4 +362,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"デモモードで初期状態にリセットするには、パスワードを入力してください"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"次へ"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"パスワード必須"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"有効な入力方法"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"システム言語を使用"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ka/arrays.xml b/packages/SettingsLib/res/values-ka/arrays.xml
index a630af2..89e5aa58 100644
--- a/packages/SettingsLib/res/values-ka/arrays.xml
+++ b/packages/SettingsLib/res/values-ka/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"overdraw არეების ჩვენება"</item>
     <item msgid="2290859360633824369">"დეუტერანომალიის არეების ჩვენება"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (ნაგულისხმევი)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"სტანდარტული ლიმიტი"</item>
     <item msgid="4071574792028999443">"ფონური პროცესები არ არის"</item>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 6838fbc..7adb0e1 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"დამახსოვრებულია"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"გამორთულია"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP კონფიგურაციის შეფერხება"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"არ არის დაკავშირებული დაბალი ხარისხის ქსელის გამო"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi კავშირის შეფერხება"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"ავთენტიკაციის პრობლემა"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"არ არის დიაპაზონში"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"არაფერი"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"დაილოდეთ, სანამ ჩაირთვება გამმართველი"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"გამართული აპლიკაცია ელოდება გამმართველის ჩართვას გაშვებამდე"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"ტელეფონიის კონტროლიორი"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"ტელეფონიის/მოდემის გამართულ მუშაობასთან დაკავშირებული პრობლემის გამოვლენისას, ტელეფონიის კონტროლიორი შეაგროვებს ჟურნალების ჩანაწერებს, ხოლო მომხმარებელს შეცდომის შესახებ მოხსენებას შეთავაზებს"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"ტექსტის შეყვანა"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"ნახაზი"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"აპარატურით დაჩქარებული გამოსახულება"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"აპარატურის დონეების განახლებების ჩვენება"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"განახლებისას სააპარატო დონეების მწვანით მონიშვნა"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU overdraw-ს გამართვა"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU Renderer-ის დაყენება"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"HW გადაფარვის გამორთვა"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"ეკრანის კომპოზიციისთვის ყოველთვის გამოიყენე GPU"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"ფერთა სივრცის სიმულაცია"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"შეიყვანეთ პაროლი დემო-რეჟიმში ქარხნულ მდგომარეობაზე დასაბრუნებლად"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"შემდეგი"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"საჭიროა პაროლი"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"შეყვანის აქტიური მეთოდები"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"სისტემის ენების გამოყენება"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-kk/arrays.xml b/packages/SettingsLib/res/values-kk/arrays.xml
index 9c6e082..a0959e1 100644
--- a/packages/SettingsLib/res/values-kk/arrays.xml
+++ b/packages/SettingsLib/res/values-kk/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Үстінен бастырылған аймақтарды көрсету"</item>
     <item msgid="2290859360633824369">"Дейтераномалия аймақтарын көрсету"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (әдепкі)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Стандартты шектеу"</item>
     <item msgid="4071574792028999443">"Фондық үрдістер жоқ"</item>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 9372dbd..e6ab846 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Сақталды"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Өшірілген"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP конфигурациясының қатесі"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Желі байланысының сапасы төмен болғандықтан қосылмады"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi байланысының қатесі"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Растау мәселесі"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Аумақта жоқ"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Ешнәрсе"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Жөндеушіні күту"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Орындау алдында бекіту үшін жөнделген қолданба жөндеушіні күтеді."</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telephony Monitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Telephony Monitor функциясы телефон не модем жұмысында ақау байқаған жағдайда деректерді жинайды да, пайдаланушыға қате туралы ақпаратты жіберуді ұсынады"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Кіріс"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Сызу"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Бейнелеуді жабдықпен жылдамдату"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Компьютерлік жабдықтама қабаттарының жаңартулары"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Жаңартылғанда компьютерлік жабдықтама қабаттарының жасыл шамы жануы"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Үстінен бастырылғанды жөндеу"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU бейне өңдеу құралын таңдау"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Жабдықпен үстінен бастыруды өшіру"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Экранды жасақтау үшін әрқашан графикалық процессор қолдану қажет"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Түстер аймағына еліктеу"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Демо режимде зауыттық мәндерге қайтару үшін құпия сөзді енгізу"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Келесі"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Құпия сөз қажет"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Белсенді енгізу әдістері"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Жүйелік тілдерді пайдалану"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-km/arrays.xml b/packages/SettingsLib/res/values-km/arrays.xml
index 87009e9..e612b74 100644
--- a/packages/SettingsLib/res/values-km/arrays.xml
+++ b/packages/SettingsLib/res/values-km/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"បង្ហាញ​តំបន់​​ដែល​លើស"</item>
     <item msgid="2290859360633824369">"បង្ហាញ​តំបន់​សម្រាប់ Deuteranomaly"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (លំនាំដើម)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"ដែន​កំណត់​ស្តង់ដារ"</item>
     <item msgid="4071574792028999443">"គ្មាន​ដំណើរការ​​ក្នុង​ផ្ទៃ​ខាង​ក្រោយ"</item>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 22360c7..1b583fa 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"បាន​រក្សាទុក"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"បាន​បិទ"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"ការ​កំណត់​រចនាសម្ព័ន្ធ IP បរាជ័យ"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"មិន​អាច​ភ្ជាប់​បាន​ទេ ដោយសារ​បណ្តាញ​មាន​គុណភាព​សេវា​ខ្សោយ"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"ការ​ភ្ជាប់​ WiFi បរាជ័យ"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"បញ្ហា​ក្នុង​ការ​ផ្ទៀងផ្ទាត់"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"នៅ​ក្រៅ​តំបន់"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"គ្មាន​អ្វីទេ"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"រង់ចាំ​កម្មវិធី​កែ​កំហុស"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"កម្មវិធី​បាន​កែ​កំហុស​រង់ចាំ​ឲ្យ​ភ្ជាប់​កម្មវិធី​កែ​កំហុស​មុន​ពេល​អនុវត្ត"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telephony Monitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"TelephonyMonitor នឹង​ប្រមូល​កំណត់​ហេតុ នៅពេល​វា​រកឃើញ​បញ្ហា​ទាក់ទង​នឹង​មុខងារ​ទូរសព្ទ/ម៉ូដឹម និង​បញ្ជូនការ​ជូន​ដំណឹង​ទៅកាន់​អ្នក​ប្រើប្រាស់​ដើម្បី​រាយការណ៍​ពី​បញ្ហា​"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"បញ្ចូល"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"គំនូរ"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"បង្ហាញ​ផ្នែក​រឹង​បាន​បង្កើន​ល្បឿន"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"បង្ហាញ​​បច្ចុប្បន្នភាព​ស្រទាប់​ផ្នែក​រឹង"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"ស្រទាប់​ផ្នែក​រឹង​បញ្ចេញ​ពន្លឺ​បៃ​តង​ ពេល​ពួក​វា​ធ្វើ​បច្ចុប្បន្នភាព"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"កែ​កំហុស​ការ​លើស GPU"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"កំណត់​កម្មវិធី​បំប្លែង GPU"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"បិទ​ការ​ត្រួត HW"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"ប្រើ GPU ជា​និច្ច​សម្រាប់​​ផ្សំ​អេក្រង់"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"ក្លែង​ធ្វើ​ចន្លោះ​ពណ៌"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"បញ្ចូល​ពាក្យ​សម្ងាត់ ដើម្បី​កំណត់ឧបករណ៍​​ឡើង​វិញ​ដូចពេលចេញ​ពី​រោងចក្រ នៅក្នុង​មុខងារ​សាកល្បង"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"បន្ទាប់"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"តម្រូវ​ឲ្យ​មានពាក្យ​សម្ងាត់"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"វិធីសាស្ត្រ​បញ្ចូល​សកម្ម"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"ប្រើភាសាប្រព័ន្ធ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-kn/arrays.xml b/packages/SettingsLib/res/values-kn/arrays.xml
index c729b42..e3a57e3 100644
--- a/packages/SettingsLib/res/values-kn/arrays.xml
+++ b/packages/SettingsLib/res/values-kn/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"ಓವರ್‌ಡ್ರಾ ಪ್ರದೇಶಗಳನ್ನು ತೋರಿಸು"</item>
     <item msgid="2290859360633824369">"ಡ್ಯೂಟರ್‌ನೋಮಲಿಗಾಗಿ ಪ್ರದೇಶಗಳನ್ನು ತೋರಿಸು"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (ಡೀಫಾಲ್ಟ್)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"ಪ್ರಮಾಣಿತ ಮಿತಿ"</item>
     <item msgid="4071574792028999443">"ಹಿನ್ನೆಲೆ ಪ್ರಕ್ರಿಯೆಗಳು ಇಲ್ಲ"</item>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 3cf5f8e..60176fa 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"ಉಳಿಸಲಾಗಿದೆ"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP ಕಾನ್ಫಿಗರೇಶನ್ ವಿಫಲತೆ"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"ಕಡಿಮೆ ಗುಣಮಟ್ಟದ ನೆಟ್‌ವರ್ಕ್‌ನಿಂದಾಗಿ ಸಂಪರ್ಕ ಸಾಧಿಸಿಲ್ಲ"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi ಸಂಪರ್ಕ ವಿಫಲತೆ"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"ಪ್ರಮಾಣೀಕರಣ ಸಮಸ್ಯೆ"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"ವ್ಯಾಪ್ತಿಯಲ್ಲಿಲ್ಲ"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"ಏನೂ ಇಲ್ಲ"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"ಡೀಬಗರ್‌‌ಗಾಗಿ ನಿರೀಕ್ಷಿಸಿ"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"ಲಗತ್ತನ್ನು ಕಾರ್ಯಗತಗೊಳಿಸುವ ಮೊದಲು ಡೀಬಗರ್‌‌ಗಾಗಿ ಡೀಬಗ್‌‌‌ ಮಾಡಿದ ಅಪ್ಲಿಕೇಶನ್‌‌ ಕಾಯುತ್ತದೆ"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"ದೂರವಾಣಿ ಮಾನಿಟರ್"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"ದೂರವಾಣಿ/ಮೊಡೆಮ್ ಕಾರ್ಯಾಚರಣೆಯಲ್ಲಿ ಸಮಸ್ಯೆಗಳು ಕಂಡುಬಂದಾಗ, ದೂರವಾಣಿ ಮಾನಿಟರ್ ಲಾಗ್‌ಗಳನ್ನು ಸಂಗ್ರಹಿಸುತ್ತದೆ ಮತ್ತು ದೋಷದ ಕುರಿತು ವರದಿ ಸಲ್ಲಿಸಲು ಬಳಕೆದಾರನಿಗೆ ಸೂಚನೆ ನೀಡುತ್ತದೆ"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"ಇನ್‌ಪುಟ್"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"ಚಿತ್ರಣ"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"ಹಾರ್ಡ್‌ವೇರ್‌ ವೇಗವರ್ಧಿತ ರೆಂಡರಿಂಗ್"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"ಹಾರ್ಡ್‌ವೇರ್‌ ಲೇಯರ್‌‌ ಅಪ್‌ಡೇಟ್‌"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"ಅವುಗಳು ನವೀಕರಿಸಿದಾಗ ಹಾರ್ಡ್‌ವೇರ್‌‌ ಲೇಯರ್‌ಗಳು ಹಸಿರು ಫ್ಲ್ಯಾಶ್‌‌ ಆಗುತ್ತದೆ"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU ಓವರ್‌ಡ್ರಾ ಡೀಬಗ್"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU ರೆಂಡರರ್ ಹೊಂದಿಸಿ"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"HW ಓವರ್‌ಲೇ ನಿಷ್ಕ್ರಿಯ"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"ಸ್ಕ್ರೀನ್ ಸಂಯೋಜನೆಗಾಗಿ ಯಾವಾಗಲೂ GPU ಬಳಸಿ"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"ಬಣ್ಣದ ಸ್ಥಳ ಸಿಮ್ಯುಲೇಟ್‌"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"ಫ್ಯಾಕ್ಟರಿ ರಿಸೆಟ್‌ಗೆ ಪಾಸ್‌ವರ್ಡ್ ನಮೂದಿಸಿ"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"ಮುಂದೆ"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"ಪಾಸ್‌ವರ್ಡ್ ಅಗತ್ಯವಿದೆ"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"ಸಕ್ರಿಯ ಇನ್‌ಪುಟ್ ವಿಧಾನಗಳು"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"ಸಿಸ್ಟಂ ಭಾಷೆಗಳನ್ನು ಬಳಸಿ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ko/arrays.xml b/packages/SettingsLib/res/values-ko/arrays.xml
index 460f947..1c0e3e1 100644
--- a/packages/SettingsLib/res/values-ko/arrays.xml
+++ b/packages/SettingsLib/res/values-ko/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"오버드로 영역 표시"</item>
     <item msgid="2290859360633824369">"녹색약 영역 표시"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL(기본)"</item>
+    <item msgid="2839130076198120436">"OpenGL(Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"표준 제한"</item>
     <item msgid="4071574792028999443">"백그라운드 프로세스 없음"</item>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 3fbf4cd..7c86313 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"저장됨"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"사용 중지됨"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP 설정 실패"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"저품질 네트워크로 인해 연결되지 않음"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi 연결 실패"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"인증 문제"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"범위 내에 없음"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"없음"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"디버거 연결을 위해 대기"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"디버깅된 애플리케이션이 실행되기 전에 디버거 연결을 위해 대기"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"통신 모니터"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"통신 모니터는 통신/모뎀 기능에서 문제가 감지될 경우 로그를 수집하며 사용자에게 버그를 신고하라는 알림을 표시합니다."</string>
     <string name="debug_input_category" msgid="1811069939601180246">"입력"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"그림"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"하드웨어 가속 렌더링"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"하드웨어 업데이트 표시"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"업데이트 할 때 하드웨어 레이어 깜박이기"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU 오버드로 디버깅"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU 렌더기 설정"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"HW 오버레이 사용 안함"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"화면 합성 목적으로 항상 GPU 사용"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"색상 공간 시뮬레이션"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"데모 모드에서 초기화하려면 비밀번호 입력"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"다음"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"비밀번호 입력 필요"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"입력 방법"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"시스템 언어 사용"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ky/arrays.xml b/packages/SettingsLib/res/values-ky/arrays.xml
index 4d1a685..84d9d63 100644
--- a/packages/SettingsLib/res/values-ky/arrays.xml
+++ b/packages/SettingsLib/res/values-ky/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Үстүнө тартуу аймагын көргөзүү"</item>
     <item msgid="2290859360633824369">"Дейтераномалиялуулар үчүн мейкиндикти көргөзүү"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (Демейки)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Стандарттык чектөө"</item>
     <item msgid="4071574792028999443">"Фондо процесстер жок"</item>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 6608ae5..c9bfc1a 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Сакталды"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Өчүрүлгөн"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP конфигурациясы бузулду"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Тармактын сапаты начар болгондуктан туташкан жок"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi туташуусу бузулду"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Аутентификация маселеси бар"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Тейлөө аймагында эмес"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Эч бирөө"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Жөндөөчү күтүлүүдө"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Жөндөлүүчү колдонмо аткаруудан мурун жөндөөчүнүнүн тиркелишин күтүп жатат"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telephony Monitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"TelephonyMonitor телефондун/модемдин функцияларында көйгөй тапса, анын таржымалын аныктайт жана мүчүлүштүк тууралуу кабарлоо үчүн колдонуучуга эскертме жөнөтөт"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Киргизүү"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Тартуу"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Визуалдаштырууну аппарат менен ылдамдатуу"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Катмарлардын аппараттык жаңырышы"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Катмарлардын аппараттык жаңырышын жашыл м-н белг."</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU үстүнө тартуусун жөндөө"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU өткөргүчүн жөндөө"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Аппар. катмарлаш-у өчүрүү"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Экранды калыптоодо ар дайым GPU колдонулсун"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Түс мейкиндигин эмуляциялоо"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Демо режиминде демейки жөндөөлөргө кайтаруу үчүн сырсөздү киргизиңиз"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Кийинки"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Сырсөз талап кылынат"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Жигердүү киргизүү ыкмалары"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Тутум тилдерин колдонуу"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-lo/arrays.xml b/packages/SettingsLib/res/values-lo/arrays.xml
index 67b5943..fdb502c 100644
--- a/packages/SettingsLib/res/values-lo/arrays.xml
+++ b/packages/SettingsLib/res/values-lo/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"ສະແດງຂອບເຂດການແຕ້ມທັບ"</item>
     <item msgid="2290859360633824369">"ສະແດງພື້ນທີ່ສຳລັບ Deuteranomaly"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (ຄ່າເລີ່ມຕົ້ນ)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"ຂີດຈຳກັດມາດຕະຖານ"</item>
     <item msgid="4071574792028999443">"ບໍ່ມີໂປຣເຊສພື້ນຫຼັງ"</item>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 9c493f2..f36edd1 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"ບັນ​ທຶກແລ້ວ"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"ປິດການນຳໃຊ້"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"ການ​ຕັ້ງ​ຄ່າ IP ລົ້ມ​ເຫຼວ"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"ບໍ່ໄດ້ເຊື່ອມຕໍ່ເນື່ອງຈາກຄຸນນະພາບເຄືອຂ່າຍຕໍ່າ"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"​ການ​ເຊື່ອມ​ຕໍ່ WiFi ລົ້ມ​ເຫຼວ"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"ບັນຫາການພິສູດຢືນຢັນ"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"ບໍ່ຢູ່ໃນໄລຍະທີ່ເຊື່ອມຕໍ່ໄດ້"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"ບໍ່ມີຫຍັງ"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"ລໍຖ້າໂຕດີບັ໊ກ"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"ແອັບພລິເຄຊັນທີ່ດີບັ໊ກແລ້ວ ຈະຖ້າໂຕດີບັ໊ກກ່ອນການເຮັດວຽກ"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telephony Monitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"TelephonyMonitor ຈະເກັບກຳບັນທຶກການເຮັດວຽກເມື່ອມັນກວດພົບບັນຫາກັບການເຮັດວຽກຂອງລະບົບໂທລະສັບ/ໂມເດັມ ແລະ ແຈ້ງເຕືອນໃຫ້ຜູ້ໃຊ້ໃຫ້ລາຍງານບັກ"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"ການປ້ອນຂໍ້ມູນ"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"ການແຕ້ມ"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"ການສະແດງຜົນໂດຍໃຊ້ຮາດແວຊ່ວຍ"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"ສະແດງການອັບເດດເລເຢີຂອງຮາດແວ"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"ກະພິບເລເຢີຂອງຮາດແວໃຫ້ເປັນສີຂຽວເມື່ອມີການອັບເດດ"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"ແກ້ບັນຫາການແຕ້ມທັບຂອງ GPU"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"ກຳນົດຕົວເຣັນເດີ GPU"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"ປິດການເຮັດວຽກ HW overlays"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"ໃຊ້ GPU ໃນການວາງອົງປະກອບໜ້າຈໍສະເໝີ"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"ຈຳລອງ color space"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Enter password to perform factory reset in demo mode"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"ຕໍ່ໄປ"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"​ຕ້ອງ​ໃສ່​ລະ​ຫັດ​ຜ່ານ"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"ວິທີປ້ອນຂໍ້ມູນທີ່ເຮັດວຽກຢູ່"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"ໃຊ້ພາສາຂອງລະບົບ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-lt/arrays.xml b/packages/SettingsLib/res/values-lt/arrays.xml
index 48fa936..2709ef0 100644
--- a/packages/SettingsLib/res/values-lt/arrays.xml
+++ b/packages/SettingsLib/res/values-lt/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Rodyti perdangos sritis"</item>
     <item msgid="2290859360633824369">"Rodyti deuteranomalijos sritis"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"„OpenGL“ (numatyt.)"</item>
+    <item msgid="2839130076198120436">"„OpenGL“ („Skia“)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Standartinis apribojimas"</item>
     <item msgid="4071574792028999443">"Nėra fono procesų"</item>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 3090d30..819c1a8 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Išsaugotas"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Neleidžiama"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP konfigūracijos triktis"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Neprisijungta dėl žemos kokybės tinklo"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"„Wi-Fi“ ryšio triktis"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Autentifikavimo problema"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Ne diapazone"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Nieko"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Laukti derintuvės"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Derinta progr. laukia derint., kad galėtų tęsti."</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telefonijos stebėjimo priemonė"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Telefonijos stebėjimo priemonė rinks žurnalus, kai aptiks problemą dėl telefonijos / modemo funkcijų, ir naudotojui pateiks raginimą pranešti apie riktą"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Įvestis"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Atvaizdavimas"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Aparatinės įrangos paspartintas pateikimas"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Rod. apar. įr. sl. nauj."</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Kai atsin. apar. įr. sl., rod. juos blyks. ž. sp."</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Derinti GPU perdangą"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Nust. graf. proc. pateik."</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Neleisti HW perdangų"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Komponuojant ekraną visada naudoti GPU"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Imituoti spalvų erdvę"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Įv. slapt. ir atk. gam. nust. dem. rež."</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Kitas"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Būtina nurodyti slaptažodį"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Aktyvūs įvesties metodai"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Sistemos kalbų naudojimas"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-lv/arrays.xml b/packages/SettingsLib/res/values-lv/arrays.xml
index 16dc981..abdfe97 100644
--- a/packages/SettingsLib/res/values-lv/arrays.xml
+++ b/packages/SettingsLib/res/values-lv/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Rādīt apgab., kur pārsn. kapacitāte"</item>
     <item msgid="2290859360633824369">"Rādīt laukumus deiteranomālijai"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (noklusējums)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Standarta ierobežojums"</item>
     <item msgid="4071574792028999443">"Nav fona procesu"</item>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index d782e89..87bd7b6 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Saglabāts"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Atspējots"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP konfigurācijas kļūme"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Savienojums nav izveidots zemas kvalitātes tīkla dēļ"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi savienojuma kļūme"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Autentificēšanas problēma"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Nav diapazona ietvaros"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Nekas"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Gaidīt atkļūdotāju"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Gaida atkļūdotāju, ko pirms izp. piev. atkļ. liet."</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telefonijas pārraugs"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Ja tiks konstatēta problēma saistībā ar telefonijas/modema funkcionalitāti, telefonijas pārraugs apkopos žurnālus un paziņojumā aicinās lietotāju reģistrēt kļūdu."</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Ievade"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Zīmējums"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Aparatūras paātrinātā atveidošana"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Rādīt apar. slāņu atjaun."</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Atjaunin. aparatūras slāņiem ir jāmirgo zaļā krāsā"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Atkļūdot graf. proc. kapac. pārsn."</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Iestatīt GPU renderētāju"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Atspējot HW pārklājumus"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Vienmēr izmantot GPU atveidi ekrāna salikšanai"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simulēt krāstelpu"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Iev. paroli, lai atiest. rūpnīcas iest. dem. režīmā"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Tālāk"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Nepieciešama parole"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Aktīvās ievades metodes"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Sistēmas valodu izmantošana"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-mk/arrays.xml b/packages/SettingsLib/res/values-mk/arrays.xml
index e334467..a7ef472 100644
--- a/packages/SettingsLib/res/values-mk/arrays.xml
+++ b/packages/SettingsLib/res/values-mk/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Прикажи пречекорени делови"</item>
     <item msgid="2290859360633824369">"Прикажи делови за лица со девтераномалија"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (стандардно)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Стандардна граница"</item>
     <item msgid="4071574792028999443">"Нема процеси во заднина"</item>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 0662c8f..3e3d58c 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Зачувано"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Оневозможено"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Конфигурирањето ИП не успеа"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Не е поврзано поради нискиот квалитет на мрежата"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Поврзувањето преку Wi-Fi не успеа"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Проблем со автентикација"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Надвор од опсег"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Ништо"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Почекај ја програмата за отстранување грешки"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Пред да се изврши, апликација за отстранување грешки чека програмата за отстранување грешки да се закачи"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Монитор за телефонија"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Мониторот за телефонија ќе води евиденција кога ќе открие проблем со функционалноста на телефонијата/модемот и ќе го извести корисникот да пријави проблем"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Внес"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Цртање"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Прикажување забрзување на хардвер"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Ажурир. слоеви на хардвер"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Осветли слоеви на хардвер со зелено кога се ажур."</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Отстр. греш. на GPU"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Постави прикажувач на GPU"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Оневозможи HW преклопувања"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Секогаш користи GPU за составување екран"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Симулирај простор на бои"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Внесете лозинка за фаб. ресет. во демо"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Следно"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Потребна е лозинка"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Методи за активно внесување"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Користете ги системските јазици"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ml/arrays.xml b/packages/SettingsLib/res/values-ml/arrays.xml
index e79a567..42cc1a1 100644
--- a/packages/SettingsLib/res/values-ml/arrays.xml
+++ b/packages/SettingsLib/res/values-ml/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"ഓവർഡ്രോ ഭാഗങ്ങൾ ദൃശ്യമാക്കുക"</item>
     <item msgid="2290859360633824369">"വർണ്ണാന്ധതയ്‌ക്കായുള്ള ഭാഗങ്ങൾ ദൃശ്യമാക്കുക"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (ഡിഫോ‌ൾട്ട്)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"അടിസ്ഥാന പരിധി"</item>
     <item msgid="4071574792028999443">"പശ്ചാത്തല പ്രോസ‌സ്സുകൾ ഒന്നുമില്ല"</item>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index b238625..cb10055 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"സംരക്ഷിച്ചു"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"പ്രവർത്തനരഹിതമാക്കി"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP കോൺഫിഗറേഷൻ പരാജയം"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"മോശം നെറ്റ്‌വർക്ക് ‌ആയതിനാൽ കണക്‌റ്റായില്ല"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi കണക്ഷൻ പരാജയം"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"ആധികാരികമാക്കുന്നതിലെ പ്രശ്‌നം"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"പരിധിയിലില്ല"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"ഒന്നുമില്ല"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"ഡീബഗ്ഗറിനായി കാത്തിരിക്കുക"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"ഡീബഗ്ഗുചെയ്‌ത അപ്ലിക്കേഷൻ നിർവ്വഹണത്തിനുമുമ്പായി അറ്റാച്ചുചെയ്യുന്നതിന് ഡീബഗ്ഗറിനായി കാത്തിരിക്കുന്നു."</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"ടെലിഫോണി മോണിറ്റർ"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"ടെലിഫോണി മോണിറ്റർ, ടെലിഫോണി/മോഡവുമായി ബന്ധപ്പെട്ട് എന്തെങ്കിലും പ്രശ്‌നം കണ്ടെത്തുമ്പോൾ, അതിന്റെ ലോഗുകൾ ശേഖരിക്കുകയും ഒരു ബഗ് ഫയൽ ചെയ്യാൻ ഉപയോക്താവിന് അറിയിപ്പ് നൽകുകയും ചെയ്യും"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"ഇൻപുട്ട്"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"ഡ്രോയിംഗ്"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"ഹാർഡ്‌വെയർ ത്വരിതപ്പെടുത്തിയ റെൻഡർ ചെയ്യൽ"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"ഹാർഡ്‌വെയർ ലേയർ അപ്‌ഡേറ്റ് കാണിക്കൂ"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"ഹാർഡ്‌വെയർ ലേയറുകളുടെ അപ്‌ഡേറ്റുകൾ പൂർത്തിയാകുമ്പോൾ അവ പച്ച നിറത്തിൽ പ്രകാശിപ്പിക്കുക"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU ഓവർഡ്രോ ഡീബഗ്ഗുചെയ്യുക"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU റെൻഡറർ സജ്ജീകരിക്കുക"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"HW ഓവർലേ നിഷ്ക്രിയമാക്കൂ"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"സ്‌ക്രീൻ കമ്പോസിറ്റുചെയ്യലിനായി എല്ലായ്‌പ്പോഴും GPU ഉപയോഗിക്കുക"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"വർണ്ണ സ്‌പെയ്‌സ് പ്രവർത്തിപ്പിക്കുക"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"ഡെമോ ‌മോഡിൽ ഫാക്ടറി റീസെറ്റിന് പാസ്‌വേഡ് നൽകുക"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"അടുത്തത്"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"പാസ്‌വേഡ് ആവശ്യമാണ്"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"സജീവ ടൈപ്പുചെയ്യൽ രീതികൾ"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"സിസ്റ്റം ഭാഷകൾ ഉപയോഗിക്കുക"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-mn/arrays.xml b/packages/SettingsLib/res/values-mn/arrays.xml
index bb61310..eff48e0 100644
--- a/packages/SettingsLib/res/values-mn/arrays.xml
+++ b/packages/SettingsLib/res/values-mn/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Давхар дүрслэлтэй хэсгийг харуулах"</item>
     <item msgid="2290859360633824369">"Өнгө үл ялгагчид зориулсан бүсүүдийг харуулах"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (Өгөгдмөл)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Стандарт хязгаар"</item>
     <item msgid="4071574792028999443">"Далд процесс байхгүй"</item>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 68f3df5..db9bc55 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Хадгалагдсан"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Идэвхгүйжүүлсэн"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP тохируулга амжилтгүй"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Сүлжээний чанар муу байгаа тул холбогдож чадсангүй"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi холболт амжилтгүй"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Гэрчлэлийн асуудал"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Хүрээнд байхгүй"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Юуг ч биш"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Согог засагчийг хүлээх"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Согог засагдсан аппликешн ажиллахын өмнө согог засагчийг хавсаргагдахыг хүлээнэ"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Утасны хяналт"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Утасны хяналт нь утас/модемын ажиллагаанд асуудал илрүүлсэн тохиолдолд лог цуглуулж, хэрэглэгчид алдааг засах мэдэгдэл илгээнэ"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Оруулах"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Зураг"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Техник хангамжийн хурдатгалтай үзүүлэлт"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Техник хангамжийн давхаргын шинэчлэлтүүдийг харуулах"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Техник хангамжууд шинэчлэх үед давхаргыг анивчуулах"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU давхар дүрслэлийг дебаг хийх"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU Renderer-г тохируулах"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"HW давхаргыг идэвхгүйжүүлэх"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Дэлгэц нийлүүлэхэд GPU-г байнга ашиглах"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Өнгөний орчныг дууриах"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Үйлдвэрийн тохиргоог демо горимд ажиллуулахын тулд нууц үг оруулна уу"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Дараагийн"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Нууц үг шаардлагатай"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Оруулах аргуудыг идэвхжүүлэх"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Системийн хэлүүдийг ашиглах"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-mr/arrays.xml b/packages/SettingsLib/res/values-mr/arrays.xml
index e83b1f9..b18d6a56 100644
--- a/packages/SettingsLib/res/values-mr/arrays.xml
+++ b/packages/SettingsLib/res/values-mr/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"अधोरेखांकित क्षेत्रे दर्शवा"</item>
     <item msgid="2290859360633824369">"हरित असंगतिसाठी क्षेत्रे दर्शवा"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (डीफॉल्ट)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"मानक मर्यादा"</item>
     <item msgid="4071574792028999443">"एकही पार्श्वभूमी प्रक्रिया नाही"</item>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 243885f..b2fbbd7 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"जतन केले"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"अक्षम"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP कॉन्फिगरेशन अयशस्वी"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"कमी दर्जाच्या नेटवर्कमुळे कनेक्ट केलेले नाही"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi कनेक्शन अयशस्वी"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"प्रमाणीकरण समस्या"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"परिक्षेत्रामध्ये नाही"</string>
@@ -203,7 +204,7 @@
     <string name="dev_settings_warning_title" msgid="7244607768088540165">"विकास सेटिंग्जला अनुमती द्यायची?"</string>
     <string name="dev_settings_warning_message" msgid="2298337781139097964">"या सेटिंग्जचा हेतू फक्त विकास करण्याच्या वापरासाठी आहे. त्यामुळे आपले डिव्हाइस आणि त्यावरील अनुप्रयोग विघटित होऊ शकतात किंवा गैरवर्तन करू शकतात."</string>
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB वरील अॅप्स सत्यापित करा"</string>
-    <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"हानीकारक वर्तनासाठी ADB/ADT द्वारे स्थापित अॅप्स तपासा."</string>
+    <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"हानिकारक वर्तनासाठी ADB/ADT द्वारे स्थापित अॅप्स तपासा."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"दूरस्थ डिव्हाइसेसमध्ये सहन न होणारा मोठा आवाज किंवा नियंत्रणचा अभाव यासारखी आवाजाची समस्या असल्यास ब्लूटुथ संपूर्ण आवाज वैशिष्ट्य अक्षम करते."</string>
     <string name="enable_terminal_title" msgid="95572094356054120">"स्थानिक टर्मिनल"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"स्थानिक शेल प्रवेश देणारा टर्मिनल अॅप सक्षम करा"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"काहीही नाही"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"डीबगरची प्रतीक्षा करा"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"डीबग केलेला अनुप्रयोग अंमलात आणण्यापूर्वी डीबगर संलग्न करण्याची प्रतीक्षा करतो"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"टेलिफोनी मॉनिटर"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"टेलिफोनी/मोडेमच्‍या कार्यक्षमतेत समस्‍या आढळल्‍यावर टेलिफोनी मॉनिटर लॉग्‍ज गोळा करेल आणि दोष फाइल करण्‍यासाठी वापरकर्त्याला सूचनेचे संकेत देईल"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"इनपुट"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"रेखांकन"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"हार्डवेअर प्रवेगक प्रस्तुती"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"हार्डवेअर स्तर अद्यतने दर्शवा"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"हार्डवेअर स्तर अद्ययावत झाल्यावर ते हिरव्या रंगात फ्लॅश करा"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU अधोरेखांकित डीबग करा"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU प्रदाता सेट करा"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"HW आच्छादने अक्षम करा"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"स्क्रीन तयार करण्यासाठी नेहमी GPU वापरा"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"रंग स्थानाची बतावणी करा"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"डेमो मोडमध्ये फॅक्टरी रीसेट करण्यासाठी संकेतशब्द प्रविष्ट करा"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"पुढील"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"संकेतशब्द आवश्यक"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"सक्रिय इनपुट पद्धती"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"सिस्टीम भाषा वापरा"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ms/arrays.xml b/packages/SettingsLib/res/values-ms/arrays.xml
index 886dd44..233bf60 100644
--- a/packages/SettingsLib/res/values-ms/arrays.xml
+++ b/packages/SettingsLib/res/values-ms/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Tunjukkan kawasan lebih lukis"</item>
     <item msgid="2290859360633824369">"Tunjukkan kawasan untuk Deuteranomaly"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (Lalai)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Had standard"</item>
     <item msgid="4071574792028999443">"Tiada proses latar belakang"</item>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 234f4cf..9d373d8 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Disimpan"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Dinyahdayakan"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Kegagalan Konfigurasi IP"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Tidak disambungkan kerana rangkaian berkualiti rendah"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Kegagalan Sambungan WiFi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Masalah pengesahan"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Tidak dalam liputan"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Tiada apa-apa"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Nantikan penyahpepijat"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Menanti penyahpepijat sebelum aplikasi melaksana"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telephony Monitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"TelephonyMonitor akan mengumpulkan log apabila apl ini mengesan masalah berhubung kefungsian telefoni/modem dan memaparkan pemberitahuan kepada pengguna supaya memfailkan pepijat"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Input"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Lukisan"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Pemaparan dipercepat perkakasan"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Tunjukkan kemas kini perkakasan"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Denyar hijau lapisan perkakasan yang dikemas kini"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Nyahpepijat lebih lukis GPU"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Tetapkan Pemapar GPU"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Lumpuhkan tindihan HW"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Sentiasa gunakan GPU untuk komposit skrin"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Tiru ruang warna"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Mskkn kta laluan utk ttpn sml kilang dlm mod demo"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Seterusnya"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Kata laluan diperlukan"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Kaedah input aktif"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Gunakan bahasa sistem"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-my/arrays.xml b/packages/SettingsLib/res/values-my/arrays.xml
index c30bd20..f0ccff3 100644
--- a/packages/SettingsLib/res/values-my/arrays.xml
+++ b/packages/SettingsLib/res/values-my/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"ရှိရင်းစွဲထက်ပိုသော ဧရိယာများကိုပြရန်"</item>
     <item msgid="2290859360633824369">"အရောင်ရောနှောသောဧရိယာများပြရန်"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (မူရင်း)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"သတ်မှတ်စံနှုန်း"</item>
     <item msgid="4071574792028999443">"နောက်ခံပြုလုပ်နေသောလုပ်ငန်းစဉ်မရှိ"</item>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 93507d2..a2a800d 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"သိမ်းဆည်းပြီး"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"သုံးမရအောင် ပိတ်ထားသည်"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP ပြုပြင်ခြင်း မအောင်မြင်ပါ"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"ကွန်ရက်ချိတ်ဆက်မှု အားနည်းသည့်အတွက် ချိတ်ဆက်ထားခြင်း မရှိပါ"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi ချိတ်ဆက်မှု မအောင်မြင်ပါ"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"စစ်မှန်ကြောင်းအတည်ပြုရန်၌ ပြသနာရှိခြင်း"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"စက်ကွင်းထဲတွင် မဟုတ်ပါ"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"တခုမှမရှိ"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"အပြစ်ရှာဖွေ ဖယ်ရှားချက်ကိုစောင့်ရန်"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"အမှားပြင်ဆင်ရှာဖွေသည့် အပလီကေးရှင်းသည် လုပ်ငန်းမစမီ တွဲဖက်ရန် အမှားရှာဖွေမည့်သူကို စောင့်နေသည်။"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"တယ်လီဖုန်းဆက်သွယ်မှု မော်နီတာ"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"တယ်လီဖုန်းဆက်သွယ်မှု မော်နီတာသည် တယ်လီဖုန်းဆက်သွယ်မှု/မိုဒမ် လုပ်ဆောင်ချက်တို့တွင် ပြဿနာရှိနေလျှင် မှတ်တမ်းပြုစုပြီး ချွတ်ယွင်းချက် အစီရင်ခံရန် အသုံးပြုသူကို အကြောင်းကြားပေးမည် ဖြစ်သည်။"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"ထည့်သွင်းရန်"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"ရေးဆွဲခြင်း"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"ဟာ့ဒ်ဝဲ အရှိန်မြှင့် ပုံဖော်ခြင်း"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"ဟာ့ဒ်ဝဲအလွှာများအဆင်မြှင့်မှုကိုပြရန်"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"အပ်ဒိတ်လုပ်ချိန် ဟာ့ဒ်ဝဲအလွှာများ အစိမ်းရောင်ပြပါ"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU ပိုသုံးစွဲမှုအမှားရှာဖွေပြင်ဆင်ရန်"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU Renderer သတ်မှတ်ပါ"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"HWထပ်ဆင့်အရာများပိတ်ရန်"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"GPU ကိုမျက်နှာပြင်ခင်းကျင်းရာတွင် အမြဲသုံးပါ။"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"အရောင်နေရာတူအောင် ဖန်တီးသည်"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"ဒီမိုမုဒ်၌မူလဆက်တင်ထားရန် စကားဝှက်ထည့်ပါ"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"ရှေ့သို့"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"စကားဝှက် လိုအပ်သည်"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"ရနိုင်သောထည့်သွင်းရန်နည်းလမ်းများ"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"စနစ်ဘာသာစကားများကို အသုံးပြုပါ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-nb/arrays.xml b/packages/SettingsLib/res/values-nb/arrays.xml
index 36bc9e0..d4a66e5 100644
--- a/packages/SettingsLib/res/values-nb/arrays.xml
+++ b/packages/SettingsLib/res/values-nb/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Vis overtrekksområder"</item>
     <item msgid="2290859360633824369">"Vis områder for deuteranomali"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (standard)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Standard grense"</item>
     <item msgid="4071574792028999443">"Ingen bakgrunnsprosesser"</item>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 172d59c..c650b23 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Lagret"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Slått av"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-konfigurasjonsfeil"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Ikke tilkoblet på grunn av nettverk av lav kvalitet"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi-tilkoblingsfeil"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Autentiseringsproblem"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Utenfor område"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Ingen"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Vent på feilsøkingsverktøyet"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Feilsøkt app venter til feilsøkingsverktøyet er lagt til før den kjører"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telefonimonitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"TelephonyMonitor logger problemer som oppdages med funksjonaliteten til telefoni/modem, og varsler brukeren om å sende inn en feilrapport."</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Inndata"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Tegning"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Maskinvareakselerert gjengivelse"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Vis maskinvarelag-oppdat."</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Maskinvarelag blinker grønt under oppdatering"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Feilsøk GPU-overtrekk"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Angi GPU-gjengivelse"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Slå av maskinvareoverlegg"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Bruk alltid GPU for skjermsammensetting"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simuler fargeområde"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Skriv inn passordet for å tilbakestille til fabrikkstandard i demomodus"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Neste"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Passord er obligatorisk"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Aktive inndatametoder"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Bruk systemspråk"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ne/arrays.xml b/packages/SettingsLib/res/values-ne/arrays.xml
index cee130b..f1bd5c2 100644
--- a/packages/SettingsLib/res/values-ne/arrays.xml
+++ b/packages/SettingsLib/res/values-ne/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"overdraw क्षेत्रहरू देखाउनुहोस्"</item>
     <item msgid="2290859360633824369">"Deuteranomaly का लागि क्षेत्रहरू देखाउनुहोस्"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (पूर्वनिर्धारित मान)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"मानक सीमा"</item>
     <item msgid="4071574792028999443">"कुनै पृष्ठभूमि प्रक्रियाहरू छैनन्"</item>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 8df60f3..a5742b0 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"सुरक्षित गरियो"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"असक्षम पारियो"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP विन्यास असफल"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"कम गुणस्तरको नेटवर्कका कारण जडान गर्न सकिएन"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"वाईफाई जडान असफल"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"प्रमाणीकरण समस्या"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"दायराभित्र छैन"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"केही पनि होइन"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"डिबग गर्नेलाई पर्खनुहोस्"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"डिबग भएको अनुप्रयोग कार्यन्वयन हुनु अघि संलग्न हुन डिबग गर्नेलाई पर्खन्छ"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"टेलिफोनी मनिटर"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"TelephonyMonitor ले टेलिफोन/मोडेमको सञ्चालनमा कुनै समस्या भेट्टायो भने लगहरू सङ्कलन गर्नेछ र प्रयोगकर्तालाई बग बारे रिपोर्ट गर्न सूचना पठाउनेछ"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"इनपुट"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"रेखाचित्र"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"हार्डवेयर प्रतिपादन फुर्तिलो बनाइयो"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"हार्डवेयर तह अद्यावधिक देखाउनुहोस्"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"फ्ल्यास हार्डवेयर तहहरू अपडेट हुँदा हरिया हुन्छन्"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU overdraw डिबग गर्नुहोस्"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU रेन्डरर सेट गर्नुहोस्‌"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"HW ओवरले असक्षम पार्नुहोस्"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"स्क्रिन कोम्पजिट गर्न लागि सधैँ GPU प्रयोग गर्नुहोस्"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"रंग स्पेस अनुकरण गर्नुहोस्"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"डेमो मोडमा फ्याक्ट्री रिसेट गर्न पासवर्ड प्रविष्ट गर्नुहोस्"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"अर्को"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"पासवर्ड आवश्यक छ"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"आगत विधिहरू सक्रिय गर्नुहोस्"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"प्रणालीका भाषाहरू प्रयोग गर्नुहोस्"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-nl/arrays.xml b/packages/SettingsLib/res/values-nl/arrays.xml
index 93db1c6..96894b5 100644
--- a/packages/SettingsLib/res/values-nl/arrays.xml
+++ b/packages/SettingsLib/res/values-nl/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Gedeeltes met overbelasting weergeven"</item>
     <item msgid="2290859360633824369">"Gebieden voor deuteranomalie weergeven"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (standaard)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Standaardlimiet"</item>
     <item msgid="4071574792028999443">"Geen achtergrondprocessen"</item>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 30439710..433c0a8 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Opgeslagen"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Uitgeschakeld"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-configuratie mislukt"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Niet verbonden wegens netwerk van lage kwaliteit"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wifi-verbinding mislukt"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Authenticatieprobleem"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Niet binnen bereik"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Niets"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Wachten op debugger"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Gedebugde app wacht op koppelen van debugger vóór uitvoering"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telephony Monitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"TelephonyMonitor verzamelt logbestanden wanneer een probleem wordt gedetecteerd met de functionaliteit van telefonie/modem. De gebruiker krijgt een melding te zien waarin wordt gevraagd of hij een bug wil indienen."</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Invoer"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Tekening"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Rendering met hardwareversnelling"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Updaten hardwarelgn wrgvn"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Hardwarelagen knipperen groen bij updates"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Foutopsporing GPU-overbelasting"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU-renderer instellen"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"HW-overlays uitschakelen"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"GPU altijd gebruiken voor schermcompositing"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Kleurruimte simuleren"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Geef wachtwoord op om terug te zetten op fabrieksinstellingen in demomodus"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Volgende"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Wachtwoord vereist"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Actieve invoermethoden"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Systeemtalen gebruiken"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pa/arrays.xml b/packages/SettingsLib/res/values-pa/arrays.xml
index f7ca9e1..06fe20d 100644
--- a/packages/SettingsLib/res/values-pa/arrays.xml
+++ b/packages/SettingsLib/res/values-pa/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"ਓਵਰਡ੍ਰਾ ਖੇਤਰ ਦਿਖਾਓ"</item>
     <item msgid="2290859360633824369">"Deuteranomaly ਲਈ ਖੇਤਰ ਦਿਖਾਓ"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (ਪੂਰਵ-ਨਿਰਧਾਰਤ)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"ਸਟੈਂਡਰਡ ਸੀਮਾ"</item>
     <item msgid="4071574792028999443">"ਕੋਈ ਪਿਛੋਕੜ ਪ੍ਰਕਿਰਿਆਵਾਂ ਨਹੀਂ"</item>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 13c817e..e9db1a7 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"ਰੱਖਿਅਤ ਕੀਤਾ"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"ਅਯੋਗ ਬਣਾਇਆ"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP ਕੌਂਫਿਗਰੇਸ਼ਨ ਅਸਫਲਤਾ"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"ਘੱਟ ਗੁਣਵੱਤਾ ਵਾਲੇ ਨੈੱਟਵਰਕ ਕਾਰਨ ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਗਿਆ"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi ਕਨੈਕਸ਼ਨ ਅਸਫਲਤਾ"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"ਪ੍ਰਮਾਣੀਕਰਨ ਸਮੱਸਿਆ"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"ਰੇਂਜ ਵਿੱਚ ਨਹੀਂ ਹੈ"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"ਕੁਝ ਨਹੀਂ"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"ਡੀਬਗਰ ਦੀ ਉਡੀਕ ਕਰੋ"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"ਡੀਬਗ ਕੀਤੇ ਐਪਲੀਕੇਸ਼ਨ ਐਗਜੀਕਿਊਟ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਅਟੈਚ ਕਰਨ ਲਈ ਡੀਬਗਰ ਦੀ ਉਡੀਕ ਕਰਦੇ ਹਨ"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"ਟੈਲੀਫ਼ੋਨੀ ਮੋਨੀਟਰ"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"ਟੈਲੀਫ਼ੋਨੀ ਮੋਨੀਟਰ ਟੈਲੀਫ਼ੋਨੀ/ਮੌਡਮ ਪ੍ਰਕਾਰਜਾਤਮਕਤਾ ਵਿੱਚ ਕਿਸੇ ਸਮੱਸਿਆ ਦਾ ਪਤਾ ਲੱਗਣ \'ਤੇ ਲੌਗਾਂ ਨੂੰ ਇਕੱਤਰ ਕਰੇਗਾ ਅਤੇ ਵਰਤੋਂਕਾਰ ਨੂੰ ਇੱਕ ਬੱਗ ਦਾਇਰ ਕਰਨ ਲਈ ਸੂਚਨਾ ਦੇਵੇਗਾ"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"ਇਨਪੁਟ"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"ਡਰਾਇੰਗ"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"ਹਾਰਡਵੇਅਰ ਤੇਜ਼ ਕੀਤਾ ਪ੍ਰਗਟਾਅ"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"ਹਾਰਡਵੇਅਰ ਲੇਅਰਸ ਅਪਡੇਟਾਂ ਦਿਖਾਓ"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"ਹਾਰਡਵੇਅਰ ਲੇਅਰਾਂ ਨੂੰ ਹਰੀਆਂ ਫਲੈਸ਼ ਕਰੋ ਜਦੋਂ ਉਹ ਅਪਡੇਟ ਹੁੰਦੀਆਂ ਹਨ"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU ਓਵਰਡ੍ਰਾ ਡੀਬਗ ਕਰੋ"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU ਰੈਂਡਰਰ ਸੈੱਟ ਕਰੋ"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"HW ਓਵਰਲੇਜ ਨੂੰ ਅਸਮਰੱਥ ਬਣਾਓ"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"ਸਕ੍ਰੀਨ ਕੰਪੋਜਿਟਿੰਗ ਲਈ ਹਮੇਸ਼ਾਂ GPU ਵਰਤੋ"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"ਰੰਗ ਸਪੇਸ ਦੀ ਨਕਲ ਕਰੋ"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"ਡੈਮੋ ਮੋਡ \'ਚ ਫੈਕਟਰੀ ਰੀਸੈੱਟ ਲਈ ਪਾਸਵਰਡ ਦਿਓ"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"ਅੱਗੇ"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"ਪਾਸਵਰਡ ਦੀ ਲੋੜ ਹੈ"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"ਸਰਗਰਮ ਇਨਪੁਟ ਵਿਧੀਆਂ"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"ਸਿਸਟਮ ਭਾਸ਼ਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pl/arrays.xml b/packages/SettingsLib/res/values-pl/arrays.xml
index cd7eb7d..f8bd510 100644
--- a/packages/SettingsLib/res/values-pl/arrays.xml
+++ b/packages/SettingsLib/res/values-pl/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Pokaż przerysowywane obszary"</item>
     <item msgid="2290859360633824369">"Pokaż obszary dostosowane do deuteranomalii"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (domyślnie)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Standardowy limit"</item>
     <item msgid="4071574792028999443">"Brak procesów w tle"</item>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index fcf974c..f26f108 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Zapisana"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Wyłączona"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Błąd konfiguracji IP"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Brak połączenia z powodu słabego sygnału sieci"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Błąd połączenia Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problem z uwierzytelnianiem"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Poza zasięgiem"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Brak"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Poczekaj na debugera"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Aplikacja do debugowania czeka na przyłączenie debugera"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Monitorowanie telefonii"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"TelephonyMonitor zbiera dzienniki po wykryciu problemu z funkcją telefonu/modemu i powiadamia użytkownika o możliwości zgłoszenia błędu"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Ekran dotykowy"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Rysowanie"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Sprzętowa akceleracja renderowania"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Pokaż zmiany warstw sprzęt."</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Oznaczaj aktualizowane warstwy sprzętowe na zielono"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Debuguj przerysowania GPU"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Ustaw mech. render. GPU"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Wyłącz nakładki HW"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Zawsze używaj GPU do komponowania ekranu"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Symuluj przestrzeń kolorów"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Wpisz hasło, by przywrócić ustawienia fabryczne w trybie demonstracyjnym"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Dalej"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Wymagane hasło"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Aktywne metody wprowadzania"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Użyj języków systemu"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pt-rBR/arrays.xml b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
index 8a2fdc6..ccd04df 100644
--- a/packages/SettingsLib/res/values-pt-rBR/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Mostrar áreas de overdraw"</item>
     <item msgid="2290859360633824369">"Mostrar áreas para daltonismo"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (padrão)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Limite padrão"</item>
     <item msgid="4071574792028999443">"Sem processos em segundo plano"</item>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index dcbac24..15ff94e 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Salva"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Desativado"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Falha de configuração de IP"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Não conectado devido à baixa qualidade da rede"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Falha de conexão Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problema de autenticação"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Fora do alcance"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Nada"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Aguardar depurador"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"App depurado espera conexão com debugger antes de ser executado."</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Monitor de telefonia"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Ao detectar um problema com a funcionalidade de modem/telefonia, o Monitor de telefonia coletará registros e enviará uma notificação ao usuário para informar um bug"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Entrada"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Desenho"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Renderização acelerada por hardware"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Atual. camad. de hardware"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Piscar camadas de hardware em verde ao atualizar"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Depurar overdraw da GPU"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Definir renderiz. de GPU"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Desativar sobreposição HW"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Sempre usar a GPU para composição de tela"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simular espaço de cores"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Digite a senha para redef. p/ configuração original em modo demo"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Próxima"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Senha necessária"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Métodos ativos de entrada"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Usar idiomas do sistema"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pt-rPT/arrays.xml b/packages/SettingsLib/res/values-pt-rPT/arrays.xml
index 1b10a3f..170cd82 100644
--- a/packages/SettingsLib/res/values-pt-rPT/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Mostrar áreas de sobreposição"</item>
     <item msgid="2290859360633824369">"Mostrar áreas para Deuteranomaly"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (predefinição)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Limite padrão"</item>
     <item msgid="4071574792028999443">"Sem processos em segundo plano"</item>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index fb2bd6e..8c6de66 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Guardada"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Desativado"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Falha de configuração de IP"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Não ligado devido à baixa qualidade da rede"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Falha de ligação Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problema de autenticação"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Fora do alcance"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Nenhuma"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Aguarde pelo depurador"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"A aplicação depurada aguarda a anexação do depurador antes da execução"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Monitor de telefonia"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"O Monitor de telefonia recolhe registos quando deteta um problema de funcionalidade de telefonia/modem e apresenta uma notificação ao utilizador para reportar um erro"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Introdução"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Desenho"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Conversão acelerada de hardware"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Mostrar atual. cam. hard."</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Camadas de hard. flash verdes quando estão atuali."</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Depurar sobreposição GPU"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Definir renderizador GPU"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Desativ. sobreposições HW"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Utilizar sempre GPU para a composição do ecrã"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simular espaço da cor"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Introduzir palavra-passe para efetuar a reposição de fábrica no modo demo"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Próximo"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Palavra-passe obrigatória"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Métodos de introdução activos"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Utilizar idiomas do sistema"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pt/arrays.xml b/packages/SettingsLib/res/values-pt/arrays.xml
index 8a2fdc6..ccd04df 100644
--- a/packages/SettingsLib/res/values-pt/arrays.xml
+++ b/packages/SettingsLib/res/values-pt/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Mostrar áreas de overdraw"</item>
     <item msgid="2290859360633824369">"Mostrar áreas para daltonismo"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (padrão)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Limite padrão"</item>
     <item msgid="4071574792028999443">"Sem processos em segundo plano"</item>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index dcbac24..15ff94e 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Salva"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Desativado"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Falha de configuração de IP"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Não conectado devido à baixa qualidade da rede"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Falha de conexão Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problema de autenticação"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Fora do alcance"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Nada"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Aguardar depurador"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"App depurado espera conexão com debugger antes de ser executado."</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Monitor de telefonia"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Ao detectar um problema com a funcionalidade de modem/telefonia, o Monitor de telefonia coletará registros e enviará uma notificação ao usuário para informar um bug"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Entrada"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Desenho"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Renderização acelerada por hardware"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Atual. camad. de hardware"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Piscar camadas de hardware em verde ao atualizar"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Depurar overdraw da GPU"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Definir renderiz. de GPU"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Desativar sobreposição HW"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Sempre usar a GPU para composição de tela"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simular espaço de cores"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Digite a senha para redef. p/ configuração original em modo demo"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Próxima"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Senha necessária"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Métodos ativos de entrada"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Usar idiomas do sistema"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ro/arrays.xml b/packages/SettingsLib/res/values-ro/arrays.xml
index 2f4d0c7..172d94f 100644
--- a/packages/SettingsLib/res/values-ro/arrays.xml
+++ b/packages/SettingsLib/res/values-ro/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Afișați zonele cu suprapunere"</item>
     <item msgid="2290859360633824369">"Afișați zonele de deuteranomalie"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (prestabilit)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Limita standard"</item>
     <item msgid="4071574792028999443">"Nu există procese de fundal"</item>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 372833d..270611c 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Salvată"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Dezactivată"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Eroare de configurație IP"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Nu există conexiune din cauza rețelei de calitate slabă"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Eroare de conexiune Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problemă la autentificare"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"În afara ariei de acoperire"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Niciuna"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Așteptați depanatorul"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Înaintea executării, aplicația așteaptă atașarea depanatorului"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telephony Monitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"TelephonyMonitor colectează jurnale când detectează o problemă privind performanțele serviciilor de telefonie/modemului și trimite notificări utilizatorului să semnaleze o eroare"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Intrare"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Desen"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Redare accelerată hardware"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Actualiz. strat. hardware"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Straturile hardware clipesc verde la actualizare"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Depanați suprapunerea"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Setați GPU pentru redare"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Dezactivați suprapun. HW"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Utilizați mereu GPU pentru compunerea ecranului"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simulați spațiu culoare"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Introduceți parola pentru a reveni la setările din fabrică în modul demo"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Înainte"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Trebuie să introduceți o parolă"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Metode active de introducere de text"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Folosește limbile sistemului"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ru/arrays.xml b/packages/SettingsLib/res/values-ru/arrays.xml
index 6498ea0..0dd1922 100644
--- a/packages/SettingsLib/res/values-ru/arrays.xml
+++ b/packages/SettingsLib/res/values-ru/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Показывать области наложения"</item>
     <item msgid="2290859360633824369">"Выделять области определенного цвета"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (по умолчанию)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Стандартное ограничение"</item>
     <item msgid="4071574792028999443">"Без фоновых процессов"</item>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 97aea30..6cb1d91 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Сохранено"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Отключено"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Ошибка IP-конфигурации"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Подключение невозможно из-за низкого качества сети"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Ошибка подключения Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Ошибка аутентификации"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Недоступна"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Нет"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Подождите, пока подключится отладчик"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Приложение ожидает подключения отладчика"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telephony Monitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Обнаружив проблему в работе модема или телефонной связи, Telephony Monitor будет собирать журналы и предлагать пользователю отправить информацию об ошибке"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Ввод текста"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Рисование"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Аппаратное ускорение визуализации"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Показ. аппаратные обновл."</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Выделять аппаратные уровни зеленым при обновлении"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Отладка наложения"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Средство визуализации"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Откл. аппарат. наложения"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Всегда использовать GPU при компоновке экрана"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Имитировать аномалию"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Чтобы сбросить настройки в деморежиме, введите пароль."</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Далее"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Требуется пароль"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Активные способы ввода"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Языки системы"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-si/arrays.xml b/packages/SettingsLib/res/values-si/arrays.xml
index 4af877d..89dca74 100644
--- a/packages/SettingsLib/res/values-si/arrays.xml
+++ b/packages/SettingsLib/res/values-si/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"වැඩිකොට දක්වනවා ඇති ප්‍රදේශ පෙන්වන්න"</item>
     <item msgid="2290859360633824369">"අපවිෂවීම සඳහා ප්‍රදේශ පෙන්වන්න"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (පෙරනිමි)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"සම්මත සීමාව"</item>
     <item msgid="4071574792028999443">"පසුබිම් ක්‍රියාවලි නොමැත"</item>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index b53a46f..9417cef 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"සුරකින ලදි"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"අබලයි"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP වින්‍යාස කිරීම අසාර්ථකයි"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"අඩු ගුණත්වයේ ජාලය හේතුවෙන් සම්බන්ධ නොවීය"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi සම්බන්ධතාව අසාර්ථකයි"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"සත්‍යාපනයේ ගැටලුවකි"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"පරාසයේ නැත"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"කිසිවක් නැත"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"නිදොස්කරණය සඳහා රැඳෙන්න"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"නිදොස් කළ යෙදුම් ක්‍රියාකිරීමට පෙර ඇමිණීම සඳහා නිදොස්කරණය වෙත බලා සිටියි"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telephony Monitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"දුරකථන/මොඩම් ක්‍රියාකාරිත්වයේ ගැටළුවක් හඳුනාගත් විට TelephonyMonitor ලොග එකතු කර දෝෂයක්ගොනු කිරීමට පරිශීලකයා වෙත දැනුම් දෙයි"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"ආදානය"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"ඇඳීම්"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"දෘඩාංග වේගය වැඩි කළ පිරිනැමීම"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"දෘඨාංග ස්ථර යාවත්කාලීන"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"යාවත්කාලින වන විට දෘඩාංග තලය කොළ පහන් දැල්වෙන්න"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU වැඩිකොට දැක්වීම නිදොස් කරන්න"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU විදැහුම සකසන්න"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"HW වසාලන අක්‍රිය කරන්න"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"තිර සංයුක්ත කිරීමට සැමවිටම GPU භාවිතා කරන්න"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"වර්ණ අවකාශය අනුකරණය කරන්න"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"ආදර්ශන ප්‍රකාර කර්මාන්තශාලා යළි සැකසීමට මුරපදය ඇ. ක."</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"ඊළඟ"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"මුරපදය අවශ්‍යයි"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"සක්‍රීය ආදායක මාර්ග"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"පද්ධති භාෂා භාවිත කරන්න"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sk/arrays.xml b/packages/SettingsLib/res/values-sk/arrays.xml
index c0cc99e..6d92464 100644
--- a/packages/SettingsLib/res/values-sk/arrays.xml
+++ b/packages/SettingsLib/res/values-sk/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Zobraziť oblasti prekreslení"</item>
     <item msgid="2290859360633824369">"Zobraziť oblasti pre deuteranomáliu"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (predvolené)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Štandardný limit"</item>
     <item msgid="4071574792028999443">"Žiadne procesy na pozadí"</item>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index ce1315a..c4bf152 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Uložené"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Zakázané"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Zlyhanie konfigurácie adresy IP"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Nepripojené z dôvodu siete nízkej kvality"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Zlyhanie pripojenia Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problém s overením totožnosti"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Mimo dosah"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Nič"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Čakať na ladiaci nástroj"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Aplikácia čaká na pripojenie ladiaceho nástroja"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Monitorovanie telefonických služieb"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Keď monitorovanie telefonických služieb zistí problém s fungovaním telefonických služieb alebo modemu, bude zhromažďovať denníky a zobrazí používateľovi upozornenie s výzvou na nahlásenie chyby"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Vstup"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Vykreslovanie"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Hardvérom zrýchlené vykresľovanie"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Obnovenie hardvér. vrstiev"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Rozblikať zelene hardvérové vrstvy pri obnovení"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Ladenie prekresľovania GPU"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Nastaviť vykr. modul GPU"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Zakázať hardvérové prekrytia"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Vždy používať GPU na skladanie obrazovky"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simulácia far. priestoru"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Zadajte heslo na obnovenie továrenských nastavení v režime ukážky"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Ďalej"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Vyžaduje sa heslo"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Aktívne metódy vstupu"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Použiť jazyky systému"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sl/arrays.xml b/packages/SettingsLib/res/values-sl/arrays.xml
index 5560936..fed93c0 100644
--- a/packages/SettingsLib/res/values-sl/arrays.xml
+++ b/packages/SettingsLib/res/values-sl/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Pokaži risanje zunaj vidnega območja"</item>
     <item msgid="2290859360633824369">"Pokaži območja za devteranomalijo"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (privzeto)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Standardna omejitev"</item>
     <item msgid="4071574792028999443">"Ni postopkov v ozadju"</item>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index ca9eb95..3e0b86f 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Shranjeno"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Onemogočeno"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Konfiguracija IP-ja ni uspela"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Ni povezano zaradi slabe kakovosti omrežja"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Povezava prek Wi-Fi-ja ni uspela"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Težava s preverjanjem pristnosti"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Ni v obsegu"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Nič"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Počakajte na iskalnik napak"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Aplikacija, v kateri iščete napako, pred izvajanjem čaka na povezavo z iskalnikom napak"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Nadziranje telefonije"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Funkcija Nadziranje telefonije pridobi dnevnike, ko zazna težavo s funkcijami telefonije/modema, in uporabnika z obvestilom pozove, naj prijavi napako."</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Vnos"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Risba"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Upodabljanje s strojnim pospeševanjem"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Pokaži pos. sl. str. opr."</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Obarvaj sloje strojne opreme zeleno ob posodobitvi"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Prekoračitev območja GPE"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Nastavi upodabljalnik GPE"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Onem. strojni medp."</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Za sestavljanje slike vedno uporabi graf. procesor"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simul. barvnega prostora"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Geslo za tovar. nast. v predstav. načinu"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Naprej"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Vnesite geslo"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Aktivni načini vnosa"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Uporaba sistemskih jezikov"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sq/arrays.xml b/packages/SettingsLib/res/values-sq/arrays.xml
index 0f8269a..f4e4361 100644
--- a/packages/SettingsLib/res/values-sq/arrays.xml
+++ b/packages/SettingsLib/res/values-sq/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Shfaq zonat e konfliktit"</item>
     <item msgid="2290859360633824369">"Shfaq zonat për deuteranomalinë"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (e parazgjedhur)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Kufizim standard"</item>
     <item msgid="4071574792028999443">"Nuk ka procese në sfond"</item>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 7163852..6a823f1 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"U ruajt"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Të çaktivizuara"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Dështim në konfigurimin e IP-së"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Nuk është lidhur për shkak të rrjetit me cilësi të dobët"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Dështim i lidhjes WiFi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problem me vërtetimin"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Nuk është brenda rrezes"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Asnjë"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Prit për korrigjuesin"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Aplikacioni i korrigjimit të gabimeve pret që korrigjuesi të bashkëngjitet para ekzekutimit"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Monitori i telefonisë"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Monitori i telefonisë do të mbledhë regjistrat kur të zbulojë një problem me funksionalitetin e telefonisë/modemit dhe do t\'i paraqesë një njoftim përdoruesit që të regjistrojë një defekt në kod"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Hyrja"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Vizatime"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Interpretimi i përshpejtuar i harduerit"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Shfaq përditësimet e shtresave të harduerit"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Ndriço në të gjelbër shtresat e harduerit që përditësohen"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Korrigjo konfliktet e GPU-së"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Cakto interpret. e GPU-së"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Çaktivizo mbishtresimin e HW-së"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Përdor gjithmonë GPU-në për përbërjen e ekranit"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simulo hapësirën e ngjyrës"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Fut fjalëkalimin për të kryer rivendosje në gjendje fabrike në modalitetin e demonstrimit"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Përpara"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Kërkohet fjalëkalimi"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Metodat aktive të hyrjeve"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Përdor gjuhët e sistemit"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sr/arrays.xml b/packages/SettingsLib/res/values-sr/arrays.xml
index 912d20b..bf0e3ad 100644
--- a/packages/SettingsLib/res/values-sr/arrays.xml
+++ b/packages/SettingsLib/res/values-sr/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Прикажи области преклапања"</item>
     <item msgid="2290859360633824369">"Прикажи области за деутераномалију"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (подразумевано)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Стандардно ограничење"</item>
     <item msgid="4071574792028999443">"Без позадинских процеса"</item>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 7ea3bf3..a9df5bb 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Сачувано"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Онемогућено"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP конфигурација је отказала"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Није повезано због лошег квалитета мреже"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi веза је отказала"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Проблем са потврдом аутентичности"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Није у опсегу"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Ниједна"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Сачекај програм за отклањање грешака"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Апликација чека програм за отклањање грешака да приложи пре извршавања"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"TelephonyMonitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"TelephonyMonitor ће прикупљати евиденцију када открије проблем са функционисањем телефоније/модема и затражиће од корисника да пријави грешку"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Унос"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Цртање"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Хардверски убрзано приказивање"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Прикажи ажурирања хардверских слојева"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Хардверски слојеви трепере зелено када се ажурирају"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Отклони грешке GPU преклапања"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Подеси GPU приказивач"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Онемог. HW пост. елементе"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Увек користи GPU за компоновање екрана"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Симулирај простор боје"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Унесите лозинку да бисте обавили ресетовање на фабричка подешавања у режиму демонстрације"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Даље"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Потребна је лозинка"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Методе активног уноса"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Користи језике система"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sv/arrays.xml b/packages/SettingsLib/res/values-sv/arrays.xml
index 26496aa..718c39c 100644
--- a/packages/SettingsLib/res/values-sv/arrays.xml
+++ b/packages/SettingsLib/res/values-sv/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Visa områden som överskrider gränsen"</item>
     <item msgid="2290859360633824369">"Visa områden för deuteranomali"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (standard)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Standardgräns"</item>
     <item msgid="4071574792028999443">"Inga bakgrundsprocesser"</item>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index c8d3127..a64ad77 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Sparat"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Inaktiverad"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-konfigurationsfel"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Ingen anslutning på grund av låg kvalitet på nätverket"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi-anslutningsfel"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Autentiseringsproblem"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Utom räckhåll"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Ingen"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Vänta på felsökningen"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Felsökaren måste ansluta till appen först"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telephony Monitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"TelephonyMonitor samlar in loggar när ett problem upptäcks i telefoni-/modemfunktionen och uppmanar användaren att skicka in en felrapport"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Indata"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Ritning"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Maskinvaruaccelererad rendering"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Visa maskinvaruskiktuppd."</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Låt maskinvaruskikt blinka grönt vid uppdateringar"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Felsök överskriden GPU"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Ange GPU-renderare"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Inaktivera HW-överlagringar"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Använd alltid GPU för skärmsammansättning"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Simulera färgrymd"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Ange lösenord och utför fabriksåterställning i demoläge"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Nästa"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Lösenord krävs"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Aktiva inmatningsmetoder"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Använda systemspråk"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sw/arrays.xml b/packages/SettingsLib/res/values-sw/arrays.xml
index 92dbaeb..5df0fdd 100644
--- a/packages/SettingsLib/res/values-sw/arrays.xml
+++ b/packages/SettingsLib/res/values-sw/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Onyesha maeneo yaliyoondolewa"</item>
     <item msgid="2290859360633824369">"Onyesha sehemu za Upofu Rangi Kijani"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (Chaguo-msingi)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Kiwango cha wastani"</item>
     <item msgid="4071574792028999443">"Hakuna mchakato wa mandari nyuma"</item>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 9296e81..198ab7d 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Imehifadhiwa"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Imezimwa"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Haikuweza Kusanidi IP"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Haijaunganishwa kwa sababu intaneti si thabiti"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Haikuweza Kuunganisha kwenye WiFi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Tatizo la uthibitishaji"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Haiko karibu"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Hakuna chochote"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Subiri kitatuaji"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Programu ya utatuaji husubiri kitatuaji ili kuambatisha kabla ya kutekeleza"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Kichunguzi cha Shughuli za Simu"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Kichunguzi cha Shughuli za Simu kitakusanya kumbukumbu wakati kinatambua tatizo katika utendaji wa simu au modemu, na kumwarifu mtumiaji kuwasilisha ripoti ya hitilafu"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Ingizo"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Uchoraji"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Kutunguliza kwa maunzi kulikoharakishwa"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Onyesha sasisho za safu za maunzi"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Angaza kijani safu za maunzi zinaposasisha"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Tatua uondoaji wa GPU"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Weka Kiwasilishaji cha GPU"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Lemaza miekeleo ya HW"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Daima tumia GPU kwa mchanganyiko wa skrini"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Kuiga nafasi ya rangi"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Weka nenosiri ili urejeshe mipangilio ya kiwandani ikiwa katika hali ya onyesho."</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Inayofuata"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Nenosiri linahitajika"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Mbinu zinazotumika"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Tumia lugha za mfumo"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ta/arrays.xml b/packages/SettingsLib/res/values-ta/arrays.xml
index cefb5de..b37c041 100644
--- a/packages/SettingsLib/res/values-ta/arrays.xml
+++ b/packages/SettingsLib/res/values-ta/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"ஓவர்டிரா பகுதிகளைக் காட்டு"</item>
     <item msgid="2290859360633824369">"நிறக்குருடின் பகுதிகளைக் காட்டு"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (இயல்பு)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"நிலையான வரம்பு"</item>
     <item msgid="4071574792028999443">"பின்புலச் செயல்முறைகள் இல்லை"</item>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 7768dfd..11597cd 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"சேமிக்கப்பட்டது"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"முடக்கப்பட்டது"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP உள்ளமைவில் தோல்வி"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"தரம் குறைவான நெட்வொர்க்கின் காரணமாக, இணைக்கப்படவில்லை"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"வைஃபை இணைப்பில் தோல்வி"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"அங்கீகரிப்புச் சிக்கல்"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"தொடர்பு எல்லையில் இல்லை"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"ஒன்றுமில்லை"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"பிழைதிருத்திக்குக் காத்திருக்கவும்"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"பிழைதிருத்தப்பட்ட பயன்பாடு செயல்படுவதற்கு முன்பு பிழைதிருத்தியை இணைப்பதற்குக் காத்திருக்கிறது"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"டெலிஃபோனி மானிட்டர்"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"TelephonyMonitor ஆனது டெலிஃபோனி/மோடம் செயல்பாட்டில் சிக்கல் இருப்பதைக் கண்டறியும் போது, பதிவுகளைச் சேகரிக்கும். அத்துடன், பிழையைப் புகாரளிக்கும்படி பயனருக்கு அறிவிப்பைக் காட்டும்"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"உள்ளீடு"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"வரைபொருள்"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"வன்பொருள் முடுக்கத்துடன் கூடிய காட்சியாக்கம்"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"வன்பொருள் லேயர்களின் புதுப்பிப்புகளைக் காட்டு"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"வன்பொருள் லேயர்களைப் புதுப்பிக்கும்போது, அவற்றைப் பச்சை நிறத்தில் காட்டு"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU ஓவர்டிராவைப் பிழைதிருத்து"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU ரெண்டரரை அமை"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"HW மேலடுக்குகளை முடக்கு"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"திரைத் தொகுத்தலுக்கு எப்போதும் GPU ஐப் பயன்படுத்து"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"வண்ணத்தின் இடைவெளியை உருவகப்படுத்து"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"டெமோ பயன்முறையில் ஆரம்பநிலை மீட்டமைவைச் செயல்படுத்த, கடவுச்சொல்லை உள்ளிடவும்"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"அடுத்து"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"கடவுச்சொல் தேவை"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"செயலில் உள்ள உள்ளீட்டு முறைகள்"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"முறைமை மொழிகளைப் பயன்படுத்து"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-te/arrays.xml b/packages/SettingsLib/res/values-te/arrays.xml
index dd9810b..75e13be 100644
--- a/packages/SettingsLib/res/values-te/arrays.xml
+++ b/packages/SettingsLib/res/values-te/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"ఓవర్‌డ్రా ప్రాంతాలను చూపండి"</item>
     <item msgid="2290859360633824369">"డ్యూటెరానోమలీ కోసం ప్రాంతాలను చూపండి"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (డిఫాల్ట్)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"ప్రామాణిక పరిమితి"</item>
     <item msgid="4071574792028999443">"నేపథ్య ప్రాసెస్‌లు లేవు"</item>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 8379dd8..9d4f8de 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"సేవ్ చేయబడింది"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"నిలిపివేయబడింది"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP కాన్ఫిగరేషన్ వైఫల్యం"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"తక్కువ నాణ్యతా నెట్‌వర్క్ కారణంగా కనెక్ట్ చేయబడలేదు"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi కనెక్షన్ వైఫల్యం"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"ప్రామాణీకరణ సమస్య"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"పరిధిలో లేదు"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"ఏదీ వద్దు"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"డీబగ్గర్ కోసం వేచి ఉండండి"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"డీబగ్ చేయబడిన అనువర్తనం అమలు కావడానికి ముందు జోడించాల్సిన డీబగ్గర్ కోసం వేచి ఉంటుంది"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"టెలిఫోనీ మానిటర్"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"టెలిఫోనీ/మోడెమ్ కార్యాచరణలో సమస్యను గుర్తించినప్పుడు TelephonyMonitor లాగ్‌లను సేకరిస్తుంది మరియు బగ్‌ని ఫైల్ చేయమని వినియోగదారును ప్రోత్సహిస్తుంది"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"ఇన్‌పుట్"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"డ్రాయింగ్"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"హార్డ్‌వేర్ వేగవంతమైన భాషాంతరీకరణ"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"హార్డ్‌వేర్ లేయర్‌ల నవీకరణలను చూపండి"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"హార్డ్‌వేర్ లేయర్‌లు నవీకరించబడినప్పుడు వాటిని ఆకుపచ్చ రంగులో ఫ్లాష్ చేయండి"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU ఓవర్‌డ్రాను డీబగ్ చేయండి"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU Rendererని సెట్ చేయండి"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"HW అతివ్యాప్తులను నిలిపివేయి"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"స్క్రీన్ కంపోజిషనింగ్ కోసం ఎల్లప్పుడూ GPUని ఉపయోగించు"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"రంగు అంతరాన్ని అనుకరించు"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"డెమో మోడ్‌లో ఫ్యాక్టరీ రీసెట్‌ను నిర్వహించడానికి పాస్‌వర్డ్‌ను నమోదు చేయండి"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"తదుపరి"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"పాస్‌వర్డ్ అవసరం"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"సక్రియ ఇన్‌పుట్ పద్ధతులు"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"సిస్టమ్ భాషలను ఉపయోగించు"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-th/arrays.xml b/packages/SettingsLib/res/values-th/arrays.xml
index c1178d2..784a9d5 100644
--- a/packages/SettingsLib/res/values-th/arrays.xml
+++ b/packages/SettingsLib/res/values-th/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"แสดงพื้นที่การวาดทับ"</item>
     <item msgid="2290859360633824369">"แสดงพื้นที่สำหรับคนตาบอดสีเขียว"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (ค่าเริ่มต้น)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"ขีดจำกัดมาตรฐาน"</item>
     <item msgid="4071574792028999443">"ไม่มีกระบวนการพื้นหลัง"</item>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 8f9bd86..9bd2f04 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"บันทึกแล้ว"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"ปิดอยู่"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"การกำหนดค่า IP ล้มเหลว"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"ไม่ได้เชื่อมต่อเนื่องจากเครือข่ายคุณภาพต่ำ"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"การเชื่อมต่อ Wi-Fi ล้มเหลว"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"ปัญหาในการตรวจสอบสิทธิ์"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"ไม่อยู่ในพื้นที่ให้บริการ"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"ไม่มี"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"รอโปรแกรมแก้ไขข้อบกพร่อง"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"แอปพลิเคชันที่มีการแก้ปัญหาจะรอให้โปรแกรมแก้ไขข้อบกพร่องแนบข้อมูลก่อนปฏิบัติการ"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"การตรวจสอบโทรศัพท์"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"การตรวจสอบโทรศัพท์จะรวบรวมบันทึกเมื่อตรวจพบปัญหาด้านฟังก์ชันการทำงานของโทรศัพท์/โมเด็มและแจ้งเตือนให้ผู้ใช้ส่งข้อบกพร่อง"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"อินพุต"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"การวาดภาพ"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"การแสดงผลที่มีการเร่งด้วยฮาร์ดแวร์"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"แสดงอัปเดตเลเยอร์ฮาร์ดแวร์"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"เลเยอร์ฮาร์ดแวร์กะพริบเป็นสีเขียว เมื่อมีการอัปเดต"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"แก้ปัญหาการวาดทับด้วย GPU"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"ตั้งค่า GPU Renderer"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"ปิดใช้งานการวางซ้อน HW"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"ใช้ GPU ในการจัดวางองค์ประกอบหน้าจอเสมอ"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"จำลองระบบสี"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"ป้อนรหัสผ่านเพื่อรีเซ็ตค่าในโหมดสาธิต"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"ถัดไป"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"ต้องป้อนรหัสผ่าน"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"วิธีการป้อนข้อมูลที่ใช้งาน"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"ใช้ภาษาของระบบ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-tl/arrays.xml b/packages/SettingsLib/res/values-tl/arrays.xml
index a5a8219..ed3315c 100644
--- a/packages/SettingsLib/res/values-tl/arrays.xml
+++ b/packages/SettingsLib/res/values-tl/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Tingnan ang mga overdraw na bahagi"</item>
     <item msgid="2290859360633824369">"Ipakita ang mga lugar para sa Deuteranomaly"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (Default)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Karaniwang limitasyon"</item>
     <item msgid="4071574792028999443">"Walang mga proseso sa background"</item>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 47fdae2..2cbd0fc 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Na-save"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Naka-disable"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Pagkabigo ng Configuration ng IP"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Hindi nakakonekta dahil mababa ang kalidad ng network"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Pagkabigo ng Koneksyon sa WiFi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problema sa pagpapatotoo"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Wala sa sakop"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Wala"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Maghintay ng debugger"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Hinihintay ng na-debug na application na ma-attach ang debugger bago magsagawa"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telephony Monitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Mangongolekta ang TelephonyMonitor ng mga log kapag nakatukoy ito ng problema sa functionality ng telephony/modem at magpo-prompt ito ng notification sa user na mag-file ng bug"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Input"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Pagguhit"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Pag-render na pinapabilis ng hardware"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Ipakita ang mga update ng hardware layers"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"I-flash nang berde ang hardware layer pag nag-update ito"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"I-debug ang GPU overdraw"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Itakda ang GPU Renderer"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Wag paganahin HW overlay"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Laging gamitin ang GPU para sa screen compositing"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Gayahin ang color space"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Ilagay ang password upang mag-factory reset sa demo mode"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Susunod"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Kinakailangan ang password"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Mga aktibong paraan ng pag-input"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Gamitin ang mga wika ng system"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-tr/arrays.xml b/packages/SettingsLib/res/values-tr/arrays.xml
index 234ab28..f6c7ee9 100644
--- a/packages/SettingsLib/res/values-tr/arrays.xml
+++ b/packages/SettingsLib/res/values-tr/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Fazla çizilen alanları göster"</item>
     <item msgid="2290859360633824369">"Alanları renk körlüğüne uygun olarak göster"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (Varsayılan)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Standart sınır"</item>
     <item msgid="4071574792028999443">"Arka planda işlem yok"</item>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 57acf21..2e9a39eb 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Kaydedildi"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Devre dışı"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Yapılandırması Hatası"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Ağ kalitesi düşük olduğundan bağlanamadı"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Kablosuz Bağlantı Hatası"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Kimlik doğrulama sorunu"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Kapsama alanı dışında"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Hiçbiri"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Hata ayıklayıcıyı bekle"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Hata ayıklanan uygulama, çalıştırılmadan önce hata ayıklayıcının eklenmesini bekler"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telephony Monitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"TelephonyMonitor, telefon/modem işleviyle ilgili bir sorun algıladığında günlükleri toplar ve hatayı bildirmesi için kullanıcıya bir bildirim gösterir."</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Girdi"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Çizim"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Donanım hızlandırmalı oluşturma"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Donanım katmanı güncellemelerini göster"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Flash donanım katmanları güncellendiğinde yeşildir"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU fazla çizim hatasını ayıkla"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU Oluşturucu\'yu ayarla"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Donanım katmanlarını devre dışı bırak"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Ekran oluştururken her zaman GPU\'yu kullan"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Renk uzayını simüle et"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Demo modunda sıfırlamak için şifreyi girin"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Sonraki"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Şifre gerekli"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Etkin giriş yöntemleri"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Sistem dillerini kullan"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-uk/arrays.xml b/packages/SettingsLib/res/values-uk/arrays.xml
index ea7af71..3956caf 100644
--- a/packages/SettingsLib/res/values-uk/arrays.xml
+++ b/packages/SettingsLib/res/values-uk/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Показувати області накладання"</item>
     <item msgid="2290859360633824369">"Показувати області дейтераномалії"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (за умовчанням)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Стандартне обмеження"</item>
     <item msgid="4071574792028999443">"Без фонових процесів"</item>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 9a742cb..43d7eed 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Збережено"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Вимкнено"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Помилка конфігурації IP-адреси"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Не під’єднано через низьку якість мережі"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Помилка з’єднання Wi-Fi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Проблема з автентифікацією"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Не в діапазоні"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Нічого"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Зачекайте на налагоджувач"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Додаток очікує підключення налагоджувача"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telephony Monitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Коли функція Telephony Monitor виявить проблеми в роботі телефона чи модема, вона збере дані та запропонує користувачеві повідомити про помилку"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Ввід"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Рисування"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Апаратне прискорення"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Показ. апаратні оновлення"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Виділяти апаратні рівні зеленим під час оновлення"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Налагодити накладання GPU"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Вибрати засіб обробки відео для ГП"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Вимк. апаратн. накладання"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Завжди використовувати GPU для компонування екрана"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Моделювання кольорів"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Введіть пароль, щоб скинути налаштування в демо-режимі"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Далі"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Потрібен пароль"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Активні методи введення"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Використовувати мови системи"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ur/arrays.xml b/packages/SettingsLib/res/values-ur/arrays.xml
index 7ad1d17..1d4c9db 100644
--- a/packages/SettingsLib/res/values-ur/arrays.xml
+++ b/packages/SettingsLib/res/values-ur/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"اوور ڈرا والے حصے دکھائیں"</item>
     <item msgid="2290859360633824369">"‏Deuteranomaly کیلئے حصے دکھائیں"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"‏OpenGL (ڈیفالٹ)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"معیاری حد"</item>
     <item msgid="4071574792028999443">"کوئی پس منظر والے پروسیسز نہیں ہیں"</item>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index b5a52ba..00dfd87 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"محفوظ کردیا گیا"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"غیر فعال"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"‏IP کنفیگریشن کی ناکامی"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"کم معیاری نیٹ ورک کی وجہ سے منسلک نہیں ہے"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"‏WiFi کنکشن کی ناکامی"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"توثیق کا مسئلہ"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"رینج میں نہیں ہے"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"کچھ نہیں"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"ڈیبگر کا انتظار کریں"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"ڈیبگ کردہ ایپلیکیشن کاروائی سے پہلے ڈیبگر کے منسلک ہونے کا انتظار کرتی ہے"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telephony Monitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"‏ٹیلیفونی/موڈم کی فعالیت کے ساتھ در پیش مسئلہ کا پتہ چلنے پر TelephonyMonitor لاگز اکٹھا کر کے بگ دائر کرنے کیلئے صارف کو اطلاع بھیجے گا"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"ان پٹ"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"ڈرائنگ"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"ہارڈ ویئر کے ذریعے تیز کردہ رینڈرنگ"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"ہارڈویئر پرتوں کی اپ ڈیٹس دکھائیں"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"ہارڈویئر پرتیں اپ ڈیٹ ہونے پر سبز رنگ میں جھلملائیں"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"‏GPU اوور ڈرا کو ڈیبگ کریں"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"‏GPU رینڈرر سیٹ کریں"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"‏HW اوور لیز غیر فعال کریں"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"‏سکرین کی ساخت بنانے کیلئے ہمیشہ GPU استعمال کریں"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"رنگ کی جگہ کو تحریک دیں"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"ڈیمو موڈ میں فیکٹری ری سیٹ کیلئے پاس ورڈ درج کریں"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"اگلا"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"پاس ورڈ درکار ہے"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"فعال اندراج کے طریقے"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"سسٹم زبانیں استعمال کریں"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-uz/arrays.xml b/packages/SettingsLib/res/values-uz/arrays.xml
index 9790d65..e9ed638 100644
--- a/packages/SettingsLib/res/values-uz/arrays.xml
+++ b/packages/SettingsLib/res/values-uz/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Ortiqcha chizilgan joylarni ko‘rsatish"</item>
     <item msgid="2290859360633824369">"Muayyan rangdagi hududlarni ajratib belgilash"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (standart)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Standard cheklov"</item>
     <item msgid="4071574792028999443">"Fondagi jarayonlarsiz"</item>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index b5460c2..7b7f8d2 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Saqlandi"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"O‘chiq"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP manzilini sozlab bo‘lmadi"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Sifatsiz tarmoq sababli ulanib bo‘lmadi"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi ulanishini o‘rnatib bo‘lmadi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Tasdiqdan o‘tishda muammo"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Aloqada emas"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Yo‘q"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Tuzatuvchi dasturni kuting"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Ilova nosozliklarni tuzatuvchi dasturga ulanishni kutmoqda"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telefoniya nazorati"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Telefoniya nazorati telefoniya/model funksiyalari bilan bog‘liq muammolar aniqlansa va foydalanuvchiga xatolikni yuborishi uchun bildirishnoma yuborib, jurnallarni to‘playdi"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Matn kiritish"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Chizma"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Vizualizatsiyani apparatli tezlatish"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Apparatli yangilanishlarni ko‘rsatish"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Yangilanganda apparatli darajalarni yashil bilan belgilash"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU ortiqcha chiziqlarini o‘chirish"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU renderlash vositasi"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Apparatli qatlamlarni o‘ch. qo‘yish"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Ekranda tasvirlarni biriktirish uchun doim GPU ishlatilsin"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Rang maydonini simulyatsiyalash"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Demo rejimda zavod holatiga qaytarish uchun parolni kiriting"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Keyingisi"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Parolni kiritish zarur"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Faol matn kiritish usullari"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Tizimda mavjud tillar"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-vi/arrays.xml b/packages/SettingsLib/res/values-vi/arrays.xml
index c239039..85c2b2e 100644
--- a/packages/SettingsLib/res/values-vi/arrays.xml
+++ b/packages/SettingsLib/res/values-vi/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Hiển thị các vùng vẽ quá"</item>
     <item msgid="2290859360633824369">"Hiển thị các vùng mô phỏng mù màu lục"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (Mặc định)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Giới hạn tiêu chuẩn"</item>
     <item msgid="4071574792028999443">"Không có quá trình nền"</item>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index ff9a557..7320a2b 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Đã lưu"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Đã tắt"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Lỗi cấu hình IP"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Không được kết nối do mạng chất lượng kém"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Lỗi kết nối WiFi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Sự cố xác thực"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Ngoài vùng phủ sóng"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Không có ứng dụng"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Đợi trình gỡ lỗi"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Ứng dụng được gỡ lỗi chờ trình gỡ lỗi đính kèm trước khi thực hiện"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Giám sát điện thoại"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"TelephonyMonitor sẽ thu thập nhật ký khi phát hiện thấy sự cố với chức năng điện thoại/modem và gửi thông báo khẩn cấp tới người dùng để gửi lỗi"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Nhập"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Vẽ"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Kết xuất có tăng tốc phần cứng"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Hiện c.nhật lớp phần cứng"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Lớp phần cứng flash có màu xanh khi chúng cập nhật"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Hiển thị mức vẽ quá GPU"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Đặt kết xuất đồ họa GPU"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Vô hiệu hóa các lớp phủ HW"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Luôn sử dụng GPU để tổng hợp màn hình"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Mô phỏng không gian màu"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Nhập mật khẩu để tiến hành khôi phục cài đặt gốc ở chế độ trình diễn"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Tiếp theo"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Yêu cầu mật khẩu"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Phương pháp nhập liệu hoạt động"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Sử dụng ngôn ngữ hệ thống"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rCN/arrays.xml b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
index 7c6e2ee..1f5f284 100644
--- a/packages/SettingsLib/res/values-zh-rCN/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"显示过度绘制区域"</item>
     <item msgid="2290859360633824369">"显示适合绿色弱视患者查看的区域"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL(默认)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"标准限制"</item>
     <item msgid="4071574792028999443">"不允许后台进程"</item>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 97a5678..cb94514 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"已保存"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"已停用"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP 配置失败"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"网络质量较差,因此未连接"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WLAN 连接失败"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"身份验证出现问题"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"不在范围内"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"无"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"等待调试器"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"调试应用会在执行前等待附加调试器"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"电话监控器"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"电话监控器会在检测到电话/调制解调器功能存在问题时收集相关日志,并向用户发出通知,提醒用户提交错误报告"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"输入"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"绘图"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"硬件加速渲染"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"显示硬件层更新"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Flash 硬件层在进行更新时会显示为绿色"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"调试 GPU 过度绘制"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"设置 GPU 渲染程序"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"停用 HW 叠加层"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"始终使用 GPU 进行屏幕合成"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"模拟颜色空间"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"输入密码即可在演示模式下恢复出厂设置"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"下一步"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"需要输入密码"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"有效的输入法"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"使用系统语言"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rHK/arrays.xml b/packages/SettingsLib/res/values-zh-rHK/arrays.xml
index 642d616..b5d12b1 100644
--- a/packages/SettingsLib/res/values-zh-rHK/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"顯示過度繪製區域"</item>
     <item msgid="2290859360633824369">"顯示綠色弱視區域"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (預設)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"標準限制"</item>
     <item msgid="4071574792028999443">"無背景處理程序"</item>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 0838496..1dc8abd 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"已儲存"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"已停用"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP 設定失敗"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"網絡品質欠佳,因此無法連線"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi 連線失敗"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"驗證問題"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"超出可用範圍"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"無"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"等待除錯程式"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"執行已除錯的應用程式前等待附加除錯程式"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"電話監控工具"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"「電話監控工具」會在偵測到電話/數據機功能發生問題時收集記錄,並向使用者發出通知,以便舉報錯誤"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"輸入"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"繪圖"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"硬件加速轉譯"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"顯示硬件層更新"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"在硬件層更新時閃動綠燈"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU 透支偵錯"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"設定 GPU 轉譯器"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"停用 HW 重疊效果"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"永遠使用 GPU 進行畫面合成"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"模擬色彩空間"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"輸入密碼即可在示範模式下重設原廠設定"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"下一步"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"請輸入密碼"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"可用的輸入法"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"使用系統語言"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rTW/arrays.xml b/packages/SettingsLib/res/values-zh-rTW/arrays.xml
index 449ccc1..81e9bdb 100644
--- a/packages/SettingsLib/res/values-zh-rTW/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"顯示透支區域"</item>
     <item msgid="2290859360633824369">"顯示綠色弱視區域"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"OpenGL (預設)"</item>
+    <item msgid="2839130076198120436">"OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"標準限制"</item>
     <item msgid="4071574792028999443">"不執行背景處理程序"</item>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 4d7f736..fd0b9ff 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"已儲存"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"已停用"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP 設定失敗"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"網路品質不佳,因此未連線"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi 連線失敗"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"驗證問題"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"不在有效範圍內"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"無"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"等待偵錯程式"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"執行受偵錯的應用程式之前,先等待偵錯程序附加完成"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telephony Monitor"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"Telephony Monitor 會在偵測到電話/數據機功能發生問題時收集相關紀錄,並顯示通知方便使用者回報錯誤"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"輸入"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"繪圖"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"硬體加速轉譯"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"顯示硬體層更新"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"在硬體層更新時閃綠燈"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"針對 GPU 重複繪圖進行偵錯"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"設定 GPU 轉譯器"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"停用硬體重疊圖層"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"一律使用 GPU 進行畫面合成"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"模擬色彩空間"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"如要在示範模式中恢復原廠設定,請輸入密碼"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"下一步"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"請輸入密碼"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"啟用的輸入法"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"使用系統語言"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zu/arrays.xml b/packages/SettingsLib/res/values-zu/arrays.xml
index ed78ed8..4263772e 100644
--- a/packages/SettingsLib/res/values-zu/arrays.xml
+++ b/packages/SettingsLib/res/values-zu/arrays.xml
@@ -216,6 +216,10 @@
     <item msgid="7688197031296835369">"Bonisa izindawo zokukhipha okungaphezulu"</item>
     <item msgid="2290859360633824369">"Bonisa izindawo ze-Deuteranomaly"</item>
   </string-array>
+  <string-array name="debug_hw_renderer_entries">
+    <item msgid="2578620445459945681">"I-OpenGL (Okuzenzakalelayo)"</item>
+    <item msgid="2839130076198120436">"I-OpenGL (Skia)"</item>
+  </string-array>
   <string-array name="app_process_limit_entries">
     <item msgid="3401625457385943795">"Isilanganiso esivamile"</item>
     <item msgid="4071574792028999443">"Azikho izinqubo zesizinda"</item>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 9f7e72e..d51a3ae 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -25,6 +25,7 @@
     <string name="wifi_remembered" msgid="4955746899347821096">"Kulondoloziwe"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Akusebenzi"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Ukwehluleka kokulungiswa kwe-IP"</string>
+    <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Ayixhunyiwe ngenxa yenethiwekhi yekhwalithi ephansi"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Ukwehlulekla koxhumo le-WiFi"</string>
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Inkinga yokufakazela ubuqiniso"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"Ayikho ebubanzini"</string>
@@ -217,6 +218,8 @@
     <string name="no_application" msgid="2813387563129153880">"Lutho"</string>
     <string name="wait_for_debugger" msgid="1202370874528893091">"Linda isilungisi senkinga"</string>
     <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Uhlelo lokusebenza olulungiswe inkinga lulinda isilungisi senkinga ukuba sinamathisele ngaphambi kokuphuma"</string>
+    <string name="telephony_monitor_switch" msgid="1764958220062121194">"Ukuqashwa kwefoni"</string>
+    <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"I-TelephonyMonitor izoqoqa amalogi uma ithola inkinga ngokusebenza kwefoni/imodemu iphinde ikhiphe isaziso esiya kumsebenzisi ukuthi athumele isiphazamisi"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"Okufakwayo"</string>
     <string name="debug_drawing_category" msgid="6755716469267367852">"Umdwebo"</string>
     <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Ukunikezelwa okusheshisiwe kwezingxenyekazi zekhompyutha"</string>
@@ -235,6 +238,7 @@
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"Bonisa izibuyekezo zezendlalelo izingxenyekazi zekhompyutha"</string>
     <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Izendlalelo zengxenyekazi zekhompyutha eziluhlaza uma zibuyekeza"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"Susa iphutha lokukhipha okungaphezulu kwe-GPU"</string>
+    <string name="debug_hw_renderer" msgid="7568529019431785816">"Setha isinikezeli se-GPU"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"Khubaza izimbondela ze-HW"</string>
     <string name="disable_overlays_summary" msgid="3578941133710758592">"Njalo sebenzisa i-GPU ukwakha isikrini"</string>
     <string name="simulate_color_space" msgid="6745847141353345872">"Qoqa isikhala sombala"</string>
@@ -356,4 +360,6 @@
     <string name="retail_demo_reset_message" msgid="118771671364131297">"Faka iphasiwedi ukuze wenze ukusetha kwefekthri kumodi yedemo"</string>
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"Okulandelayo"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"Iphasiwedi iyadingeka"</string>
+    <string name="active_input_method_subtypes" msgid="3596398805424733238">"Izindlela zokufakwayo okusebenzayo"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Sebenzisa izilimi zesistimu"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml
index eb64b3a..9ff22c7 100644
--- a/packages/SettingsLib/res/values/arrays.xml
+++ b/packages/SettingsLib/res/values/arrays.xml
@@ -444,6 +444,18 @@
         <item>show_deuteranomaly</item>
     </string-array>
 
+    <!-- Titles for debug renderer preference. [CHAR LIMIT=50] -->
+    <string-array name="debug_hw_renderer_entries">
+        <item>OpenGL (Default)</item>
+        <item>OpenGL (Skia)</item>
+    </string-array>
+
+    <!-- Values for debug renderer preference. -->
+    <string-array name="debug_hw_renderer_values" translatable="false" >
+        <item>opengl</item>
+        <item>skiagl</item>
+    </string-array>
+
     <!-- Titles for app process limit preference. [CHAR LIMIT=35] -->
     <string-array name="app_process_limit_entries">
         <item>Standard limit</item>
@@ -526,7 +538,7 @@
         <item>100</item>
     </array>
     <array name="batterymeter_color_values">
-        <item>@*android:color/battery_saver_mode_color</item>
+        <item>?android:attr/colorError</item>
         <item>@android:color/white</item>
     </array>
     <array name="batterymeter_bolt_points">
diff --git a/packages/SettingsLib/res/values/config.xml b/packages/SettingsLib/res/values/config.xml
index ee69b56..64f21b5 100755
--- a/packages/SettingsLib/res/values/config.xml
+++ b/packages/SettingsLib/res/values/config.xml
@@ -26,9 +26,6 @@
     <!-- Whether to send a custom package name with the PSD.-->
     <bool name="config_sendPackageName">false</bool>
 
-    <!-- Whether to enable the left nav drawer in all Settings UI.-->
-    <bool name="config_enable_nav_drawer">false</bool>
-
     <!-- Name for the set of keys associating package names -->
     <string name="config_helpPackageNameKey" translatable="false"></string>
 
diff --git a/packages/SettingsLib/res/values/dimens.xml b/packages/SettingsLib/res/values/dimens.xml
index aa36617..3322839 100644
--- a/packages/SettingsLib/res/values/dimens.xml
+++ b/packages/SettingsLib/res/values/dimens.xml
@@ -51,12 +51,6 @@
 
     <dimen name="usage_graph_dot_size">.75dp</dimen>
     <dimen name="usage_graph_dot_interval">7dp</dimen>
-    <dimen name="drawer_icon_size">24dp</dimen>
-    <dimen name="normal_icon_size">24dp</dimen>
-    <dimen name="drawer_icon_margin">24dp</dimen>
-    <dimen name="drawer_width">300dp</dimen>
-    <dimen name="drawer_item_top_bottom_margin">4dp</dimen>
-    <dimen name="drawer_spacer_height">32dp</dimen>
 
     <dimen name="battery_height">14.5dp</dimen>
     <dimen name="battery_width">9.5dp</dimen>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index e8e9cc5..f77d466 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -537,6 +537,11 @@
     <string name="wait_for_debugger_summary">Debugged application waits for debugger to
         attach before executing</string>
 
+    <!-- UI debug setting: title for Telephonymonitor switch [CHAR LIMIT=50] -->
+    <string name="telephony_monitor_switch">Telephony Monitor</string>
+    <!-- UI debug setting: summary for switch of Telephonymonitor [CHAR LIMIT=500] -->
+    <string name="telephony_monitor_switch_summary">TelephonyMonitor will collect logs when it detects a problem with telephony/modem functionality and prompt notification to user to file a bug</string>
+
     <!-- Preference category for input debugging development settings. [CHAR LIMIT=25] -->
     <string name="debug_input_category">Input</string>
 
@@ -586,6 +591,9 @@
     <!-- UI debug setting: show the amount of overdraw in apps using the GPU [CHAR LIMIT=25] -->
     <string name="debug_hw_overdraw">Debug GPU overdraw</string>
 
+    <!-- UI debug setting: select the renderer to use by RenderThread [CHAR LIMIT=25] -->
+    <string name="debug_hw_renderer">Set GPU Renderer</string>
+
     <!-- UI debug setting: disable use of overlays? [CHAR LIMIT=25] -->
     <string name="disable_overlays">Disable HW overlays</string>
     <!-- UI debug setting: disable use of overlays summary [CHAR LIMIT=50] -->
@@ -905,4 +913,12 @@
 
     <!-- Glyph to be overlaid atop the battery when the level is extremely low. Do not translate. -->
     <string name="battery_meter_very_low_overlay_symbol">!</string>
+
+    <!-- Title for settings of active input methods in each IME [CHAR LIMIT=35] -->
+    <string name="active_input_method_subtypes">Active input methods</string>
+    <!-- Title for settings whether or not the framework will select input methods in an IME based
+         on the current system locales. (The user can select multiple system locales)
+         [CHAR LIMIT=35] -->
+    <string name="use_system_language_to_select_input_method_subtypes">Use system languages</string>
+
 </resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/BatteryInfo.java b/packages/SettingsLib/src/com/android/settingslib/BatteryInfo.java
index fa1f91f..22f8856 100644
--- a/packages/SettingsLib/src/com/android/settingslib/BatteryInfo.java
+++ b/packages/SettingsLib/src/com/android/settingslib/BatteryInfo.java
@@ -38,6 +38,7 @@
     public long remainingTimeUs = 0;
     public String batteryPercentString;
     public String remainingLabel;
+    public String statusLabel;
     private BatteryStats mStats;
     private boolean mCharging;
     private long timePeriod;
@@ -135,6 +136,7 @@
         info.batteryPercentString = Utils.formatPercentage(info.mBatteryLevel);
         info.mCharging = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
         final Resources resources = context.getResources();
+        info.statusLabel = Utils.getBatteryStatus(resources, batteryBroadcast, shortString);
         if (!info.mCharging) {
             final long drainTime = stats.computeBatteryTimeRemaining(elapsedRealtimeUs);
             if (drainTime > 0) {
@@ -155,8 +157,6 @@
             }
         } else {
             final long chargeTime = stats.computeChargeTimeRemaining(elapsedRealtimeUs);
-            final String statusLabel = Utils.getBatteryStatus(
-                    resources, batteryBroadcast, shortString);
             final int status = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_STATUS,
                     BatteryManager.BATTERY_STATUS_UNKNOWN);
             if (chargeTime > 0 && status != BatteryManager.BATTERY_STATUS_FULL) {
@@ -184,9 +184,9 @@
                 info.mChargeLabelString = resources.getString(
                         resId, info.batteryPercentString, timeString);
             } else {
-                info.remainingLabel = statusLabel;
+                info.remainingLabel = null;
                 info.mChargeLabelString = resources.getString(
-                        R.string.power_charging, info.batteryPercentString, statusLabel);
+                        R.string.power_charging, info.batteryPercentString, info.statusLabel);
             }
         }
         return info;
diff --git a/packages/SettingsLib/src/com/android/settingslib/HelpUtils.java b/packages/SettingsLib/src/com/android/settingslib/HelpUtils.java
index fc697ce..58047bb 100644
--- a/packages/SettingsLib/src/com/android/settingslib/HelpUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/HelpUtils.java
@@ -76,12 +76,14 @@
     public static boolean prepareHelpMenuItem(Activity activity, Menu menu, String helpUri,
             String backupContext) {
         MenuItem helpItem = menu.add(0, MENU_HELP, 0, R.string.help_feedback_label);
+        helpItem.setIcon(R.drawable.ic_help_actionbar);
         return prepareHelpMenuItem(activity, helpItem, helpUri, backupContext);
     }
 
     public static boolean prepareHelpMenuItem(Activity activity, Menu menu, int helpUriResource,
             String backupContext) {
         MenuItem helpItem = menu.add(0, MENU_HELP, 0, R.string.help_feedback_label);
+        helpItem.setIcon(R.drawable.ic_help_actionbar);
         return prepareHelpMenuItem(activity, helpItem, activity.getString(helpUriResource),
                 backupContext);
     }
@@ -125,7 +127,7 @@
                         return true;
                     }
                 });
-                helpMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
+                helpMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
                 helpMenuItem.setVisible(true);
             } else {
                 helpMenuItem.setVisible(false);
@@ -209,7 +211,7 @@
      * of the app's package as gotten via the context.
      * @return the uri with added query parameters
      */
-    public static Uri uriWithAddedParameters(Context context, Uri baseUri) {
+    private static Uri uriWithAddedParameters(Context context, Uri baseUri) {
         Uri.Builder builder = baseUri.buildUpon();
 
         // Add in the preferred language
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
index 99d7f1e..49fc2ea 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
@@ -16,6 +16,11 @@
 
 package com.android.settingslib;
 
+import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE;
+import static android.app.admin.DevicePolicyManager.PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.AppGlobals;
 import android.app.admin.DevicePolicyManager;
@@ -29,6 +34,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
+import android.support.annotation.VisibleForTesting;
 import android.text.Spanned;
 import android.text.SpannableStringBuilder;
 import android.text.style.ForegroundColorSpan;
@@ -108,47 +114,68 @@
     }
 
     /**
-     * Checks if keyguard features are disabled by policy.
+     * Checks whether keyguard features are disabled by policy.
      *
-     * @param keyguardFeatures Could be any of keyguard features that can be
+     * @param context {@link Context} for the calling user.
+     *
+     * @param keyguardFeatures Any one of keyguard features that can be
      * disabled by {@link android.app.admin.DevicePolicyManager#setKeyguardDisabledFeatures}.
+     *
+     * @param userId User to check enforced admin status for.
+     *
      * @return EnforcedAdmin Object containing the enforced admin component and admin user details,
      * or {@code null} If the notification features are not disabled. If the restriction is set by
      * multiple admins, then the admin component will be set to {@code null} and userId to
      * {@link UserHandle#USER_NULL}.
      */
     public static EnforcedAdmin checkIfKeyguardFeaturesDisabled(Context context,
-            int keyguardFeatures, int userId) {
-        final LockSettingCheck check =
-                (DevicePolicyManager dpm, ComponentName admin, @UserIdInt int checkUser) ->
-                        (dpm.getKeyguardDisabledFeatures(admin, checkUser) & keyguardFeatures) != 0;
+            int keyguardFeatures, final @UserIdInt int userId) {
+        final LockSettingCheck check = (dpm, admin, checkUser) -> {
+            int effectiveFeatures = dpm.getKeyguardDisabledFeatures(admin, checkUser);
+            if (checkUser != userId) {
+                effectiveFeatures &= PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER;
+            }
+            return (effectiveFeatures & keyguardFeatures) != KEYGUARD_DISABLE_FEATURES_NONE;
+        };
+        if (UserManager.get(context).getUserInfo(userId).isManagedProfile()) {
+            DevicePolicyManager dpm =
+                    (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
+            return findEnforcedAdmin(dpm.getActiveAdminsAsUser(userId), dpm, userId, check);
+        }
+        return checkForLockSetting(context, userId, check);
+    }
 
-        final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
-                Context.DEVICE_POLICY_SERVICE);
-        if (dpm == null) {
+    /**
+     * Filter a set of device admins based on a predicate {@code check}. This is equivalent to
+     * {@code admins.stream().filter(check).map(x → new EnforcedAdmin(admin, userId)} except it's
+     * returning a zero/one/many-type thing.
+     *
+     * @param admins set of candidate device admins identified by {@link ComponentName}.
+     * @param userId user to create the resultant {@link EnforcedAdmin} as.
+     * @param check filter predicate.
+     *
+     * @return {@code null} if none of the {@param admins} match.
+     *         An {@link EnforcedAdmin} if exactly one of the admins matches.
+     *         Otherwise, {@link EnforcedAdmin#MULTIPLE_ENFORCED_ADMIN} for multiple matches.
+     */
+    @Nullable
+    private static EnforcedAdmin findEnforcedAdmin(@Nullable List<ComponentName> admins,
+            @NonNull DevicePolicyManager dpm, @UserIdInt int userId,
+            @NonNull LockSettingCheck check) {
+        if (admins == null) {
             return null;
         }
-
-        final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
-        if (um.getUserInfo(userId).isManagedProfile()) {
-            final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userId);
-            if (admins == null) {
-                return null;
-            }
-            EnforcedAdmin enforcedAdmin = null;
-            for (ComponentName admin : admins) {
-                if (check.isEnforcing(dpm, admin, userId)) {
-                    if (enforcedAdmin == null) {
-                        enforcedAdmin = new EnforcedAdmin(admin, userId);
-                    } else {
-                        return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
-                    }
+        EnforcedAdmin enforcedAdmin = null;
+        for (ComponentName admin : admins) {
+            if (check.isEnforcing(dpm, admin, userId)) {
+                if (enforcedAdmin == null) {
+                    enforcedAdmin = new EnforcedAdmin(admin, userId);
+                } else {
+                    return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
                 }
             }
-            return enforcedAdmin;
-        } else {
-            return checkForLockSetting(context, userId, check);
         }
+        return enforcedAdmin;
     }
 
     public static EnforcedAdmin checkIfUninstallBlocked(Context context,
@@ -361,7 +388,7 @@
         }
 
         LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
-        if (lockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
+        if (sProxy.isSeparateProfileChallengeEnabled(lockPatternUtils, userId)) {
             // userId is managed profile and has a separate challenge, only consider
             // the admins in that user.
             final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userId);
@@ -428,7 +455,7 @@
                 if (userInfo.isManagedProfile()) {
                     // If userInfo.id is a managed profile, we also need to look at
                     // the policies set on the parent.
-                    final DevicePolicyManager parentDpm = dpm.getParentProfileInstance(userInfo);
+                    DevicePolicyManager parentDpm = sProxy.getParentProfileInstance(dpm, userInfo);
                     if (parentDpm.getMaximumTimeToLock(admin, userInfo.id) > 0) {
                         if (enforcedAdmin == null) {
                             enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
@@ -448,8 +475,9 @@
 
     /**
      * Checks whether any of the user's profiles enforce the lock setting. A managed profile is only
-     * included if it does not have a separate challenege but the settings for it's parent (i.e. the
-     * user being checked) are always included.
+     * included if it does not have a separate challenge.
+     *
+     * The user identified by {@param userId} is always included.
      */
     private static EnforcedAdmin checkForLockSetting(
             Context context, @UserIdInt int userId, LockSettingCheck check) {
@@ -468,7 +496,7 @@
                 continue;
             }
             final boolean isSeparateProfileChallengeEnabled =
-                    lockPatternUtils.isSeparateProfileChallengeEnabled(userInfo.id);
+                    sProxy.isSeparateProfileChallengeEnabled(lockPatternUtils, userInfo.id);
             for (ComponentName admin : admins) {
                 if (!isSeparateProfileChallengeEnabled) {
                     if (check.isEnforcing(dpm, admin, userInfo.id)) {
@@ -487,7 +515,7 @@
                 if (userInfo.isManagedProfile()) {
                     // If userInfo.id is a managed profile, we also need to look at
                     // the policies set on the parent.
-                    final DevicePolicyManager parentDpm = dpm.getParentProfileInstance(userInfo);
+                    DevicePolicyManager parentDpm = sProxy.getParentProfileInstance(dpm, userInfo);
                     if (check.isEnforcing(parentDpm, admin, userInfo.id)) {
                         if (enforcedAdmin == null) {
                             enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
@@ -733,4 +761,23 @@
             other.userId = userId;
         }
     }
+
+    /**
+     * Static {@link LockPatternUtils} and {@link DevicePolicyManager} wrapper for testing purposes.
+     * {@link LockPatternUtils} is an internal API not supported by robolectric.
+     * {@link DevicePolicyManager} has a {@code getProfileParent} not yet suppored by robolectric.
+     */
+    @VisibleForTesting
+    static Proxy sProxy = new Proxy();
+
+    @VisibleForTesting
+    static class Proxy {
+        public boolean isSeparateProfileChallengeEnabled(LockPatternUtils utils, int userHandle) {
+            return utils.isSeparateProfileChallengeEnabled(userHandle);
+        }
+
+        public DevicePolicyManager getParentProfileInstance(DevicePolicyManager dpm, UserInfo ui) {
+            return dpm.getParentProfileInstance(ui);
+        }
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/TronUtils.java b/packages/SettingsLib/src/com/android/settingslib/TronUtils.java
index 1d9d03a..bea6e8f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/TronUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/TronUtils.java
@@ -16,7 +16,7 @@
 package com.android.settingslib;
 
 import android.content.Context;
-import android.net.ScoredNetwork;
+import android.net.NetworkBadging;
 
 import com.android.internal.logging.MetricsLogger;
 
@@ -34,7 +34,7 @@
      *
      * @param context Context
      * @param histogram the Tron histogram name to write to
-     * @param badgeEnum the {@link ScoredNetwork.Badging} badge value
+     * @param badgeEnum the {@link NetworkBadging.Badging} badge value
      * @throws IllegalArgumentException if the given badge enum is not supported
      */
     private static void logNetworkBadgeMetric(
@@ -42,16 +42,16 @@
             throws IllegalArgumentException {
         int bucket;
         switch (badgeEnum) {
-            case ScoredNetwork.BADGING_NONE:
+            case NetworkBadging.BADGING_NONE:
                 bucket = 0;
                 break;
-            case ScoredNetwork.BADGING_SD:
+            case NetworkBadging.BADGING_SD:
                 bucket = 1;
                 break;
-            case ScoredNetwork.BADGING_HD:
+            case NetworkBadging.BADGING_HD:
                 bucket = 2;
                 break;
-            case ScoredNetwork.BADGING_4K:
+            case NetworkBadging.BADGING_4K:
                 bucket = 3;
                 break;
             default:
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index 8653523..7e7b391 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -17,7 +17,7 @@
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.LayerDrawable;
 import android.net.ConnectivityManager;
-import android.net.ScoredNetwork;
+import android.net.NetworkBadging;
 import android.os.BatteryManager;
 import android.os.UserManager;
 import android.print.PrintManager;
@@ -112,6 +112,12 @@
                 UserIcons.getDefaultUserIcon(user.id, /* light= */ false)).bake();
     }
 
+    /** Formats a double from 0.0..100.0 with an option to round **/
+    public static String formatPercentage(double percentage, boolean round) {
+        final int localPercentage = round ? Math.round((float) percentage) : (int) percentage;
+        return formatPercentage(localPercentage);
+    }
+
     /** Formats the ratio of amount/total as a percentage. */
     public static String formatPercentage(long amount, long total) {
         return formatPercentage(((double) amount) / total);
@@ -124,7 +130,7 @@
 
     /** Formats a double from 0.0..1.0 as a percentage. */
     private static String formatPercentage(double percentage) {
-      return NumberFormat.getPercentInstance().format(percentage);
+        return NumberFormat.getPercentInstance().format(percentage);
     }
 
     public static int getBatteryLevel(Intent batteryChangedIntent) {
@@ -178,10 +184,7 @@
 
     @ColorInt
     public static int getColorError(Context context) {
-        TypedArray ta = context.obtainStyledAttributes(new int[]{android.R.attr.textColorError});
-        @ColorInt int colorError = ta.getColor(0, 0);
-        ta.recycle();
-        return colorError;
+        return getColorAttr(context, android.R.attr.colorError);
     }
 
     @ColorInt
@@ -304,13 +307,13 @@
      */
     public static int getWifiBadgeResource(int badge) {
         switch (badge) {
-            case ScoredNetwork.BADGING_NONE:
+            case NetworkBadging.BADGING_NONE:
                 return View.NO_ID;
-            case ScoredNetwork.BADGING_SD:
+            case NetworkBadging.BADGING_SD:
                 return com.android.internal.R.drawable.ic_signal_wifi_badged_sd;
-            case ScoredNetwork.BADGING_HD:
+            case NetworkBadging.BADGING_HD:
                 return com.android.internal.R.drawable.ic_signal_wifi_badged_hd;
-            case ScoredNetwork.BADGING_4K:
+            case NetworkBadging.BADGING_4K:
                 return com.android.internal.R.drawable.ic_signal_wifi_badged_4k;
             default:
                 throw new IllegalArgumentException(
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/AppUtils.java b/packages/SettingsLib/src/com/android/settingslib/applications/AppUtils.java
index f6d9134..b06b032 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/AppUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/AppUtils.java
@@ -19,13 +19,16 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.hardware.usb.IUsbManager;
 import android.os.RemoteException;
+import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.util.Log;
 
 import com.android.settingslib.R;
+import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -33,6 +36,13 @@
 public class AppUtils {
     private static final String TAG = "AppUtils";
 
+    /**
+     * This should normally only be set in robolectric tests, to avoid getting a method not found
+     * exception when calling the isInstantApp method of the ApplicationInfo class, because
+     * robolectric does not yet have an implementation of it.
+     */
+    private static InstantAppDataProvider sInstantAppDataProvider = null;
+
     public static CharSequence getLaunchByDefaultSummary(ApplicationsState.AppEntry appEntry,
             IUsbManager usbManager, PackageManager pm, Context context) {
         String packageName = appEntry.info.packageName;
@@ -68,4 +78,33 @@
         return prefActList.size() > 0;
     }
 
+    /**
+     * Returns a boolean indicating whether the given package should be considered an instant app
+     */
+    public static boolean isInstant(ApplicationInfo info) {
+        if (sInstantAppDataProvider != null) {
+            if (sInstantAppDataProvider.isInstantApp(info)) {
+                return true;
+            }
+        } else if (info.isInstantApp()) {
+            return true;
+        }
+
+        // For debugging/testing, we support setting the following property to a comma-separated
+        // list of search terms (typically, but not necessarily, full package names) to match
+        // against the package names of the app.
+        String propVal = SystemProperties.get("settingsdebug.instant.packages");
+        if (propVal != null && !propVal.isEmpty() && info.packageName != null) {
+            String[] searchTerms = propVal.split(",");
+            if (searchTerms != null) {
+                for (String term : searchTerms) {
+                    if (info.packageName.contains(term)) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index 1f03b51..8f7efb5 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -19,6 +19,8 @@
 import android.app.ActivityManager;
 import android.app.AppGlobals;
 import android.app.Application;
+import android.app.usage.StorageStats;
+import android.app.usage.StorageStatsManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -92,12 +94,14 @@
     final PackageManager mPm;
     final IPackageManager mIpm;
     final UserManager mUm;
+    final StorageStatsManager mStats;
     final int mAdminRetrieveFlags;
     final int mRetrieveFlags;
     PackageIntentReceiver mPackageIntentReceiver;
 
     boolean mResumed;
     boolean mHaveDisabledApps;
+    boolean mHaveInstantApps;
 
     // Information about all applications.  Synchronize on mEntriesMap
     // to protect access to these.
@@ -110,6 +114,7 @@
     final ArrayList<AppEntry> mAppEntries = new ArrayList<AppEntry>();
     List<ApplicationInfo> mApplications = new ArrayList<ApplicationInfo>();
     long mCurId = 1;
+    String mCurComputingSizeUuid;
     String mCurComputingSizePkg;
     int mCurComputingSizeUserId;
     boolean mSessionsChanged;
@@ -125,7 +130,8 @@
         mContext = app;
         mPm = mContext.getPackageManager();
         mIpm = AppGlobals.getPackageManager();
-        mUm = (UserManager) app.getSystemService(Context.USER_SERVICE);
+        mUm = mContext.getSystemService(UserManager.class);
+        mStats = mContext.getSystemService(StorageStatsManager.class);
         for (int userId : mUm.getProfileIdsWithDisabled(UserHandle.myUserId())) {
             mEntriesMap.put(userId, new HashMap<String, AppEntry>());
         }
@@ -212,6 +218,7 @@
         }
 
         mHaveDisabledApps = false;
+        mHaveInstantApps = false;
         for (int i=0; i<mApplications.size(); i++) {
             final ApplicationInfo info = mApplications.get(i);
             // Need to trim out any applications that are disabled by
@@ -224,6 +231,10 @@
                 }
                 mHaveDisabledApps = true;
             }
+            if (!mHaveInstantApps && AppUtils.isInstant(info)) {
+                mHaveInstantApps = true;
+            }
+
             int userId = UserHandle.getUserId(info.uid);
             final AppEntry entry = mEntriesMap.get(userId).get(info.packageName);
             if (entry != null) {
@@ -250,6 +261,9 @@
     public boolean haveDisabledApps() {
         return mHaveDisabledApps;
     }
+    public boolean haveInstantApps() {
+        return mHaveInstantApps;
+    }
 
     void doPauseIfNeededLocked() {
         if (!mResumed) {
@@ -319,7 +333,18 @@
         synchronized (mEntriesMap) {
             AppEntry entry = mEntriesMap.get(userId).get(packageName);
             if (entry != null) {
-                mPm.getPackageSizeInfoAsUser(packageName, userId, mBackgroundHandler.mStatsObserver);
+                mBackgroundHandler.post(() -> {
+                    final StorageStats stats = mStats.queryStatsForPackage(entry.info.volumeUuid,
+                            packageName, UserHandle.of(userId));
+                    final PackageStats legacyStats = new PackageStats(packageName, userId);
+                    legacyStats.codeSize = stats.getCodeBytes();
+                    legacyStats.dataSize = stats.getDataBytes();
+                    legacyStats.cacheSize = stats.getCacheBytes();
+                    try {
+                        mBackgroundHandler.mStatsObserver.onGetStatsCompleted(legacyStats, true);
+                    } catch (RemoteException ignored) {
+                    }
+                });
             }
             if (DEBUG_LOCKING) Log.v(TAG, "...requestSize releasing lock");
         }
@@ -379,6 +404,9 @@
                     }
                     mHaveDisabledApps = true;
                 }
+                if (AppUtils.isInstant(info)) {
+                    mHaveInstantApps = true;
+                }
                 mApplications.add(info);
                 if (!mBackgroundHandler.hasMessages(BackgroundHandler.MSG_LOAD_ENTRIES)) {
                     mBackgroundHandler.sendEmptyMessage(BackgroundHandler.MSG_LOAD_ENTRIES);
@@ -408,13 +436,22 @@
                 mApplications.remove(idx);
                 if (!info.enabled) {
                     mHaveDisabledApps = false;
-                    for (int i=0; i<mApplications.size(); i++) {
-                        if (!mApplications.get(i).enabled) {
+                    for (ApplicationInfo otherInfo : mApplications) {
+                        if (!otherInfo.enabled) {
                             mHaveDisabledApps = true;
                             break;
                         }
                     }
                 }
+                if (AppUtils.isInstant(info)) {
+                    mHaveInstantApps = false;
+                    for (ApplicationInfo otherInfo : mApplications) {
+                        if (AppUtils.isInstant(otherInfo)) {
+                            mHaveInstantApps = true;
+                            break;
+                        }
+                    }
+                }
                 if (!mMainHandler.hasMessages(MainHandler.MSG_PACKAGE_LIST_CHANGED)) {
                     mMainHandler.sendEmptyMessage(MainHandler.MSG_PACKAGE_LIST_CHANGED);
                 }
@@ -937,10 +974,24 @@
                                         mMainHandler.sendMessage(m);
                                     }
                                     entry.sizeLoadStart = now;
+                                    mCurComputingSizeUuid = entry.info.volumeUuid;
                                     mCurComputingSizePkg = entry.info.packageName;
                                     mCurComputingSizeUserId = UserHandle.getUserId(entry.info.uid);
-                                    mPm.getPackageSizeInfoAsUser(mCurComputingSizePkg,
-                                            mCurComputingSizeUserId, mStatsObserver);
+
+                                    mBackgroundHandler.post(() -> {
+                                        final StorageStats stats = mStats.queryStatsForPackage(
+                                                mCurComputingSizeUuid, mCurComputingSizePkg,
+                                                UserHandle.of(mCurComputingSizeUserId));
+                                        final PackageStats legacyStats = new PackageStats(
+                                                mCurComputingSizePkg, mCurComputingSizeUserId);
+                                        legacyStats.codeSize = stats.getCodeBytes();
+                                        legacyStats.dataSize = stats.getDataBytes();
+                                        legacyStats.cacheSize = stats.getCacheBytes();
+                                        try {
+                                            mStatsObserver.onGetStatsCompleted(legacyStats, true);
+                                        } catch (RemoteException ignored) {
+                                        }
+                                    });
                                 }
                                 if (DEBUG_LOCKING) Log.v(TAG, "MSG_LOAD_SIZES releasing: now computing");
                                 return;
@@ -1290,6 +1341,7 @@
     public static final AppFilter FILTER_PERSONAL = new AppFilter() {
         private int mCurrentUser;
 
+        @Override
         public void init() {
             mCurrentUser = ActivityManager.getCurrentUser();
         }
@@ -1301,8 +1353,9 @@
     };
 
     public static final AppFilter FILTER_WITHOUT_DISABLED_UNTIL_USED = new AppFilter() {
+        @Override
         public void init() {
-            // do nothings
+            // do nothing
         }
 
         @Override
@@ -1315,6 +1368,7 @@
     public static final AppFilter FILTER_WORK = new AppFilter() {
         private int mCurrentUser;
 
+        @Override
         public void init() {
             mCurrentUser = ActivityManager.getCurrentUser();
         }
@@ -1329,6 +1383,7 @@
      * Displays a combined list with "downloaded" and "visible in launcher" apps only.
      */
     public static final AppFilter FILTER_DOWNLOADED_AND_LAUNCHER = new AppFilter() {
+        @Override
         public void init() {
         }
 
@@ -1348,6 +1403,7 @@
     };
 
     public static final AppFilter FILTER_THIRD_PARTY = new AppFilter() {
+        @Override
         public void init() {
         }
 
@@ -1363,26 +1419,40 @@
     };
 
     public static final AppFilter FILTER_DISABLED = new AppFilter() {
+        @Override
         public void init() {
         }
 
         @Override
         public boolean filterApp(AppEntry entry) {
-            return !entry.info.enabled;
+            return !entry.info.enabled && !AppUtils.isInstant(entry.info);
+        }
+    };
+
+    public static final AppFilter FILTER_INSTANT = new AppFilter() {
+        @Override
+        public void init() {
+        }
+
+        @Override
+        public boolean filterApp(AppEntry entry) {
+            return AppUtils.isInstant(entry.info);
         }
     };
 
     public static final AppFilter FILTER_ALL_ENABLED = new AppFilter() {
+        @Override
         public void init() {
         }
 
         @Override
         public boolean filterApp(AppEntry entry) {
-            return entry.info.enabled;
+            return entry.info.enabled && !AppUtils.isInstant(entry.info);
         }
     };
 
     public static final AppFilter FILTER_EVERYTHING = new AppFilter() {
+        @Override
         public void init() {
         }
 
@@ -1393,6 +1463,7 @@
     };
 
     public static final AppFilter FILTER_WITH_DOMAIN_URLS = new AppFilter() {
+        @Override
         public void init() {
         }
 
@@ -1405,6 +1476,7 @@
     public static final AppFilter FILTER_NOT_HIDE = new AppFilter() {
         private String[] mHidePackageNames;
 
+        @Override
         public void init(Context context) {
             mHidePackageNames = context.getResources()
                 .getStringArray(R.array.config_hideWhenDisabled_packageNames);
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/InterestingConfigChanges.java b/packages/SettingsLib/src/com/android/settingslib/applications/InterestingConfigChanges.java
index d4623d6..82da9a3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/InterestingConfigChanges.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/InterestingConfigChanges.java
@@ -31,7 +31,8 @@
 
     public InterestingConfigChanges(int extraFlags) {
         mFlags = extraFlags | ActivityInfo.CONFIG_LOCALE
-                | ActivityInfo.CONFIG_UI_MODE | ActivityInfo.CONFIG_SCREEN_LAYOUT;
+                | ActivityInfo.CONFIG_UI_MODE | ActivityInfo.CONFIG_SCREEN_LAYOUT
+                | ActivityInfo.CONFIG_ASSETS_PATHS;
     }
 
     public boolean applyNewConfig(Resources res) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/PermissionsSummaryHelper.java b/packages/SettingsLib/src/com/android/settingslib/applications/PermissionsSummaryHelper.java
new file mode 100644
index 0000000..ec8e956
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/PermissionsSummaryHelper.java
@@ -0,0 +1,80 @@
+/*
+ * 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.settingslib.applications;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.content.pm.permission.RuntimePermissionPresentationInfo;
+import android.content.pm.permission.RuntimePermissionPresenter;
+
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class PermissionsSummaryHelper  {
+
+    public static void getPermissionSummary(Context context, String pkg,
+            final PermissionsResultCallback callback) {
+        final RuntimePermissionPresenter presenter =
+                RuntimePermissionPresenter.getInstance(context);
+        presenter.getAppPermissions(pkg, new RuntimePermissionPresenter.OnResultCallback() {
+            @Override
+            public void onGetAppPermissions(
+                    @NonNull List<RuntimePermissionPresentationInfo> permissions) {
+                final int permissionCount = permissions.size();
+
+                int grantedStandardCount = 0;
+                int grantedAdditionalCount = 0;
+                int requestedCount = 0;
+                List<CharSequence> grantedStandardLabels = new ArrayList<>();
+
+                for (int i = 0; i < permissionCount; i++) {
+                    RuntimePermissionPresentationInfo permission = permissions.get(i);
+                    requestedCount++;
+                    if (permission.isGranted()) {
+                        if (permission.isStandard()) {
+                            grantedStandardLabels.add(permission.getLabel());
+                            grantedStandardCount++;
+                        } else {
+                            grantedAdditionalCount++;
+                        }
+                    }
+                }
+
+                Collator collator = Collator.getInstance();
+                collator.setStrength(Collator.PRIMARY);
+                Collections.sort(grantedStandardLabels, collator);
+
+                callback.onPermissionSummaryResult(grantedStandardCount, requestedCount,
+                        grantedAdditionalCount, grantedStandardLabels);
+            }
+        }, null);
+    }
+
+    public static abstract class PermissionsResultCallback {
+        public void onAppWithPermissionsCountsResult(int standardGrantedPermissionAppCount,
+                int standardUsedPermissionAppCount) {
+            /* do nothing - stub */
+        }
+
+        public void onPermissionSummaryResult(int standardGrantedPermissionCount,
+                int requestedPermissionCount, int additionalGrantedPermissionCount,
+                List<CharSequence> grantedGroupLabels) {
+            /* do nothing - stub */
+        }
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java b/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java
index acb0650..2183573 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java
@@ -20,6 +20,7 @@
 import android.app.usage.StorageStatsManager;
 import android.content.Context;
 import android.os.UserHandle;
+import android.support.annotation.VisibleForTesting;
 
 /**
  * StorageStatsSource wraps the StorageStatsManager for testability purposes.
@@ -40,6 +41,12 @@
         return new StorageStatsSource.AppStorageStatsImpl(mStorageStatsManager.queryStatsForUid(volumeUuid, uid));
     }
 
+    public StorageStatsSource.AppStorageStats getStatsForPackage(
+            String volumeUuid, String packageName, UserHandle user) {
+        return new StorageStatsSource.AppStorageStatsImpl(
+                mStorageStatsManager.queryStatsForPackage(volumeUuid, packageName, user));
+    }
+
     /**
      * Static class that provides methods for querying the amount of external storage available as
      * well as breaking it up into several media types.
@@ -50,11 +57,10 @@
         public long videoBytes;
         public long imageBytes;
 
-        /**
-         * Convenience method for testing.
-         */
-        public ExternalStorageStats(long totalBytes, long audioBytes, long videoBytes,
-                long imageBytes) {
+        /** Convenience method for testing. */
+        @VisibleForTesting
+        public ExternalStorageStats(
+                long totalBytes, long audioBytes, long videoBytes, long imageBytes) {
             this.totalBytes = totalBytes;
             this.audioBytes = audioBytes;
             this.videoBytes = videoBytes;
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/instantapps/InstantAppDataProvider.java b/packages/SettingsLib/src/com/android/settingslib/applications/instantapps/InstantAppDataProvider.java
new file mode 100644
index 0000000..8b15715
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/instantapps/InstantAppDataProvider.java
@@ -0,0 +1,28 @@
+/*
+ * 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.settingslib.applications.instantapps;
+
+import android.content.pm.ApplicationInfo;
+
+/**
+ * This helps deal with the fact that robolectric does not yet have an implementation of the
+ * isInstantApp method of ApplicationInfo, so we get a method not found exception when running tests
+ * if we try to call it directly.
+ */
+public interface InstantAppDataProvider {
+    public boolean isInstantApp(ApplicationInfo info);
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
index e520319..953dda2 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
@@ -16,22 +16,14 @@
 
 package com.android.settingslib.deviceinfo;
 
-import android.app.ActivityManager;
-import android.content.ComponentName;
+import android.app.usage.ExternalStorageStats;
+import android.app.usage.StorageStats;
+import android.app.usage.StorageStatsManager;
 import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageStatsObserver;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageStats;
 import android.content.pm.UserInfo;
+import android.os.AsyncTask;
 import android.os.Environment;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.storage.StorageVolume;
@@ -40,93 +32,54 @@
 import android.util.SparseArray;
 import android.util.SparseLongArray;
 
-import com.android.internal.app.IMediaContainerService;
-import com.android.internal.util.ArrayUtils;
-import com.google.android.collect.Sets;
-
-import java.io.File;
 import java.lang.ref.WeakReference;
-import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
-import java.util.Objects;
-import java.util.Set;
 
 /**
  * Utility for measuring the disk usage of internal storage or a physical
- * {@link StorageVolume}. Connects with a remote {@link IMediaContainerService}
- * and delivers results to {@link MeasurementReceiver}.
+ * {@link StorageVolume}.
  */
 public class StorageMeasurement {
     private static final String TAG = "StorageMeasurement";
 
-    private static final boolean LOCAL_LOGV = false;
-    static final boolean LOGV = LOCAL_LOGV && Log.isLoggable(TAG, Log.VERBOSE);
-
-    private static final String DEFAULT_CONTAINER_PACKAGE = "com.android.defcontainer";
-
-    public static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
-            DEFAULT_CONTAINER_PACKAGE, "com.android.defcontainer.DefaultContainerService");
-
-    /** Media types to measure on external storage. */
-    private static final Set<String> sMeasureMediaTypes = Sets.newHashSet(
-            Environment.DIRECTORY_DCIM, Environment.DIRECTORY_MOVIES,
-            Environment.DIRECTORY_PICTURES, Environment.DIRECTORY_MUSIC,
-            Environment.DIRECTORY_ALARMS, Environment.DIRECTORY_NOTIFICATIONS,
-            Environment.DIRECTORY_RINGTONES, Environment.DIRECTORY_PODCASTS,
-            Environment.DIRECTORY_DOWNLOADS, Environment.DIRECTORY_ANDROID);
-
     public static class MeasurementDetails {
+        /** Size of storage device. */
         public long totalSize;
+        /** Size of available space. */
         public long availSize;
+        /** Size of all cached data. */
+        public long cacheSize;
 
         /**
-         * Total apps disk usage per profiles of the current user.
+         * Total disk space used by everything.
          * <p>
-         * When measuring internal storage, this value includes the code size of
-         * all apps (regardless of install status for the given profile), and
-         * internal disk used by the profile's apps. When the device
-         * emulates external storage, this value also includes emulated storage
-         * used by the profile's apps.
-         * <p>
-         * When measuring a physical {@link StorageVolume}, this value includes
-         * usage by all apps on that volume and only for the primary profile.
+         * Key is {@link UserHandle}.
+         */
+        public SparseLongArray usersSize = new SparseLongArray();
+
+        /**
+         * Total disk space used by apps.
          * <p>
          * Key is {@link UserHandle}.
          */
         public SparseLongArray appsSize = new SparseLongArray();
 
         /**
-         * Total cache disk usage by apps (over all users and profiles).
-         */
-        public long cacheSize;
-
-        /**
-         * Total media disk usage, categorized by types such as
-         * {@link Environment#DIRECTORY_MUSIC} for every user profile of the current user.
+         * Total disk space used by media on shared storage.
          * <p>
-         * When measuring internal storage, this reflects media on emulated
-         * storage for the respective profile.
-         * <p>
-         * When measuring a physical {@link StorageVolume}, this reflects media
-         * on that volume.
-         * <p>
-         * Key of the {@link SparseArray} is {@link UserHandle}.
+         * First key is {@link UserHandle}. Second key is media type, such as
+         * {@link Environment#DIRECTORY_PICTURES}.
          */
         public SparseArray<HashMap<String, Long>> mediaSize = new SparseArray<>();
 
         /**
-         * Misc external disk usage for the current user's profiles, unaccounted in
-         * {@link #mediaSize}. Key is {@link UserHandle}.
+         * Total disk space used by non-media on shared storage.
+         * <p>
+         * Key is {@link UserHandle}.
          */
         public SparseLongArray miscSize = new SparseLongArray();
 
-        /**
-         * Total disk usage for users, which is only meaningful for emulated
-         * internal storage. Key is {@link UserHandle}.
-         */
-        public SparseLongArray usersSize = new SparseLongArray();
-
         @Override
         public String toString() {
             return "MeasurementDetails: [totalSize: " + totalSize + " availSize: " + availSize
@@ -142,25 +95,19 @@
     private WeakReference<MeasurementReceiver> mReceiver;
 
     private final Context mContext;
+    private final UserManager mUser;
+    private final StorageStatsManager mStats;
 
     private final VolumeInfo mVolume;
     private final VolumeInfo mSharedVolume;
 
-    private final MainHandler mMainHandler;
-    private final MeasurementHandler mMeasurementHandler;
-
     public StorageMeasurement(Context context, VolumeInfo volume, VolumeInfo sharedVolume) {
         mContext = context.getApplicationContext();
+        mUser = mContext.getSystemService(UserManager.class);
+        mStats = mContext.getSystemService(StorageStatsManager.class);
 
         mVolume = volume;
         mSharedVolume = sharedVolume;
-
-        // Start the thread that will measure the disk usage.
-        final HandlerThread handlerThread = new HandlerThread("MemoryMeasurement");
-        handlerThread.start();
-
-        mMainHandler = new MainHandler();
-        mMeasurementHandler = new MeasurementHandler(handlerThread.getLooper());
     }
 
     public void setReceiver(MeasurementReceiver receiver) {
@@ -170,315 +117,94 @@
     }
 
     public void forceMeasure() {
-        invalidate();
         measure();
     }
 
     public void measure() {
-        if (!mMeasurementHandler.hasMessages(MeasurementHandler.MSG_MEASURE)) {
-            mMeasurementHandler.sendEmptyMessage(MeasurementHandler.MSG_MEASURE);
-        }
+        new MeasureTask().execute();
     }
 
     public void onDestroy() {
         mReceiver = null;
-        mMeasurementHandler.removeMessages(MeasurementHandler.MSG_MEASURE);
-        mMeasurementHandler.sendEmptyMessage(MeasurementHandler.MSG_DISCONNECT);
     }
 
-    private void invalidate() {
-        mMeasurementHandler.sendEmptyMessage(MeasurementHandler.MSG_INVALIDATE);
-    }
-
-    private static class StatsObserver extends IPackageStatsObserver.Stub {
-        private final boolean mIsPrivate;
-        private final MeasurementDetails mDetails;
-        private final int mCurrentUser;
-        private final Message mFinished;
-
-        private int mRemaining;
-
-        public StatsObserver(boolean isPrivate, MeasurementDetails details, int currentUser,
-                List<UserInfo> profiles, Message finished, int remaining) {
-            mIsPrivate = isPrivate;
-            mDetails = details;
-            mCurrentUser = currentUser;
-            if (isPrivate) {
-                // Add the profile ids as keys to detail's app sizes.
-                for (UserInfo userInfo : profiles) {
-                    mDetails.appsSize.put(userInfo.id, 0);
-                }
-            }
-            mFinished = finished;
-            mRemaining = remaining;
+    private class MeasureTask extends AsyncTask<Void, Void, MeasurementDetails> {
+        @Override
+        protected MeasurementDetails doInBackground(Void... params) {
+            return measureExactStorage();
         }
 
         @Override
-        public void onGetStatsCompleted(PackageStats stats, boolean succeeded) {
-            synchronized (mDetails) {
-                if (succeeded) {
-                    addStatsLocked(stats);
-                }
-                if (--mRemaining == 0) {
-                    mFinished.sendToTarget();
-                }
-            }
-        }
-
-        private void addStatsLocked(PackageStats stats) {
-            if (mIsPrivate) {
-                long codeSize = stats.codeSize;
-                long dataSize = stats.dataSize;
-                long cacheSize = stats.cacheSize;
-                if (Environment.isExternalStorageEmulated()) {
-                    // Include emulated storage when measuring internal. OBB is
-                    // shared on emulated storage, so treat as code.
-                    codeSize += stats.externalCodeSize + stats.externalObbSize;
-                    dataSize += stats.externalDataSize + stats.externalMediaSize;
-                    cacheSize += stats.externalCacheSize;
-                }
-
-                // Count code and data for current user's profiles (keys prepared in constructor)
-                addValueIfKeyExists(mDetails.appsSize, stats.userHandle, codeSize + dataSize);
-
-                // User summary only includes data (code is only counted once
-                // for the current user)
-                addValue(mDetails.usersSize, stats.userHandle, dataSize);
-
-                // Include cache for all users
-                mDetails.cacheSize += cacheSize;
-
-            } else {
-                // Physical storage; only count external sizes
-                addValue(mDetails.appsSize, mCurrentUser,
-                        stats.externalCodeSize + stats.externalDataSize
-                        + stats.externalMediaSize + stats.externalObbSize);
-                mDetails.cacheSize += stats.externalCacheSize;
-            }
-        }
-    }
-
-    private class MainHandler extends Handler {
-        @Override
-        public void handleMessage(Message msg) {
-            final MeasurementDetails details = (MeasurementDetails) msg.obj;
+        protected void onPostExecute(MeasurementDetails result) {
             final MeasurementReceiver receiver = (mReceiver != null) ? mReceiver.get() : null;
             if (receiver != null) {
-                receiver.onDetailsChanged(details);
+                receiver.onDetailsChanged(result);
             }
         }
     }
 
-    private class MeasurementHandler extends Handler {
-        public static final int MSG_MEASURE = 1;
-        public static final int MSG_CONNECTED = 2;
-        public static final int MSG_DISCONNECT = 3;
-        public static final int MSG_COMPLETED = 4;
-        public static final int MSG_INVALIDATE = 5;
+    private MeasurementDetails measureExactStorage() {
+        final List<UserInfo> users = mUser.getUsers();
 
-        private Object mLock = new Object();
-
-        private IMediaContainerService mDefaultContainer;
-
-        private volatile boolean mBound = false;
-
-        private MeasurementDetails mCached;
-
-        private final ServiceConnection mDefContainerConn = new ServiceConnection() {
-            @Override
-            public void onServiceConnected(ComponentName name, IBinder service) {
-                final IMediaContainerService imcs = IMediaContainerService.Stub.asInterface(
-                        service);
-                mDefaultContainer = imcs;
-                mBound = true;
-                sendMessage(obtainMessage(MSG_CONNECTED, imcs));
-            }
-
-            @Override
-            public void onServiceDisconnected(ComponentName name) {
-                mBound = false;
-                removeMessages(MSG_CONNECTED);
-            }
-        };
-
-        public MeasurementHandler(Looper looper) {
-            super(looper);
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_MEASURE: {
-                    if (mCached != null) {
-                        mMainHandler.obtainMessage(0, mCached).sendToTarget();
-                        break;
-                    }
-
-                    synchronized (mLock) {
-                        if (mBound) {
-                            removeMessages(MSG_DISCONNECT);
-                            sendMessage(obtainMessage(MSG_CONNECTED, mDefaultContainer));
-                        } else {
-                            Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
-                            mContext.bindServiceAsUser(service, mDefContainerConn,
-                                    Context.BIND_AUTO_CREATE, UserHandle.SYSTEM);
-                        }
-                    }
-                    break;
-                }
-                case MSG_CONNECTED: {
-                    final IMediaContainerService imcs = (IMediaContainerService) msg.obj;
-                    measureExactStorage(imcs);
-                    break;
-                }
-                case MSG_DISCONNECT: {
-                    synchronized (mLock) {
-                        if (mBound) {
-                            mBound = false;
-                            mContext.unbindService(mDefContainerConn);
-                        }
-                    }
-                    break;
-                }
-                case MSG_COMPLETED: {
-                    mCached = (MeasurementDetails) msg.obj;
-                    mMainHandler.obtainMessage(0, mCached).sendToTarget();
-                    break;
-                }
-                case MSG_INVALIDATE: {
-                    mCached = null;
-                    break;
-                }
-            }
-        }
-    }
-
-    private void measureExactStorage(IMediaContainerService imcs) {
-        final UserManager userManager = mContext.getSystemService(UserManager.class);
-        final PackageManager packageManager = mContext.getPackageManager();
-
-        final List<UserInfo> users = userManager.getUsers();
-        final List<UserInfo> currentProfiles = userManager.getEnabledProfiles(
-                ActivityManager.getCurrentUser());
+        final long start = SystemClock.elapsedRealtime();
 
         final MeasurementDetails details = new MeasurementDetails();
-        final Message finished = mMeasurementHandler.obtainMessage(MeasurementHandler.MSG_COMPLETED,
-                details);
+        if (mVolume == null) return details;
 
-        if (mVolume == null || !mVolume.isMountedReadable()) {
-            finished.sendToTarget();
-            return;
-        }
+        details.totalSize = mStats.getTotalBytes(mVolume.fsUuid);
+        details.availSize = mStats.getFreeBytes(mVolume.fsUuid);
+
+        final long finishTotal = SystemClock.elapsedRealtime();
+        Log.d(TAG, "Measured total storage in " + (finishTotal - start) + "ms");
 
         if (mSharedVolume != null && mSharedVolume.isMountedReadable()) {
-            for (UserInfo currentUserInfo : currentProfiles) {
-                final int userId = currentUserInfo.id;
-                final File basePath = mSharedVolume.getPathForUser(userId);
-                HashMap<String, Long> mediaMap = new HashMap<>(sMeasureMediaTypes.size());
-                details.mediaSize.put(userId, mediaMap);
-
-                // Measure media types for emulated storage, or for primary physical
-                // external volume
-                for (String type : sMeasureMediaTypes) {
-                    final File path = new File(basePath, type);
-                    final long size = getDirectorySize(imcs, path);
-                    mediaMap.put(type, size);
-                }
-
-                // Measure misc files not counted under media
-                addValue(details.miscSize, userId, measureMisc(imcs, basePath));
-            }
-
-            if (mSharedVolume.getType() == VolumeInfo.TYPE_EMULATED) {
-                // Measure total emulated storage of all users; internal apps data
-                // will be spliced in later
-                for (UserInfo user : users) {
-                    final File userPath = mSharedVolume.getPathForUser(user.id);
-                    final long size = getDirectorySize(imcs, userPath);
-                    addValue(details.usersSize, user.id, size);
-                }
-            }
-        }
-
-        final File file = mVolume.getPath();
-        if (file != null) {
-            details.totalSize = file.getTotalSpace();
-            details.availSize = file.getFreeSpace();
-        }
-
-        // Measure all apps hosted on this volume for all users
-        if (mVolume.getType() == VolumeInfo.TYPE_PRIVATE) {
-            final List<ApplicationInfo> apps = packageManager.getInstalledApplications(
-                    PackageManager.MATCH_ANY_USER
-                    | PackageManager.MATCH_DISABLED_COMPONENTS);
-
-            final List<ApplicationInfo> volumeApps = new ArrayList<>();
-            for (ApplicationInfo app : apps) {
-                if (Objects.equals(app.volumeUuid, mVolume.getFsUuid())) {
-                    volumeApps.add(app);
-                }
-            }
-
-            final int count = users.size() * volumeApps.size();
-            if (count == 0) {
-                finished.sendToTarget();
-                return;
-            }
-
-            final StatsObserver observer = new StatsObserver(true, details,
-                    ActivityManager.getCurrentUser(), currentProfiles, finished, count);
             for (UserInfo user : users) {
-                for (ApplicationInfo app : volumeApps) {
-                    packageManager.getPackageSizeInfoAsUser(app.packageName, user.id, observer);
+                final HashMap<String, Long> mediaMap = new HashMap<>();
+                details.mediaSize.put(user.id, mediaMap);
+
+                final ExternalStorageStats stats = mStats
+                        .queryExternalStatsForUser(mSharedVolume.fsUuid, UserHandle.of(user.id));
+
+                addValue(details.usersSize, user.id, stats.getTotalBytes());
+
+                // Track detailed data types
+                mediaMap.put(Environment.DIRECTORY_MUSIC, stats.getAudioBytes());
+                mediaMap.put(Environment.DIRECTORY_MOVIES, stats.getVideoBytes());
+                mediaMap.put(Environment.DIRECTORY_PICTURES, stats.getImageBytes());
+
+                final long miscBytes = stats.getTotalBytes() - stats.getAudioBytes()
+                        - stats.getVideoBytes() - stats.getImageBytes();
+                addValue(details.miscSize, user.id, miscBytes);
+            }
+        }
+
+        final long finishShared = SystemClock.elapsedRealtime();
+        Log.d(TAG, "Measured shared storage in " + (finishShared - finishTotal) + "ms");
+
+        if ((mVolume.getType() == VolumeInfo.TYPE_PRIVATE) && mVolume.isMountedReadable()) {
+            for (UserInfo user : users) {
+                final StorageStats stats = mStats.queryStatsForUser(mVolume.fsUuid,
+                        UserHandle.of(user.id));
+
+                // Only count code once against current user
+                if (user.id == UserHandle.myUserId()) {
+                    addValue(details.usersSize, user.id, stats.getCodeBytes());
                 }
-            }
 
-        } else {
-            finished.sendToTarget();
-            return;
-        }
-    }
+                addValue(details.usersSize, user.id, stats.getDataBytes());
+                addValue(details.appsSize, user.id, stats.getCodeBytes() + stats.getDataBytes());
 
-    private static long getDirectorySize(IMediaContainerService imcs, File path) {
-        try {
-            final long size = imcs.calculateDirectorySize(path.toString());
-            if (LOGV) Log.v(TAG, "getDirectorySize(" + path + ") returned " + size);
-            return size;
-        } catch (Exception e) {
-            Log.w(TAG, "Could not read memory from default container service for " + path, e);
-            return 0;
-        }
-    }
-
-    private long measureMisc(IMediaContainerService imcs, File dir) {
-        final File[] files = dir.listFiles();
-        if (ArrayUtils.isEmpty(files)) return 0;
-
-        // Get sizes of all top level nodes except the ones already computed
-        long miscSize = 0;
-        for (File file : files) {
-            final String name = file.getName();
-            if (sMeasureMediaTypes.contains(name)) {
-                continue;
-            }
-
-            if (file.isFile()) {
-                miscSize += file.length();
-            } else if (file.isDirectory()) {
-                miscSize += getDirectorySize(imcs, file);
+                details.cacheSize += stats.getCacheBytes();
             }
         }
-        return miscSize;
+
+        final long finishPrivate = SystemClock.elapsedRealtime();
+        Log.d(TAG, "Measured private storage in " + (finishPrivate - finishShared) + "ms");
+
+        return details;
     }
 
     private static void addValue(SparseLongArray array, int key, long value) {
         array.put(key, array.get(key) + value);
     }
-
-    private static void addValueIfKeyExists(SparseLongArray array, int key, long value) {
-        final int index = array.indexOfKey(key);
-        if (index >= 0) {
-            array.put(key, array.valueAt(index) + value);
-        }
-    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
index 9ad0b3e..457ce76 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -18,7 +18,6 @@
 import android.annotation.LayoutRes;
 import android.annotation.Nullable;
 import android.app.Activity;
-import android.content.ActivityNotFoundException;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -29,20 +28,15 @@
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.provider.Settings;
-import android.support.v4.widget.DrawerLayout;
 import android.util.ArraySet;
 import android.util.Log;
 import android.util.Pair;
-import android.view.Gravity;
 import android.view.LayoutInflater;
-import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.Window;
 import android.view.WindowManager.LayoutParams;
-import android.widget.AdapterView;
 import android.widget.FrameLayout;
-import android.widget.ListView;
 import android.widget.Toolbar;
 
 import com.android.settingslib.R;
@@ -67,10 +61,7 @@
     private final PackageReceiver mPackageReceiver = new PackageReceiver();
     private final List<CategoryListener> mCategoryListeners = new ArrayList<>();
 
-    private SettingsDrawerAdapter mDrawerAdapter;
     private FrameLayout mContentHeaderContainer;
-    private DrawerLayout mDrawerLayout;
-    private boolean mShowingMenu;
 
     // Remove below after new IA
     @Deprecated
@@ -94,122 +85,50 @@
         }
         super.setContentView(R.layout.settings_with_drawer);
         mContentHeaderContainer = (FrameLayout) findViewById(R.id.content_header_container);
-        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
-        if (mDrawerLayout == null) {
-            return;
-        }
+
         Toolbar toolbar = (Toolbar) findViewById(R.id.action_bar);
         if (theme.getBoolean(android.R.styleable.Theme_windowNoTitle, false)) {
             toolbar.setVisibility(View.GONE);
-            mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
-            mDrawerLayout = null;
             return;
         }
-        if (!isNavDrawerEnabled()) {
-            setIsDrawerPresent(false);
-        }
-        if (!isDashboardFeatureEnabled()) {
-            getDashboardCategories();
-        }
         setActionBar(toolbar);
-        mDrawerAdapter = new SettingsDrawerAdapter(this);
-        ListView listView = (ListView) findViewById(R.id.left_drawer);
-        listView.setAdapter(mDrawerAdapter);
-        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
-            public void onItemClick(android.widget.AdapterView<?> parent, View view, int position,
-                    long id) {
-                onTileClicked(mDrawerAdapter.getTile(position));
-            }
-        });
 
-        if (DEBUG_TIMING) Log.d(TAG, "onCreate took " + (System.currentTimeMillis() - startTime)
-                + " ms");
-    }
-
-    @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-        if (mShowingMenu && mDrawerLayout != null && item.getItemId() == android.R.id.home
-                && mDrawerAdapter.getCount() != 0) {
-            openDrawer();
-            return true;
+        if (DEBUG_TIMING) {
+            Log.d(TAG, "onCreate took " + (System.currentTimeMillis() - startTime)
+                    + " ms");
         }
-        return super.onOptionsItemSelected(item);
     }
 
     @Override
     public boolean onNavigateUp() {
-        if (!isNavDrawerEnabled()) {
-            finish();
-            return true;
-        }
-        return super.onNavigateUp();
+        finish();
+        return true;
     }
 
     @Override
     protected void onResume() {
         super.onResume();
+        final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
+        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+        filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
+        filter.addDataScheme("package");
+        registerReceiver(mPackageReceiver, filter);
 
-        if (mDrawerLayout != null) {
-            final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
-            filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
-            filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
-            filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
-            filter.addDataScheme("package");
-            registerReceiver(mPackageReceiver, filter);
-
-            if (isDashboardFeatureEnabled()) {
-                new CategoriesUpdateTask().execute();
-            } else {
-                new CategoriesUpdater().execute();
-            }
-        }
+        new CategoriesUpdateTask().execute();
         final Intent intent = getIntent();
-        if (intent != null) {
-            if (intent.hasExtra(EXTRA_SHOW_MENU)) {
-                if (intent.getBooleanExtra(EXTRA_SHOW_MENU, false)) {
-                    // Intent explicitly set to show menu.
-                    showMenuIcon();
-                }
-            } else if (isNavDrawerEnabled() && isTopLevelTile(intent)) {
-                showMenuIcon();
-            }
+        if (intent != null && intent.getBooleanExtra(EXTRA_SHOW_MENU, false)) {
+            // Intent explicitly set to show menu.
+            showMenuIcon();
         }
     }
 
     @Override
     protected void onPause() {
-        if (mDrawerLayout != null) {
-            unregisterReceiver(mPackageReceiver);
-        }
-
+        unregisterReceiver(mPackageReceiver);
         super.onPause();
     }
 
-    private boolean isTopLevelTile(Intent intent) {
-        final ComponentName componentName = intent.getComponent();
-        if (componentName == null) {
-            return false;
-        }
-        if (isDashboardFeatureEnabled()) {
-            final DashboardCategory homepageCategories = CategoryManager.get(this)
-                    .getTilesByCategory(this, CategoryKey.CATEGORY_HOMEPAGE, getSettingPkg());
-            return homepageCategories ==
-                    null ? false : homepageCategories.containsComponent(componentName);
-        } else {
-            // Look for a tile that has the same component as incoming intent
-            final List<DashboardCategory> categories = getDashboardCategories();
-            for (DashboardCategory category : categories) {
-                if (category.containsComponent(componentName)) {
-                    return true;
-                }
-            }
-            if (DEBUG) {
-                Log.d(TAG, "Intent is not for top level settings " + intent);
-            }
-            return false;
-        }
-    }
-
     /**
      * Gets the name of the intent action of the default setting app. Used to launch setting app
      * when Settings Home is clicked.
@@ -226,30 +145,6 @@
         mCategoryListeners.remove(listener);
     }
 
-    public void setIsDrawerPresent(boolean isPresent) {
-        if (isPresent) {
-            mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
-            updateDrawer();
-        } else {
-            if (mDrawerLayout != null) {
-                mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
-                mDrawerLayout = null;
-            }
-        }
-    }
-
-    public void openDrawer() {
-        if (mDrawerLayout != null) {
-            mDrawerLayout.openDrawer(Gravity.START);
-        }
-    }
-
-    public void closeDrawer() {
-        if (mDrawerLayout != null) {
-            mDrawerLayout.closeDrawers();
-        }
-    }
-
     public void setContentHeaderView(View headerView) {
         mContentHeaderContainer.removeAllViews();
         if (headerView != null) {
@@ -276,31 +171,8 @@
         ((ViewGroup) findViewById(R.id.content_frame)).addView(view, params);
     }
 
-    public void updateDrawer() {
-        if (mDrawerLayout == null) {
-            return;
-        }
-        // TODO: Do this in the background with some loading.
-        if (isDashboardFeatureEnabled()) {
-            mDrawerAdapter.updateHomepageCategories(getSettingPkg());
-        } else {
-            mDrawerAdapter.updateCategories();
-        }
-        if (mDrawerAdapter.getCount() != 0) {
-            mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
-        } else {
-            mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
-        }
-    }
-
     public void showMenuIcon() {
         getActionBar().setDisplayHomeAsUpEnabled(true);
-        if (isNavDrawerEnabled()) {
-            mShowingMenu = true;
-            getActionBar().setHomeAsUpIndicator(R.drawable.ic_menu);
-            getActionBar().setHomeActionContentDescription(
-                    R.string.content_description_menu_button);
-        }
     }
 
     public List<DashboardCategory> getDashboardCategories() {
@@ -315,51 +187,12 @@
     }
 
     protected void onCategoriesChanged() {
-        updateDrawer();
         final int N = mCategoryListeners.size();
         for (int i = 0; i < N; i++) {
             mCategoryListeners.get(i).onCategoriesChanged();
         }
     }
 
-    @Deprecated
-    public boolean openTile(Tile tile) {
-        closeDrawer();
-        if (tile == null) {
-            Intent intent = new Intent(getSettingAction()).addFlags(
-                        Intent.FLAG_ACTIVITY_CLEAR_TASK);
-            startActivity(intent);
-            return true;
-        }
-        try {
-            ProfileSelectDialog.updateUserHandlesIfNeeded(this /* context */, tile);
-            int numUserHandles = tile.userHandle.size();
-            if (numUserHandles > 1) {
-                ProfileSelectDialog.show(getFragmentManager(), tile);
-                return false;
-            } else if (numUserHandles == 1) {
-                // Show menu on top level items.
-                tile.intent.putExtra(EXTRA_SHOW_MENU, true);
-                tile.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
-                startActivityAsUser(tile.intent, tile.userHandle.get(0));
-            } else {
-                // Show menu on top level items.
-                tile.intent.putExtra(EXTRA_SHOW_MENU, true);
-                tile.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
-                startActivity(tile.intent);
-            }
-        } catch (ActivityNotFoundException e) {
-            Log.w(TAG, "Couldn't find tile " + tile.intent, e);
-        }
-        return true;
-    }
-
-    protected void onTileClicked(Tile tile) {
-        if (openTile(tile)) {
-            finish();
-        }
-    }
-
     public void onProfileTileOpen() {
         finish();
     }
@@ -375,8 +208,8 @@
                 sTileBlacklist.add(component);
             }
             pm.setComponentEnabledSetting(component, enabled
-                    ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
-                    : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+                            ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
+                            : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                     PackageManager.DONT_KILL_APP);
         }
     }
@@ -385,11 +218,7 @@
      * Updates dashboard categories. Only necessary to call this after setTileEnabled
      */
     public void updateCategories() {
-        if (isDashboardFeatureEnabled()) {
-            new CategoriesUpdateTask().execute();
-        } else {
-            new CategoriesUpdater().execute();
-        }
+        new CategoriesUpdateTask().execute();
     }
 
     public String getSettingPkg() {
@@ -400,42 +229,6 @@
         void onCategoriesChanged();
     }
 
-    /**
-     * @deprecated remove after new IA
-     */
-    @Deprecated
-    private class CategoriesUpdater extends AsyncTask<Void, Void, List<DashboardCategory>> {
-        @Override
-        protected List<DashboardCategory> doInBackground(Void... params) {
-            if (sConfigTracker.applyNewConfig(getResources())) {
-                sTileCache.clear();
-            }
-            return TileUtils.getCategories(SettingsDrawerActivity.this, sTileCache);
-        }
-
-        @Override
-        protected void onPreExecute() {
-            if (sConfigTracker == null || sTileCache == null) {
-                getDashboardCategories();
-            }
-        }
-
-        @Override
-        protected void onPostExecute(List<DashboardCategory> dashboardCategories) {
-            for (int i = 0; i < dashboardCategories.size(); i++) {
-                DashboardCategory category = dashboardCategories.get(i);
-                for (int j = 0; j < category.tiles.size(); j++) {
-                    Tile tile = category.tiles.get(j);
-                    if (sTileBlacklist.contains(tile.intent.getComponent())) {
-                        category.tiles.remove(j--);
-                    }
-                }
-            }
-            sDashboardCategories = dashboardCategories;
-            onCategoriesChanged();
-        }
-    }
-
     private class CategoriesUpdateTask extends AsyncTask<Void, Void, Void> {
 
         private final CategoryManager mCategoryManager;
@@ -457,26 +250,10 @@
         }
     }
 
-    /**
-     * @return {@code true} if IA (Information Architecture) is enabled.
-     */
-    protected boolean isDashboardFeatureEnabled() {
-        return false;
-    }
-
-    boolean isNavDrawerEnabled() {
-        return !isDashboardFeatureEnabled()
-                || getResources().getBoolean(R.bool.config_enable_nav_drawer);
-    }
-
     private class PackageReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
-            if (isDashboardFeatureEnabled()) {
-                new CategoriesUpdateTask().execute();
-            } else {
-                new CategoriesUpdater().execute();
-            }
+            new CategoriesUpdateTask().execute();
         }
     }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerAdapter.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerAdapter.java
deleted file mode 100644
index 75942f9..0000000
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerAdapter.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * 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.drawer;
-
-import android.graphics.drawable.Icon;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.android.settingslib.R;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class SettingsDrawerAdapter extends BaseAdapter {
-
-    private final ArrayList<Item> mItems = new ArrayList<>();
-    private final SettingsDrawerActivity mActivity;
-
-    public SettingsDrawerAdapter(SettingsDrawerActivity activity) {
-        mActivity = activity;
-    }
-
-    /**
-     * @deprecated Remove after new IA
-     */
-    @Deprecated
-    void updateCategories() {
-        List<DashboardCategory> categories = mActivity.getDashboardCategories();
-        mItems.clear();
-        // Spacer.
-        mItems.add(null);
-        Item tile = new Item();
-        tile.label = mActivity.getString(R.string.home);
-        tile.icon = Icon.createWithResource(mActivity, R.drawable.home);
-        mItems.add(tile);
-        for (int i = 0; i < categories.size(); i++) {
-            Item category = new Item();
-            category.icon = null;
-            DashboardCategory dashboardCategory = categories.get(i);
-            category.label = dashboardCategory.title;
-            mItems.add(category);
-            for (int j = 0; j < dashboardCategory.tiles.size(); j++) {
-                tile = new Item();
-                Tile dashboardTile = dashboardCategory.tiles.get(j);
-                tile.label = dashboardTile.title;
-                tile.icon = dashboardTile.icon;
-                tile.tile = dashboardTile;
-                mItems.add(tile);
-            }
-        }
-        notifyDataSetChanged();
-    }
-
-    public void updateHomepageCategories(String settingPkg) {
-        final DashboardCategory category = CategoryManager.get(mActivity)
-                        .getTilesByCategory(mActivity, CategoryKey.CATEGORY_HOMEPAGE, settingPkg);
-        mItems.clear();
-        // Spacer.
-        mItems.add(null);
-        Item tile = new Item();
-        tile.label = mActivity.getString(R.string.home);
-        tile.icon = Icon.createWithResource(mActivity, R.drawable.home);
-        mItems.add(tile);
-        for (int j = 0; j < category.tiles.size(); j++) {
-            tile = new Item();
-            Tile dashboardTile = category.tiles.get(j);
-            tile.label = dashboardTile.title;
-            tile.icon = dashboardTile.icon;
-            tile.tile = dashboardTile;
-            mItems.add(tile);
-        }
-        notifyDataSetChanged();
-    }
-
-    public Tile getTile(int position) {
-        return mItems.get(position) != null ? mItems.get(position).tile : null;
-    }
-
-    @Override
-    public int getCount() {
-        return mItems.size();
-    }
-
-    @Override
-    public Object getItem(int position) {
-        return mItems.get(position);
-    }
-
-    @Override
-    public long getItemId(int position) {
-        return position;
-    }
-
-    @Override
-    public boolean isEnabled(int position) {
-        return mItems.get(position) != null && mItems.get(position).icon != null;
-    }
-
-    @Override
-    public View getView(int position, View convertView, ViewGroup parent) {
-        Item item = mItems.get(position);
-        if (item == null) {
-            if (convertView == null || convertView.getId() != R.id.spacer) {
-                convertView = LayoutInflater.from(mActivity).inflate(R.layout.drawer_spacer,
-                        parent, false);
-            }
-            return convertView;
-        }
-        if (convertView != null && convertView.getId() == R.id.spacer) {
-            convertView = null;
-        }
-        boolean isTile = item.icon != null;
-        if (convertView == null || (isTile != (convertView.getId() == R.id.tile_item))) {
-            convertView = LayoutInflater.from(mActivity).inflate(isTile ? R.layout.drawer_item
-                            : R.layout.drawer_category,
-                    parent, false);
-        }
-        if (isTile) {
-            ((ImageView) convertView.findViewById(android.R.id.icon)).setImageIcon(item.icon);
-        }
-        ((TextView) convertView.findViewById(android.R.id.title)).setText(item.label);
-        return convertView;
-    }
-
-    private static class Item {
-        public Icon icon;
-        public CharSequence label;
-        public Tile tile;
-    }
-}
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
index 6e10aab..f31c09b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
@@ -33,7 +33,6 @@
 import android.os.UserManager;
 import android.provider.Settings.Global;
 import android.text.TextUtils;
-import android.util.ArrayMap;
 import android.util.Log;
 import android.util.Pair;
 
@@ -353,10 +352,7 @@
             CharSequence title = null;
             String summary = null;
             String keyHint = null;
-            String uriString = null;
             Uri uri = null;
-            // Several resources can be using the same provider. Only acquire a single provider.
-            Map<String, IContentProvider> providerMap = new ArrayMap<>();
 
             // Get the activity's meta-data
             try {
@@ -365,11 +361,7 @@
                 Bundle metaData = activityInfo.metaData;
 
                 if (res != null && metaData != null) {
-                    if (metaData.containsKey(META_DATA_PREFERENCE_ICON_URI)) {
-                        iconFromUri = getIconFromUri(context, activityInfo.packageName,
-                                metaData.getString(META_DATA_PREFERENCE_ICON_URI), providerMap);
-                    }
-                    if (iconFromUri == null && metaData.containsKey(META_DATA_PREFERENCE_ICON)) {
+                    if (metaData.containsKey(META_DATA_PREFERENCE_ICON)) {
                         icon = metaData.getInt(META_DATA_PREFERENCE_ICON);
                     }
                     if (metaData.containsKey(META_DATA_PREFERENCE_TITLE)) {
@@ -379,13 +371,7 @@
                             title = metaData.getString(META_DATA_PREFERENCE_TITLE);
                         }
                     }
-                    if (metaData.containsKey(META_DATA_PREFERENCE_SUMMARY_URI)) {
-                        summary = getTextFromUri(context,
-                                metaData.getString(META_DATA_PREFERENCE_SUMMARY_URI), providerMap,
-                                META_DATA_PREFERENCE_SUMMARY);
-                    }
-                    if (TextUtils.isEmpty(summary)
-                            && metaData.containsKey(META_DATA_PREFERENCE_SUMMARY)) {
+                    if (metaData.containsKey(META_DATA_PREFERENCE_SUMMARY)) {
                         if (metaData.get(META_DATA_PREFERENCE_SUMMARY) instanceof Integer) {
                             summary = res.getString(metaData.getInt(META_DATA_PREFERENCE_SUMMARY));
                         } else {
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
index fd2e7ca..6764a6b 100755
--- a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
@@ -29,7 +29,8 @@
 import android.graphics.RectF;
 import android.graphics.Typeface;
 import android.graphics.drawable.Drawable;
-import android.provider.Settings;
+import android.util.TypedValue;
+
 import com.android.settingslib.R;
 import com.android.settingslib.Utils;
 
@@ -97,9 +98,13 @@
 
         final int N = levels.length();
         mColors = new int[2 * N];
-        for (int i = 0; i < N; i++) {
+        for (int i=0; i < N; i++) {
             mColors[2 * i] = levels.getInt(i, 0);
-            mColors[2 * i + 1] = colors.getColor(i, 0);
+            if (colors.getType(i) == TypedValue.TYPE_ATTRIBUTE) {
+                mColors[2 * i + 1] = Utils.getColorAttr(context, colors.getResourceId(i, 0));
+            } else {
+                mColors[2 * i + 1] = colors.getColor(i, 0);
+            }
         }
         levels.recycle();
         colors.recycle();
diff --git a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeEnablerManager.java b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeEnablerManager.java
new file mode 100644
index 0000000..c9e3475
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeEnablerManager.java
@@ -0,0 +1,263 @@
+/*
+ * 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.settingslib.inputmethod;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
+import android.support.v14.preference.PreferenceFragment;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceCategory;
+import android.support.v7.preference.PreferenceScreen;
+import android.support.v7.preference.TwoStatePreference;
+import android.text.TextUtils;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.settingslib.R;
+
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+public class InputMethodAndSubtypeEnablerManager implements Preference.OnPreferenceChangeListener {
+
+    private final PreferenceFragment mFragment;
+
+    private boolean mHaveHardKeyboard;
+    private final HashMap<String, List<Preference>> mInputMethodAndSubtypePrefsMap =
+            new HashMap<>();
+    private final HashMap<String, TwoStatePreference> mAutoSelectionPrefsMap = new HashMap<>();
+    private InputMethodManager mImm;
+    // TODO: Change mInputMethodInfoList to Map
+    private List<InputMethodInfo> mInputMethodInfoList;
+    private final Collator mCollator = Collator.getInstance();
+
+    public InputMethodAndSubtypeEnablerManager(PreferenceFragment fragment) {
+        mFragment = fragment;
+        mImm = fragment.getContext().getSystemService(InputMethodManager.class);
+
+        mInputMethodInfoList = mImm.getInputMethodList();
+    }
+
+    public void init(PreferenceFragment fragment, String targetImi, PreferenceScreen root) {
+        final Configuration config = fragment.getResources().getConfiguration();
+        mHaveHardKeyboard = (config.keyboard == Configuration.KEYBOARD_QWERTY);
+
+        for (final InputMethodInfo imi : mInputMethodInfoList) {
+            // Add subtype preferences of this IME when it is specified or no IME is specified.
+            if (imi.getId().equals(targetImi) || TextUtils.isEmpty(targetImi)) {
+                addInputMethodSubtypePreferences(fragment, imi, root);
+            }
+        }
+    }
+
+    public void refresh(Context context, PreferenceFragment fragment) {
+        // Refresh internal states in mInputMethodSettingValues to keep the latest
+        // "InputMethodInfo"s and "InputMethodSubtype"s
+        InputMethodSettingValuesWrapper
+                .getInstance(context).refreshAllInputMethodAndSubtypes();
+        InputMethodAndSubtypeUtil.loadInputMethodSubtypeList(fragment, context.getContentResolver(),
+                mInputMethodInfoList, mInputMethodAndSubtypePrefsMap);
+        updateAutoSelectionPreferences();
+    }
+
+    public void save(Context context, PreferenceFragment fragment) {
+        InputMethodAndSubtypeUtil.saveInputMethodSubtypeList(fragment, context.getContentResolver(),
+                mInputMethodInfoList, mHaveHardKeyboard);
+    }
+
+    @Override
+    public boolean onPreferenceChange(final Preference pref, final Object newValue) {
+        if (!(newValue instanceof Boolean)) {
+            return true; // Invoke default behavior.
+        }
+        final boolean isChecking = (Boolean) newValue;
+        for (final String imiId : mAutoSelectionPrefsMap.keySet()) {
+            // An auto select subtype preference is changing.
+            if (mAutoSelectionPrefsMap.get(imiId) == pref) {
+                final TwoStatePreference autoSelectionPref = (TwoStatePreference) pref;
+                autoSelectionPref.setChecked(isChecking);
+                // Enable or disable subtypes depending on the auto selection preference.
+                setAutoSelectionSubtypesEnabled(imiId, autoSelectionPref.isChecked());
+                return false;
+            }
+        }
+        // A subtype preference is changing.
+        if (pref instanceof InputMethodSubtypePreference) {
+            final InputMethodSubtypePreference subtypePref = (InputMethodSubtypePreference) pref;
+            subtypePref.setChecked(isChecking);
+            if (!subtypePref.isChecked()) {
+                // It takes care of the case where no subtypes are explicitly enabled then the auto
+                // selection preference is going to be checked.
+                updateAutoSelectionPreferences();
+            }
+            return false;
+        }
+        return true; // Invoke default behavior.
+    }
+
+    private void addInputMethodSubtypePreferences(PreferenceFragment fragment, InputMethodInfo imi,
+            final PreferenceScreen root) {
+        Context prefContext = fragment.getPreferenceManager().getContext();
+
+        final int subtypeCount = imi.getSubtypeCount();
+        if (subtypeCount <= 1) {
+            return;
+        }
+        final String imiId = imi.getId();
+        final PreferenceCategory keyboardSettingsCategory =
+                new PreferenceCategory(prefContext);
+        root.addPreference(keyboardSettingsCategory);
+        final PackageManager pm = prefContext.getPackageManager();
+        final CharSequence label = imi.loadLabel(pm);
+
+        keyboardSettingsCategory.setTitle(label);
+        keyboardSettingsCategory.setKey(imiId);
+        // TODO: Use toggle Preference if images are ready.
+        final TwoStatePreference autoSelectionPref =
+                new SwitchWithNoTextPreference(prefContext);
+        mAutoSelectionPrefsMap.put(imiId, autoSelectionPref);
+        keyboardSettingsCategory.addPreference(autoSelectionPref);
+        autoSelectionPref.setOnPreferenceChangeListener(this);
+
+        final PreferenceCategory activeInputMethodsCategory =
+                new PreferenceCategory(prefContext);
+        activeInputMethodsCategory.setTitle(R.string.active_input_method_subtypes);
+        root.addPreference(activeInputMethodsCategory);
+
+        CharSequence autoSubtypeLabel = null;
+        final ArrayList<Preference> subtypePreferences = new ArrayList<>();
+        for (int index = 0; index < subtypeCount; ++index) {
+            final InputMethodSubtype subtype = imi.getSubtypeAt(index);
+            if (subtype.overridesImplicitlyEnabledSubtype()) {
+                if (autoSubtypeLabel == null) {
+                    autoSubtypeLabel = InputMethodAndSubtypeUtil.getSubtypeLocaleNameAsSentence(
+                            subtype, prefContext, imi);
+                }
+            } else {
+                final Preference subtypePref = new InputMethodSubtypePreference(
+                        prefContext, subtype, imi);
+                subtypePreferences.add(subtypePref);
+            }
+        }
+        subtypePreferences.sort((lhs, rhs) -> {
+            if (lhs instanceof InputMethodSubtypePreference) {
+                return ((InputMethodSubtypePreference) lhs).compareTo(rhs, mCollator);
+            }
+            return lhs.compareTo(rhs);
+        });
+        for (final Preference pref : subtypePreferences) {
+            activeInputMethodsCategory.addPreference(pref);
+            pref.setOnPreferenceChangeListener(this);
+            InputMethodAndSubtypeUtil.removeUnnecessaryNonPersistentPreference(pref);
+        }
+        mInputMethodAndSubtypePrefsMap.put(imiId, subtypePreferences);
+        if (TextUtils.isEmpty(autoSubtypeLabel)) {
+            autoSelectionPref.setTitle(
+                    R.string.use_system_language_to_select_input_method_subtypes);
+        } else {
+            autoSelectionPref.setTitle(autoSubtypeLabel);
+        }
+    }
+
+    private boolean isNoSubtypesExplicitlySelected(final String imiId) {
+        final List<Preference> subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId);
+        for (final Preference pref : subtypePrefs) {
+            if (pref instanceof TwoStatePreference && ((TwoStatePreference) pref).isChecked()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private void setAutoSelectionSubtypesEnabled(final String imiId,
+            final boolean autoSelectionEnabled) {
+        final TwoStatePreference autoSelectionPref = mAutoSelectionPrefsMap.get(imiId);
+        if (autoSelectionPref == null) {
+            return;
+        }
+        autoSelectionPref.setChecked(autoSelectionEnabled);
+        final List<Preference> subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId);
+        for (final Preference pref : subtypePrefs) {
+            if (pref instanceof TwoStatePreference) {
+                // When autoSelectionEnabled is true, all subtype prefs need to be disabled with
+                // implicitly checked subtypes. In case of false, all subtype prefs need to be
+                // enabled.
+                pref.setEnabled(!autoSelectionEnabled);
+                if (autoSelectionEnabled) {
+                    ((TwoStatePreference) pref).setChecked(false);
+                }
+            }
+        }
+        if (autoSelectionEnabled) {
+            InputMethodAndSubtypeUtil.saveInputMethodSubtypeList(
+                    mFragment, mFragment.getContext().getContentResolver(),
+                    mInputMethodInfoList, mHaveHardKeyboard);
+            updateImplicitlyEnabledSubtypes(imiId);
+        }
+    }
+
+    private void updateImplicitlyEnabledSubtypes(final String targetImiId) {
+        // When targetImiId is null, apply to all subtypes of all IMEs
+        for (final InputMethodInfo imi : mInputMethodInfoList) {
+            final String imiId = imi.getId();
+            final TwoStatePreference autoSelectionPref = mAutoSelectionPrefsMap.get(imiId);
+            // No need to update implicitly enabled subtypes when the user has unchecked the
+            // "subtype auto selection".
+            if (autoSelectionPref == null || !autoSelectionPref.isChecked()) {
+                continue;
+            }
+            if (imiId.equals(targetImiId) || targetImiId == null) {
+                updateImplicitlyEnabledSubtypesOf(imi);
+            }
+        }
+    }
+
+    private void updateImplicitlyEnabledSubtypesOf(final InputMethodInfo imi) {
+        final String imiId = imi.getId();
+        final List<Preference> subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId);
+        final List<InputMethodSubtype> implicitlyEnabledSubtypes =
+                mImm.getEnabledInputMethodSubtypeList(imi, true);
+        if (subtypePrefs == null || implicitlyEnabledSubtypes == null) {
+            return;
+        }
+        for (final Preference pref : subtypePrefs) {
+            if (!(pref instanceof TwoStatePreference)) {
+                continue;
+            }
+            final TwoStatePreference subtypePref = (TwoStatePreference) pref;
+            subtypePref.setChecked(false);
+            for (final InputMethodSubtype subtype : implicitlyEnabledSubtypes) {
+                final String implicitlyEnabledSubtypePrefKey = imiId + subtype.hashCode();
+                if (subtypePref.getKey().equals(implicitlyEnabledSubtypePrefKey)) {
+                    subtypePref.setChecked(true);
+                    break;
+                }
+            }
+        }
+    }
+
+    private void updateAutoSelectionPreferences() {
+        for (final String imiId : mInputMethodAndSubtypePrefsMap.keySet()) {
+            setAutoSelectionSubtypesEnabled(imiId, isNoSubtypesExplicitlySelected(imiId));
+        }
+        updateImplicitlyEnabledSubtypes(null /* targetImiId */  /* check */);
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtil.java b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtil.java
new file mode 100644
index 0000000..55be137
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtil.java
@@ -0,0 +1,420 @@
+/*
+ * 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.settingslib.inputmethod;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.res.Configuration;
+import android.icu.text.ListFormatter;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
+import android.support.v14.preference.PreferenceFragment;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.support.v7.preference.TwoStatePreference;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.internal.app.LocaleHelper;
+import com.android.internal.inputmethod.InputMethodUtils;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+// TODO: Consolidate this with {@link InputMethodSettingValuesWrapper}.
+public class InputMethodAndSubtypeUtil {
+
+    private static final boolean DEBUG = false;
+    private static final String TAG = "InputMethdAndSubtypeUtl";
+
+    private static final char INPUT_METHOD_SEPARATER = ':';
+    private static final char INPUT_METHOD_SUBTYPE_SEPARATER = ';';
+    private static final int NOT_A_SUBTYPE_ID = -1;
+
+    private static final TextUtils.SimpleStringSplitter sStringInputMethodSplitter
+            = new TextUtils.SimpleStringSplitter(INPUT_METHOD_SEPARATER);
+
+    private static final TextUtils.SimpleStringSplitter sStringInputMethodSubtypeSplitter
+            = new TextUtils.SimpleStringSplitter(INPUT_METHOD_SUBTYPE_SEPARATER);
+
+    // InputMethods and subtypes are saved in the settings as follows:
+    // ime0;subtype0;subtype1:ime1;subtype0:ime2:ime3;subtype0;subtype1
+    private static String buildInputMethodsAndSubtypesString(
+            final HashMap<String, HashSet<String>> imeToSubtypesMap) {
+        final StringBuilder builder = new StringBuilder();
+        for (final String imi : imeToSubtypesMap.keySet()) {
+            if (builder.length() > 0) {
+                builder.append(INPUT_METHOD_SEPARATER);
+            }
+            final HashSet<String> subtypeIdSet = imeToSubtypesMap.get(imi);
+            builder.append(imi);
+            for (final String subtypeId : subtypeIdSet) {
+                builder.append(INPUT_METHOD_SUBTYPE_SEPARATER).append(subtypeId);
+            }
+        }
+        return builder.toString();
+    }
+
+    private static String buildInputMethodsString(final HashSet<String> imiList) {
+        final StringBuilder builder = new StringBuilder();
+        for (final String imi : imiList) {
+            if (builder.length() > 0) {
+                builder.append(INPUT_METHOD_SEPARATER);
+            }
+            builder.append(imi);
+        }
+        return builder.toString();
+    }
+
+    private static int getInputMethodSubtypeSelected(ContentResolver resolver) {
+        try {
+            return Settings.Secure.getInt(resolver,
+                    Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE);
+        } catch (SettingNotFoundException e) {
+            return NOT_A_SUBTYPE_ID;
+        }
+    }
+
+    private static boolean isInputMethodSubtypeSelected(ContentResolver resolver) {
+        return getInputMethodSubtypeSelected(resolver) != NOT_A_SUBTYPE_ID;
+    }
+
+    private static void putSelectedInputMethodSubtype(ContentResolver resolver, int hashCode) {
+        Settings.Secure.putInt(resolver, Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE, hashCode);
+    }
+
+    // Needs to modify InputMethodManageService if you want to change the format of saved string.
+    private static HashMap<String, HashSet<String>> getEnabledInputMethodsAndSubtypeList(
+            ContentResolver resolver) {
+        final String enabledInputMethodsStr = Settings.Secure.getString(
+                resolver, Settings.Secure.ENABLED_INPUT_METHODS);
+        if (DEBUG) {
+            Log.d(TAG, "--- Load enabled input methods: " + enabledInputMethodsStr);
+        }
+        return parseInputMethodsAndSubtypesString(enabledInputMethodsStr);
+    }
+
+    private static HashMap<String, HashSet<String>> parseInputMethodsAndSubtypesString(
+            final String inputMethodsAndSubtypesString) {
+        final HashMap<String, HashSet<String>> subtypesMap = new HashMap<>();
+        if (TextUtils.isEmpty(inputMethodsAndSubtypesString)) {
+            return subtypesMap;
+        }
+        sStringInputMethodSplitter.setString(inputMethodsAndSubtypesString);
+        while (sStringInputMethodSplitter.hasNext()) {
+            final String nextImsStr = sStringInputMethodSplitter.next();
+            sStringInputMethodSubtypeSplitter.setString(nextImsStr);
+            if (sStringInputMethodSubtypeSplitter.hasNext()) {
+                final HashSet<String> subtypeIdSet = new HashSet<>();
+                // The first element is {@link InputMethodInfoId}.
+                final String imiId = sStringInputMethodSubtypeSplitter.next();
+                while (sStringInputMethodSubtypeSplitter.hasNext()) {
+                    subtypeIdSet.add(sStringInputMethodSubtypeSplitter.next());
+                }
+                subtypesMap.put(imiId, subtypeIdSet);
+            }
+        }
+        return subtypesMap;
+    }
+
+    private static HashSet<String> getDisabledSystemIMEs(ContentResolver resolver) {
+        HashSet<String> set = new HashSet<>();
+        String disabledIMEsStr = Settings.Secure.getString(
+                resolver, Settings.Secure.DISABLED_SYSTEM_INPUT_METHODS);
+        if (TextUtils.isEmpty(disabledIMEsStr)) {
+            return set;
+        }
+        sStringInputMethodSplitter.setString(disabledIMEsStr);
+        while(sStringInputMethodSplitter.hasNext()) {
+            set.add(sStringInputMethodSplitter.next());
+        }
+        return set;
+    }
+
+    public static void saveInputMethodSubtypeList(PreferenceFragment context,
+            ContentResolver resolver, List<InputMethodInfo> inputMethodInfos,
+            boolean hasHardKeyboard) {
+        String currentInputMethodId = Settings.Secure.getString(resolver,
+                Settings.Secure.DEFAULT_INPUT_METHOD);
+        final int selectedInputMethodSubtype = getInputMethodSubtypeSelected(resolver);
+        final HashMap<String, HashSet<String>> enabledIMEsAndSubtypesMap =
+                getEnabledInputMethodsAndSubtypeList(resolver);
+        final HashSet<String> disabledSystemIMEs = getDisabledSystemIMEs(resolver);
+
+        boolean needsToResetSelectedSubtype = false;
+        for (final InputMethodInfo imi : inputMethodInfos) {
+            final String imiId = imi.getId();
+            final Preference pref = context.findPreference(imiId);
+            if (pref == null) {
+                continue;
+            }
+            // In the choose input method screen or in the subtype enabler screen,
+            // <code>pref</code> is an instance of TwoStatePreference.
+            final boolean isImeChecked = (pref instanceof TwoStatePreference) ?
+                    ((TwoStatePreference) pref).isChecked()
+                    : enabledIMEsAndSubtypesMap.containsKey(imiId);
+            final boolean isCurrentInputMethod = imiId.equals(currentInputMethodId);
+            final boolean systemIme = InputMethodUtils.isSystemIme(imi);
+            if ((!hasHardKeyboard && InputMethodSettingValuesWrapper.getInstance(
+                    context.getActivity()).isAlwaysCheckedIme(imi, context.getActivity()))
+                    || isImeChecked) {
+                if (!enabledIMEsAndSubtypesMap.containsKey(imiId)) {
+                    // imiId has just been enabled
+                    enabledIMEsAndSubtypesMap.put(imiId, new HashSet<>());
+                }
+                final HashSet<String> subtypesSet = enabledIMEsAndSubtypesMap.get(imiId);
+
+                boolean subtypePrefFound = false;
+                final int subtypeCount = imi.getSubtypeCount();
+                for (int i = 0; i < subtypeCount; ++i) {
+                    final InputMethodSubtype subtype = imi.getSubtypeAt(i);
+                    final String subtypeHashCodeStr = String.valueOf(subtype.hashCode());
+                    final TwoStatePreference subtypePref = (TwoStatePreference) context
+                            .findPreference(imiId + subtypeHashCodeStr);
+                    // In the Configure input method screen which does not have subtype preferences.
+                    if (subtypePref == null) {
+                        continue;
+                    }
+                    if (!subtypePrefFound) {
+                        // Once subtype preference is found, subtypeSet needs to be cleared.
+                        // Because of system change, hashCode value could have been changed.
+                        subtypesSet.clear();
+                        // If selected subtype preference is disabled, needs to reset.
+                        needsToResetSelectedSubtype = true;
+                        subtypePrefFound = true;
+                    }
+                    // Checking <code>subtypePref.isEnabled()</code> is insufficient to determine
+                    // whether the user manually enabled this subtype or not.  Implicitly-enabled
+                    // subtypes are also checked just as an indicator to users.  We also need to
+                    // check <code>subtypePref.isEnabled()</code> so that only manually enabled
+                    // subtypes can be saved here.
+                    if (subtypePref.isEnabled() && subtypePref.isChecked()) {
+                        subtypesSet.add(subtypeHashCodeStr);
+                        if (isCurrentInputMethod) {
+                            if (selectedInputMethodSubtype == subtype.hashCode()) {
+                                // Selected subtype is still enabled, there is no need to reset
+                                // selected subtype.
+                                needsToResetSelectedSubtype = false;
+                            }
+                        }
+                    } else {
+                        subtypesSet.remove(subtypeHashCodeStr);
+                    }
+                }
+            } else {
+                enabledIMEsAndSubtypesMap.remove(imiId);
+                if (isCurrentInputMethod) {
+                    // We are processing the current input method, but found that it's not enabled.
+                    // This means that the current input method has been uninstalled.
+                    // If currentInputMethod is already uninstalled, InputMethodManagerService will
+                    // find the applicable IME from the history and the system locale.
+                    if (DEBUG) {
+                        Log.d(TAG, "Current IME was uninstalled or disabled.");
+                    }
+                    currentInputMethodId = null;
+                }
+            }
+            // If it's a disabled system ime, add it to the disabled list so that it
+            // doesn't get enabled automatically on any changes to the package list
+            if (systemIme && hasHardKeyboard) {
+                if (disabledSystemIMEs.contains(imiId)) {
+                    if (isImeChecked) {
+                        disabledSystemIMEs.remove(imiId);
+                    }
+                } else {
+                    if (!isImeChecked) {
+                        disabledSystemIMEs.add(imiId);
+                    }
+                }
+            }
+        }
+
+        final String enabledIMEsAndSubtypesString = buildInputMethodsAndSubtypesString(
+                enabledIMEsAndSubtypesMap);
+        final String disabledSystemIMEsString = buildInputMethodsString(disabledSystemIMEs);
+        if (DEBUG) {
+            Log.d(TAG, "--- Save enabled inputmethod settings. :" + enabledIMEsAndSubtypesString);
+            Log.d(TAG, "--- Save disabled system inputmethod settings. :"
+                    + disabledSystemIMEsString);
+            Log.d(TAG, "--- Save default inputmethod settings. :" + currentInputMethodId);
+            Log.d(TAG, "--- Needs to reset the selected subtype :" + needsToResetSelectedSubtype);
+            Log.d(TAG, "--- Subtype is selected :" + isInputMethodSubtypeSelected(resolver));
+        }
+
+        // Redefines SelectedSubtype when all subtypes are unchecked or there is no subtype
+        // selected. And if the selected subtype of the current input method was disabled,
+        // We should reset the selected input method's subtype.
+        if (needsToResetSelectedSubtype || !isInputMethodSubtypeSelected(resolver)) {
+            if (DEBUG) {
+                Log.d(TAG, "--- Reset inputmethod subtype because it's not defined.");
+            }
+            putSelectedInputMethodSubtype(resolver, NOT_A_SUBTYPE_ID);
+        }
+
+        Settings.Secure.putString(resolver,
+                Settings.Secure.ENABLED_INPUT_METHODS, enabledIMEsAndSubtypesString);
+        if (disabledSystemIMEsString.length() > 0) {
+            Settings.Secure.putString(resolver, Settings.Secure.DISABLED_SYSTEM_INPUT_METHODS,
+                    disabledSystemIMEsString);
+        }
+        // If the current input method is unset, InputMethodManagerService will find the applicable
+        // IME from the history and the system locale.
+        Settings.Secure.putString(resolver, Settings.Secure.DEFAULT_INPUT_METHOD,
+                currentInputMethodId != null ? currentInputMethodId : "");
+    }
+
+    public static void loadInputMethodSubtypeList(final PreferenceFragment context,
+            final ContentResolver resolver, final List<InputMethodInfo> inputMethodInfos,
+            final Map<String, List<Preference>> inputMethodPrefsMap) {
+        final HashMap<String, HashSet<String>> enabledSubtypes =
+                getEnabledInputMethodsAndSubtypeList(resolver);
+
+        for (final InputMethodInfo imi : inputMethodInfos) {
+            final String imiId = imi.getId();
+            final Preference pref = context.findPreference(imiId);
+            if (pref instanceof TwoStatePreference) {
+                final TwoStatePreference subtypePref = (TwoStatePreference) pref;
+                final boolean isEnabled = enabledSubtypes.containsKey(imiId);
+                subtypePref.setChecked(isEnabled);
+                if (inputMethodPrefsMap != null) {
+                    for (final Preference childPref: inputMethodPrefsMap.get(imiId)) {
+                        childPref.setEnabled(isEnabled);
+                    }
+                }
+                setSubtypesPreferenceEnabled(context, inputMethodInfos, imiId, isEnabled);
+            }
+        }
+        updateSubtypesPreferenceChecked(context, inputMethodInfos, enabledSubtypes);
+    }
+
+    private static void setSubtypesPreferenceEnabled(final PreferenceFragment context,
+            final List<InputMethodInfo> inputMethodProperties, final String id,
+            final boolean enabled) {
+        final PreferenceScreen preferenceScreen = context.getPreferenceScreen();
+        for (final InputMethodInfo imi : inputMethodProperties) {
+            if (id.equals(imi.getId())) {
+                final int subtypeCount = imi.getSubtypeCount();
+                for (int i = 0; i < subtypeCount; ++i) {
+                    final InputMethodSubtype subtype = imi.getSubtypeAt(i);
+                    final TwoStatePreference pref = (TwoStatePreference) preferenceScreen
+                            .findPreference(id + subtype.hashCode());
+                    if (pref != null) {
+                        pref.setEnabled(enabled);
+                    }
+                }
+            }
+        }
+    }
+
+    private static void updateSubtypesPreferenceChecked(final PreferenceFragment context,
+            final List<InputMethodInfo> inputMethodProperties,
+            final HashMap<String, HashSet<String>> enabledSubtypes) {
+        final PreferenceScreen preferenceScreen = context.getPreferenceScreen();
+        for (final InputMethodInfo imi : inputMethodProperties) {
+            final String id = imi.getId();
+            if (!enabledSubtypes.containsKey(id)) {
+                // There is no need to enable/disable subtypes of disabled IMEs.
+                continue;
+            }
+            final HashSet<String> enabledSubtypesSet = enabledSubtypes.get(id);
+            final int subtypeCount = imi.getSubtypeCount();
+            for (int i = 0; i < subtypeCount; ++i) {
+                final InputMethodSubtype subtype = imi.getSubtypeAt(i);
+                final String hashCode = String.valueOf(subtype.hashCode());
+                if (DEBUG) {
+                    Log.d(TAG, "--- Set checked state: " + "id" + ", " + hashCode + ", "
+                            + enabledSubtypesSet.contains(hashCode));
+                }
+                final TwoStatePreference pref = (TwoStatePreference) preferenceScreen
+                        .findPreference(id + hashCode);
+                if (pref != null) {
+                    pref.setChecked(enabledSubtypesSet.contains(hashCode));
+                }
+            }
+        }
+    }
+
+    public static void removeUnnecessaryNonPersistentPreference(final Preference pref) {
+        final String key = pref.getKey();
+        if (pref.isPersistent() || key == null) {
+            return;
+        }
+        final SharedPreferences prefs = pref.getSharedPreferences();
+        if (prefs != null && prefs.contains(key)) {
+            prefs.edit().remove(key).apply();
+        }
+    }
+
+    @NonNull
+    public static String getSubtypeLocaleNameAsSentence(@Nullable InputMethodSubtype subtype,
+            @NonNull final Context context, @NonNull final InputMethodInfo inputMethodInfo) {
+        if (subtype == null) {
+            return "";
+        }
+        final Locale locale = getDisplayLocale(context);
+        final CharSequence subtypeName = subtype.getDisplayName(context,
+                inputMethodInfo.getPackageName(), inputMethodInfo.getServiceInfo()
+                        .applicationInfo);
+        return LocaleHelper.toSentenceCase(subtypeName.toString(), locale);
+    }
+
+    @NonNull
+    public static String getSubtypeLocaleNameListAsSentence(
+            @NonNull final List<InputMethodSubtype> subtypes, @NonNull final Context context,
+            @NonNull final InputMethodInfo inputMethodInfo) {
+        if (subtypes.isEmpty()) {
+            return "";
+        }
+        final Locale locale = getDisplayLocale(context);
+        final int subtypeCount = subtypes.size();
+        final CharSequence[] subtypeNames = new CharSequence[subtypeCount];
+        for (int i = 0; i < subtypeCount; i++) {
+            subtypeNames[i] = subtypes.get(i).getDisplayName(context,
+                    inputMethodInfo.getPackageName(), inputMethodInfo.getServiceInfo()
+                            .applicationInfo);
+        }
+        return LocaleHelper.toSentenceCase(
+                ListFormatter.getInstance(locale).format((Object[]) subtypeNames), locale);
+    }
+
+    @NonNull
+    private static Locale getDisplayLocale(@Nullable final Context context) {
+        if (context == null) {
+            return Locale.getDefault();
+        }
+        if (context.getResources() == null) {
+            return Locale.getDefault();
+        }
+        final Configuration configuration = context.getResources().getConfiguration();
+        if (configuration == null) {
+            return Locale.getDefault();
+        }
+        final Locale configurationLocale = configuration.getLocales().get(0);
+        if (configurationLocale == null) {
+            return Locale.getDefault();
+        }
+        return configurationLocale;
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodSettingValuesWrapper.java b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodSettingValuesWrapper.java
new file mode 100644
index 0000000..fac50bd
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodSettingValuesWrapper.java
@@ -0,0 +1,185 @@
+/*
+ * 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.settingslib.inputmethod;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.os.RemoteException;
+import android.util.Log;
+import android.util.Slog;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.internal.inputmethod.InputMethodUtils;
+import com.android.internal.inputmethod.InputMethodUtils.InputMethodSettings;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * This class is a wrapper for InputMethodSettings. You need to refresh internal states
+ * manually on some events when "InputMethodInfo"s and "InputMethodSubtype"s can be
+ * changed.
+ */
+// TODO: Consolidate this with {@link InputMethodAndSubtypeUtil}.
+public class InputMethodSettingValuesWrapper {
+    private static final String TAG = InputMethodSettingValuesWrapper.class.getSimpleName();
+
+    private static volatile InputMethodSettingValuesWrapper sInstance;
+    private final ArrayList<InputMethodInfo> mMethodList = new ArrayList<>();
+    private final HashMap<String, InputMethodInfo> mMethodMap = new HashMap<>();
+    private final InputMethodSettings mSettings;
+    private final InputMethodManager mImm;
+    private final HashSet<InputMethodInfo> mAsciiCapableEnabledImis = new HashSet<>();
+
+    public static InputMethodSettingValuesWrapper getInstance(Context context) {
+        if (sInstance == null) {
+            synchronized (TAG) {
+                if (sInstance == null) {
+                    sInstance = new InputMethodSettingValuesWrapper(context);
+                }
+            }
+        }
+        return sInstance;
+    }
+
+    private static int getDefaultCurrentUserId() {
+        try {
+            return ActivityManager.getService().getCurrentUser().id;
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Couldn't get current user ID; guessing it's 0", e);
+        }
+        return 0;
+    }
+
+    // Ensure singleton
+    private InputMethodSettingValuesWrapper(Context context) {
+        mSettings = new InputMethodSettings(context.getResources(), context.getContentResolver(),
+                mMethodMap, mMethodList, getDefaultCurrentUserId(), false /* copyOnWrite */);
+        mImm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
+        refreshAllInputMethodAndSubtypes();
+    }
+
+    public void refreshAllInputMethodAndSubtypes() {
+        synchronized (mMethodMap) {
+            mMethodList.clear();
+            mMethodMap.clear();
+            final List<InputMethodInfo> imms = mImm.getInputMethodList();
+            mMethodList.addAll(imms);
+            for (InputMethodInfo imi : imms) {
+                mMethodMap.put(imi.getId(), imi);
+            }
+            updateAsciiCapableEnabledImis();
+        }
+    }
+
+    // TODO: Add a cts to ensure at least one AsciiCapableSubtypeEnabledImis exist
+    private void updateAsciiCapableEnabledImis() {
+        synchronized (mMethodMap) {
+            mAsciiCapableEnabledImis.clear();
+            final List<InputMethodInfo> enabledImis = mSettings.getEnabledInputMethodListLocked();
+            for (final InputMethodInfo imi : enabledImis) {
+                final int subtypeCount = imi.getSubtypeCount();
+                for (int i = 0; i < subtypeCount; ++i) {
+                    final InputMethodSubtype subtype = imi.getSubtypeAt(i);
+                    if (InputMethodUtils.SUBTYPE_MODE_KEYBOARD.equalsIgnoreCase(subtype.getMode())
+                            && subtype.isAsciiCapable()) {
+                        mAsciiCapableEnabledImis.add(imi);
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    public List<InputMethodInfo> getInputMethodList() {
+        synchronized (mMethodMap) {
+            return mMethodList;
+        }
+    }
+
+    public boolean isAlwaysCheckedIme(InputMethodInfo imi, Context context) {
+        final boolean isEnabled = isEnabledImi(imi);
+        synchronized (mMethodMap) {
+            if (mSettings.getEnabledInputMethodListLocked().size() <= 1 && isEnabled) {
+                return true;
+            }
+        }
+
+        final int enabledValidSystemNonAuxAsciiCapableImeCount =
+                getEnabledValidSystemNonAuxAsciiCapableImeCount(context);
+
+        return enabledValidSystemNonAuxAsciiCapableImeCount <= 1
+                && !(enabledValidSystemNonAuxAsciiCapableImeCount == 1 && !isEnabled)
+                && InputMethodUtils.isSystemIme(imi)
+                && isValidSystemNonAuxAsciiCapableIme(imi, context);
+
+    }
+
+    private int getEnabledValidSystemNonAuxAsciiCapableImeCount(Context context) {
+        int count = 0;
+        final List<InputMethodInfo> enabledImis;
+        synchronized (mMethodMap) {
+            enabledImis = mSettings.getEnabledInputMethodListLocked();
+        }
+        for (final InputMethodInfo imi : enabledImis) {
+            if (isValidSystemNonAuxAsciiCapableIme(imi, context)) {
+                ++count;
+            }
+        }
+        if (count == 0) {
+            Log.w(TAG, "No \"enabledValidSystemNonAuxAsciiCapableIme\"s found.");
+        }
+        return count;
+    }
+
+    public boolean isEnabledImi(InputMethodInfo imi) {
+        final List<InputMethodInfo> enabledImis;
+        synchronized (mMethodMap) {
+            enabledImis = mSettings.getEnabledInputMethodListLocked();
+        }
+        for (final InputMethodInfo tempImi : enabledImis) {
+            if (tempImi.getId().equals(imi.getId())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean isValidSystemNonAuxAsciiCapableIme(InputMethodInfo imi, Context context) {
+        if (imi.isAuxiliaryIme()) {
+            return false;
+        }
+        final Locale systemLocale = context.getResources().getConfiguration().locale;
+        if (InputMethodUtils.isSystemImeThatHasSubtypeOf(imi, context,
+                    true /* checkDefaultAttribute */, systemLocale, false /* checkCountry */,
+                    InputMethodUtils.SUBTYPE_MODE_ANY)) {
+            return true;
+        }
+        if (mAsciiCapableEnabledImis.isEmpty()) {
+            Log.w(TAG, "ascii capable subtype enabled imi not found. Fall back to English"
+                    + " Keyboard subtype.");
+            return InputMethodUtils.containsSubtypeOf(imi, Locale.ENGLISH, false /* checkCountry */,
+                    InputMethodUtils.SUBTYPE_MODE_KEYBOARD);
+        }
+        return mAsciiCapableEnabledImis.contains(imi);
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodSubtypePreference.java b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodSubtypePreference.java
new file mode 100644
index 0000000..5fdab29
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodSubtypePreference.java
@@ -0,0 +1,91 @@
+/*
+ * 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.settingslib.inputmethod;
+
+import android.content.Context;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.Preference;
+import android.text.TextUtils;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.internal.inputmethod.InputMethodUtils;
+
+import java.text.Collator;
+import java.util.Locale;
+
+/**
+ * Input method subtype preference.
+ *
+ * This preference represents a subtype of an IME. It is used to enable or disable the subtype.
+ */
+public class InputMethodSubtypePreference extends SwitchWithNoTextPreference {
+    private final boolean mIsSystemLocale;
+    private final boolean mIsSystemLanguage;
+
+    public InputMethodSubtypePreference(final Context context, final InputMethodSubtype subtype,
+            final InputMethodInfo imi) {
+        super(context);
+        setPersistent(false);
+        setKey(imi.getId() + subtype.hashCode());
+        final CharSequence subtypeLabel =
+                InputMethodAndSubtypeUtil.getSubtypeLocaleNameAsSentence(subtype, context, imi);
+        setTitle(subtypeLabel);
+        final String subtypeLocaleString = subtype.getLocale();
+        if (TextUtils.isEmpty(subtypeLocaleString)) {
+            mIsSystemLocale = false;
+            mIsSystemLanguage = false;
+        } else {
+            final Locale systemLocale = context.getResources().getConfiguration().locale;
+            mIsSystemLocale = subtypeLocaleString.equals(systemLocale.toString());
+            mIsSystemLanguage = mIsSystemLocale
+                    || InputMethodUtils.getLanguageFromLocaleString(subtypeLocaleString)
+                            .equals(systemLocale.getLanguage());
+        }
+    }
+
+    public int compareTo(final Preference rhs, final Collator collator) {
+        if (this == rhs) {
+            return 0;
+        }
+        if (rhs instanceof InputMethodSubtypePreference) {
+            final InputMethodSubtypePreference rhsPref = (InputMethodSubtypePreference) rhs;
+            if (mIsSystemLocale && !rhsPref.mIsSystemLocale) {
+                return -1;
+            }
+            if (!mIsSystemLocale && rhsPref.mIsSystemLocale) {
+                return 1;
+            }
+            if (mIsSystemLanguage && !rhsPref.mIsSystemLanguage) {
+                return -1;
+            }
+            if (!mIsSystemLanguage && rhsPref.mIsSystemLanguage) {
+                return 1;
+            }
+            final CharSequence t0 = getTitle();
+            final CharSequence t1 = rhs.getTitle();
+            if (t0 == null && t1 == null) {
+                return Integer.compare(hashCode(), rhs.hashCode());
+            }
+            if (t0 != null && t1 != null) {
+                return collator.compare(t0.toString(), t1.toString());
+            }
+            return t0 == null ? -1 : 1;
+        }
+        return super.compareTo(rhs);
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/inputmethod/SwitchWithNoTextPreference.java b/packages/SettingsLib/src/com/android/settingslib/inputmethod/SwitchWithNoTextPreference.java
new file mode 100644
index 0000000..798f8fe
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/inputmethod/SwitchWithNoTextPreference.java
@@ -0,0 +1,30 @@
+/*
+ * 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.settingslib.inputmethod;
+
+import android.content.Context;
+import android.support.v14.preference.SwitchPreference;
+
+public class SwitchWithNoTextPreference extends SwitchPreference {
+    private static final String EMPTY_TEXT = "";
+
+    public SwitchWithNoTextPreference(final Context context) {
+        super(context);
+        setSwitchTextOn(EMPTY_TEXT);
+        setSwitchTextOff(EMPTY_TEXT);
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index dc9b798..6fe581e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -22,12 +22,11 @@
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.net.ConnectivityManager;
-import android.net.Network;
+import android.net.NetworkBadging;
 import android.net.NetworkCapabilities;
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.DetailedState;
 import android.net.NetworkInfo.State;
-import android.net.NetworkKey;
 import android.net.ScoredNetwork;
 import android.net.wifi.IWifiManager;
 import android.net.wifi.ScanResult;
@@ -51,7 +50,6 @@
 import com.android.settingslib.R;
 
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Iterator;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -91,15 +89,15 @@
             new ConcurrentHashMap<String, ScanResult>(32);
     private static final long MAX_SCAN_RESULT_AGE_MS = 15000;
 
-    private static final String KEY_NETWORKINFO = "key_networkinfo";
-    private static final String KEY_WIFIINFO = "key_wifiinfo";
-    private static final String KEY_SCANRESULT = "key_scanresult";
-    private static final String KEY_SSID = "key_ssid";
-    private static final String KEY_SECURITY = "key_security";
-    private static final String KEY_PSKTYPE = "key_psktype";
-    private static final String KEY_SCANRESULTCACHE = "key_scanresultcache";
-    private static final String KEY_CONFIG = "key_config";
-    private static final AtomicInteger sLastId = new AtomicInteger(0);
+    static final String KEY_NETWORKINFO = "key_networkinfo";
+    static final String KEY_WIFIINFO = "key_wifiinfo";
+    static final String KEY_SCANRESULT = "key_scanresult";
+    static final String KEY_SSID = "key_ssid";
+    static final String KEY_SECURITY = "key_security";
+    static final String KEY_PSKTYPE = "key_psktype";
+    static final String KEY_SCANRESULTCACHE = "key_scanresultcache";
+    static final String KEY_CONFIG = "key_config";
+    static final AtomicInteger sLastId = new AtomicInteger(0);
 
     /**
      * These values are matched in string arrays -- changes must be kept in sync
@@ -116,6 +114,8 @@
 
     public static final int SIGNAL_LEVELS = 4;
 
+    static final int UNREACHABLE_RSSI = Integer.MAX_VALUE;
+
     private final Context mContext;
 
     private String ssid;
@@ -127,7 +127,7 @@
 
     private WifiConfiguration mConfig;
 
-    private int mRssi = Integer.MAX_VALUE;
+    private int mRssi = UNREACHABLE_RSSI;
     private long mSeen = 0;
 
     private WifiInfo mInfo;
@@ -137,7 +137,7 @@
     private Object mTag;
 
     private int mRankingScore = Integer.MIN_VALUE;
-    private int mBadge = ScoredNetwork.BADGING_NONE;
+    private int mBadge = NetworkBadging.BADGING_NONE;
 
     // used to co-relate internal vs returned accesspoint.
     int mId;
@@ -216,6 +216,21 @@
         this.mRankingScore = that.mRankingScore;
     }
 
+    /**
+    * Returns a negative integer, zero, or a positive integer if this AccessPoint is less than,
+    * equal to, or greater than the other AccessPoint.
+    *
+    * Sort order rules for AccessPoints:
+    *   1. Active before inactive
+    *   2. Reachable before unreachable
+    *   3. Saved before unsaved
+    *   4. (Internal only) Network ranking score
+    *   5. Stronger signal before weaker signal
+    *   6. SSID alphabetically
+    *
+    * Note that AccessPoints with a signal are usually also Reachable,
+    * and will thus appear before unreachable saved AccessPoints.
+    */
     @Override
     public int compareTo(@NonNull AccessPoint other) {
         // Active one goes first.
@@ -223,18 +238,16 @@
         if (!isActive() && other.isActive()) return 1;
 
         // Reachable one goes before unreachable one.
-        if (mRssi != Integer.MAX_VALUE && other.mRssi == Integer.MAX_VALUE) return -1;
-        if (mRssi == Integer.MAX_VALUE && other.mRssi != Integer.MAX_VALUE) return 1;
+        if (isReachable() && !other.isReachable()) return -1;
+        if (!isReachable() && other.isReachable()) return 1;
 
         // Configured (saved) one goes before unconfigured one.
-        if (networkId != WifiConfiguration.INVALID_NETWORK_ID
-                && other.networkId == WifiConfiguration.INVALID_NETWORK_ID) return -1;
-        if (networkId == WifiConfiguration.INVALID_NETWORK_ID
-                && other.networkId != WifiConfiguration.INVALID_NETWORK_ID) return 1;
+        if (isSaved() && !other.isSaved()) return -1;
+        if (!isSaved() && other.isSaved()) return 1;
 
         // Higher scores go before lower scores
-        if (mRankingScore != other.mRankingScore) {
-            return (mRankingScore > other.mRankingScore) ? -1 : 1;
+        if (getRankingScore() != other.getRankingScore()) {
+            return (getRankingScore() > other.getRankingScore()) ? -1 : 1;
         }
 
         // Sort by signal strength, bucketed by level
@@ -244,7 +257,7 @@
             return difference;
         }
         // Sort by ssid.
-        return ssid.compareToIgnoreCase(other.ssid);
+        return getSsidStr().compareToIgnoreCase(other.getSsidStr());
     }
 
     @Override
@@ -267,6 +280,9 @@
     public String toString() {
         StringBuilder builder = new StringBuilder().append("AccessPoint(")
                 .append(ssid);
+        if (bssid != null) {
+            builder.append(":").append(bssid);
+        }
         if (isSaved()) {
             builder.append(',').append("saved");
         }
@@ -282,6 +298,7 @@
         if (security != SECURITY_NONE) {
             builder.append(',').append(securityToString(security, pskType));
         }
+        builder.append(",level=").append(getLevel());
         builder.append(",rankingScore=").append(mRankingScore);
         builder.append(",badge=").append(mBadge);
 
@@ -296,7 +313,7 @@
     boolean updateScores(WifiNetworkScoreCache scoreCache) {
         int oldBadge = mBadge;
         int oldRankingScore = mRankingScore;
-        mBadge = ScoredNetwork.BADGING_NONE;
+        mBadge = NetworkBadging.BADGING_NONE;
         mRankingScore = Integer.MIN_VALUE;
 
         for (ScanResult result : mScanResultCache.values()) {
@@ -353,7 +370,7 @@
     }
 
     public int getLevel() {
-        if (mRssi == Integer.MAX_VALUE) {
+        if (!isReachable()) {
             return -1;
         }
         return WifiManager.calculateSignalLevel(mRssi, SIGNAL_LEVELS);
@@ -529,7 +546,7 @@
             }
         } else if (config != null && config.getNetworkSelectionStatus().isNotRecommended()) {
             summary.append(mContext.getString(R.string.wifi_disabled_by_recommendation_provider));
-        } else if (mRssi == Integer.MAX_VALUE) { // Wifi out of range
+        } else if (!isReachable()) { // Wifi out of range
             summary.append(mContext.getString(R.string.wifi_not_in_range));
         } else { // In range, not disabled.
             if (config != null) { // Is saved network
@@ -768,11 +785,7 @@
     }
 
     void loadConfig(WifiConfiguration config) {
-        if (config.isPasspoint())
-            ssid = config.providerFriendlyName;
-        else
-            ssid = (config.SSID == null ? "" : removeDoubleQuotes(config.SSID));
-
+        ssid = (config.SSID == null ? "" : removeDoubleQuotes(config.SSID));
         bssid = config.BSSID;
         security = getSecurity(config);
         networkId = config.networkId;
@@ -876,6 +889,11 @@
         return mBadge;
     }
 
+    /** Return true if the current RSSI is reachable, and false otherwise. */
+    boolean isReachable() {
+        return mRssi != UNREACHABLE_RSSI;
+    }
+
     public static String getSummary(Context context, String ssid, DetailedState state,
             boolean isEphemeral, String passpointProvider) {
         if (state == DetailedState.CONNECTED && ssid == null) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
index a77c310..50972c7 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
@@ -22,8 +22,8 @@
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.StateListDrawable;
 import android.net.NetworkBadging;
-import android.net.ScoredNetwork;
 import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
 import android.os.Looper;
 import android.os.UserHandle;
 import android.support.v7.preference.Preference;
@@ -61,7 +61,7 @@
     private int mLevel;
     private CharSequence mContentDescription;
     private int mDefaultIconResId;
-    private int mWifiBadge = ScoredNetwork.BADGING_NONE;
+    private int mWifiBadge = NetworkBadging.BADGING_NONE;
 
     static final int[] WIFI_CONNECTION_STRENGTH = {
             R.string.accessibility_wifi_one_bar,
@@ -223,7 +223,8 @@
         }
 
         final Context context = getContext();
-        int level = mAccessPoint.getLevel();
+        int level = WifiManager.calculateSignalLevel(
+                mAccessPoint.getRssi(), WifiManager.RSSI_LEVELS);
         int wifiBadge = mAccessPoint.getBadge();
         if (level != mLevel || wifiBadge != mWifiBadge) {
             mLevel = level;
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index 9ac4d2d..8421c2c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -271,7 +271,6 @@
         if (mWifiManager.isWifiEnabled()) {
             mScanner.resume();
         }
-        mWorkHandler.sendEmptyMessage(WorkHandler.MSG_UPDATE_ACCESS_POINTS);
     }
 
     /**
@@ -469,29 +468,22 @@
                 }
                 AccessPoint accessPoint = getCachedOrCreate(config, cachedAccessPoints);
                 if (mLastInfo != null && mLastNetworkInfo != null) {
-                    if (config.isPasspoint() == false) {
-                        accessPoint.update(connectionConfig, mLastInfo, mLastNetworkInfo);
-                    }
+                    accessPoint.update(connectionConfig, mLastInfo, mLastNetworkInfo);
                 }
                 if (mIncludeSaved) {
-                    if (!config.isPasspoint() || mIncludePasspoints) {
-                        // If saved network not present in scan result then set its Rssi to MAX_VALUE
-                        boolean apFound = false;
-                        for (ScanResult result : results) {
-                            if (result.SSID.equals(accessPoint.getSsidStr())) {
-                                apFound = true;
-                                break;
-                            }
+                    // If saved network not present in scan result then set its Rssi to MAX_VALUE
+                    boolean apFound = false;
+                    for (ScanResult result : results) {
+                        if (result.SSID.equals(accessPoint.getSsidStr())) {
+                            apFound = true;
+                            break;
                         }
-                        if (!apFound) {
-                            accessPoint.setRssi(Integer.MAX_VALUE);
-                        }
-                        accessPoints.add(accessPoint);
                     }
-
-                    if (config.isPasspoint() == false) {
-                        apMap.put(accessPoint.getSsidStr(), accessPoint);
+                    if (!apFound) {
+                        accessPoint.setRssi(Integer.MAX_VALUE);
                     }
+                    accessPoints.add(accessPoint);
+                    apMap.put(accessPoint.getSsidStr(), accessPoint);
                 } else {
                     // If we aren't using saved networks, drop them into the cache so that
                     // we have access to their saved info.
@@ -528,20 +520,16 @@
                     }
 
                     if (result.isPasspointNetwork()) {
+                        // Retrieve a WifiConfiguration for a Passpoint provider that matches
+                        // the given ScanResult.  This is used for showing that a given AP
+                        // (ScanResult) is available via a Passpoint provider (provider friendly
+                        // name).
                         WifiConfiguration config = mWifiManager.getMatchingWifiConfig(result);
                         if (config != null) {
                             accessPoint.update(config);
                         }
                     }
 
-                    if (mLastInfo != null && mLastInfo.getBSSID() != null
-                            && mLastInfo.getBSSID().equals(result.BSSID)
-                            && connectionConfig != null && connectionConfig.isPasspoint()) {
-                    /* This network is connected via this passpoint config */
-                    /* SSID match is not going to work for it; so update explicitly */
-                        accessPoint.update(connectionConfig);
-                    }
-
                     accessPoints.add(accessPoint);
                     apMap.put(accessPoint.getSsidStr(), accessPoint);
                 }
@@ -726,9 +714,9 @@
 
                 mMainHandler.sendEmptyMessage(MainHandler.MSG_CONNECTED_CHANGED);
 
-                mWorkHandler.sendEmptyMessage(WorkHandler.MSG_UPDATE_ACCESS_POINTS);
                 mWorkHandler.obtainMessage(WorkHandler.MSG_UPDATE_NETWORK_INFO, info)
                         .sendToTarget();
+                mWorkHandler.sendEmptyMessage(WorkHandler.MSG_UPDATE_ACCESS_POINTS);
             }
         }
     };
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java
index 80e1cbf..e204a3a 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java
@@ -19,6 +19,7 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 import android.content.pm.ApplicationInfo;
 
@@ -107,4 +108,32 @@
 
         assertThat(ApplicationsState.FILTER_OTHER_APPS.filterApp(mEntry)).isTrue();
     }
+
+    @Test
+    public void testInstantFilterAcceptsInstantApp() {
+        when(mEntry.info.isInstantApp()).thenReturn(true);
+        assertThat(ApplicationsState.FILTER_INSTANT.filterApp(mEntry)).isTrue();
+    }
+
+    @Test
+    public void testInstantFilterRejectsNonInstantApp() {
+        when(mEntry.info.isInstantApp()).thenReturn(false);
+        assertThat(ApplicationsState.FILTER_INSTANT.filterApp(mEntry)).isFalse();
+    }
+
+    @Test
+    public void testEnabledFilterRejectsInstantApp() {
+        mEntry.info.enabled = true;
+        assertThat(ApplicationsState.FILTER_ALL_ENABLED.filterApp(mEntry)).isTrue();
+        when(mEntry.info.isInstantApp()).thenReturn(true);
+        assertThat(ApplicationsState.FILTER_ALL_ENABLED.filterApp(mEntry)).isFalse();
+    }
+
+    @Test
+    public void testDisabledFilterRejectsInstantApp() {
+        mEntry.info.enabled = false;
+        assertThat(ApplicationsState.FILTER_DISABLED.filterApp(mEntry)).isTrue();
+        when(mEntry.info.isInstantApp()).thenReturn(true);
+        assertThat(ApplicationsState.FILTER_DISABLED.filterApp(mEntry)).isFalse();
+    }
 }
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawer/SettingsDrawerActivityTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawer/SettingsDrawerActivityTest.java
index 2fd5ec0..752b5b0 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawer/SettingsDrawerActivityTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawer/SettingsDrawerActivityTest.java
@@ -16,6 +16,7 @@
 
 package com.android.settingslib.drawer;
 
+import android.app.Activity;
 import android.app.Instrumentation;
 import android.content.Intent;
 import android.support.test.InstrumentationRegistry;
@@ -25,6 +26,8 @@
 
 import com.android.settingslib.R;
 
+import com.google.common.truth.Truth;
+
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -36,12 +39,12 @@
 import static android.support.test.espresso.assertion.ViewAssertions.matches;
 import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
 import static android.support.test.espresso.matcher.ViewMatchers.withContentDescription;
+import static com.google.common.truth.Truth.assertThat;
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class SettingsDrawerActivityTest {
 
-
     @Rule
     public ActivityTestRule<TestActivity> mActivityRule =
             new ActivityTestRule<>(TestActivity.class, true, true);
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 6481f4d..ec0190c 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
@@ -15,9 +15,8 @@
  */
 package com.android.settingslib.wifi;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
 
 import android.content.Context;
 import android.net.ConnectivityManager;
@@ -39,6 +38,7 @@
 import org.junit.runner.RunWith;
 
 import java.util.ArrayList;
+import java.util.Collections;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
@@ -59,12 +59,12 @@
         final AccessPoint ap = new AccessPoint(InstrumentationRegistry.getTargetContext(), bundle);
         final CharSequence ssid = ap.getSsid();
 
-        assertTrue(ssid instanceof SpannableString);
+        assertThat(ssid instanceof SpannableString).isTrue();
 
         TtsSpan[] spans = ((SpannableString) ssid).getSpans(0, TEST_SSID.length(), TtsSpan.class);
 
-        assertEquals(1, spans.length);
-        assertEquals(TtsSpan.TYPE_TELEPHONE, spans[0].getType());
+        assertThat(spans.length).isEqualTo(1);
+        assertThat(spans[0].getType()).isEqualTo(TtsSpan.TYPE_TELEPHONE);
     }
 
     @Test
@@ -80,11 +80,11 @@
         originalAccessPoint.update(configuration, wifiInfo, networkInfo);
         AccessPoint copy = new AccessPoint(mContext, originalAccessPoint);
 
-        assertEquals(originalAccessPoint.getSsid().toString(), copy.getSsid().toString());
-        assertEquals(originalAccessPoint.getBssid(), copy.getBssid());
-        assertSame(originalAccessPoint.getConfig(), copy.getConfig());
-        assertEquals(originalAccessPoint.getSecurity(), copy.getSecurity());
-        assertTrue(originalAccessPoint.compareTo(copy) == 0);
+        assertThat(originalAccessPoint.getSsid().toString()).isEqualTo(copy.getSsid().toString());
+        assertThat(originalAccessPoint.getBssid()).isEqualTo(copy.getBssid());
+        assertThat(originalAccessPoint.getConfig()).isEqualTo(copy.getConfig());
+        assertThat(originalAccessPoint.getSecurity()).isEqualTo(copy.getSecurity());
+        assertThat(originalAccessPoint.compareTo(copy) == 0).isTrue();
     }
 
     @Test
@@ -101,11 +101,93 @@
 
         bundle.putParcelableArrayList("key_scanresultcache", scanResults);
         AccessPoint original = new AccessPoint(mContext, bundle);
-        assertEquals(4, original.getRssi());
+        assertThat(original.getRssi()).isEqualTo(4);
         AccessPoint copy = new AccessPoint(mContext, createWifiConfiguration());
-        assertEquals(Integer.MIN_VALUE, copy.getRssi());
+        assertThat(copy.getRssi()).isEqualTo(Integer.MIN_VALUE);
         copy.copyFrom(original);
-        assertEquals(original.getRssi(), copy.getRssi());
+        assertThat(original.getRssi()).isEqualTo(copy.getRssi());
+    }
+
+    @Test
+    public void testCompareTo_GivesActiveBeforeInactive() {
+        AccessPoint activeAp = new TestAccessPointBuilder(mContext).setActive(true).build();
+        AccessPoint inactiveAp = new TestAccessPointBuilder(mContext).setActive(false).build();
+
+        assertSortingWorks(activeAp, inactiveAp);
+    }
+
+    @Test
+    public void testCompareTo_GivesReachableBeforeUnreachable() {
+        AccessPoint nearAp = new TestAccessPointBuilder(mContext).setReachable(true).build();
+        AccessPoint farAp = new TestAccessPointBuilder(mContext).setReachable(false).build();
+
+        assertSortingWorks(nearAp, farAp);
+    }
+
+    @Test
+    public void testCompareTo_GivesSavedBeforeUnsaved() {
+        AccessPoint savedAp = new TestAccessPointBuilder(mContext).setSaved(true).build();
+        AccessPoint notSavedAp = new TestAccessPointBuilder(mContext).setSaved(false).build();
+
+        assertSortingWorks(savedAp, notSavedAp);
+    }
+
+    //TODO: add tests for mRankingScore sort order if ranking is exposed
+
+    @Test
+    public void testCompareTo_GivesHighLevelBeforeLowLevel() {
+        final int highLevel = AccessPoint.SIGNAL_LEVELS - 1;
+        final int lowLevel = 1;
+        assertThat(highLevel).isGreaterThan(lowLevel);
+
+        AccessPoint strongAp = new TestAccessPointBuilder(mContext).setLevel(highLevel).build();
+        AccessPoint weakAp = new TestAccessPointBuilder(mContext).setLevel(lowLevel).build();
+
+        assertSortingWorks(strongAp, weakAp);
+    }
+
+    @Test
+    public void testCompareTo_GivesSsidAlphabetically() {
+
+        final String firstName = "AAAAAA";
+        final String secondName = "zzzzzz";
+
+        AccessPoint firstAp = new TestAccessPointBuilder(mContext).setSsid(firstName).build();
+        AccessPoint secondAp = new TestAccessPointBuilder(mContext).setSsid(secondName).build();
+
+        assertThat(firstAp.getSsidStr().compareToIgnoreCase(secondAp.getSsidStr()) < 0).isTrue();
+        assertSortingWorks(firstAp, secondAp);
+    }
+
+    @Test
+    public void testCompareTo_AllSortingRulesCombined() {
+
+        AccessPoint active = new TestAccessPointBuilder(mContext).setActive(true).build();
+        AccessPoint reachableAndMinLevel = new TestAccessPointBuilder(mContext)
+                .setReachable(true).build();
+        AccessPoint saved = new TestAccessPointBuilder(mContext).setSaved(true).build();
+        AccessPoint highLevelAndReachable = new TestAccessPointBuilder(mContext)
+                .setLevel(AccessPoint.SIGNAL_LEVELS - 1).build();
+        AccessPoint firstName = new TestAccessPointBuilder(mContext).setSsid("a").build();
+        AccessPoint lastname = new TestAccessPointBuilder(mContext).setSsid("z").build();
+
+        ArrayList<AccessPoint> points = new ArrayList<AccessPoint>();
+        points.add(lastname);
+        points.add(firstName);
+        points.add(highLevelAndReachable);
+        points.add(saved);
+        points.add(reachableAndMinLevel);
+        points.add(active);
+
+        Collections.sort(points);
+        assertThat(points.indexOf(active)).isLessThan(points.indexOf(reachableAndMinLevel));
+        assertThat(points.indexOf(reachableAndMinLevel)).isLessThan(points.indexOf(saved));
+        // note: the saved AP will not appear before highLevelAndReachable,
+        // because all APs with a signal level are reachable,
+        // and isReachable() takes higher sorting precedence than isSaved().
+        assertThat(points.indexOf(saved)).isLessThan(points.indexOf(firstName));
+        assertThat(points.indexOf(highLevelAndReachable)).isLessThan(points.indexOf(firstName));
+        assertThat(points.indexOf(firstName)).isLessThan(points.indexOf(lastname));
     }
 
     private WifiConfiguration createWifiConfiguration() {
@@ -115,4 +197,85 @@
         configuration.networkId = 123;
         return configuration;
     }
+
+    /**
+    * Assert that the first AccessPoint appears after the second AccessPoint
+    * once sorting has been completed.
+    */
+    private void assertSortingWorks(AccessPoint first, AccessPoint second) {
+
+        ArrayList<AccessPoint> points = new ArrayList<AccessPoint>();
+
+        // add in reverse order so we can tell that sorting actually changed something
+        points.add(second);
+        points.add(first);
+        Collections.sort(points);
+        assertWithMessage(
+                String.format("After sorting: second AccessPoint should have higher array index "
+                    + "than the first, but found indicies second '%s' and first '%s'.",
+                    points.indexOf(second), points.indexOf(first)))
+            .that(points.indexOf(second)).isGreaterThan(points.indexOf(first));
+    }
+
+    @Test
+    public void testBuilder_setActive() {
+        AccessPoint activeAp = new TestAccessPointBuilder(mContext).setActive(true).build();
+        assertThat(activeAp.isActive()).isTrue();
+
+        AccessPoint inactiveAp = new TestAccessPointBuilder(mContext).setActive(false).build();
+        assertThat(inactiveAp.isActive()).isFalse();
+    }
+
+    @Test
+    public void testBuilder_setReachable() {
+        AccessPoint nearAp = new TestAccessPointBuilder(mContext).setReachable(true).build();
+        assertThat(nearAp.isReachable()).isTrue();
+
+        AccessPoint farAp = new TestAccessPointBuilder(mContext).setReachable(false).build();
+        assertThat(farAp.isReachable()).isFalse();
+    }
+
+    @Test
+    public void testBuilder_setSaved() {
+        AccessPoint savedAp = new TestAccessPointBuilder(mContext).setSaved(true).build();
+        assertThat(savedAp.isSaved()).isTrue();
+
+        AccessPoint newAp = new TestAccessPointBuilder(mContext).setSaved(false).build();
+        assertThat(newAp.isSaved()).isFalse();
+    }
+
+    @Test
+    public void testBuilder_setLevel() {
+        AccessPoint testAp;
+
+        for (int i = 0; i < AccessPoint.SIGNAL_LEVELS; i++) {
+            testAp = new TestAccessPointBuilder(mContext).setLevel(i).build();
+            assertThat(testAp.getLevel()).isEqualTo(i);
+        }
+
+        // numbers larger than the max level should be set to max
+        testAp = new TestAccessPointBuilder(mContext).setLevel(AccessPoint.SIGNAL_LEVELS).build();
+        assertThat(testAp.getLevel()).isEqualTo(AccessPoint.SIGNAL_LEVELS - 1);
+
+        // numbers less than 0 should give level 0
+        testAp = new TestAccessPointBuilder(mContext).setLevel(-100).build();
+        assertThat(testAp.getLevel()).isEqualTo(0);
+    }
+
+    @Test
+    public void testBuilder_settingReachableAfterLevelDoesNotAffectLevel() {
+        int level = 1;
+        assertThat(level).isLessThan(AccessPoint.SIGNAL_LEVELS - 1);
+
+        AccessPoint testAp =
+                new TestAccessPointBuilder(mContext).setLevel(level).setReachable(true).build();
+        assertThat(testAp.getLevel()).isEqualTo(level);
+    }
+
+    @Test
+    public void testBuilder_setSsid() {
+        String name = "AmazingSsid!";
+        AccessPoint namedAp = new TestAccessPointBuilder(mContext).setSsid(name).build();
+        assertThat(namedAp.getSsidStr()).isEqualTo(name);
+    }
 }
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/TestAccessPointBuilder.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/TestAccessPointBuilder.java
new file mode 100644
index 0000000..665c439
--- /dev/null
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/TestAccessPointBuilder.java
@@ -0,0 +1,128 @@
+/*
+ * 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.settingslib.wifi;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.wifi.WifiConfiguration;
+import android.os.Bundle;
+
+/**
+* Build and return a valid AccessPoint.
+*
+* Only intended for testing the AccessPoint class;
+* AccessPoints were designed to only be populated
+* by the mechanisms of scan results and wifi configurations.
+*/
+public class TestAccessPointBuilder {
+    // match the private values in WifiManager
+    private static final int MIN_RSSI = -100;
+    private static final int MAX_RSSI = -55;
+
+    // set some sensible defaults
+    private int mRssi = AccessPoint.UNREACHABLE_RSSI;
+    private int networkId = WifiConfiguration.INVALID_NETWORK_ID;
+    private String ssid = "TestSsid";
+    private NetworkInfo mNetworkInfo = null;
+
+    Context mContext;
+
+    public TestAccessPointBuilder(Context context) {
+        mContext = context;
+    }
+
+    public AccessPoint build() {
+        Bundle bundle = new Bundle();
+
+        WifiConfiguration wifiConig = new WifiConfiguration();
+        wifiConig.networkId = networkId;
+
+        bundle.putString(AccessPoint.KEY_SSID, ssid);
+        bundle.putParcelable(AccessPoint.KEY_CONFIG, wifiConig);
+        bundle.putParcelable(AccessPoint.KEY_NETWORKINFO, mNetworkInfo);
+        AccessPoint ap = new AccessPoint(mContext, bundle);
+        ap.setRssi(mRssi);
+        return ap;
+    }
+
+    public TestAccessPointBuilder setActive(boolean active) {
+        if (active) {
+            mNetworkInfo = new NetworkInfo(
+                ConnectivityManager.TYPE_DUMMY,
+                ConnectivityManager.TYPE_DUMMY,
+                "TestNetwork",
+                "TestNetwork");
+        } else {
+            mNetworkInfo = null;
+        }
+        return this;
+    }
+
+    /**
+    * Set the signal level.
+    * Side effect: if this AccessPoint was previously unreachable,
+    * setting the level will also make it reachable.
+    */
+    public TestAccessPointBuilder setLevel(int level) {
+        int outputRange = AccessPoint.SIGNAL_LEVELS - 1;
+
+        if (level > outputRange) {
+            level = outputRange;
+        } else if (level < 0) {
+            level = 0;
+        }
+
+        int inputRange = MAX_RSSI - MIN_RSSI;
+
+        // calculate the rssi required to get the level we want.
+        // this is a rearrangement of the formula from WifiManager.calculateSignalLevel()
+        mRssi = (int)((float)(level * inputRange) / (float)outputRange) + MIN_RSSI;
+        return this;
+    }
+
+    /**
+    * Set whether the AccessPoint is reachable.
+    * Side effect: if the signal level was not previously set,
+    * making an AccessPoint reachable will set the signal to the minimum level.
+    */
+    public TestAccessPointBuilder setReachable(boolean reachable) {
+        if (reachable) {
+            // only override the mRssi if it hasn't been set yet
+            if (mRssi == AccessPoint.UNREACHABLE_RSSI) {
+                mRssi = MIN_RSSI;
+            }
+        } else {
+            mRssi = AccessPoint.UNREACHABLE_RSSI;
+        }
+        return this;
+    }
+
+    public TestAccessPointBuilder setSaved(boolean saved){
+        if (saved) {
+             networkId = 1;
+        } else {
+             networkId = WifiConfiguration.INVALID_NETWORK_ID;
+        }
+        return this;
+    }
+
+    public TestAccessPointBuilder setSsid(String newSsid) {
+        ssid = newSsid;
+        return this;
+    }
+}
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
index 0f220aa..e100884 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
@@ -15,6 +15,8 @@
  */
 package com.android.settingslib.wifi;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
@@ -27,6 +29,8 @@
 import android.content.Context;
 import android.content.Intent;
 import android.net.ConnectivityManager;
+import android.net.NetworkBadging;
+import android.net.NetworkInfo;
 import android.net.NetworkKey;
 import android.net.NetworkScoreManager;
 import android.net.ScoredNetwork;
@@ -34,6 +38,7 @@
 import android.net.WifiKey;
 import android.net.wifi.ScanResult;
 import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.net.wifi.WifiNetworkScoreCache;
 import android.net.wifi.WifiSsid;
@@ -67,6 +72,8 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
+// TODO(sghuman): Change these to robolectric tests b/35766684.
+
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class WifiTrackerTest {
@@ -80,7 +87,7 @@
             new NetworkKey(new WifiKey('"' + SSID_1 + '"', BSSID_1));
     private static final int RSSI_1 = -30;
     private static final byte SCORE_1 = 10;
-    private static final int BADGE_1 = ScoredNetwork.BADGING_SD;
+    private static final int BADGE_1 = NetworkBadging.BADGING_SD;
 
     private static final String SSID_2 = "ssid2";
     private static final String BSSID_2 = "AA:AA:AA:AA:AA:AA";
@@ -88,7 +95,7 @@
             new NetworkKey(new WifiKey('"' + SSID_2 + '"', BSSID_2));
     private static final int RSSI_2 = -30;
     private static final byte SCORE_2 = 15;
-    private static final int BADGE_2 = ScoredNetwork.BADGING_HD;
+    private static final int BADGE_2 = NetworkBadging.BADGING_HD;
 
     @Captor ArgumentCaptor<WifiNetworkScoreCache> mScoreCacheCaptor;
     @Mock private ConnectivityManager mockConnectivityManager;
@@ -114,9 +121,10 @@
 
     @Before
     public void setUp() {
-        mContext = InstrumentationRegistry.getTargetContext();
         MockitoAnnotations.initMocks(this);
 
+        mContext = InstrumentationRegistry.getTargetContext();
+
         mWorkerThread = new HandlerThread("TestHandlerWorkerThread");
         mWorkerThread.start();
         mLooper = mWorkerThread.getLooper();
@@ -220,9 +228,15 @@
                 SystemClock.elapsedRealtime() * 1000 /* microsecond timestamp */);
     }
 
-    private WifiTracker createTrackerAndInjectInitialScanResults() throws InterruptedException {
+    private WifiTracker createTrackerWithImmediateBroadcastsAndInjectInitialScanResults(
+                    Intent ... intents)
+            throws InterruptedException {
         WifiTracker tracker = createMockedWifiTracker();
+
         startTracking(tracker);
+        for (Intent intent : intents) {
+            tracker.mReceiver.onReceive(mContext, intent);
+        }
 
         mAccessPointsChangedLatch = new CountDownLatch(1);
         sendScanResultsAndProcess(tracker);
@@ -234,16 +248,16 @@
     private WifiTracker createMockedWifiTracker() {
         WifiTracker tracker =
                 new WifiTracker(
-                    mContext,
-                    mockWifiListener,
-                    mLooper,
-                    true,
-                    true,
-                    true,
-                    mockWifiManager,
-                    mockConnectivityManager,
-                    mockNetworkScoreManager,
-                    mMainLooper
+                        mContext,
+                        mockWifiListener,
+                        mLooper,
+                        true,
+                        true,
+                        true,
+                        mockWifiManager,
+                        mockConnectivityManager,
+                        mockNetworkScoreManager,
+                        mMainLooper
                 );
 
         return tracker;
@@ -293,6 +307,31 @@
         scoreCache.updateScores(Arrays.asList(sc1, sc2));
     }
 
+    private WifiTracker createTrackerWithScanResultsAndAccessPoint1Connected()
+            throws InterruptedException {
+        int networkId = 123;
+
+        WifiInfo wifiInfo = new WifiInfo();
+        wifiInfo.setSSID(WifiSsid.createFromAsciiEncoded(SSID_1));
+        wifiInfo.setBSSID(BSSID_1);
+        wifiInfo.setNetworkId(networkId);
+        when(mockWifiManager.getConnectionInfo()).thenReturn(wifiInfo);
+
+        WifiConfiguration configuration = new WifiConfiguration();
+        configuration.SSID = SSID_1;
+        configuration.BSSID = BSSID_1;
+        configuration.networkId = networkId;
+        when(mockWifiManager.getConfiguredNetworks()).thenReturn(Arrays.asList(configuration));
+
+        NetworkInfo networkInfo = new NetworkInfo(
+                ConnectivityManager.TYPE_WIFI, 0, "Type Wifi", "subtype");
+        networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "connected", "test");
+
+        Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+        intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, networkInfo);
+        return createTrackerWithImmediateBroadcastsAndInjectInitialScanResults(intent);
+    }
+
     @Test
     public void testAccessPointListenerSetWhenLookingUpUsingScanResults() {
         ScanResult scanResult = new ScanResult();
@@ -356,12 +395,21 @@
     }
 
     @Test
+    public void startTrackingShouldSetConnectedAccessPointAsActive() throws InterruptedException {
+        WifiTracker tracker =  createTrackerWithScanResultsAndAccessPoint1Connected();
+
+        List<AccessPoint> aps = tracker.getAccessPoints();
+
+        assertThat(aps).hasSize(2);
+        assertThat(aps.get(0).isActive()).isTrue();
+    }
+
+    @Test
     public void startTrackingShouldRequestScoresForCurrentAccessPoints() throws InterruptedException {
         // Start the tracker and inject the initial scan results and then stop tracking
-        WifiTracker tracker =  createTrackerAndInjectInitialScanResults();
+        WifiTracker tracker =  createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
 
         tracker.stopTracking();
-        android.util.Log.d("WifiTrackerTest", "Clearing previously captured requested keys");
         mRequestedKeys.clear();
 
         mRequestScoresLatch = new CountDownLatch(1);
@@ -369,7 +417,6 @@
         assertTrue("Latch timed out",
                 mRequestScoresLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
 
-        android.util.Log.d("WifiTrackerTest", "requested keys: " + mRequestedKeys);
         assertTrue(mRequestedKeys.contains(NETWORK_KEY_1));
         assertTrue(mRequestedKeys.contains(NETWORK_KEY_2));
     }
@@ -393,7 +440,7 @@
 
     @Test
     public void scoreCacheUpdateScoresShouldChangeSortOrder() throws InterruptedException {
-        WifiTracker tracker = createTrackerAndInjectInitialScanResults();
+        WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
         List<AccessPoint> aps = tracker.getAccessPoints();
         assertTrue(aps.size() == 2);
         assertEquals(aps.get(0).getSsidStr(), SSID_1);
@@ -415,7 +462,7 @@
                 Settings.Global.NETWORK_SCORING_UI_ENABLED,
                 0 /* disabled */);
 
-        WifiTracker tracker = createTrackerAndInjectInitialScanResults();
+        WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
         List<AccessPoint> aps = tracker.getAccessPoints();
         assertTrue(aps.size() == 2);
         assertEquals(aps.get(0).getSsidStr(), SSID_1);
@@ -431,7 +478,7 @@
 
     @Test
     public void scoreCacheUpdateScoresShouldInsertBadgeIntoAccessPoint() throws InterruptedException {
-        WifiTracker tracker = createTrackerAndInjectInitialScanResults();
+        WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
         updateScoresAndWaitForAccessPointsChangedCallback();
 
         List<AccessPoint> aps = tracker.getAccessPoints();
@@ -453,16 +500,16 @@
                 Settings.Global.NETWORK_SCORING_UI_ENABLED,
                 0 /* disabled */);
 
-        WifiTracker tracker = createTrackerAndInjectInitialScanResults();
+        WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
         updateScoresAndWaitForAccessPointsChangedCallback();
 
         List<AccessPoint> aps = tracker.getAccessPoints();
 
         for (AccessPoint ap : aps) {
             if (ap.getSsidStr().equals(SSID_1)) {
-                assertEquals(ScoredNetwork.BADGING_NONE, ap.getBadge());
+                assertEquals(NetworkBadging.BADGING_NONE, ap.getBadge());
             } else if (ap.getSsidStr().equals(SSID_2)) {
-                assertEquals(ScoredNetwork.BADGING_NONE, ap.getBadge());
+                assertEquals(NetworkBadging.BADGING_NONE, ap.getBadge());
             }
         }
     }
@@ -472,7 +519,7 @@
         // Scores can be requested together or serially depending on how the scan results are
         // processed.
         mRequestScoresLatch = new CountDownLatch(2);
-        WifiTracker tracker = createTrackerAndInjectInitialScanResults();
+        WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
         mRequestScoresLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
         mRequestedKeys.clear();
 
@@ -502,7 +549,7 @@
     @Test
     public void scoreCacheAndListenerShouldBeUnregisteredWhenStopTrackingIsCalled() throws Exception
     {
-        WifiTracker tracker =  createTrackerAndInjectInitialScanResults();
+        WifiTracker tracker =  createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
         WifiNetworkScoreCache cache = mScoreCacheCaptor.getValue();
 
         tracker.stopTracking();
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/BatteryInfoTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/BatteryInfoTest.java
new file mode 100644
index 0000000..1364958
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/BatteryInfoTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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.settingslib;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.BatteryManager;
+import android.os.BatteryStats;
+import android.os.SystemClock;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.when;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class BatteryInfoTest {
+    private static final String STATUS_FULL = "Full";
+    private Intent mBatteryBroadcast;
+    @Mock
+    private BatteryStats mBatteryStats;
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private Context mContext;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mBatteryBroadcast = new Intent();
+        mBatteryBroadcast.putExtra(BatteryManager.EXTRA_PLUGGED, 0);
+        mBatteryBroadcast.putExtra(BatteryManager.EXTRA_LEVEL, 0);
+        mBatteryBroadcast.putExtra(BatteryManager.EXTRA_SCALE, 100);
+        mBatteryBroadcast.putExtra(BatteryManager.EXTRA_STATUS, BatteryManager.BATTERY_STATUS_FULL);
+
+        when(mContext.getResources().getString(R.string.battery_info_status_full))
+                .thenReturn(STATUS_FULL);
+    }
+
+    @Test
+    public void testGetBatteryInfo_HasStatusLabel() {
+        BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mBatteryBroadcast, mBatteryStats,
+                SystemClock.elapsedRealtime() * 1000, true);
+
+        assertThat(info.statusLabel).isEqualTo(STATUS_FULL);
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/HelpUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/HelpUtilsTest.java
index 5d843c1..56891f6 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/HelpUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/HelpUtilsTest.java
@@ -16,10 +16,18 @@
 
 package com.android.settingslib;
 
+import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
+import android.provider.Settings;
+import android.view.MenuItem;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -27,11 +35,14 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 
 import static com.google.common.truth.Truth.assertThat;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 /**
@@ -40,6 +51,7 @@
 @RunWith(RobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class HelpUtilsTest {
+    private static final String TEST_HELP_URL = "intent:#Intent;action=com.android.test;end";
     private static final String PACKAGE_NAME_KEY = "package-name-key";
     private static final String PACKAGE_NAME_VALUE = "package-name-value";
     private static final String HELP_INTENT_EXTRA_KEY = "help-intent-extra";
@@ -49,6 +61,11 @@
 
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private Context mContext;
+    @Mock
+    private Activity mActivity;
+    @Mock
+    private PackageManager mPackageManager;
+
 
     @Before
     public void setUp() {
@@ -65,6 +82,8 @@
                 .thenReturn(FEEDBACK_INTENT_EXTRA_KEY);
         when(mContext.getResources().getString(R.string.config_feedbackIntentNameKey))
                 .thenReturn(FEEDBACK_INTENT_NAME_KEY);
+        when(mActivity.getPackageManager()).thenReturn(mPackageManager);
+
 
     }
 
@@ -127,4 +146,31 @@
         assertThat(intent.hasExtra(FEEDBACK_INTENT_EXTRA_KEY)).isFalse();
         assertThat(intent.hasExtra(FEEDBACK_INTENT_NAME_KEY)).isFalse();
     }
-}
+
+    @Test
+    public void prepareHelpMenuItem_shouldShowIcon() {
+        Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(),
+                Settings.Global.DEVICE_PROVISIONED, 1);
+        final Resources res = mock(Resources.class);
+        final ResolveInfo resolveInfo = new ResolveInfo();
+        resolveInfo.activityInfo = new ActivityInfo();
+        resolveInfo.activityInfo.applicationInfo = new ApplicationInfo();
+        resolveInfo.activityInfo.applicationInfo.packageName = "pkg";
+        resolveInfo.activityInfo.name = "name";
+        final MenuItem item = mock(MenuItem.class);
+
+
+        when(mActivity.getContentResolver())
+                .thenReturn(RuntimeEnvironment.application.getContentResolver());
+        when(mActivity.getResources()).thenReturn(res);
+        when(mActivity.obtainStyledAttributes(any(int[].class)))
+                .thenReturn(mock(TypedArray.class));
+        when(mPackageManager.resolveActivity(any(Intent.class), anyInt()))
+                .thenReturn(resolveInfo);
+
+        HelpUtils.prepareHelpMenuItem(mActivity, item, TEST_HELP_URL, "backup_url");
+
+        verify(item).setVisible(true);
+        verify(item).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
+    }
+}
\ No newline at end of file
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java
index 2958740..c506358 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java
@@ -16,6 +16,17 @@
 
 package com.android.settingslib;
 
+import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE;
+import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT;
+import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_REMOTE_INPUT;
+import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS;
+import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.when;
+
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
 import android.content.Context;
@@ -25,18 +36,13 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Answers;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.annotation.Config;
 
 import java.util.Arrays;
 
-import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT;
-import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_REMOTE_INPUT;
-import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.when;
-
 @RunWith(SettingLibRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class RestrictedLockUtilsTest {
@@ -47,8 +53,11 @@
     private DevicePolicyManager mDevicePolicyManager;
     @Mock
     private UserManager mUserManager;
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private RestrictedLockUtils.Proxy mProxy;
 
     private static final int mUserId = 194;
+    private static final int mProfileId = 160;
     private static final ComponentName mAdmin1 = new ComponentName("admin1", "admin1class");
     private static final ComponentName mAdmin2 = new ComponentName("admin2", "admin2class");
 
@@ -60,12 +69,13 @@
                 .thenReturn(mDevicePolicyManager);
         when(mContext.getSystemService(Context.USER_SERVICE))
                 .thenReturn(mUserManager);
+
+        RestrictedLockUtils.sProxy = mProxy;
     }
 
     @Test
     public void checkIfKeyguardFeaturesDisabled_noEnforcedAdminForManagedProfile() {
-        setUpManagedProfile(mUserId);
-        setUpActiveAdmins(mUserId, new ComponentName[] {mAdmin1, mAdmin2});
+        setUpManagedProfile(mUserId, new ComponentName[] {mAdmin1, mAdmin2});
 
         final EnforcedAdmin enforcedAdmin = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
                 mContext, KEYGUARD_DISABLE_FINGERPRINT, mUserId);
@@ -75,8 +85,7 @@
 
     @Test
     public void checkIfKeyguardFeaturesDisabled_oneEnforcedAdminForManagedProfile() {
-        setUpManagedProfile(mUserId);
-        setUpActiveAdmins(mUserId, new ComponentName[] {mAdmin1, mAdmin2});
+        setUpManagedProfile(mUserId, new ComponentName[] {mAdmin1, mAdmin2});
 
         when(mDevicePolicyManager.getKeyguardDisabledFeatures(mAdmin1, mUserId))
                 .thenReturn(KEYGUARD_DISABLE_FINGERPRINT);
@@ -89,8 +98,7 @@
 
     @Test
     public void checkIfKeyguardFeaturesDisabled_multipleEnforcedAdminForManagedProfile() {
-        setUpManagedProfile(mUserId);
-        setUpActiveAdmins(mUserId, new ComponentName[] {mAdmin1, mAdmin2});
+        setUpManagedProfile(mUserId, new ComponentName[] {mAdmin1, mAdmin2});
 
         when(mDevicePolicyManager.getKeyguardDisabledFeatures(mAdmin1, mUserId))
                 .thenReturn(KEYGUARD_DISABLE_REMOTE_INPUT);
@@ -103,9 +111,129 @@
         assertThat(enforcedAdmin).isEqualTo(EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN);
     }
 
-    private UserInfo setUpManagedProfile(int userId) {
-        final UserInfo userInfo = new UserInfo(userId, "myuser", UserInfo.FLAG_MANAGED_PROFILE);
+    @Test
+    public void checkIfKeyguardFeaturesAreDisabled_doesMatchAllowedFeature_unifiedManagedProfile() {
+        UserInfo userInfo = setUpUser(mUserId, new ComponentName[] {mAdmin1});
+        UserInfo profileInfo = setUpManagedProfile(mProfileId, new ComponentName[] {mAdmin2});
+        when(mUserManager.getProfiles(mUserId)).thenReturn(Arrays.asList(new UserInfo[] {
+                userInfo, profileInfo}));
+
+        when(mDevicePolicyManager.getKeyguardDisabledFeatures(mAdmin1, mUserId))
+                .thenReturn(KEYGUARD_DISABLE_FEATURES_NONE);
+        when(mDevicePolicyManager.getKeyguardDisabledFeatures(mAdmin2, mProfileId))
+                .thenReturn(KEYGUARD_DISABLE_FINGERPRINT);
+
+        // Querying the parent should return the policy, since it affects the parent.
+        EnforcedAdmin parent = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+                mContext, KEYGUARD_DISABLE_FINGERPRINT, mUserId);
+        assertThat(parent).isEqualTo(new EnforcedAdmin(mAdmin2, mProfileId));
+
+        // Querying the child should return that too.
+        EnforcedAdmin profile = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+                mContext, KEYGUARD_DISABLE_FINGERPRINT, mProfileId);
+        assertThat(profile).isEqualTo(new EnforcedAdmin(mAdmin2, mProfileId));
+
+        // Querying for some unrelated feature should return nothing. Nothing!
+        assertThat(RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+                mContext, KEYGUARD_DISABLE_REMOTE_INPUT, mUserId)).isNull();
+        assertThat(RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+                mContext, KEYGUARD_DISABLE_REMOTE_INPUT, mProfileId)).isNull();
+    }
+
+    @Test
+    public void checkIfKeyguardFeaturesAreDisabled_notMatchOtherFeatures_unifiedManagedProfile() {
+        UserInfo userInfo = setUpUser(mUserId, new ComponentName[] {mAdmin1});
+        UserInfo profileInfo = setUpManagedProfile(mProfileId, new ComponentName[] {mAdmin2});
+        when(mUserManager.getProfiles(mUserId)).thenReturn(Arrays.asList(new UserInfo[] {
+                userInfo, profileInfo}));
+
+        when(mDevicePolicyManager.getKeyguardDisabledFeatures(mAdmin1, mUserId))
+                .thenReturn(KEYGUARD_DISABLE_FEATURES_NONE);
+        when(mDevicePolicyManager.getKeyguardDisabledFeatures(mAdmin2, mProfileId))
+                .thenReturn(KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
+
+        // Querying the parent should not return the policy, because it's not a policy that should
+        // affect parents even when the lock screen is unified.
+        EnforcedAdmin primary = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+                mContext, KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS, mUserId);
+        assertThat(primary).isNull();
+
+        // Querying the child should still return the policy.
+        EnforcedAdmin profile = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+                mContext, KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS, mProfileId);
+        assertThat(profile).isEqualTo(new EnforcedAdmin(mAdmin2, mProfileId));
+    }
+
+    @Test
+    public void checkIfKeyguardFeaturesAreDisabled_onlyMatchesProfile_separateManagedProfile() {
+        UserInfo userInfo = setUpUser(mUserId, new ComponentName[] {mAdmin1});
+        UserInfo profileInfo = setUpManagedProfile(mProfileId, new ComponentName[] {mAdmin2});
+        when(mUserManager.getProfiles(mUserId)).thenReturn(Arrays.asList(new UserInfo[] {
+                userInfo, profileInfo}));
+
+        when(mDevicePolicyManager.getKeyguardDisabledFeatures(mAdmin1, mUserId))
+                .thenReturn(KEYGUARD_DISABLE_FEATURES_NONE);
+        when(mDevicePolicyManager.getKeyguardDisabledFeatures(mAdmin2, mProfileId))
+                .thenReturn(KEYGUARD_DISABLE_FINGERPRINT);
+
+        // Crucially for this test, isSeparateWorkChallengeEnabled => true.
+        doReturn(true).when(mProxy).isSeparateProfileChallengeEnabled(any(), eq(mProfileId));
+
+        // Querying the parent should not return the policy, even though it's shared by default,
+        // because the parent doesn't share a lock screen with the profile any more.
+        EnforcedAdmin parent = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+                mContext, KEYGUARD_DISABLE_FINGERPRINT, mUserId);
+        assertThat(parent).isNull();
+
+        // Querying the child should still return the policy.
+        EnforcedAdmin profile = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+                mContext, KEYGUARD_DISABLE_FINGERPRINT, mProfileId);
+        assertThat(profile).isEqualTo(new EnforcedAdmin(mAdmin2, mProfileId));
+    }
+
+    /**
+     * This test works great. The real world implementation is sketchy though.
+     * <p>
+     * DevicePolicyManager.getParentProfileInstance(UserInfo) does not do what it looks like it does
+     * (which would be to get an instance for the parent of the user that's passed in to it.)
+     * <p>
+     * Instead it just always returns a parent instance for the current user.
+     * <p>
+     * Still, the test works.
+     */
+    @Test
+    public void checkIfKeyguardFeaturesAreDisabled_onlyMatchesParent_profileParentPolicy() {
+        UserInfo userInfo = setUpUser(mUserId, new ComponentName[] {mAdmin1});
+        UserInfo profileInfo = setUpManagedProfile(mProfileId, new ComponentName[] {mAdmin2});
+        when(mUserManager.getProfiles(mUserId)).thenReturn(Arrays.asList(new UserInfo[] {
+                userInfo, profileInfo}));
+
+        when(mProxy.getParentProfileInstance(any(DevicePolicyManager.class), any())
+                .getKeyguardDisabledFeatures(mAdmin2, mProfileId))
+                .thenReturn(KEYGUARD_DISABLE_FINGERPRINT);
+
+        // Parent should get the policy.
+        EnforcedAdmin parent = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+                mContext, KEYGUARD_DISABLE_FINGERPRINT, mUserId);
+        assertThat(parent).isEqualTo(new EnforcedAdmin(mAdmin2, mProfileId));
+
+        // Profile should not get the policy.
+        EnforcedAdmin profile = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
+                mContext, KEYGUARD_DISABLE_FINGERPRINT, mProfileId);
+        assertThat(profile).isNull();
+    }
+
+    private UserInfo setUpUser(int userId, ComponentName[] admins) {
+        UserInfo userInfo = new UserInfo(userId, "primary", 0);
         when(mUserManager.getUserInfo(userId)).thenReturn(userInfo);
+        setUpActiveAdmins(userId, admins);
+        return userInfo;
+    }
+
+    private UserInfo setUpManagedProfile(int userId, ComponentName[] admins) {
+        UserInfo userInfo = new UserInfo(userId, "profile", UserInfo.FLAG_MANAGED_PROFILE);
+        when(mUserManager.getUserInfo(userId)).thenReturn(userInfo);
+        setUpActiveAdmins(userId, admins);
         return userInfo;
     }
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SettingLibRobolectricTestRunner.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SettingLibRobolectricTestRunner.java
index 11c925e..fd3b1dc6 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SettingLibRobolectricTestRunner.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SettingLibRobolectricTestRunner.java
@@ -20,9 +20,6 @@
 import org.robolectric.annotation.Config;
 import org.robolectric.manifest.AndroidManifest;
 import org.robolectric.res.Fs;
-import org.robolectric.res.ResourcePath;
-
-import java.util.List;
 
 public class SettingLibRobolectricTestRunner extends RobolectricTestRunner {
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
new file mode 100644
index 0000000..e42c35b
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.settingslib;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+import static com.google.common.truth.Truth.assertThat;
+
+@RunWith(SettingLibRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class UtilsTest {
+    private static final double[] TEST_PERCENTAGES = {0, 0.4, 0.5, 0.6, 49, 49.3, 49.8, 50, 100};
+    private static final String PERCENTAGE_0 = "0%";
+    private static final String PERCENTAGE_1 = "1%";
+    private static final String PERCENTAGE_49 = "49%";
+    private static final String PERCENTAGE_50 = "50%";
+    private static final String PERCENTAGE_100 = "100%";
+
+    @Test
+    public void testFormatPercentage_RoundTrue_RoundUpIfPossible() {
+        final String[] expectedPercentages = {PERCENTAGE_0, PERCENTAGE_0, PERCENTAGE_1,
+                PERCENTAGE_1, PERCENTAGE_49, PERCENTAGE_49, PERCENTAGE_50, PERCENTAGE_50,
+                PERCENTAGE_100};
+
+        for (int i = 0, size = TEST_PERCENTAGES.length; i < size; i++) {
+            final String percentage = Utils.formatPercentage(TEST_PERCENTAGES[i], true);
+            assertThat(percentage).isEqualTo(expectedPercentages[i]);
+        }
+    }
+
+    @Test
+    public void testFormatPercentage_RoundFalse_NoRound() {
+        final String[] expectedPercentages = {PERCENTAGE_0, PERCENTAGE_0, PERCENTAGE_0,
+                PERCENTAGE_0, PERCENTAGE_49, PERCENTAGE_49, PERCENTAGE_49, PERCENTAGE_50,
+                PERCENTAGE_100};
+
+        for (int i = 0, size = TEST_PERCENTAGES.length; i < size; i++) {
+            final String percentage = Utils.formatPercentage(TEST_PERCENTAGES[i], false);
+            assertThat(percentage).isEqualTo(expectedPercentages[i]);
+        }
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryManagerTest.java
index 573ec1f0..434241d 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryManagerTest.java
@@ -21,12 +21,12 @@
 import android.content.Intent;
 import android.util.Pair;
 
+import com.android.settingslib.SettingLibRobolectricTestRunner;
 import com.android.settingslib.TestConfig;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
 import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowApplication;
 
@@ -35,7 +35,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-@RunWith(RobolectricTestRunner.class)
+@RunWith(SettingLibRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class CategoryManagerTest {
 
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 1683901..2d3c4a7 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
@@ -282,26 +282,11 @@
         when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt()))
                 .thenReturn(info);
 
-        Bundle bundle = new Bundle();
-        bundle.putInt("com.android.settings.icon", 161803);
-        bundle.putString("com.android.settings.icon_package", "abc");
-        bundle.putString("com.android.settings.summary", "dynamic-summary");
-        when(mIContentProvider.call(anyString(),
-                eq(TileUtils.getMethodFromUri(Uri.parse(URI_GET_ICON))), eq(URI_GET_ICON), any()))
-                .thenReturn(bundle);
-        when(mIContentProvider.call(anyString(),
-                eq(TileUtils.getMethodFromUri(Uri.parse(URI_GET_SUMMARY))), eq(URI_GET_SUMMARY),
-                any())).thenReturn(bundle);
-        when(mContentResolver.acquireProvider(anyString())).thenReturn(mIContentProvider);
-        when(mContentResolver.acquireProvider(any(Uri.class))).thenReturn(mIContentProvider);
-
         TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
                 null /* defaultCategory */, outTiles, false /* usePriority */,
                 false /* checkCategory */);
 
         assertThat(outTiles.size()).isEqualTo(1);
-        assertThat(outTiles.get(0).icon.getResId()).isEqualTo(161803);
-        assertThat(outTiles.get(0).summary).isEqualTo("dynamic-summary");
     }
 
     public static ResolveInfo newInfo(boolean systemApp, String category) {
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 136f17e..14bb02d 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -38,7 +38,7 @@
 
     <bool name="def_bluetooth_on">true</bool>
     <bool name="def_wifi_display_on">false</bool>
-    <bool name="def_install_non_market_apps">true</bool>
+    <bool name="def_install_non_market_apps">false</bool>
     <bool name="def_package_verifier_enable">true</bool>
     <!-- Comma-separated list of location providers.
          Network location is off by default because it requires
@@ -98,7 +98,7 @@
     <bool name="def_accessibility_script_injection">false</bool>
 
     <!-- Default for Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD -->
-    <bool name="def_accessibility_speak_password">false</bool>
+    <bool name="def_accessibility_speak_password">true</bool>
 
     <!-- Default for Settings.Secure.ACCESSIBILITY_WEB_CONTENT_KEY_BINDINGS -->
     <string name="def_accessibility_web_content_key_bindings" translatable="false">
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 88fc9cf..0916abe 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -32,6 +32,8 @@
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
 import android.content.pm.UserInfo;
 import android.database.Cursor;
 import android.database.MatrixCursor;
@@ -58,7 +60,7 @@
 import android.os.UserManager;
 import android.os.UserManagerInternal;
 import android.provider.Settings;
-import android.provider.Settings.Global;
+import android.service.notification.NotificationListenerService;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -86,6 +88,7 @@
 import java.security.SecureRandom;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
@@ -1007,8 +1010,9 @@
                 final int owningUserId = resolveOwningUserIdForSecureSettingLocked(callingUserId,
                         name);
 
-                // Special case for location (sigh).
-                if (isLocationProvidersAllowedRestricted(name, callingUserId, owningUserId)) {
+                if (!isSecureSettingAccessible(name, callingUserId, owningUserId)) {
+                    // This caller is not permitted to access this setting. Pretend the setting
+                    // doesn't exist.
                     continue;
                 }
 
@@ -1037,13 +1041,14 @@
         final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId);
 
         // Ensure the caller can access the setting.
-        enforceSettingReadable(name, SETTINGS_TYPE_SECURE, callingUserId);
+        enforceSettingReadable(name, SETTINGS_TYPE_SECURE, UserHandle.getCallingUserId());
 
         // Determine the owning user as some profile settings are cloned from the parent.
         final int owningUserId = resolveOwningUserIdForSecureSettingLocked(callingUserId, name);
 
-        // Special case for location (sigh).
-        if (isLocationProvidersAllowedRestricted(name, callingUserId, owningUserId)) {
+        if (!isSecureSettingAccessible(name, callingUserId, owningUserId)) {
+            // This caller is not permitted to access this setting. Pretend the setting doesn't
+            // exist.
             SettingsState settings = mSettingsRegistry.getSettingsLocked(SETTINGS_TYPE_SECURE,
                     owningUserId);
             return settings != null ? settings.getNullSetting() : null;
@@ -1233,7 +1238,7 @@
         final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId);
 
         // Ensure the caller can access the setting.
-        enforceSettingReadable(name, SETTINGS_TYPE_SYSTEM, callingUserId);
+        enforceSettingReadable(name, SETTINGS_TYPE_SYSTEM, UserHandle.getCallingUserId());
 
         // Determine the owning user as some profile settings are cloned from the parent.
         final int owningUserId = resolveOwningUserIdForSystemSettingLocked(callingUserId, name);
@@ -1355,6 +1360,34 @@
         }
     }
 
+    /**
+     * Returns {@code true} if the specified secure setting should be accessible to the caller.
+     */
+    private boolean isSecureSettingAccessible(String name, int callingUserId,
+            int owningUserId) {
+        // Special case for location (sigh).
+        // This check is not inside the name-based checks below because this method performs checks
+        // only if the calling user ID is not the same as the owning user ID.
+        if (isLocationProvidersAllowedRestricted(name, callingUserId, owningUserId)) {
+            return false;
+        }
+
+        switch (name) {
+            case "bluetooth_address":
+                // BluetoothManagerService for some reason stores the Android's Bluetooth MAC
+                // address in this secure setting. Secure settings can normally be read by any app,
+                // which thus enables them to bypass the recently introduced restrictions on access
+                // to device identifiers.
+                // To mitigate this we make this setting available only to callers privileged to see
+                // this device's MAC addresses, same as through public API
+                // BluetoothAdapter.getAddress() (see BluetoothManagerService for details).
+                return getContext().checkCallingOrSelfPermission(
+                        Manifest.permission.LOCAL_MAC_ADDRESS) == PackageManager.PERMISSION_GRANTED;
+            default:
+                return true;
+        }
+    }
+
     private boolean isLocationProvidersAllowedRestricted(String name, int callingUserId,
             int owningUserId) {
         // Optimization - location providers are restricted only for managed profiles.
@@ -1654,7 +1687,7 @@
             return false;
         }
 
-        String oldProviders = (settingValue != null) ? settingValue.getValue() : "";
+        String oldProviders = !settingValue.isNull() ? settingValue.getValue() : "";
 
         int index = oldProviders.indexOf(value);
         int end = index + value.length();
@@ -2615,6 +2648,8 @@
             if (isSecureSettingsKey(key)) {
                 maybeNotifyProfiles(getTypeFromKey(key), userId, uri, name,
                         sSecureCloneToManagedSettings);
+                maybeNotifyProfiles(SETTINGS_TYPE_SYSTEM, userId, uri, name,
+                        sSystemCloneFromParentOnDependency.values());
             } else if (isSystemSettingsKey(key)) {
                 maybeNotifyProfiles(getTypeFromKey(key), userId, uri, name,
                         sSystemCloneToManagedSettings);
@@ -2624,7 +2659,7 @@
         }
 
         private void maybeNotifyProfiles(int type, int userId, Uri uri, String name,
-                Set<String> keysCloned) {
+                Collection<String> keysCloned) {
             if (keysCloned.contains(name)) {
                 for (int profileId : mUserManager.getProfileIdsWithDisabled(userId)) {
                     // the notification for userId has already been sent.
@@ -2735,7 +2770,7 @@
         }
 
         private final class UpgradeController {
-            private static final int SETTINGS_VERSION = 139;
+            private static final int SETTINGS_VERSION = 142;
 
             private final int mUserId;
 
@@ -3174,9 +3209,17 @@
                     // setting through the UI.
                     final SettingsState secureSetting = getSecureSettingsLocked(userId);
                     if (!mUserManager.hasUserRestriction(
-                            UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, UserHandle.of(userId))) {
+                            UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, UserHandle.of(userId))
+                            && secureSetting.getSettingLocked(
+                            Settings.Secure.INSTALL_NON_MARKET_APPS).getValue().equals("0")) {
+
                         secureSetting.insertSettingLocked(Settings.Secure.INSTALL_NON_MARKET_APPS,
                                 "1", null, true, SettingsState.SYSTEM_PACKAGE_NAME);
+                        // For managed profiles with profile owners, DevicePolicyManagerService
+                        // may want to set the user restriction in this case
+                        secureSetting.insertSettingLocked(
+                                Settings.Secure.UNKNOWN_SOURCES_DEFAULT_REVERSED, "1", null, true,
+                                SettingsState.SYSTEM_PACKAGE_NAME);
                     }
                     currentVersion = 138;
                 }
@@ -3186,6 +3229,92 @@
                     currentVersion = 139;
                 }
 
+                if (currentVersion == 139) {
+                    // Version 140: Settings.Secure#ACCESSIBILITY_SPEAK_PASSWORD is deprecated and
+                    // the user can no longer change the value of this setting through the UI.
+                    // Force to true.
+                    final SettingsState secureSettings = getSecureSettingsLocked(userId);
+                    secureSettings.updateSettingLocked(Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD,
+                            "1", null, true, SettingsState.SYSTEM_PACKAGE_NAME);
+                    currentVersion = 140;
+                }
+
+                if (currentVersion == 140) {
+                    // Version 141: One-time grant of notification listener privileges
+                    // to packages specified in overlay.
+                    String defaultListenerAccess = getContext().getResources().getString(
+                            com.android.internal.R.string.config_defaultListenerAccessPackages);
+                    if (defaultListenerAccess != null) {
+                        StringBuffer newListeners = new StringBuffer();
+                        for (String whitelistPkg : defaultListenerAccess.split(":")) {
+                            // Gather all notification listener components for candidate pkgs.
+                            Intent serviceIntent =
+                                    new Intent(NotificationListenerService.SERVICE_INTERFACE)
+                                            .setPackage(whitelistPkg);
+                            List<ResolveInfo> installedServices =
+                                    getContext().getPackageManager().queryIntentServicesAsUser(
+                                            serviceIntent,
+                                            PackageManager.GET_SERVICES
+                                                    | PackageManager.GET_META_DATA
+                                                    | PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                                    | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+                                            userId);
+
+                            for (int i = 0, count = installedServices.size(); i < count; i++) {
+                                ResolveInfo resolveInfo = installedServices.get(i);
+                                ServiceInfo info = resolveInfo.serviceInfo;
+                                if (!android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE
+                                        .equals(info.permission)) {
+                                    continue;
+                                }
+                                newListeners.append(":")
+                                        .append(info.getComponentName().flattenToString());
+                            }
+                        }
+
+                        if (newListeners.length() > 0) {
+                            final SettingsState secureSetting = getSecureSettingsLocked(userId);
+                            final Setting existingSetting = secureSetting.getSettingLocked(
+                                    Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
+                            if (existingSetting.isNull()) {
+                                secureSetting.insertSettingLocked(
+                                        Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
+                                        newListeners.toString(), null, true,
+                                        SettingsState.SYSTEM_PACKAGE_NAME);
+                            } else {
+                                StringBuilder currentSetting =
+                                        new StringBuilder(existingSetting.getValue());
+                                currentSetting.append(newListeners.toString());
+                                secureSetting.updateSettingLocked(
+                                        Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
+                                        currentSetting.toString(), null, true,
+                                        SettingsState.SYSTEM_PACKAGE_NAME);
+                            }
+                        }
+                    }
+                    currentVersion = 141;
+                }
+
+                if (currentVersion == 141) {
+                    // Version 141: We added the notion of a default and whether the system set
+                    // the setting. This is used for resetting the internal state and we need
+                    // to make sure this value is updated for the existing settings, otherwise
+                    // we would delete system set settings while they should stay unmodified.
+                    SettingsState globalSettings = getGlobalSettingsLocked();
+                    ensureLegacyDefaultValueAndSystemSetUpdatedLocked(globalSettings);
+                    globalSettings.persistSyncLocked();
+
+                    SettingsState secureSettings = getSecureSettingsLocked(mUserId);
+                    ensureLegacyDefaultValueAndSystemSetUpdatedLocked(secureSettings);
+                    secureSettings.persistSyncLocked();
+
+                    SettingsState systemSettings = getSystemSettingsLocked(mUserId);
+                    ensureLegacyDefaultValueAndSystemSetUpdatedLocked(systemSettings);
+                    systemSettings.persistSyncLocked();
+
+                    currentVersion = 142;
+                }
+
                 if (currentVersion != newVersion) {
                     Slog.wtf("SettingsProvider", "warning: upgrading settings database to version "
                             + newVersion + " left it at "
@@ -3201,5 +3330,22 @@
                 return currentVersion;
             }
         }
+
+        private void ensureLegacyDefaultValueAndSystemSetUpdatedLocked(SettingsState settings) {
+            List<String> names = settings.getSettingNamesLocked();
+            final int nameCount = names.size();
+            for (int i = 0; i < nameCount; i++) {
+                String name = names.get(i);
+                Setting setting = settings.getSettingLocked(name);
+                if (setting.getDefaultValue() == null) {
+                    boolean systemSet = SettingsState.isSystemPackage(getContext(),
+                            setting.getPackageName());
+                    if (systemSet) {
+                        settings.insertSettingLocked(name, setting.getValue(),
+                                setting.getTag(), true, setting.getPackageName());
+                    }
+                }
+            }
+        }
     }
 }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index 56ae618..5f4b239 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -143,6 +143,8 @@
     @GuardedBy("sLock")
     private static Signature sSystemSignature;
 
+    private final Object mWriteLock = new Object();
+
     private final Object mLock;
 
     private final Handler mHandler;
@@ -551,12 +553,7 @@
     }
 
     private void doWriteState() {
-        if (DEBUG_PERSISTENCE) {
-            Slog.i(LOG_TAG, "[PERSIST START]");
-        }
-
-        AtomicFile destination = new AtomicFile(mStatePersistFile);
-
+        boolean wroteState = false;
         final int version;
         final ArrayMap<String, Setting> settings;
 
@@ -567,46 +564,59 @@
             mWriteScheduled = false;
         }
 
-        FileOutputStream out = null;
-        try {
-            out = destination.startWrite();
-
-            XmlSerializer serializer = Xml.newSerializer();
-            serializer.setOutput(out, StandardCharsets.UTF_8.name());
-            serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
-            serializer.startDocument(null, true);
-            serializer.startTag(null, TAG_SETTINGS);
-            serializer.attribute(null, ATTR_VERSION, String.valueOf(version));
-
-            final int settingCount = settings.size();
-            for (int i = 0; i < settingCount; i++) {
-                Setting setting = settings.valueAt(i);
-
-                writeSingleSetting(mVersion, serializer, setting.getId(), setting.getName(),
-                        setting.getValue(), setting.getDefaultValue(), setting.getPackageName(),
-                        setting.getTag(), setting.isDefaultFromSystem());
-
-                if (DEBUG_PERSISTENCE) {
-                    Slog.i(LOG_TAG, "[PERSISTED]" + setting.getName() + "=" + setting.getValue());
-                }
+        synchronized (mWriteLock) {
+            if (DEBUG_PERSISTENCE) {
+                Slog.i(LOG_TAG, "[PERSIST START]");
             }
 
-            serializer.endTag(null, TAG_SETTINGS);
-            serializer.endDocument();
-            destination.finishWrite(out);
+            AtomicFile destination = new AtomicFile(mStatePersistFile);
+            FileOutputStream out = null;
+            try {
+                out = destination.startWrite();
 
+                XmlSerializer serializer = Xml.newSerializer();
+                serializer.setOutput(out, StandardCharsets.UTF_8.name());
+                serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output",
+                        true);
+                serializer.startDocument(null, true);
+                serializer.startTag(null, TAG_SETTINGS);
+                serializer.attribute(null, ATTR_VERSION, String.valueOf(version));
+
+                final int settingCount = settings.size();
+                for (int i = 0; i < settingCount; i++) {
+                    Setting setting = settings.valueAt(i);
+
+                    writeSingleSetting(mVersion, serializer, setting.getId(), setting.getName(),
+                            setting.getValue(), setting.getDefaultValue(), setting.getPackageName(),
+                            setting.getTag(), setting.isDefaultFromSystem());
+
+                    if (DEBUG_PERSISTENCE) {
+                        Slog.i(LOG_TAG, "[PERSISTED]" + setting.getName() + "="
+                                + setting.getValue());
+                    }
+                }
+
+                serializer.endTag(null, TAG_SETTINGS);
+                serializer.endDocument();
+                destination.finishWrite(out);
+
+                wroteState = true;
+
+                if (DEBUG_PERSISTENCE) {
+                    Slog.i(LOG_TAG, "[PERSIST END]");
+                }
+            } catch (Throwable t) {
+                Slog.wtf(LOG_TAG, "Failed to write settings, restoring backup", t);
+                destination.failWrite(out);
+            } finally {
+                IoUtils.closeQuietly(out);
+            }
+        }
+
+        if (wroteState) {
             synchronized (mLock) {
                 addHistoricalOperationLocked(HISTORICAL_OPERATION_PERSIST, null);
             }
-
-            if (DEBUG_PERSISTENCE) {
-                Slog.i(LOG_TAG, "[PERSIST END]");
-            }
-        } catch (Throwable t) {
-            Slog.wtf(LOG_TAG, "Failed to write settings, restoring backup", t);
-            destination.failWrite(out);
-        } finally {
-            IoUtils.closeQuietly(out);
         }
     }
 
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/InstallNonMarketAppsDeprecationTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/InstallNonMarketAppsDeprecationTest.java
index 51e4373..d8ee9b6 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/InstallNonMarketAppsDeprecationTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/InstallNonMarketAppsDeprecationTest.java
@@ -22,6 +22,7 @@
 
 import android.content.Context;
 import android.content.pm.UserInfo;
+import android.os.Process;
 import android.os.SystemClock;
 import android.os.UserManager;
 import android.provider.Settings;
@@ -37,6 +38,7 @@
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStreamReader;
+import java.util.ArrayList;
 import java.util.List;
 
 @LargeTest
@@ -47,7 +49,8 @@
 
     private UserManager mUm;
     private boolean mHasUserRestriction;
-    private List<UserInfo> mCurrentUsers;
+    private boolean mSystemSetUserRestriction;
+    private List<Integer> mUsersAddedByTest;
 
     private String waitTillValueChanges(String errorMessage, String oldValue) {
         boolean interrupted = false;
@@ -84,7 +87,10 @@
     public void setUp() {
         mUm = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
         mHasUserRestriction = mUm.hasUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
-        mCurrentUsers = mUm.getUsers();
+        mSystemSetUserRestriction = mUm.getUserRestrictionSource(
+                UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, Process.myUserHandle())
+                == UserManager.RESTRICTION_SOURCE_SYSTEM;
+        mUsersAddedByTest = new ArrayList<>();
     }
 
     @Test
@@ -108,6 +114,7 @@
     @Test
     public void testValueForNewUser() throws Exception {
         UserInfo newUser = mUm.createUser("TEST_USER", 0);
+        mUsersAddedByTest.add(newUser.id);
         String value = getSecureSettingForUserViaShell(newUser.id);
         assertEquals("install_non_market_apps should be 1 for a new user", value, "1");
     }
@@ -117,6 +124,13 @@
         String value = getSetting(SETTING_TYPE_SECURE, Settings.Secure.INSTALL_NON_MARKET_APPS);
         assertEquals(value, mHasUserRestriction ? "0" : "1");
 
+        if (mHasUserRestriction && !mSystemSetUserRestriction) {
+            // User restriction set by device policy. This case should be covered in DO/PO related
+            // tests. Pass.
+            Log.w(TAG, "User restriction set by PO/DO. Skipping testValueRespectsUserRestriction");
+            return;
+        }
+
         mUm.setUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, !mHasUserRestriction);
         value = waitTillValueChanges(
                 "Changing user restriction did not change the value of install_non_market_apps",
@@ -132,15 +146,13 @@
 
     @After
     public void tearDown() {
-        if (mUm.hasUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES)
-                != mHasUserRestriction) {
+        if (!mHasUserRestriction || mSystemSetUserRestriction) {
+            // The test may have modified the user restriction state. Restore it.
             mUm.setUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,
                     mHasUserRestriction);
         }
-        mUm.getUsers().forEach(user -> {
-            if (!mCurrentUsers.contains(user)) {
-                mUm.removeUser(user.id);
-            }
-        });
+        for (int userId : mUsersAddedByTest) {
+            mUm.removeUser(userId);
+        }
     }
 }
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 34164b16..3cce299 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -38,6 +38,7 @@
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
     <uses-permission android:name="android.permission.BLUETOOTH" />
+    <uses-permission android:name="android.permission.LOCAL_MAC_ADDRESS" />
     <uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
     <uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" />
@@ -118,6 +119,8 @@
     <uses-permission android:name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME" />
     <!-- Permission needed to hold a wakelock in dumpstate.cpp (drop_root_user()) -->
     <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <!-- Permission needed to enable/disable overlays -->
+    <uses-permission android:name="android.permission.CHANGE_OVERLAY_PACKAGES" />
 
     <application android:label="@string/app_label"
                  android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 12d0c03..1df626f 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -44,6 +44,7 @@
 import libcore.io.Streams;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.app.ChooserActivity;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.util.FastPrintWriter;
@@ -943,8 +944,13 @@
     }
 
     static void sendShareIntent(Context context, Intent intent) {
-        context.startActivity(Intent.createChooser(intent,
-                context.getResources().getText(R.string.bugreport_intent_chooser_title)));
+        final Intent chooserIntent = Intent.createChooser(intent,
+                context.getResources().getText(R.string.bugreport_intent_chooser_title));
+
+        // Since we may be launched behind lockscreen, make sure that ChooserActivity doesn't finish
+        // itself in onStop.
+        chooserIntent.putExtra(ChooserActivity.EXTRA_PRIVATE_RETAIN_IN_ON_STOP, true);
+        context.startActivity(chooserIntent);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/ActivityStarter.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java
similarity index 88%
rename from packages/SystemUI/src/com/android/systemui/ActivityStarter.java
rename to packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java
index a4d8a10..b58ea00 100644
--- a/packages/SystemUI/src/com/android/systemui/ActivityStarter.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java
@@ -12,17 +12,21 @@
  * permissions and limitations under the License.
  */
 
-package com.android.systemui;
+package com.android.systemui.plugins;
 
 import android.app.PendingIntent;
 import android.content.Intent;
 
+import com.android.systemui.plugins.annotations.ProvidesInterface;
+
 /**
  * An interface to start activities. This is used as a callback from the views to
  * {@link PhoneStatusBar} to allow custom handling for starting the activity, i.e. dismissing the
  * Keyguard.
  */
+@ProvidesInterface(version = ActivityStarter.VERSION)
 public interface ActivityStarter {
+    int VERSION = 1;
 
     void startPendingIntentDismissingKeyguard(PendingIntent intent);
     void startActivity(Intent intent, boolean dismissShade);
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginDependency.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginDependency.java
new file mode 100644
index 0000000..25ce3dd
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginDependency.java
@@ -0,0 +1,31 @@
+/*
+ * 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.plugins;
+
+import com.android.systemui.plugins.annotations.ProvidesInterface;
+
+@ProvidesInterface(version = PluginDependency.VERSION)
+public class PluginDependency {
+    public static final int VERSION = 1;
+    static DependencyProvider sProvider;
+
+    public static <T> T get(Plugin p, Class<T> cls) {
+        return sProvider.get(p, cls);
+    }
+
+    static abstract class DependencyProvider {
+        abstract <T> T get(Plugin p, Class<T> cls);
+    }
+}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/DetailAdapter.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/DetailAdapter.java
new file mode 100644
index 0000000..f6f8f53
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/DetailAdapter.java
@@ -0,0 +1,47 @@
+/*
+ * 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.plugins.qs;
+
+import android.content.Context;
+import android.content.Intent;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.systemui.plugins.annotations.ProvidesInterface;
+
+@ProvidesInterface(version = DetailAdapter.VERSION)
+public interface DetailAdapter {
+    public static final int VERSION = 1;
+
+    CharSequence getTitle();
+    Boolean getToggleState();
+
+    default boolean getToggleEnabled() {
+        return true;
+    }
+
+    View createDetailView(Context context, View convertView, ViewGroup parent);
+    Intent getSettingsIntent();
+    void setToggleState(boolean state);
+    int getMetricsCategory();
+
+    /**
+     * Indicates whether the detail view wants to have its header (back button, title and
+     * toggle) shown.
+     */
+    default boolean hasHeader() {
+        return true;
+    }
+}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java
index b7467eb..4a5a681 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java
@@ -14,58 +14,53 @@
 
 package com.android.systemui.plugins.qs;
 
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+
 import com.android.systemui.plugins.FragmentBase;
 import com.android.systemui.plugins.annotations.DependsOn;
 import com.android.systemui.plugins.annotations.ProvidesInterface;
-import com.android.systemui.plugins.qs.QS.Callback;
-import com.android.systemui.plugins.qs.QS.DetailAdapter;
 import com.android.systemui.plugins.qs.QS.HeightListener;
 
-import android.content.Context;
-import android.content.Intent;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.RelativeLayout;
-
 /**
  * Fragment that contains QS in the notification shade.  Most of the interface is for
  * handling the expand/collapsing of the view interaction.
  */
 @ProvidesInterface(action = QS.ACTION, version = QS.VERSION)
 @DependsOn(target = HeightListener.class)
-@DependsOn(target = Callback.class)
-@DependsOn(target = DetailAdapter.class)
 public interface QS extends FragmentBase {
 
     public static final String ACTION = "com.android.systemui.action.PLUGIN_QS";
 
-    public static final int VERSION = 5;
+    public static final int VERSION = 6;
 
     String TAG = "QS";
 
-    public abstract void setPanelView(HeightListener notificationPanelView);
-    public abstract BaseStatusBarHeader getHeader();
+    void setPanelView(HeightListener notificationPanelView);
 
-    public abstract void hideImmediately();
-    public abstract int getQsMinExpansionHeight();
-    public abstract int getDesiredHeight();
-    public abstract void setHeightOverride(int desiredHeight);
-    public abstract void setHeaderClickable(boolean qsExpansionEnabled);
-    public abstract boolean isCustomizing();
-    public abstract void setOverscrolling(boolean overscrolling);
-    public abstract void setExpanded(boolean qsExpanded);
-    public abstract void setListening(boolean listening);
-    public abstract boolean isShowingDetail();
-    public abstract void closeDetail();
-    public abstract void setKeyguardShowing(boolean keyguardShowing);
-    public abstract void animateHeaderSlidingIn(long delay);
-    public abstract void animateHeaderSlidingOut();
-    public abstract void setQsExpansion(float qsExpansionFraction, float headerTranslation);
-    public abstract void setHeaderListening(boolean listening);
-    public abstract void notifyCustomizeChanged();
+    void hideImmediately();
+    int getQsMinExpansionHeight();
+    int getDesiredHeight();
+    void setHeightOverride(int desiredHeight);
+    void setHeaderClickable(boolean qsExpansionEnabled);
+    boolean isCustomizing();
+    void setOverscrolling(boolean overscrolling);
+    void setExpanded(boolean qsExpanded);
+    void setListening(boolean listening);
+    boolean isShowingDetail();
+    void closeDetail();
+    void setKeyguardShowing(boolean keyguardShowing);
+    void animateHeaderSlidingIn(long delay);
+    void animateHeaderSlidingOut();
+    void setQsExpansion(float qsExpansionFraction, float headerTranslation);
+    void setHeaderListening(boolean listening);
+    void notifyCustomizeChanged();
 
-    public abstract void setContainer(ViewGroup container);
+    void setContainer(ViewGroup container);
+    void setExpandClickListener(OnClickListener onClickListener);
+
+    View getHeader();
 
     @ProvidesInterface(version = HeightListener.VERSION)
     public interface HeightListener {
@@ -73,51 +68,4 @@
         void onQsHeightChanged();
     }
 
-    @ProvidesInterface(version = Callback.VERSION)
-    public interface Callback {
-        public static final int VERSION = 1;
-        void onShowingDetail(DetailAdapter detail, int x, int y);
-        void onToggleStateChanged(boolean state);
-        void onScanStateChanged(boolean state);
-    }
-
-    @ProvidesInterface(version = DetailAdapter.VERSION)
-    public interface DetailAdapter {
-        public static final int VERSION = 1;
-        CharSequence getTitle();
-        Boolean getToggleState();
-        default boolean getToggleEnabled() {
-            return true;
-        }
-        View createDetailView(Context context, View convertView, ViewGroup parent);
-        Intent getSettingsIntent();
-        void setToggleState(boolean state);
-        int getMetricsCategory();
-
-        /**
-         * Indicates whether the detail view wants to have its header (back button, title and
-         * toggle) shown.
-         */
-        default boolean hasHeader() { return true; }
-    }
-
-    @ProvidesInterface(version = BaseStatusBarHeader.VERSION)
-    public abstract static class BaseStatusBarHeader extends RelativeLayout {
-        public static final int VERSION = 1;
-
-        public BaseStatusBarHeader(Context context, AttributeSet attrs) {
-            super(context, attrs);
-        }
-
-        public abstract int getCollapsedHeight();
-        public abstract int getExpandedHeight();
-
-        public abstract void setExpanded(boolean b);
-        public abstract void setExpansion(float headerExpansionFraction);
-        public abstract void setListening(boolean listening);
-        public abstract void updateEverything();
-        public abstract void setCallback(Callback qsPanelCallback);
-        public abstract View getExpandView();
-    }
-
 }
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSFactory.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSFactory.java
new file mode 100644
index 0000000..9dd0811
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSFactory.java
@@ -0,0 +1,36 @@
+/*
+ * 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.plugins.qs;
+
+import com.android.systemui.plugins.Plugin;
+import com.android.systemui.plugins.annotations.DependsOn;
+import com.android.systemui.plugins.annotations.ProvidesInterface;
+
+/**
+ * Plugin that has the ability to create or override any part of
+ * QS tiles.
+ */
+@ProvidesInterface(action = QSFactory.ACTION, version = QSFactory.VERSION)
+@DependsOn(target = QSTile.class)
+@DependsOn(target = QSTileView.class)
+public interface QSFactory extends Plugin {
+
+    String ACTION = "com.android.systemui.action.PLUGIN_QS_FACTORY";
+    int VERSION = 1;
+
+    QSTile createTile(String tileSpec);
+    QSTileView createTileView(QSTile tile, boolean collapsedView);
+
+}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSIconView.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSIconView.java
new file mode 100644
index 0000000..c268d32
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSIconView.java
@@ -0,0 +1,35 @@
+/*
+ * 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.plugins.qs;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.systemui.plugins.annotations.ProvidesInterface;
+import com.android.systemui.plugins.qs.QSTile.State;
+
+@ProvidesInterface(version = QSIconView.VERSION)
+public abstract class QSIconView extends ViewGroup {
+    public static final int VERSION = 1;
+
+    public QSIconView(Context context) {
+        super(context);
+    }
+
+    public abstract void setIcon(State state);
+    public abstract void disableAnimation();
+    public abstract View getIconView();
+}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
new file mode 100644
index 0000000..7bb31c0
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
@@ -0,0 +1,240 @@
+/*
+ * 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.plugins.qs;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.service.quicksettings.Tile;
+
+import com.android.systemui.plugins.annotations.DependsOn;
+import com.android.systemui.plugins.annotations.ProvidesInterface;
+import com.android.systemui.plugins.qs.QSTile.Callback;
+import com.android.systemui.plugins.qs.QSTile.Icon;
+import com.android.systemui.plugins.qs.QSTile.State;
+
+import java.util.Objects;
+
+@ProvidesInterface(version = QSTile.VERSION)
+@DependsOn(target = QSIconView.class)
+@DependsOn(target = DetailAdapter.class)
+@DependsOn(target = Callback.class)
+@DependsOn(target = Icon.class)
+@DependsOn(target = State.class)
+public interface QSTile {
+    int VERSION = 1;
+
+    DetailAdapter getDetailAdapter();
+    String getTileSpec();
+
+    boolean isAvailable();
+    void setTileSpec(String tileSpec);
+
+    void clearState();
+    void refreshState();
+
+    void addCallback(Callback callback);
+    void removeCallback(Callback callback);
+    void removeCallbacks();
+
+    QSIconView createTileView(Context context);
+    
+    void click();
+    void secondaryClick();
+    void longClick();
+
+    void userSwitch(int currentUser);
+    int getMetricsCategory();
+
+    void setListening(Object client, boolean listening);
+    void setDetailListening(boolean show);
+
+    void destroy();
+
+    CharSequence getTileLabel();
+
+    State getState();
+
+    @ProvidesInterface(version = Callback.VERSION)
+    public interface Callback {
+        public static final int VERSION = 1;
+        void onStateChanged(State state);
+        void onShowDetail(boolean show);
+        void onToggleStateChanged(boolean state);
+        void onScanStateChanged(boolean state);
+        void onAnnouncementRequested(CharSequence announcement);
+    }
+
+    @ProvidesInterface(version = Icon.VERSION)
+    public static abstract class Icon {
+        public static final int VERSION = 1;
+        abstract public Drawable getDrawable(Context context);
+
+        public Drawable getInvisibleDrawable(Context context) {
+            return getDrawable(context);
+        }
+
+        @Override
+        public int hashCode() {
+            return Icon.class.hashCode();
+        }
+
+        public int getPadding() {
+            return 0;
+        }
+    }
+
+    @ProvidesInterface(version = State.VERSION)
+    public static class State {
+        public static final int VERSION = 1;
+        public Icon icon;
+        public int state = Tile.STATE_ACTIVE;
+        public CharSequence label;
+        public CharSequence contentDescription;
+        public CharSequence dualLabelContentDescription;
+        public boolean disabledByPolicy;
+        public boolean dualTarget = false;
+        public String expandedAccessibilityClassName;
+
+        public boolean copyTo(State other) {
+            if (other == null) throw new IllegalArgumentException();
+            if (!other.getClass().equals(getClass())) throw new IllegalArgumentException();
+            final boolean changed = !Objects.equals(other.icon, icon)
+                    || !Objects.equals(other.label, label)
+                    || !Objects.equals(other.contentDescription, contentDescription)
+                    || !Objects.equals(other.dualLabelContentDescription,
+                            dualLabelContentDescription)
+                    || !Objects.equals(other.expandedAccessibilityClassName,
+                            expandedAccessibilityClassName)
+                    || !Objects.equals(other.disabledByPolicy, disabledByPolicy)
+                    || !Objects.equals(other.state, state)
+                    || !Objects.equals(other.dualTarget, dualTarget);
+            other.icon = icon;
+            other.label = label;
+            other.contentDescription = contentDescription;
+            other.dualLabelContentDescription = dualLabelContentDescription;
+            other.expandedAccessibilityClassName = expandedAccessibilityClassName;
+            other.disabledByPolicy = disabledByPolicy;
+            other.state = state;
+            other.dualTarget = dualTarget;
+            return changed;
+        }
+
+        @Override
+        public String toString() {
+            return toStringBuilder().toString();
+        }
+
+        protected StringBuilder toStringBuilder() {
+            final StringBuilder sb = new StringBuilder(getClass().getSimpleName()).append('[');
+            sb.append(",icon=").append(icon);
+            sb.append(",label=").append(label);
+            sb.append(",contentDescription=").append(contentDescription);
+            sb.append(",dualLabelContentDescription=").append(dualLabelContentDescription);
+            sb.append(",expandedAccessibilityClassName=").append(expandedAccessibilityClassName);
+            sb.append(",disabledByPolicy=").append(disabledByPolicy);
+            sb.append(",dualTarget=").append(dualTarget);
+            sb.append(",state=").append(state);
+            return sb.append(']');
+        }
+
+        public State copy() {
+            State state = new State();
+            copyTo(state);
+            return state;
+        }
+    }
+
+    @ProvidesInterface(version = BooleanState.VERSION)
+    public static class BooleanState extends State {
+        public static final int VERSION = 1;
+        public boolean value;
+
+        @Override
+        public boolean copyTo(State other) {
+            final BooleanState o = (BooleanState) other;
+            final boolean changed = super.copyTo(other) || o.value != value;
+            o.value = value;
+            return changed;
+        }
+
+        @Override
+        protected StringBuilder toStringBuilder() {
+            final StringBuilder rt = super.toStringBuilder();
+            rt.insert(rt.length() - 1, ",value=" + value);
+            return rt;
+        }
+
+        @Override
+        public State copy() {
+            BooleanState state = new BooleanState();
+            copyTo(state);
+            return state;
+        }
+    }
+
+    @ProvidesInterface(version = SignalState.VERSION)
+    public static final class SignalState extends BooleanState {
+        public static final int VERSION = 1;
+        public boolean activityIn;
+        public boolean activityOut;
+
+        @Override
+        public boolean copyTo(State other) {
+            final SignalState o = (SignalState) other;
+            final boolean changed = o.activityIn != activityIn
+                    || o.activityOut != activityOut;
+            o.activityIn = activityIn;
+            o.activityOut = activityOut;
+            return super.copyTo(other) || changed;
+        }
+
+        @Override
+        protected StringBuilder toStringBuilder() {
+            final StringBuilder rt = super.toStringBuilder();
+            rt.insert(rt.length() - 1, ",activityIn=" + activityIn);
+            rt.insert(rt.length() - 1, ",activityOut=" + activityOut);
+            return rt;
+        }
+
+        @Override
+        public State copy() {
+            SignalState state = new SignalState();
+            copyTo(state);
+            return state;
+        }
+    }
+
+
+    @ProvidesInterface(version = AirplaneBooleanState.VERSION)
+    public static class AirplaneBooleanState extends BooleanState {
+        public static final int VERSION = 1;
+        public boolean isAirplaneMode;
+
+        @Override
+        public boolean copyTo(State other) {
+            final AirplaneBooleanState o = (AirplaneBooleanState) other;
+            final boolean changed = super.copyTo(other) || o.isAirplaneMode != isAirplaneMode;
+            o.isAirplaneMode = isAirplaneMode;
+            return changed;
+        }
+
+        public State copy() {
+            AirplaneBooleanState state = new AirplaneBooleanState();
+            copyTo(state);
+            return state;
+        }
+    }
+
+}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTileView.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTileView.java
new file mode 100644
index 0000000..18d27bb
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTileView.java
@@ -0,0 +1,41 @@
+/*
+ * 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.plugins.qs;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.LinearLayout;
+
+import com.android.systemui.plugins.annotations.DependsOn;
+import com.android.systemui.plugins.annotations.ProvidesInterface;
+import com.android.systemui.plugins.qs.QSTile.State;
+
+@ProvidesInterface(version = QSTileView.VERSION)
+@DependsOn(target = QSIconView.class)
+@DependsOn(target = QSTile.class)
+public abstract class QSTileView extends LinearLayout {
+    public static final int VERSION = 1;
+
+    public QSTileView(Context context) {
+        super(context);
+    }
+
+    public abstract View updateAccessibilityOrder(View previousView);
+    public abstract QSIconView getIcon();
+    public abstract void init(QSTile tile);
+    public abstract void onStateChanged(State state);
+
+    public abstract int getDetailY();
+}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavGesture.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavGesture.java
index ddee89e..674ed5a 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavGesture.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavGesture.java
@@ -19,7 +19,7 @@
 import com.android.systemui.plugins.Plugin;
 import com.android.systemui.plugins.annotations.ProvidesInterface;
 
-@ProvidesInterface(action = NavGesture.ACTION, version = NavBarButtonProvider.VERSION)
+@ProvidesInterface(action = NavGesture.ACTION, version = NavGesture.VERSION)
 public interface NavGesture extends Plugin {
 
     public static final String ACTION = "com.android.systemui.action.PLUGIN_NAV_GESTURE";
diff --git a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
index 73161656..c7cfe88 100644
--- a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
@@ -51,8 +51,8 @@
     <string name="keyguard_accessibility_sim_puk_area" msgid="136979425761438705">"Oblast za PUK za SIM"</string>
     <string name="keyguard_accessibility_next_alarm" msgid="5835196989158584991">"Sledeći alarm je podešen za <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="6883116827512721630">"Izbriši"</string>
-    <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Unesi"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Zaboravili ste šablon?"</string>
+    <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Zaboravio/la sam šablon"</string>
     <string name="kg_wrong_pattern" msgid="7620081431514773802">"Pogrešan šablon"</string>
     <string name="kg_wrong_password" msgid="4580683060277329277">"Pogrešna lozinka"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Pogrešan PIN"</string>
diff --git a/packages/SystemUI/res-keyguard/values-bs/strings.xml b/packages/SystemUI/res-keyguard/values-bs/strings.xml
index bb1baca..04256f1 100644
--- a/packages/SystemUI/res-keyguard/values-bs/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bs/strings.xml
@@ -20,7 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3171996292755059205">"Čuvar tastature"</string>
+    <string name="app_name" msgid="3171996292755059205">"Zaključavanje tastature"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3420548423949593123">"Upišite PIN kôd"</string>
     <string name="keyguard_password_enter_puk_code" msgid="670683628782925409">"Upišite PUK kôd za SIM karticu i novi PIN kôd"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="3747778500166059332">"PUK kôd za SIM karticu"</string>
@@ -105,7 +105,7 @@
     <string name="kg_password_puk_failed" msgid="1331621440873439974">"Korištenje PUK koda za SIM karticu nije uspjelo!"</string>
     <string name="kg_pin_accepted" msgid="7637293533973802143">"Kôd je prihvaćen"</string>
     <string name="keyguard_carrier_default" msgid="4274828292998453695">"Nema mreže."</string>
-    <string name="accessibility_ime_switch_button" msgid="2695096475319405612">"Promijena način unosa"</string>
+    <string name="accessibility_ime_switch_button" msgid="2695096475319405612">"Promjena načina unosa"</string>
     <string name="airplane_mode" msgid="3807209033737676010">"Način rada u avionu"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="7246972020562621506">"Potreban je uzorak nakon što se uređaj ponovo pokrene"</string>
     <string name="kg_prompt_reason_restart_pin" msgid="6303592361322290145">"Potreban je PIN kôd nakon što se uređaj ponovo pokrene"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ca/strings.xml b/packages/SystemUI/res-keyguard/values-ca/strings.xml
index 6406771..3e8f2fa 100644
--- a/packages/SystemUI/res-keyguard/values-ca/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ca/strings.xml
@@ -25,7 +25,7 @@
     <string name="keyguard_password_enter_puk_code" msgid="670683628782925409">"Escriu el PUK de la SIM i el codi PIN nou"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="3747778500166059332">"Codi PUK de la SIM"</string>
     <string name="keyguard_password_enter_pin_prompt" msgid="8188243197504453830">"Codi PIN de la SIM nou"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="5790410752696806482"><font size="17">"Toca i escriu la contrasenya"</font></string>
+    <string name="keyguard_password_entry_touch_hint" msgid="5790410752696806482"><font size="17">"Toca per escriure la contrasenya"</font></string>
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Escriu la contrasenya per desbloquejar"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Escriu el PIN per desbloquejar"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"El codi PIN no és correcte."</string>
@@ -42,7 +42,7 @@
     <string name="keyguard_missing_sim_instructions" msgid="7350295932015220392">"Insereix una targeta SIM."</string>
     <string name="keyguard_missing_sim_instructions_long" msgid="589889372883904477">"Falta la targeta SIM o no es pot llegir. Insereix-ne una."</string>
     <string name="keyguard_permanent_disabled_sim_message_short" msgid="654102080186420706">"La targeta SIM no es pot fer servir."</string>
-    <string name="keyguard_permanent_disabled_sim_instructions" msgid="4683178224791318347">"La targeta SIM s\'ha desactivat permanentment.\n Contacta amb el teu proveïdor de serveis sense fil per obtenir-ne una altra."</string>
+    <string name="keyguard_permanent_disabled_sim_instructions" msgid="4683178224791318347">"La targeta SIM s\'ha desactivat permanentment.\nContacta amb el teu proveïdor de serveis sense fil per obtenir-ne una altra."</string>
     <string name="keyguard_sim_locked_message" msgid="953766009432168127">"La targeta SIM està bloquejada."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="1772789643694942073">"La targeta SIM està bloquejada pel PUK."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="3586601150825821675">"S\'està desbloquejant la targeta SIM…"</string>
@@ -52,18 +52,18 @@
     <string name="keyguard_accessibility_next_alarm" msgid="5835196989158584991">"S\'ha definit la pròxima alarma per a l\'hora següent: <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="6883116827512721630">"Suprimeix"</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Retorn"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Patró oblidat"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"He oblidat el patró"</string>
     <string name="kg_wrong_pattern" msgid="7620081431514773802">"El patró no és correcte"</string>
-    <string name="kg_wrong_password" msgid="4580683060277329277">"La contrasenya és incorrecta"</string>
+    <string name="kg_wrong_password" msgid="4580683060277329277">"La contrasenya no és correcta"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"El PIN no és correcte"</string>
     <string name="kg_too_many_failed_attempts_countdown" msgid="527455490371878356">"Torna-ho a provar d\'aquí a <xliff:g id="NUMBER">%d</xliff:g> segons."</string>
     <string name="kg_pattern_instructions" msgid="5547646893001491340">"Dibuixa el patró"</string>
     <string name="kg_sim_pin_instructions" msgid="1795013002231184046">"Introdueix el PIN de la SIM"</string>
-    <string name="kg_sim_pin_instructions_multi" msgid="1586316574649150223">"Introdueix el PIN de la SIM de l\'operador <xliff:g id="CARRIER">%1$s</xliff:g>"</string>
+    <string name="kg_sim_pin_instructions_multi" msgid="1586316574649150223">"Introdueix el PIN de la SIM següent: <xliff:g id="CARRIER">%1$s</xliff:g>"</string>
     <string name="kg_pin_instructions" msgid="4069609316644030034">"Introdueix el PIN"</string>
     <string name="kg_password_instructions" msgid="136952397352976538">"Introdueix la contrasenya"</string>
     <string name="kg_puk_enter_puk_hint" msgid="2288964170039899277">"La SIM està desactivada. Introdueix el codi PUK per continuar. Contacta amb l\'operador de telefonia mòbil per obtenir més informació."</string>
-    <string name="kg_puk_enter_puk_hint_multi" msgid="1373131883510840794">"La SIM de l\'operador <xliff:g id="CARRIER">%1$s</xliff:g> està desactivada. Introdueix el codi PUK per continuar. Contacta amb l\'operador de telefonia mòbil per obtenir més informació."</string>
+    <string name="kg_puk_enter_puk_hint_multi" msgid="1373131883510840794">"La SIM <xliff:g id="CARRIER">%1$s</xliff:g> està desactivada. Introdueix el codi PUK per continuar. Contacta amb l\'operador de telefonia mòbil per obtenir més informació."</string>
     <string name="kg_puk_enter_pin_hint" msgid="3137789674920391087">"Introdueix el codi PIN que vulguis"</string>
     <string name="kg_enter_confirm_pin_hint" msgid="3089485999116759671">"Confirma el codi PIN"</string>
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4471738151810900114">"S\'està desbloquejant la targeta SIM…"</string>
@@ -72,21 +72,21 @@
     <string name="kg_invalid_puk" msgid="5399287873762592502">"Torna a introduir el codi PUK correcte. Si ho intentes diverses vegades, es desactivarà la SIM de manera permanent."</string>
     <string name="kg_invalid_confirm_pin_hint" product="default" msgid="5672736555427444330">"Els codis PIN no coincideixen"</string>
     <string name="kg_login_too_many_attempts" msgid="6604574268387867255">"Has intentat dibuixar el patró massa vegades"</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8637788033282252027">"Has escrit malament el PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades. \n\nTorna-ho a provar d\'aquí a <xliff:g id="NUMBER_1">%2$d</xliff:g> segons."</string>
-    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7724148763268377734">"Has escrit malament la contrasenya <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades. \n\nTorna-ho a provar d\'aquí a <xliff:g id="NUMBER_1">%2$d</xliff:g> segons."</string>
-    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4820967667848302092">"Has dibuixat el patró de desbloqueig de manera incorrecta <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades. \n\nTorna-ho a provar d\'aquí a <xliff:g id="NUMBER_1">%2$d</xliff:g> segons."</string>
-    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1629351522209932316">"Has provat de desbloquejar la tauleta incorrectament <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, la tauleta es restablirà i se n\'esborraran totes les dades."</string>
-    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="3921998703529189931">"Has provat de desbloquejar el telèfon incorrectament <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, el telèfon es restablirà i se n\'esborraran totes les dades."</string>
-    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="4694232971224663735">"Has provat de desbloquejar la tauleta incorrectament <xliff:g id="NUMBER">%d</xliff:g> vegades. La tauleta es restablirà i se n\'esborraran totes les dades."</string>
-    <string name="kg_failed_attempts_now_wiping" product="default" msgid="2365964340830006961">"Has provat de desbloquejar el telèfon incorrectament <xliff:g id="NUMBER">%d</xliff:g> vegades. El telèfon es restablirà i se n\'esborraran totes les dades."</string>
-    <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="1365418870560228936">"Has provat de desbloquejar la tauleta incorrectament <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, l\'usuari se suprimirà, juntament amb totes les seves dades."</string>
-    <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="2151286957817486128">"Has provat de desbloquejar el telèfon incorrectament <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, l\'usuari se suprimirà, juntament amb totes les seves dades."</string>
-    <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="5464020754932560928">"Has provat de desbloquejar la tauleta incorrectament <xliff:g id="NUMBER">%d</xliff:g> vegades. L\'usuari se suprimirà, juntament amb totes les seves dades."</string>
-    <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="6171564974118059">"Has provat de desbloquejar el telèfon incorrectament <xliff:g id="NUMBER">%d</xliff:g> vegades. L\'usuari se suprimirà, juntament amb totes les seves dades."</string>
-    <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="9154513795928824239">"Has provat de desbloquejar la tauleta incorrectament <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, el perfil professional se suprimirà, juntament amb totes les dades que contingui."</string>
-    <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="2162434417489128282">"Has provat de desbloquejar el telèfon incorrectament <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, el perfil professional se suprimirà, juntament amb totes les dades que contingui."</string>
-    <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="8966727588974691544">"Has provat de desbloquejar la tauleta incorrectament <xliff:g id="NUMBER">%d</xliff:g> vegades. El perfil professional se suprimirà, juntament amb totes les dades que contingui."</string>
-    <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="8476407539834855">"Has provat de desbloquejar el telèfon incorrectament <xliff:g id="NUMBER">%d</xliff:g> vegades. El perfil professional se suprimirà, juntament amb totes les dades que contingui."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8637788033282252027">"Has escrit el PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. \n\nTorna-ho a provar d\'aquí a <xliff:g id="NUMBER_1">%2$d</xliff:g> segons."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7724148763268377734">"Has escrit la contrasenya <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. \n\nTorna-ho a provar d\'aquí a <xliff:g id="NUMBER_1">%2$d</xliff:g> segons."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4820967667848302092">"Has dibuixat el patró de desbloqueig <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. \n\nTorna-ho a provar d\'aquí a <xliff:g id="NUMBER_1">%2$d</xliff:g> segons."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1629351522209932316">"Has provat de desbloquejar la tauleta <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, la tauleta es restablirà i se\'n suprimiran totes les dades."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="3921998703529189931">"Has provat de desbloquejar el telèfon <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, el telèfon es restablirà i se\'n suprimiran totes les dades."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="4694232971224663735">"Has provat de desbloquejar la tauleta <xliff:g id="NUMBER">%d</xliff:g> vegades de manera incorrecta. La tauleta es restablirà i se\'n suprimiran totes les dades."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="2365964340830006961">"Has provat de desbloquejar el telèfon <xliff:g id="NUMBER">%d</xliff:g> vegades de manera incorrecta. El telèfon es restablirà i se\'n suprimiran totes les dades."</string>
+    <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="1365418870560228936">"Has provat de desbloquejar la tauleta <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, l\'usuari se suprimirà, juntament amb totes les seves dades."</string>
+    <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="2151286957817486128">"Has provat de desbloquejar el telèfon <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, l\'usuari se suprimirà, juntament amb totes les seves dades."</string>
+    <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="5464020754932560928">"Has provat de desbloquejar la tauleta <xliff:g id="NUMBER">%d</xliff:g> vegades de manera incorrecta. L\'usuari se suprimirà, juntament amb totes les seves dades."</string>
+    <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="6171564974118059">"Has provat de desbloquejar el telèfon <xliff:g id="NUMBER">%d</xliff:g> vegades de manera incorrecta. L\'usuari se suprimirà, juntament amb totes les seves dades."</string>
+    <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="9154513795928824239">"Has provat de desbloquejar la tauleta <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, el perfil professional se suprimirà, juntament amb totes les dades que contingui."</string>
+    <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="2162434417489128282">"Has provat de desbloquejar el telèfon <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, el perfil professional se suprimirà, juntament amb totes les dades que contingui."</string>
+    <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="8966727588974691544">"Has provat de desbloquejar la tauleta <xliff:g id="NUMBER">%d</xliff:g> vegades de manera incorrecta. El perfil professional se suprimirà, juntament amb totes les dades que contingui."</string>
+    <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="8476407539834855">"Has provat de desbloquejar el telèfon <xliff:g id="NUMBER">%d</xliff:g> vegades de manera incorrecta. El perfil professional se suprimirà, juntament amb totes les dades que contingui."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="956706236554092172">"Has dibuixat el patró de desbloqueig <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, se\'t demanarà que desbloquegis la tauleta amb un compte de correu electrònic.\n\n Torna-ho a provar d\'aquí a <xliff:g id="NUMBER_2">%3$d</xliff:g> segons."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="8364140853305528449">"Has dibuixat el patró de desbloqueig <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, se\'t demanarà que desbloquegis el telèfon amb un compte de correu electrònic.\n\n Torna-ho a provar d\'aquí a <xliff:g id="NUMBER_2">%3$d</xliff:g> segons."</string>
     <string name="kg_password_wrong_pin_code_pukked" msgid="3389829202093674267">"El codi PIN de la SIM no és correcte. Contacta amb l\'operador de telefonia mòbil per desbloquejar el dispositiu."</string>
@@ -96,11 +96,11 @@
     </plurals>
     <string name="kg_password_wrong_puk_code_dead" msgid="3329017604125179374">"La SIM no es pot fer servir. Contacta amb l\'operador de telefonia mòbil."</string>
     <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="2287504898931957513">
-      <item quantity="other">El codi PUK de la SIM no és correcte. Et queden <xliff:g id="NUMBER_1">%d</xliff:g> intents; si no l\'encertes, la SIM no es podrà tornar a fer servir.</item>
+      <item quantity="other">El codi PUK de la SIM no és correcte. Et queden <xliff:g id="NUMBER_1">%d</xliff:g> intents; si els esgotes tots, la SIM no es podrà tornar a fer servir.</item>
       <item quantity="one">El codi PUK de la SIM no és correcte. Et queda <xliff:g id="NUMBER_0">%d</xliff:g> intent; si no l\'encertes, la SIM no es podrà tornar a fer servir.</item>
     </plurals>
-    <string name="kg_password_pin_failed" msgid="8769990811451236223">"No s\'ha pogut dur a terme l\'operació del PIN de la SIM."</string>
-    <string name="kg_password_puk_failed" msgid="1331621440873439974">"No s\'ha pogut dur a terme l\'operació del PUK de la SIM."</string>
+    <string name="kg_password_pin_failed" msgid="8769990811451236223">"No s\'ha pogut desbloquejar la SIM amb el codi PIN."</string>
+    <string name="kg_password_puk_failed" msgid="1331621440873439974">"No s\'ha pogut desbloquejar la SIM amb el codi PUK."</string>
     <string name="kg_pin_accepted" msgid="7637293533973802143">"S\'ha acceptat el codi."</string>
     <string name="keyguard_carrier_default" msgid="4274828292998453695">"Sense servei"</string>
     <string name="accessibility_ime_switch_button" msgid="2695096475319405612">"Canvia el mètode d\'introducció"</string>
diff --git a/packages/SystemUI/res-keyguard/values-eu/strings.xml b/packages/SystemUI/res-keyguard/values-eu/strings.xml
index 32ee9bf..0b580c9 100644
--- a/packages/SystemUI/res-keyguard/values-eu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-eu/strings.xml
@@ -25,7 +25,7 @@
     <string name="keyguard_password_enter_puk_code" msgid="670683628782925409">"Idatzi SIM txartelaren PUK kodea eta PIN kode berria"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="3747778500166059332">"SIM txartelaren PUK kodea"</string>
     <string name="keyguard_password_enter_pin_prompt" msgid="8188243197504453830">"SIM txartelaren PIN kode berria"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="5790410752696806482"><font size="17">"Pasahitza idazteko, ukitu hau"</font></string>
+    <string name="keyguard_password_entry_touch_hint" msgid="5790410752696806482"><font size="17">"Pasahitza idazteko, sakatu hau"</font></string>
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Idatzi desblokeatzeko pasahitza"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Idatzi desblokeatzeko PIN kodea"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"PIN kode hori ez da zuzena."</string>
@@ -33,7 +33,7 @@
     <string name="keyguard_plugged_in" msgid="89308975354638682">"Kargatzen"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="8869226755413795173">"Bizkor kargatzen"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="6637043106038550407">"Motel kargatzen"</string>
-    <string name="keyguard_low_battery" msgid="9218432555787624490">"Konektatu kargagailura."</string>
+    <string name="keyguard_low_battery" msgid="9218432555787624490">"Konektatu kargagailua."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8566679946700751371">"Desblokeatzeko, sakatu Menua."</string>
     <string name="keyguard_network_locked_message" msgid="6743537524631420759">"Sarea blokeatuta dago"</string>
     <string name="keyguard_missing_sim_message_short" msgid="6327533369959764518">"Ez dago SIM txartelik"</string>
@@ -72,9 +72,9 @@
     <string name="kg_invalid_puk" msgid="5399287873762592502">"Idatzi berriro PUK kode zuzena. Hainbat saiakera oker eginez gero, betiko desgaituko da SIM txartela."</string>
     <string name="kg_invalid_confirm_pin_hint" product="default" msgid="5672736555427444330">"PIN kodeak ez datoz bat"</string>
     <string name="kg_login_too_many_attempts" msgid="6604574268387867255">"Eredua marrazteko saiakera gehiegi egin dira"</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8637788033282252027">"PIN kodea oker idatzi duzu <xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz. \n\nSaiatu berriro <xliff:g id="NUMBER_1">%2$d</xliff:g> segundo barru."</string>
-    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7724148763268377734">"Pasahitza oker idatzi duzu <xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz. \n\nSaiatu berriro <xliff:g id="NUMBER_1">%2$d</xliff:g> segundo barru."</string>
-    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4820967667848302092">"Desblokeatzeko eredua oker marraztu duzu <xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz. \n\nSaiatu berriro <xliff:g id="NUMBER_1">%2$d</xliff:g> segundo barru."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8637788033282252027">"<xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz idatzi duzu PIN kodea, baina huts egin duzu denetan. \n\nSaiatu berriro <xliff:g id="NUMBER_1">%2$d</xliff:g> segundo barru."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7724148763268377734">"<xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz idatzi duzu pasahitza, baina huts egin duzu denetan. \n\nSaiatu berriro <xliff:g id="NUMBER_1">%2$d</xliff:g> segundo barru."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4820967667848302092">"<xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz marraztu duzu desblokeatzeko eredua, baina huts egin duzu denetan. \n\nSaiatu berriro <xliff:g id="NUMBER_1">%2$d</xliff:g> segundo barru."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1629351522209932316">"<xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz saiatu zara tableta desblokeatzen, baina huts egin duzu denetan. Beste <xliff:g id="NUMBER_1">%2$d</xliff:g> aldiz huts egiten baduzu, berrezarri egingo da tableta eta, ondorioz, bertako datu guztiak ezabatuko dira."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="3921998703529189931">"<xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz saiatu zara telefonoa desblokeatzen, baina huts egin duzu denetan. Beste <xliff:g id="NUMBER_1">%2$d</xliff:g> aldiz huts egiten baduzu, berrezarri egingo da telefonoa eta, ondorioz, bertako datu guztiak ezabatuko dira."</string>
     <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="4694232971224663735">"<xliff:g id="NUMBER">%d</xliff:g> aldiz saiatu zara tableta desblokeatzen, baina huts egin duzu denetan. Tableta berrezarri egingo da eta, ondorioz, bertako datu guztiak ezabatuko dira."</string>
@@ -87,8 +87,8 @@
     <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="2162434417489128282">"<xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz saiatu zara telefonoa desblokeatzen, baina huts egin duzu denetan. Beste <xliff:g id="NUMBER_1">%2$d</xliff:g> aldiz huts egiten baduzu, kendu egingo da laneko profila eta, ondorioz, profileko datu guztiak ezabatuko dira."</string>
     <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="8966727588974691544">"<xliff:g id="NUMBER">%d</xliff:g> aldiz saiatu zara tableta desblokeatzen, baina huts egin duzu denetan. Laneko profila kendu egingo da eta, ondorioz, profileko datu guztiak ezabatuko dira."</string>
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="8476407539834855">"<xliff:g id="NUMBER">%d</xliff:g> aldiz saiatu zara telefonoa desblokeatzen, baina huts egin duzu denetan. Laneko profila kendu egingo da eta, ondorioz, profileko datu guztiak ezabatuko dira."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="956706236554092172">"Desblokeatzeko eredua oker marraztu duzu <xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz. Beste <xliff:g id="NUMBER_1">%2$d</xliff:g> aldiz oker marrazten baduzu, tableta posta-kontu baten bidez desblokeatzeko eskatuko dizugu.\n\n Saiatu berriro <xliff:g id="NUMBER_2">%3$d</xliff:g> segundo barru."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="8364140853305528449">"Desblokeatzeko eredua oker marraztu duzu <xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz. Beste <xliff:g id="NUMBER_1">%2$d</xliff:g> aldiz oker marrazten baduzu, telefonoa posta-kontu baten bidez desblokeatzeko eskatuko dizugu.\n\n Saiatu berriro <xliff:g id="NUMBER_2">%3$d</xliff:g> segundo barru."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="956706236554092172">"<xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz marraztu duzu desblokeatzeko eredua, baina huts egin duzu denetan. Beste <xliff:g id="NUMBER_1">%2$d</xliff:g> aldiz huts egiten baduzu, tableta posta-kontu baten bidez desblokeatzeko eskatuko dizugu.\n\n Saiatu berriro <xliff:g id="NUMBER_2">%3$d</xliff:g> segundo barru."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="8364140853305528449">"<xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz marraztu duzu desblokeatzeko eredua, baina huts egin duzu denetan. Beste <xliff:g id="NUMBER_1">%2$d</xliff:g> aldiz huts egiten baduzu, telefonoa posta-kontu baten bidez desblokeatzeko eskatuko dizugu.\n\n Saiatu berriro <xliff:g id="NUMBER_2">%3$d</xliff:g> segundo barru."</string>
     <string name="kg_password_wrong_pin_code_pukked" msgid="3389829202093674267">"SIM txartelaren PIN kodea ez da zuzena. Gailua desblokeatzeko, operadorearekin jarri beharko duzu harremanetan."</string>
     <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="4314341367727055967">
       <item quantity="other">Ez da zuzena SIM txartelaren PIN kodea. <xliff:g id="NUMBER_1">%d</xliff:g> saiakera geratzen zaizkizu gailua desblokeatzeko.</item>
diff --git a/packages/SystemUI/res-keyguard/values-hi/strings.xml b/packages/SystemUI/res-keyguard/values-hi/strings.xml
index 206b8af..327dfdb 100644
--- a/packages/SystemUI/res-keyguard/values-hi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hi/strings.xml
@@ -62,15 +62,15 @@
     <string name="kg_sim_pin_instructions_multi" msgid="1586316574649150223">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" का SIM पिन डालें"</string>
     <string name="kg_pin_instructions" msgid="4069609316644030034">"पिन डालें"</string>
     <string name="kg_password_instructions" msgid="136952397352976538">"पासवर्ड डालें"</string>
-    <string name="kg_puk_enter_puk_hint" msgid="2288964170039899277">"SIM अब अक्षम हो गई है. जारी रखने के लिए PUK कोड डालें. विवरण के लिए वाहक से संपर्क करें."</string>
-    <string name="kg_puk_enter_puk_hint_multi" msgid="1373131883510840794">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" की SIM अब अक्षम हो गई है. जारी रखने के लिए PUK कोड डालें. विवरण के लिए वाहक से संपर्क करें."</string>
+    <string name="kg_puk_enter_puk_hint" msgid="2288964170039899277">"SIM अब अक्षम हो गया है. जारी रखने के लिए PUK कोड डालें. विवरण के लिए वाहक से संपर्क करें."</string>
+    <string name="kg_puk_enter_puk_hint_multi" msgid="1373131883510840794">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" का SIM अब अक्षम हो गया है. जारी रखने के लिए PUK कोड डालें. विवरण के लिए वाहक से संपर्क करें."</string>
     <string name="kg_puk_enter_pin_hint" msgid="3137789674920391087">"मनचाहा पिन कोड डालें"</string>
     <string name="kg_enter_confirm_pin_hint" msgid="3089485999116759671">"मनचाहे पिन कोड की पुष्टि करें"</string>
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4471738151810900114">"SIM कार्ड अनलॉक हो रहा है…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="3057533256729513335">"कोई ऐसा पिन लिखें, जिसमें 4 से 8 अंक हों."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="6003602401368264144">"PUK कोड 8 या अधिक संख्या वाला होना चाहिए."</string>
-    <string name="kg_invalid_puk" msgid="5399287873762592502">"सही PUK कोड दोबारा डालें. बार-बार कोशिश करने से SIM हमेशा के लिए अक्षम हो जाएगी."</string>
-    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="5672736555427444330">"पिन कोड का मिलान नहीं होता"</string>
+    <string name="kg_invalid_puk" msgid="5399287873762592502">"सही PUK कोड दोबारा डालें. बार-बार कोशिश करने से SIM हमेशा के लिए अक्षम हो जाएगा."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="5672736555427444330">"पिन कोड का मिलान नहीं हो रहा है"</string>
     <string name="kg_login_too_many_attempts" msgid="6604574268387867255">"पैटर्न के लिए बहुत ज़्यादा बार कोशिश की गई है"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8637788033282252027">"आप अपना पिन <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से लिख चुके हैं. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंड में फिर से कोशिश करें."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7724148763268377734">"आप अपना पासवर्ड <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से लिख चुके हैं. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंड में फिर से कोशिश करें."</string>
@@ -94,7 +94,7 @@
       <item quantity="one">SIM पिन कोड गलत है, आप <xliff:g id="NUMBER_1">%d</xliff:g> बार और कोशिश कर सकते हैं.</item>
       <item quantity="other">SIM पिन कोड गलत है, आप <xliff:g id="NUMBER_1">%d</xliff:g> बार और कोशिश कर सकते हैं.</item>
     </plurals>
-    <string name="kg_password_wrong_puk_code_dead" msgid="3329017604125179374">"SIM बेकार हो गई है. अपने वाहक से संपर्क करें."</string>
+    <string name="kg_password_wrong_puk_code_dead" msgid="3329017604125179374">"SIM बेकार हो गया है. अपने वाहक से संपर्क करें."</string>
     <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="2287504898931957513">
       <item quantity="one">SIM PUK कोड गलत है, SIM के हमेशा के लिए बेकार हो जाने से पहले आप <xliff:g id="NUMBER_1">%d</xliff:g> बार और कोशिश कर सकते हैं.</item>
       <item quantity="other">SIM PUK कोड गलत है, SIM के हमेशा के लिए बेकार हो जाने से पहले आप <xliff:g id="NUMBER_1">%d</xliff:g> बार और कोशिश कर सकते हैं.</item>
@@ -105,9 +105,9 @@
     <string name="keyguard_carrier_default" msgid="4274828292998453695">"कोई सेवा नहीं."</string>
     <string name="accessibility_ime_switch_button" msgid="2695096475319405612">"इनपुट पद्धति‍ बदलें"</string>
     <string name="airplane_mode" msgid="3807209033737676010">"हवाई जहाज़ मोड"</string>
-    <string name="kg_prompt_reason_restart_pattern" msgid="7246972020562621506">"डिवाइस फिर से शुरू होने के बाद पैटर्न ज़रूरी है"</string>
-    <string name="kg_prompt_reason_restart_pin" msgid="6303592361322290145">"डिवाइस फिर से शुरू होने के बाद पिन ज़रूरी है"</string>
-    <string name="kg_prompt_reason_restart_password" msgid="6984641181515902406">"डिवाइस फिर से शुरू होने के बाद पासवर्ड ज़रूरी है"</string>
+    <string name="kg_prompt_reason_restart_pattern" msgid="7246972020562621506">"डिवाइस फिर से चालू होने के बाद पैटर्न ज़रूरी है"</string>
+    <string name="kg_prompt_reason_restart_pin" msgid="6303592361322290145">"डिवाइस फिर से चालू होने के बाद पिन ज़रूरी है"</string>
+    <string name="kg_prompt_reason_restart_password" msgid="6984641181515902406">"डिवाइस फिर से चालू होने के बाद पासवर्ड ज़रूरी है"</string>
     <string name="kg_prompt_reason_timeout_pattern" msgid="5304487696073914063">"अतिरिक्‍त सुरक्षा के लिए पैटर्न ज़रूरी है"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="8851462864335757813">"अतिरिक्‍त सुरक्षा के लिए पिन ज़रूरी है"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="6563904839641583441">"अतिरिक्‍त सुरक्षा के लिए पासवर्ड ज़रूरी है"</string>
diff --git a/packages/SystemUI/res-keyguard/values-hr/strings.xml b/packages/SystemUI/res-keyguard/values-hr/strings.xml
index a35c850..10d01af 100644
--- a/packages/SystemUI/res-keyguard/values-hr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hr/strings.xml
@@ -42,7 +42,7 @@
     <string name="keyguard_missing_sim_instructions" msgid="7350295932015220392">"Umetnite SIM karticu."</string>
     <string name="keyguard_missing_sim_instructions_long" msgid="589889372883904477">"SIM kartica nedostaje ili nije čitljiva. Umetnite SIM karticu."</string>
     <string name="keyguard_permanent_disabled_sim_message_short" msgid="654102080186420706">"SIM kartica nije upotrebljiva."</string>
-    <string name="keyguard_permanent_disabled_sim_instructions" msgid="4683178224791318347">"Vaša SIM kartica trajno je onemogućena.\n Obratite se svom davatelju bežičnih usluga da biste dobili drugu SIM karticu."</string>
+    <string name="keyguard_permanent_disabled_sim_instructions" msgid="4683178224791318347">"Vaša SIM kartica trajno je onemogućena.\n Zatražite drugu SIM karticu od svog davatelja bežičnih usluga."</string>
     <string name="keyguard_sim_locked_message" msgid="953766009432168127">"SIM kartica je zaključana."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="1772789643694942073">"SIM kartica je zaključana PUK-om."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="3586601150825821675">"Otključavanje SIM kartice…"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pa/strings.xml b/packages/SystemUI/res-keyguard/values-pa/strings.xml
index d88ee42..6a4c80b 100644
--- a/packages/SystemUI/res-keyguard/values-pa/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pa/strings.xml
@@ -20,7 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3171996292755059205">"ਕੀਗਾਰਡ"</string>
+    <string name="app_name" msgid="3171996292755059205">"ਕੀ-ਗਾਰਡ"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3420548423949593123">"PIN ਕੋਡ ਟਾਈਪ ਕਰੋ"</string>
     <string name="keyguard_password_enter_puk_code" msgid="670683628782925409">"SIM PUK ਅਤੇ ਨਵਾਂ PIN ਕੋਡ ਟਾਈਪ ਕਰੋ"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="3747778500166059332">"SIM PUK ਕੋਡ"</string>
@@ -34,7 +34,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="8869226755413795173">"ਤੇਜ਼ੀ ਨਾਲ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="6637043106038550407">"ਹੌਲੀ-ਹੌਲੀ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
     <string name="keyguard_low_battery" msgid="9218432555787624490">"ਆਪਣਾ ਚਾਰਜਰ ਕਨੈਕਟ ਕਰੋ।"</string>
-    <string name="keyguard_instructions_when_pattern_disabled" msgid="8566679946700751371">"ਅਨਲੌਕ ਕਰਨ ਲਈ ਮੀਨੂ ਦਬਾਓ।"</string>
+    <string name="keyguard_instructions_when_pattern_disabled" msgid="8566679946700751371">"ਅਨਲੌਕ ਕਰਨ ਲਈ \"ਮੀਨੂ\" ਦਬਾਓ।"</string>
     <string name="keyguard_network_locked_message" msgid="6743537524631420759">"ਨੈੱਟਵਰਕ ਲੌਕ ਕੀਤਾ ਗਿਆ"</string>
     <string name="keyguard_missing_sim_message_short" msgid="6327533369959764518">"ਕੋਈ SIM ਕਾਰਡ ਮੌਜੂਦ ਨਹੀਂ"</string>
     <string name="keyguard_missing_sim_message" product="tablet" msgid="4550152848200783542">"ਟੈਬਲੈੱਟ ਵਿੱਚ ਕੋਈ SIM ਕਾਰਡ ਮੌਜੂਦ ਨਹੀਂ।"</string>
@@ -42,7 +42,7 @@
     <string name="keyguard_missing_sim_instructions" msgid="7350295932015220392">"ਇੱਕ SIM ਕਾਰਡ ਪਾਓ।"</string>
     <string name="keyguard_missing_sim_instructions_long" msgid="589889372883904477">"SIM ਕਾਰਡ ਮੌਜੂਦ ਨਹੀਂ ਜਾਂ ਪੜ੍ਹਨਯੋਗ ਨਹੀਂ ਹੈ। ਇੱਕ SIM ਕਾਰਡ ਪਾਓ।"</string>
     <string name="keyguard_permanent_disabled_sim_message_short" msgid="654102080186420706">"ਨਾ-ਵਰਤਣਯੋਗ SIM ਕਾਰਡ।"</string>
-    <string name="keyguard_permanent_disabled_sim_instructions" msgid="4683178224791318347">"ਤੁਹਾਡਾ SIM ਕਾਰਡ ਸਥਾਈ ਤੌਰ \'ਤੇ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ।\n ਦੂਜੇ SIM ਕਾਰਡ ਲਈ ਆਪਣੇ ਵਾਇਰਲੈੱਸ ਸੇਵਾ ਪ੍ਰਦਾਨਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
+    <string name="keyguard_permanent_disabled_sim_instructions" msgid="4683178224791318347">"ਤੁਹਾਡਾ SIM ਕਾਰਡ ਸਥਾਈ ਤੌਰ \'ਤੇ ਅਯੋਗ ਬਣਾ ਦਿੱਤਾ ਗਿਆ ਹੈ।\n ਇੱਕ ਹੋਰ SIM ਕਾਰਡ ਲਈ ਆਪਣੇ ਵਾਇਰਲੈੱਸ ਸੇਵਾ ਪ੍ਰਦਾਨਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
     <string name="keyguard_sim_locked_message" msgid="953766009432168127">"SIM ਕਾਰਡ ਲੌਕ ਕੀਤਾ ਹੋਇਆ ਹੈ।"</string>
     <string name="keyguard_sim_puk_locked_message" msgid="1772789643694942073">"SIM ਕਾਰਡ PUK-ਲੌਕ ਕੀਤਾ ਹੋਇਆ ਹੈ।"</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="3586601150825821675">"SIM ਕਾਰਡ ਨੂੰ ਅਨਲੌਕ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string>
@@ -62,70 +62,70 @@
     <string name="kg_sim_pin_instructions_multi" msgid="1586316574649150223">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" ਲਈ SIM PIN ਦਾਖਲ ਕਰੋ"</string>
     <string name="kg_pin_instructions" msgid="4069609316644030034">"PIN ਦਾਖਲ ਕਰੋ"</string>
     <string name="kg_password_instructions" msgid="136952397352976538">"ਪਾਸਵਰਡ ਦਾਖਲ ਕਰੋ"</string>
-    <string name="kg_puk_enter_puk_hint" msgid="2288964170039899277">"SIM ਹੁਣ ਅਯੋਗ ਬਣਾਈ ਗਈ ਹੈ। ਜਾਰੀ ਰੱਖਣ ਲਈ PUK ਕੋਡ ਦਾਖਲ ਕਰੋ। ਵੇਰਵਿਆਂ ਲਈ ਕੈਰੀਅਰ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
-    <string name="kg_puk_enter_puk_hint_multi" msgid="1373131883510840794">"SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" ਹੁਣ ਅਯੋਗ ਬਣਾਈ ਗਈ ਹੈ। ਜਾਰੀ ਰੱਖਣ ਲਈ PUK ਕੋਡ ਦਾਖਲ ਕਰੋ। ਵੇਰਵਿਆਂ ਲਈ ਕੈਰੀਅਰ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="2288964170039899277">"SIM ਹੁਣ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ। ਜਾਰੀ ਰੱਖਣ ਲਈ PUK ਕੋਡ ਦਾਖਲ ਕਰੋ। ਵੇਰਵਿਆਂ ਲਈ ਕੈਰੀਅਰ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।"</string>
+    <string name="kg_puk_enter_puk_hint_multi" msgid="1373131883510840794">"SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" ਹੁਣ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ। ਜਾਰੀ ਰੱਖਣ ਲਈ PUK ਕੋਡ ਦਾਖਲ ਕਰੋ। ਵੇਰਵਿਆਂ ਲਈ ਕੈਰੀਅਰ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।"</string>
     <string name="kg_puk_enter_pin_hint" msgid="3137789674920391087">"ਇੱਛਤ PIN ਕੋਡ ਦਾਖਲ ਕਰੋ"</string>
     <string name="kg_enter_confirm_pin_hint" msgid="3089485999116759671">"ਇੱਛਤ PIN ਕੋਡ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ"</string>
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4471738151810900114">"SIM ਕਾਰਡ ਨੂੰ ਅਨਲੌਕ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="3057533256729513335">"ਕੋਈ PIN ਟਾਈਪ ਕਰੋ ਜੋ 4 ਤੋਂ 8 ਨੰਬਰਾਂ ਦਾ ਹੋਵੇ।"</string>
     <string name="kg_invalid_sim_puk_hint" msgid="6003602401368264144">"PUK ਕੋਡ 8 ਜਾਂ ਵੱਧ ਨੰਬਰਾਂ ਦਾ ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ।"</string>
-    <string name="kg_invalid_puk" msgid="5399287873762592502">"ਸਹੀ PUK ਕੋਡ ਮੁੜ-ਦਾਖਲ ਕਰੋ। ਦੁਹਰਾਈਆਂ ਗਈਆਂ ਕੋਸ਼ਿਸ਼ਾਂ SIM ਨੂੰ ਸਥਾਈ ਤੌਰ \'ਤੇ ਅਯੋਗ ਬਣਾ ਦੇਣਗੀਆਂ।"</string>
+    <string name="kg_invalid_puk" msgid="5399287873762592502">"ਸਹੀ PUK ਕੋਡ ਮੁੜ-ਦਾਖਲ ਕਰੋ। ਬਾਰ-ਬਾਰ ਕੀਤੀਆਂ ਕੋਸ਼ਿਸ਼ਾਂ SIM ਨੂੰ ਸਥਾਈ ਤੌਰ \'ਤੇ ਅਯੋਗ ਬਣਾ ਦੇਣਗੀਆਂ।"</string>
     <string name="kg_invalid_confirm_pin_hint" product="default" msgid="5672736555427444330">"PIN ਕੋਡ ਮੇਲ ਨਹੀਂ ਖਾਂਦੇ"</string>
     <string name="kg_login_too_many_attempts" msgid="6604574268387867255">"ਬਹੁਤ ਜ਼ਿਆਦਾ ਪੈਟਰਨ ਕੋਸ਼ਿਸ਼ਾਂ"</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8637788033282252027">"ਤੁਸੀਂ ਆਪਣਾ PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟਾਈਪ ਕੀਤਾ। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
-    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7724148763268377734">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਪਾਸਵਰਡ ਗਲਤ ਢੰਗ ਨਾਲ ਟਾਈਪ ਕੀਤਾ।\n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
-    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4820967667848302092">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਨਲੌਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਉਲੀਕਿਆ। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
-    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1629351522209932316">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਇਹ ਟੈਬਲੈੱਟ ਰੀਸੈੱਟ ਕੀਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਇਸਦਾ ਸਾਰਾ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
-    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="3921998703529189931">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਇਹ ਫ਼ੋਨ ਰੀਸੈੱਟ ਕੀਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਇਸਦਾ ਸਾਰਾ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
-    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="4694232971224663735">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ। ਇਹ ਟੈਬਲੈੱਟ ਰੀਸੈੱਟ ਕੀਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਇਸਦਾ ਸਾਰਾ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
-    <string name="kg_failed_attempts_now_wiping" product="default" msgid="2365964340830006961">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ। ਇਹ ਫ਼ੋਨ ਰੀਸੈੱਟ ਕੀਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਇਸਦਾ ਸਾਰਾ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
-    <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="1365418870560228936">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਇਸ ਵਰਤੋਂਕਾਰ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਵਰਤੋਂਕਾਰ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
-    <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="2151286957817486128">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਇਸ ਵਰਤੋਂਕਾਰ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਵਰਤੋਂਕਾਰ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
-    <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="5464020754932560928">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ। ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਪ੍ਰੋਫਾਈਲ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
-    <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="6171564974118059">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ। ਇਹ ਵਰਤੋਂਕਾਰ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਵਰਤੋਂਕਾਰ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
-    <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="9154513795928824239">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਪ੍ਰੋਫਾਈਲ ਦਾ ਸਾਰਾ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
-    <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="2162434417489128282">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਪ੍ਰੋਫਾਈਲ ਦਾ ਸਾਰਾ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
-    <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="8966727588974691544">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ। ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਪ੍ਰੋਫਾਈਲ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
-    <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="8476407539834855">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ। ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਪ੍ਰੋਫਾਈਲ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
-    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="956706236554092172">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਨਲੌਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਉਲੀਕਿਆ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਤੁਹਾਨੂੰ ਇੱਕ ਈਮੇਲ ਖਾਤਾ ਵਰਤਦੇ ਹੋਏ ਆਪਣੇ ਟੈਬਲੈੱਟ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਲਈ ਕਿਹਾ ਜਾਵੇਗਾ।\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
-    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="8364140853305528449">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਨਲੌਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਉਲੀਕਿਆ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਤੁਹਾਨੂੰ ਇੱਕ ਈਮੇਲ ਖਾਤਾ ਵਰਤਦੇ ਹੋਏ ਆਪਣਾ ਫ਼ੋਨ ਅਨਲੌਕ ਕਰਨ ਲਈ ਕਿਹਾ ਜਾਵੇਗਾ।\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
-    <string name="kg_password_wrong_pin_code_pukked" msgid="3389829202093674267">"ਗਲਤ SIM PIN ਕੋਡ, ਹੁਣ ਤੁਹਾਡਾ ਆਪਣੀ ਡੀਵਾਈਸ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਲਈ ਆਪਣੇ ਕੈਰੀਅਰ ਨੂੰ ਸੰਪਰਕ ਕਰਨਾ ਲਾਜ਼ਮੀ ਹੈ।"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8637788033282252027">"ਤੁਸੀਂ ਆਪਣਾ PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟਾਈਪ ਕੀਤਾ ਹੈ। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7724148763268377734">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਪਾਸਵਰਡ ਗਲਤ ਢੰਗ ਨਾਲ ਟਾਈਪ ਕੀਤਾ ਹੈ।\n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4820967667848302092">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਨਲੌਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਉਲੀਕਿਆ ਹੈ। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1629351522209932316">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਇਹ ਟੈਬਲੈੱਟ ਰੀਸੈੱਟ ਕੀਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਇਸਦਾ ਸਾਰਾ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="3921998703529189931">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਇਹ ਫ਼ੋਨ ਰੀਸੈੱਟ ਕੀਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਇਸਦਾ ਸਾਰਾ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="4694232971224663735">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। ਇਹ ਟੈਬਲੈੱਟ ਰੀਸੈੱਟ ਕੀਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਇਸਦਾ ਸਾਰਾ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="2365964340830006961">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। ਇਹ ਫ਼ੋਨ ਰੀਸੈੱਟ ਕੀਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਇਸਦਾ ਸਾਰਾ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+    <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="1365418870560228936">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਇਸ ਵਰਤੋਂਕਾਰ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਵਰਤੋਂਕਾਰ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+    <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="2151286957817486128">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਇਸ ਵਰਤੋਂਕਾਰ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਵਰਤੋਂਕਾਰ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+    <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="5464020754932560928">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। ਇਸ ਵਰਤੋਂਕਾਰ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਵਰਤੋਂਕਾਰ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+    <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="6171564974118059">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। ਇਸ ਵਰਤੋਂਕਾਰ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਵਰਤੋਂਕਾਰ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+    <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="9154513795928824239">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਪ੍ਰੋਫਾਈਲ ਦਾ ਸਾਰਾ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+    <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="2162434417489128282">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਪ੍ਰੋਫਾਈਲ ਦਾ ਸਾਰਾ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+    <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="8966727588974691544">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਪ੍ਰੋਫਾਈਲ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+    <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="8476407539834855">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਪ੍ਰੋਫਾਈਲ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="956706236554092172">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਨਲੌਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਉਲੀਕਿਆ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਤੁਹਾਨੂੰ ਇੱਕ ਈਮੇਲ ਖਾਤਾ ਵਰਤਦੇ ਹੋਏ ਆਪਣੇ ਟੈਬਲੈੱਟ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਲਈ ਕਿਹਾ ਜਾਵੇਗਾ।\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="8364140853305528449">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਨਲੌਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਉਲੀਕਿਆ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਤੁਹਾਨੂੰ ਇੱਕ ਈਮੇਲ ਖਾਤਾ ਵਰਤਦੇ ਹੋਏ ਆਪਣਾ ਫ਼ੋਨ ਅਨਲੌਕ ਕਰਨ ਲਈ ਕਿਹਾ ਜਾਵੇਗਾ।\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="kg_password_wrong_pin_code_pukked" msgid="3389829202093674267">"ਗਲਤ SIM PIN ਕੋਡ, ਆਪਣੀ ਡੀਵਾਈਸ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਲਈ ਹੁਣ ਤੁਹਾਨੂੰ ਲਾਜ਼ਮੀ ਤੌਰ \'ਤੇ ਆਪਣੇ ਕੈਰੀਅਰ ਨਾਲ ਸੰਪਰਕ ਕਰਨਾ ਚਾਹੀਦਾ ਹੈ।"</string>
     <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="4314341367727055967">
-      <item quantity="one">ਗਲਤ SIM PIN ਕੋਡ, ਤੁਹਾਡੀ <xliff:g id="NUMBER_1">%d</xliff:g> ਕੋਸ਼ਿਸ਼ ਬਾਕੀ ਹੈ।</item>
-      <item quantity="other">ਗਲਤ SIM PIN ਕੋਡ, ਤੁਹਾਡੀਆਂ <xliff:g id="NUMBER_1">%d</xliff:g> ਕੋਸ਼ਿਸ਼ਾਂ ਬਾਕੀ ਹਨ।</item>
+      <item quantity="one">ਗਲਤ SIM PIN ਕੋਡ, ਤੁਹਾਡੇ ਕੋਲ <xliff:g id="NUMBER_1">%d</xliff:g> ਕੋਸ਼ਿਸ਼ ਬਾਕੀ ਹੈ।</item>
+      <item quantity="other">ਗਲਤ SIM PIN ਕੋਡ, ਤੁਹਾਡੇ ਕੋਲ <xliff:g id="NUMBER_1">%d</xliff:g> ਕੋਸ਼ਿਸ਼ਾਂ ਬਾਕੀ ਹਨ।</item>
     </plurals>
     <string name="kg_password_wrong_puk_code_dead" msgid="3329017604125179374">"SIM ਨਾ-ਵਰਤਣਯੋਗ ਹੈ। ਆਪਣੇ ਕੈਰੀਅਰ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
     <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="2287504898931957513">
       <item quantity="one">ਗਲਤ SIM PUK ਕੋਡ, ਇਸਤੋਂ ਪਹਿਲਾਂ ਕਿ SIM ਸਥਾਈ ਤੌਰ \'ਤੇ ਵਰਤਣਯੋਗ ਨਾ ਰਹੇ, ਤੁਹਾਡੇ ਕੋਲ <xliff:g id="NUMBER_1">%d</xliff:g> ਕੋਸ਼ਿਸ਼ ਬਾਕੀ ਹੈ।</item>
-      <item quantity="other">ਗਲਤ SIM PUK ਕੋਡ, ਇਸਤੋਂ ਪਹਿਲਾਂ ਕਿ SIM ਸਥਾਈ ਤੌਰ \'ਤੇ ਵਰਤਣਯੋਗ ਨਾ ਰਹੇ, ਤੁਹਾਡੇ ਕੋਲ <xliff:g id="NUMBER_1">%d</xliff:g> ਕੋਸ਼ਿਸ਼ ਬਾਕੀ ਹੈ।</item>
+      <item quantity="other">ਗਲਤ SIM PUK ਕੋਡ, ਇਸਤੋਂ ਪਹਿਲਾਂ ਕਿ SIM ਸਥਾਈ ਤੌਰ \'ਤੇ ਵਰਤਣਯੋਗ ਨਾ ਰਹੇ, ਤੁਹਾਡੇ ਕੋਲ <xliff:g id="NUMBER_1">%d</xliff:g> ਕੋਸ਼ਿਸ਼ਾਂ ਬਾਕੀ ਹਨ।</item>
     </plurals>
     <string name="kg_password_pin_failed" msgid="8769990811451236223">"SIM PIN ਕਾਰਵਾਈ ਅਸਫਲ ਰਹੀ!"</string>
     <string name="kg_password_puk_failed" msgid="1331621440873439974">"SIM PUK ਕਾਰਵਾਈ ਅਸਫਲ ਰਹੀ!"</string>
     <string name="kg_pin_accepted" msgid="7637293533973802143">"ਕੋਡ ਸਵੀਕਾਰ ਕੀਤਾ ਗਿਆ!"</string>
     <string name="keyguard_carrier_default" msgid="4274828292998453695">"ਕੋਈ ਸੇਵਾ ਨਹੀਂ।"</string>
-    <string name="accessibility_ime_switch_button" msgid="2695096475319405612">"ਇਨਪੁੱਟ ਵਿਧੀ \'ਤੇ ਬਦਲੀ ਕਰੋ"</string>
-    <string name="airplane_mode" msgid="3807209033737676010">"ਜਹਾਜ਼ ਮੋਡ"</string>
+    <string name="accessibility_ime_switch_button" msgid="2695096475319405612">"ਇਨਪੁੱਟ ਵਿਧੀ ਬਦਲੋ"</string>
+    <string name="airplane_mode" msgid="3807209033737676010">"ਹਵਾਈ-ਜਹਾਜ਼ ਮੋਡ"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="7246972020562621506">"ਡੀਵਾਈਸ ਦੇ ਮੁੜ-ਚਾਲੂ ਹੋਣ \'ਤੇ ਪੈਟਰਨ ਦੀ ਲੋੜ ਹੈ"</string>
     <string name="kg_prompt_reason_restart_pin" msgid="6303592361322290145">"ਡੀਵਾਈਸ ਦੇ ਮੁੜ-ਚਾਲੂ ਹੋਣ \'ਤੇ PIN ਦੀ ਲੋੜ ਹੈ"</string>
     <string name="kg_prompt_reason_restart_password" msgid="6984641181515902406">"ਡੀਵਾਈਸ ਦੇ ਮੁੜ-ਚਾਲੂ ਹੋਣ \'ਤੇ ਪਾਸਵਰਡ ਦੀ ਲੋੜ ਹੈ"</string>
     <string name="kg_prompt_reason_timeout_pattern" msgid="5304487696073914063">"ਵਧੀਕ ਸੁਰੱਖਿਆ ਲਈ ਪੈਟਰਨ ਦੀ ਲੋੜ ਹੈ"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="8851462864335757813">"ਵਧੀਕ ਸੁਰੱਖਿਆ ਲਈ PIN ਦੀ ਲੋੜ ਹੈ"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="6563904839641583441">"ਵਧੀਕ ਸੁਰੱਖਿਆ ਲਈ ਪਾਸਵਰਡ ਦੀ ਲੋੜ ਹੈ"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="3398054847288438444">"ਪ੍ਰੋਫਾਈਲਾਂ ਵਿਚਾਲੇ ਬਦਲੀ ਕਰਨ ਦੌਰਾਨ ਪੈਟਰਨ ਦੀ ਲੋੜ ਹੈ"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="7426368139226961699">"ਪ੍ਰੋਫਾਈਲਾਂ ਵਿਚਾਲੇ ਬਦਲੀ ਕਰਨ ਦੌਰਾਨ PIN ਦੀ ਲੋੜ ਹੈ"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="8383831046318421845">"ਪ੍ਰੋਫਾਈਲਾਂ ਵਿਚਾਲੇ ਬਦਲੀ ਕਰਨ ਦੌਰਾਨ ਪਾਸਵਰਡ ਦੀ ਲੋੜ ਹੈ"</string>
+    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="3398054847288438444">"ਜਦ ਤੁਸੀਂ ਇੱਕ ਪ੍ਰੋਫਾਈਲ ਤੋਂ ਦੂਜੇ \'ਤੇ ਜਾਂਦੇ ਹੋ ਤਾਂ ਪੈਟਰਨ ਦੀ ਲੋੜ ਹੈ"</string>
+    <string name="kg_prompt_reason_switch_profiles_pin" msgid="7426368139226961699">"ਜਦ ਤੁਸੀਂ ਇੱਕ ਪ੍ਰੋਫਾਈਲ ਤੋਂ ਦੂਜੇ \'ਤੇ ਜਾਂਦੇ ਹੋ ਤਾਂ PIN ਦੀ ਲੋੜ ਹੈ"</string>
+    <string name="kg_prompt_reason_switch_profiles_password" msgid="8383831046318421845">"ਜਦ ਤੁਸੀਂ ਇੱਕ ਪ੍ਰੋਫਾਈਲ ਤੋਂ ਦੂਜੇ \'ਤੇ ਜਾਂਦੇ ਹੋ ਤਾਂ ਪਾਸਵਰਡ ਦੀ ਲੋੜ ਹੈ"</string>
     <string name="kg_prompt_reason_device_admin" msgid="2438626748767361010">"ਡੀਵਾਈਸ ਦੇ ਪ੍ਰਸ਼ਾਸਕ ਨੇ ਡੀਵਾਈਸ ਨੂੰ ਲੌਕ ਕੀਤਾ"</string>
     <string name="kg_prompt_reason_user_request" msgid="8236951765212462286">"ਡੀਵਾਈਸ ਨੂੰ ਹੱਥੀਂ ਲੌਕ ਕੀਤਾ ਗਿਆ"</string>
     <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="71299470072448533">
-      <item quantity="one">ਡੀਵਾਈਸ <xliff:g id="NUMBER_1">%d</xliff:g> ਘੰਟਿਆਂ ਤੋਂ ਅਨਲੌਕ ਨਹੀਂ ਕੀਤੀ ਗਈ ਹੈ। ਪੈਟਰਨ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ।</item>
+      <item quantity="one">ਡੀਵਾਈਸ <xliff:g id="NUMBER_1">%d</xliff:g> ਘੰਟੇ ਤੋਂ ਅਨਲੌਕ ਨਹੀਂ ਕੀਤੀ ਗਈ ਹੈ। ਪੈਟਰਨ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ।</item>
       <item quantity="other">ਡੀਵਾਈਸ <xliff:g id="NUMBER_1">%d</xliff:g> ਘੰਟਿਆਂ ਤੋਂ ਅਨਲੌਕ ਨਹੀਂ ਕੀਤੀ ਗਈ ਹੈ। ਪੈਟਰਨ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ।</item>
     </plurals>
     <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="34586942088144385">
-      <item quantity="one">ਡੀਵਾਈਸ <xliff:g id="NUMBER_1">%d</xliff:g> ਘੰਟਿਆਂ ਤੋਂ ਅਨਲੌਕ ਨਹੀਂ ਕੀਤੀ ਗਈ ਹੈ। PIN ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ।</item>
+      <item quantity="one">ਡੀਵਾਈਸ <xliff:g id="NUMBER_1">%d</xliff:g> ਘੰਟੇ ਤੋਂ ਅਨਲੌਕ ਨਹੀਂ ਕੀਤੀ ਗਈ ਹੈ। PIN ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ।</item>
       <item quantity="other">ਡੀਵਾਈਸ <xliff:g id="NUMBER_1">%d</xliff:g> ਘੰਟਿਆਂ ਤੋਂ ਅਨਲੌਕ ਨਹੀਂ ਕੀਤੀ ਗਈ ਹੈ। PIN ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ।</item>
     </plurals>
     <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="257297696215346527">
-      <item quantity="one">ਡੀਵਾਈਸ <xliff:g id="NUMBER_1">%d</xliff:g> ਘੰਟਿਆਂ ਤੋਂ ਅਨਲੌਕ ਨਹੀਂ ਕੀਤੀ ਗਈ ਹੈ। ਪਾਸਵਰਡ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ।</item>
+      <item quantity="one">ਡੀਵਾਈਸ <xliff:g id="NUMBER_1">%d</xliff:g> ਘੰਟੇ ਤੋਂ ਅਨਲੌਕ ਨਹੀਂ ਕੀਤੀ ਗਈ ਹੈ। ਪਾਸਵਰਡ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ।</item>
       <item quantity="other">ਡੀਵਾਈਸ <xliff:g id="NUMBER_1">%d</xliff:g> ਘੰਟਿਆਂ ਤੋਂ ਅਨਲੌਕ ਨਹੀਂ ਕੀਤੀ ਗਈ ਹੈ। ਪਾਸਵਰਡ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ।</item>
     </plurals>
     <string name="fingerprint_not_recognized" msgid="348813995267914625">"ਪਛਾਣ ਨਹੀਂ ਹੋਈ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sr/strings.xml b/packages/SystemUI/res-keyguard/values-sr/strings.xml
index 69070e9..e420632 100644
--- a/packages/SystemUI/res-keyguard/values-sr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sr/strings.xml
@@ -51,8 +51,8 @@
     <string name="keyguard_accessibility_sim_puk_area" msgid="136979425761438705">"Област за PUK за SIM"</string>
     <string name="keyguard_accessibility_next_alarm" msgid="5835196989158584991">"Следећи аларм је подешен за <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="6883116827512721630">"Избриши"</string>
-    <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Унеси"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Заборавили сте шаблон?"</string>
+    <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Заборавио/ла сам шаблон"</string>
     <string name="kg_wrong_pattern" msgid="7620081431514773802">"Погрешан шаблон"</string>
     <string name="kg_wrong_password" msgid="4580683060277329277">"Погрешна лозинка"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Погрешан PIN"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sw/strings.xml b/packages/SystemUI/res-keyguard/values-sw/strings.xml
index 2f0a074..057f852 100644
--- a/packages/SystemUI/res-keyguard/values-sw/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sw/strings.xml
@@ -21,14 +21,14 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_name" msgid="3171996292755059205">"Kilinda vitufe"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="3420548423949593123">"Andika msimbo wa PIN"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="670683628782925409">"Chapa PUK ya SIM na msimbo mpya wa PIN"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3747778500166059332">"Msimbo wa PUK ya SIM"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="8188243197504453830">"Msimbo mpya wa PIN ya SIM"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="5790410752696806482"><font size="17">"Gusa ili uandike nenosiri "</font></string>
+    <string name="keyguard_password_enter_pin_code" msgid="3420548423949593123">"Weka nambari ya PIN"</string>
+    <string name="keyguard_password_enter_puk_code" msgid="670683628782925409">"Weka PUK na nambari mpya ya PIN ya SIM"</string>
+    <string name="keyguard_password_enter_puk_prompt" msgid="3747778500166059332">"Nambari ya PUK ya SIM"</string>
+    <string name="keyguard_password_enter_pin_prompt" msgid="8188243197504453830">"Nambari mpya ya PIN ya SIM"</string>
+    <string name="keyguard_password_entry_touch_hint" msgid="5790410752696806482"><font size="17">"Gusa ili uandike nenosiri"</font></string>
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"Andika nenosiri ili ufungue"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"Andika PIN ili ufungue"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Msimbo wa PIN usio sahihi."</string>
+    <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"Nambari ya PIN si sahihi."</string>
     <string name="keyguard_charged" msgid="2222329688813033109">"Betri imejaa"</string>
     <string name="keyguard_plugged_in" msgid="89308975354638682">"Inachaji"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="8869226755413795173">"Inachaji kwa kasi"</string>
@@ -37,12 +37,12 @@
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8566679946700751371">"Bonyeza Menyu ili kufungua."</string>
     <string name="keyguard_network_locked_message" msgid="6743537524631420759">"Mtandao umefungwa"</string>
     <string name="keyguard_missing_sim_message_short" msgid="6327533369959764518">"Hakuna SIM kadi"</string>
-    <string name="keyguard_missing_sim_message" product="tablet" msgid="4550152848200783542">"Hakuna SIM kadi katika kompyuta ndogo."</string>
+    <string name="keyguard_missing_sim_message" product="tablet" msgid="4550152848200783542">"Hakuna SIM kadi katika kompyuta kibao."</string>
     <string name="keyguard_missing_sim_message" product="default" msgid="6585414237800161146">"Hakuna SIM kadi kwenye simu."</string>
     <string name="keyguard_missing_sim_instructions" msgid="7350295932015220392">"Weka SIM kadi."</string>
     <string name="keyguard_missing_sim_instructions_long" msgid="589889372883904477">"SIM kadi haiko au haisomeki. Weka SIM kadi."</string>
     <string name="keyguard_permanent_disabled_sim_message_short" msgid="654102080186420706">"SIM kadi isiyotumika."</string>
-    <string name="keyguard_permanent_disabled_sim_instructions" msgid="4683178224791318347">"SIM kadi yako imefungwa kabisa.\n Wasiliana na mtoa huduma isiyotumia waya ili upate SIM kadi nyingine."</string>
+    <string name="keyguard_permanent_disabled_sim_instructions" msgid="4683178224791318347">"SIM kadi yako imefungwa kabisa.\n Wasiliana na mtoa huduma za mtandao ili upate SIM kadi nyingine."</string>
     <string name="keyguard_sim_locked_message" msgid="953766009432168127">"SIM kadi imefungwa."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="1772789643694942073">"SIM kadi imefungwa kwa PUK."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="3586601150825821675">"Inafungua SIM kadi..."</string>
@@ -57,24 +57,24 @@
     <string name="kg_wrong_password" msgid="4580683060277329277">"Nenosiri si Sahihi"</string>
     <string name="kg_wrong_pin" msgid="4785660766909463466">"Nambari ya PIN si sahihi"</string>
     <string name="kg_too_many_failed_attempts_countdown" msgid="527455490371878356">"Jaribu tena baada ya sekunde <xliff:g id="NUMBER">%d</xliff:g>."</string>
-    <string name="kg_pattern_instructions" msgid="5547646893001491340">"Andika mchoro wako"</string>
+    <string name="kg_pattern_instructions" msgid="5547646893001491340">"Chora mchoro wako"</string>
     <string name="kg_sim_pin_instructions" msgid="1795013002231184046">"Weka PIN ya SIM"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="1586316574649150223">"Weka PIN ya SIM ya \"<xliff:g id="CARRIER">%1$s</xliff:g>\""</string>
     <string name="kg_pin_instructions" msgid="4069609316644030034">"Weka PIN"</string>
     <string name="kg_password_instructions" msgid="136952397352976538">"Weka Nenosiri"</string>
-    <string name="kg_puk_enter_puk_hint" msgid="2288964170039899277">"SIM sasa imefungwa. Weka msimbo wa PUK ili uendelee. Wasiliana na mtoa huduma kwa maelezo."</string>
-    <string name="kg_puk_enter_puk_hint_multi" msgid="1373131883510840794">"SIM ya \"<xliff:g id="CARRIER">%1$s</xliff:g>\" sasa imezimwa. Weka msimbo wa PUK ili uendelee. Wasiliana na mtoa huduma kwa maelezo."</string>
-    <string name="kg_puk_enter_pin_hint" msgid="3137789674920391087">"Weka msimbo wa PIN unaopendelea"</string>
-    <string name="kg_enter_confirm_pin_hint" msgid="3089485999116759671">"Thibitisha msimbo wa PIN unaopendelea"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="2288964170039899277">"SIM sasa imefungwa. Weka nambari ya PUK ili uendelee. Wasiliana na mtoa huduma za mtandao kwa maelezo."</string>
+    <string name="kg_puk_enter_puk_hint_multi" msgid="1373131883510840794">"SIM ya \"<xliff:g id="CARRIER">%1$s</xliff:g>\" sasa imezimwa. Weka nambari ya PUK ili uendelee. Wasiliana na mtoa huduma kwa maelezo."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="3137789674920391087">"Weka nambari ya PIN unayopendelea"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="3089485999116759671">"Thibitisha nambari ya PIN unayopendelea"</string>
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4471738151810900114">"Inafungua SIM kadi..."</string>
     <string name="kg_invalid_sim_pin_hint" msgid="3057533256729513335">"Andika PIN ya tarakimu 4 hadi 8."</string>
-    <string name="kg_invalid_sim_puk_hint" msgid="6003602401368264144">"Msimbo wa PUK unafaa kuwa na tarakimu 8 au zaidi."</string>
-    <string name="kg_invalid_puk" msgid="5399287873762592502">"Weka upya msimbo sahihi wa PUK. Majaribio yanayorudiwa yatafunga SIM kabisa."</string>
-    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="5672736555427444330">"Misimbo ya PIN haifanani"</string>
-    <string name="kg_login_too_many_attempts" msgid="6604574268387867255">"Majaribio mengi mno ya mchoro"</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8637788033282252027">"Umekosea kuandika nenosiri lako mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. \n\n Jaribu tena baada ya sekunde <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
-    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7724148763268377734">"Umekosea kuweka nenosiri lako mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. \n\n Jaribu tena baada ya sekunde <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
-    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4820967667848302092">"Umekosea kuweka mchoro wako wa kufungua mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. \n\n Jaribu tena baada ya sekunde <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <string name="kg_invalid_sim_puk_hint" msgid="6003602401368264144">"Nambari ya PUK inafaa kuwa na tarakimu 8 au zaidi."</string>
+    <string name="kg_invalid_puk" msgid="5399287873762592502">"Weka tena nambari sahihi wa PUK. Ukirudia mara nyingi utafunga SIM kabisa."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="5672736555427444330">"Nambari za PIN hazifanani"</string>
+    <string name="kg_login_too_many_attempts" msgid="6604574268387867255">"Umejaribu kuchora mchoro mara nyingi mno"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8637788033282252027">"Umeandika vibaya PIN mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. \n\n Jaribu tena baada ya sekunde <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7724148763268377734">"Umeandika vibaya nenosiri lako mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. \n\n Jaribu tena baada ya sekunde <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4820967667848302092">"Umechora vibaya mchoro wako wa kufungua mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. \n\n Jaribu tena baada ya sekunde <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1629351522209932316">"Umejaribu kufungua kompyuta kibao mara <xliff:g id="NUMBER_0">%1$d</xliff:g> bila mafanikio. Ukikosea mara nyingine <xliff:g id="NUMBER_1">%2$d</xliff:g>,  kompyuta hii kibao itarejeshwa katika hali iliyotoka nayo kiwandani, hatua itakayofuta data yake yote."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="3921998703529189931">"Umejaribu kufungua simu mara <xliff:g id="NUMBER_0">%1$d</xliff:g> bila mafanikio. Ukikosea mara nyingine <xliff:g id="NUMBER_1">%2$d</xliff:g>, simu hii itarejeshwa katika hali iliyotoka nayo kiwandani, hatua itakayofuta data yake yote."</string>
     <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="4694232971224663735">"Umejaribu kufungua simu mara <xliff:g id="NUMBER">%d</xliff:g> bila mafanikio. Kompyuta hii kibao itarejeshwa katika hali iliyotoka nayo kiwandani, hatua itakayofuta data yake yote."</string>
@@ -89,25 +89,25 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="8476407539834855">"Umejaribu kufungua simu mara <xliff:g id="NUMBER">%d</xliff:g> bila mafanikio. Wasifu wa kazini utaondolewa, hatua itakayofuta data yote ya wasifu."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="956706236554092172">"Umekosea kuchora mchoro wako wa kufungua mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. Ukikosea mara nyingine <xliff:g id="NUMBER_1">%2$d</xliff:g>, utaombwa kufungua kompyuta yako kibao kwa kutumia akaunti yako ya barua pepe.\n\n Jaribu tena baada ya sekunde <xliff:g id="NUMBER_2">%3$d</xliff:g>."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="8364140853305528449">"Umekosea kuchora mchoro wako wa kufungua mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. Ukikosea mara nyingine <xliff:g id="NUMBER_1">%2$d</xliff:g>, utaombwa kufungua simu yako kwa kutumia akaunti ya barua pepe.\n\n Jaribu tena baada ya sekunde <xliff:g id="NUMBER_2">%3$d</xliff:g>."</string>
-    <string name="kg_password_wrong_pin_code_pukked" msgid="3389829202093674267">"Msimbo wa PIN ya SIM usio sahihi sasa lazima uwasiliane na mtoa huduma wako ili ufungue kifaa chako."</string>
+    <string name="kg_password_wrong_pin_code_pukked" msgid="3389829202093674267">"Nambari ya PIN ya SIM si sahihi, sasa lazima uwasiliane na mtoa huduma za mtandao ndipo ufungue kifaa chako."</string>
     <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="4314341367727055967">
-      <item quantity="other">Msimbo wa PIN ya SIM si sahihi, bado unaweza kujaribu mara <xliff:g id="NUMBER_1">%d</xliff:g>.</item>
-      <item quantity="one">Msimbo wa PIN ya SIM si sahihi, bado unaweza kujaribu mara <xliff:g id="NUMBER_0">%d</xliff:g> kabla ya kuwasiliana na mtoa huduma wako ili afungue kifaa chako.</item>
+      <item quantity="other">Nambari ya PIN ya SIM si sahihi. Una nafasi zingine <xliff:g id="NUMBER_1">%d</xliff:g> za kujaribu.</item>
+      <item quantity="one">Nambari ya PIN ya SIM si sahihi. Una nafasi zingine <xliff:g id="NUMBER_0">%d</xliff:g> za kujaribu kabla ulazimike kuwasiliana na mtoa huduma wako ili akufungulie kifaa chako.</item>
     </plurals>
     <string name="kg_password_wrong_puk_code_dead" msgid="3329017604125179374">"SIM haiwezi kutumika. Wasiliana na mtoa huduma wako."</string>
     <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="2287504898931957513">
-      <item quantity="other">Msimbo wa PUK ya SIM si sahihi, bado unaweza kujaribu mara <xliff:g id="NUMBER_1">%d</xliff:g> kabla ya SIM kuacha kutumika kabisa.</item>
-      <item quantity="one">Msimbo wa PUK ya SIM si sahihi, bado unaweza kujaribu mara <xliff:g id="NUMBER_0">%d</xliff:g> kabla ya SIM kuacha kutumika kabisa.</item>
+      <item quantity="other">Nambari ya PUK ya SIM si sahihi, bado unaweza kujaribu mara <xliff:g id="NUMBER_1">%d</xliff:g> kabla ya SIM kuacha kutumika kabisa.</item>
+      <item quantity="one">Nambari ya PUK ya SIM si sahihi, bado unaweza kujaribu mara <xliff:g id="NUMBER_0">%d</xliff:g> kabla ya SIM kuacha kutumika kabisa.</item>
     </plurals>
-    <string name="kg_password_pin_failed" msgid="8769990811451236223">"Utendakazi wa PIN ya SIM umeshindwa!"</string>
-    <string name="kg_password_puk_failed" msgid="1331621440873439974">"Utendakazi wa PUK ya SIM umeshindwa!"</string>
-    <string name="kg_pin_accepted" msgid="7637293533973802143">"Msimbo Umekubaliwa!"</string>
-    <string name="keyguard_carrier_default" msgid="4274828292998453695">"Hakuna huduma."</string>
+    <string name="kg_password_pin_failed" msgid="8769990811451236223">"Utendakazi wa PIN ya SIM haujafanikiwa!"</string>
+    <string name="kg_password_puk_failed" msgid="1331621440873439974">"Utendakazi wa PUK ya SIM haujafanikiwa!"</string>
+    <string name="kg_pin_accepted" msgid="7637293533973802143">"Nambari Imekubaliwa!"</string>
+    <string name="keyguard_carrier_default" msgid="4274828292998453695">"Hakuna mtandao."</string>
     <string name="accessibility_ime_switch_button" msgid="2695096475319405612">"Badilisha mbinu ya kuingiza data"</string>
     <string name="airplane_mode" msgid="3807209033737676010">"Hali ya ndegeni"</string>
-    <string name="kg_prompt_reason_restart_pattern" msgid="7246972020562621506">"Inahitaji mchoro baada ya kuwasha kifaa upya"</string>
-    <string name="kg_prompt_reason_restart_pin" msgid="6303592361322290145">"Inahitaji PIN baada ya kuwasha kifaa upya"</string>
-    <string name="kg_prompt_reason_restart_password" msgid="6984641181515902406">"Inahitaji nenosiri baada ya kuwasha kifaa upya"</string>
+    <string name="kg_prompt_reason_restart_pattern" msgid="7246972020562621506">"Unafaa kuchora mchoro baada ya kuwasha kifaa upya"</string>
+    <string name="kg_prompt_reason_restart_pin" msgid="6303592361322290145">"Unafaa kuweka PIN baada ya kuwasha kifaa upya"</string>
+    <string name="kg_prompt_reason_restart_password" msgid="6984641181515902406">"Unafaa kuweka nenosiri baada ya kuwasha kifaa upya"</string>
     <string name="kg_prompt_reason_timeout_pattern" msgid="5304487696073914063">"Mchoro unahitajika ili kuongeza usalama"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="8851462864335757813">"PIN inahitajika ili kuongeza usalama"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="6563904839641583441">"Nenosiri linahitajika ili kuongeza usalama."</string>
diff --git a/packages/SystemUI/res-keyguard/values-ta/strings.xml b/packages/SystemUI/res-keyguard/values-ta/strings.xml
index 3ac0a2b..8876750 100644
--- a/packages/SystemUI/res-keyguard/values-ta/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ta/strings.xml
@@ -62,8 +62,8 @@
     <string name="kg_sim_pin_instructions_multi" msgid="1586316574649150223">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\"க்கான சிம் பின்னை உள்ளிடவும்"</string>
     <string name="kg_pin_instructions" msgid="4069609316644030034">"பின்னை உள்ளிடவும்"</string>
     <string name="kg_password_instructions" msgid="136952397352976538">"கடவுச்சொல்லை உள்ளிடவும்"</string>
-    <string name="kg_puk_enter_puk_hint" msgid="2288964170039899277">"சிம் தற்போது முடக்கப்பட்டுள்ளது. தொடர, PUK குறியீட்டை உள்ளிடவும். விவரங்களுக்கு, தொலைதொடர்பு நிறுவனத்தைத் தொடர்புகொள்ளவும்."</string>
-    <string name="kg_puk_enter_puk_hint_multi" msgid="1373131883510840794">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" சிம் தற்போது முடக்கப்பட்டுள்ளது. தொடர, PUK குறியீட்டை உள்ளிடவும். விவரங்களுக்கு, தொலைதொடர்பு நிறுவனத்தைத் தொடர்புகொள்ளவும்."</string>
+    <string name="kg_puk_enter_puk_hint" msgid="2288964170039899277">"சிம் தற்போது முடக்கப்பட்டுள்ளது. தொடர, PUK குறியீட்டை உள்ளிடவும். விவரங்களுக்கு, தொலைத்தொடர்பு நிறுவனத்தைத் தொடர்புகொள்ளவும்."</string>
+    <string name="kg_puk_enter_puk_hint_multi" msgid="1373131883510840794">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" சிம் தற்போது முடக்கப்பட்டுள்ளது. தொடர, PUK குறியீட்டை உள்ளிடவும். விவரங்களுக்கு, தொலைத்தொடர்பு நிறுவனத்தைத் தொடர்புகொள்ளவும்."</string>
     <string name="kg_puk_enter_pin_hint" msgid="3137789674920391087">"பின் குறியீட்டை உள்ளிடவும்"</string>
     <string name="kg_enter_confirm_pin_hint" msgid="3089485999116759671">"பின் குறியீட்டை உறுதிப்படுத்தவும்"</string>
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4471738151810900114">"சிம் கார்டைத் திறக்கிறது…"</string>
@@ -74,7 +74,7 @@
     <string name="kg_login_too_many_attempts" msgid="6604574268387867255">"பேட்டர்னை அதிக முறை தவறாக வரைந்துவிட்டீர்கள்"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8637788033282252027">"உங்கள் பின்னை <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக உள்ளிட்டுவிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> வினாடிகளில் மீண்டும் முயலவும்."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7724148763268377734">"உங்கள் கடவுச்சொல்லை <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக உள்ளிட்டுவிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> வினாடிகளில் மீண்டும் முயலவும்."</string>
-    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4820967667848302092">"திறப்பதற்கானபேட்டர்னை, <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக வரைந்துவிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> வினாடிகளில் மீண்டும் முயலவும்."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4820967667848302092">"திறப்பதற்கான பேட்டர்னை, <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக வரைந்துவிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> வினாடிகளில் மீண்டும் முயலவும்."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1629351522209932316">"டேப்லெட்டைத் திறக்க, <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக முயன்றுவிட்டீர்கள். இன்னும் <xliff:g id="NUMBER_1">%2$d</xliff:g> முறை தவறாக முயன்றால், இந்த டேப்லெட் மீட்டமைக்கப்பட்டு, அதன் எல்லாத் தரவும் நீக்கப்படும்."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="3921998703529189931">"மொபைலைத் திறக்க, <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக முயன்றுவிட்டீர்கள். இன்னும் <xliff:g id="NUMBER_1">%2$d</xliff:g> முறை தவறாக முயன்றால், இந்த மொபைல் மீட்டமைக்கப்பட்டு, அதன் எல்லாத் தரவும் நீக்கப்படும்."</string>
     <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="4694232971224663735">"டேப்லெட்டைத் திறக்க, <xliff:g id="NUMBER">%d</xliff:g> முறை தவறாக முயன்றுவிட்டீர்கள். இந்த டேப்லெட் மீட்டமைக்கப்பட்டு, அதன் எல்லாத் தரவும் நீக்கப்படும்."</string>
@@ -89,15 +89,15 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="8476407539834855">"மொபைலைத் திறக்க, <xliff:g id="NUMBER">%d</xliff:g> முறை தவறாக முயன்றுவிட்டீர்கள். பணி விவரம் அகற்றப்பட்டு, எல்லாச் சுயவிவரத் தரவும் நீக்கப்படும்."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="956706236554092172">"திறப்பதற்கான பேட்டர்னை, <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக வரைந்துவிட்டீர்கள். இன்னும் <xliff:g id="NUMBER_1">%2$d</xliff:g> முறை தவறாக வரைந்தால், மின்னஞ்சல் கணக்கைப் பயன்படுத்தி டேப்லெட்டைத் திறக்கும்படி கேட்கப்படுவீர்கள்.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> வினாடிகளில் மீண்டும் முயலவும்."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="8364140853305528449">"திறப்பதற்கான பேட்டர்னை, <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக வரைந்துவிட்டீர்கள். இன்னும் <xliff:g id="NUMBER_1">%2$d</xliff:g> முறை தவறாக வரைந்தால், மின்னஞ்சல் கணக்கைப் பயன்படுத்தி மொபைலைத் திறக்கும்படி கேட்கப்படுவீர்கள்.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> வினாடிகளில் மீண்டும் முயலவும்."</string>
-    <string name="kg_password_wrong_pin_code_pukked" msgid="3389829202093674267">"சிம்மின் பின் குறியீடு தவறானது. இனி சாதனத்தைத் திறக்க, உங்கள் தொலைதொடர்பு நிறுவனத்தைத் தொடர்புகொள்ள வேண்டும்."</string>
+    <string name="kg_password_wrong_pin_code_pukked" msgid="3389829202093674267">"சிம்மின் பின் குறியீடு தவறானது. இனி சாதனத்தைத் திறக்க, உங்கள் தொலைத்தொடர்பு நிறுவனத்தைத் தொடர்புகொள்ள வேண்டும்."</string>
     <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="4314341367727055967">
       <item quantity="other">சிம்மின் பின் குறியீடு தவறானது, இன்னும் நீங்கள் <xliff:g id="NUMBER_1">%d</xliff:g> முறை முயலலாம்.</item>
-      <item quantity="one">சிம்மின் பின் குறியீடு தவறானது, மேலும் <xliff:g id="NUMBER_0">%d</xliff:g> முயற்சிகளுக்குப் பின்னர், உங்கள் தொலைதொடர்பு நிறுவனத்தைத் தொடர்பு கொண்டு மட்டுமே சாதனத்தைத் திறக்க முடியும்.</item>
+      <item quantity="one">சிம்மின் பின் குறியீடு தவறானது, மேலும் <xliff:g id="NUMBER_0">%d</xliff:g> முயற்சிகளுக்குப் பின்னர், உங்கள் தொலைத்தொடர்பு நிறுவனத்தைத் தொடர்பு கொண்டு மட்டுமே சாதனத்தைத் திறக்க முடியும்.</item>
     </plurals>
-    <string name="kg_password_wrong_puk_code_dead" msgid="3329017604125179374">"பயன்படுத்த முடியாத சிம். உங்கள் தொலைதொடர்பு நிறுவனத்தைத் தொடர்புகொள்ளவும்."</string>
+    <string name="kg_password_wrong_puk_code_dead" msgid="3329017604125179374">"பயன்படுத்த முடியாத சிம். உங்கள் தொலைத்தொடர்பு நிறுவனத்தைத் தொடர்புகொள்ளவும்."</string>
     <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="2287504898931957513">
-      <item quantity="other">சிம்மின் PUK குறியீடு தவறானது, சிம்மை நிரந்தரமாகப் பயன்படுத்த முடியாமல் போவதற்கு முன், நீங்கள் <xliff:g id="NUMBER_1">%d</xliff:g> முறை முயலலாம்.</item>
-      <item quantity="one">சிம்மின் PUK குறியீடு தவறானது, சிம்மை நிரந்தரமாகப் பயன்படுத்த முடியாமல் போவதற்கு முன், நீங்கள் <xliff:g id="NUMBER_0">%d</xliff:g> முறை முயலலாம்.</item>
+      <item quantity="other">சிம்மின் PUK குறியீடு தவறானது, மேலும் <xliff:g id="NUMBER_1">%d</xliff:g> முறை முயலலாம். தொடர்ந்து தவறான குறியீடு உள்ளிடப்பட்டால், அதன் பிறகு சிம்மை நிரந்தரமாகப் பயன்படுத்த முடியாமல் போகும்.</item>
+      <item quantity="one">சிம்மின் PUK குறியீடு தவறானது, மேலும் <xliff:g id="NUMBER_0">%d</xliff:g> முறை முயலலாம். தொடர்ந்து தவறான குறியீடு உள்ளிடப்பட்டால், அதன் பிறகு சிம்மை நிரந்தரமாகப் பயன்படுத்த முடியாமல் போகும்.</item>
     </plurals>
     <string name="kg_password_pin_failed" msgid="8769990811451236223">"சிம் பின் செயல்பாடு தோல்வியடைந்தது!"</string>
     <string name="kg_password_puk_failed" msgid="1331621440873439974">"சிம் PUK செயல்பாடு தோல்வியடைந்தது!"</string>
diff --git a/packages/SystemUI/res-keyguard/values-te/strings.xml b/packages/SystemUI/res-keyguard/values-te/strings.xml
index 1245416..ae79089 100644
--- a/packages/SystemUI/res-keyguard/values-te/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-te/strings.xml
@@ -40,7 +40,7 @@
     <string name="keyguard_missing_sim_message" product="tablet" msgid="4550152848200783542">"టాబ్లెట్‌లో SIM కార్డ్ లేదు."</string>
     <string name="keyguard_missing_sim_message" product="default" msgid="6585414237800161146">"ఫోన్‌లో SIM కార్డ్ లేదు."</string>
     <string name="keyguard_missing_sim_instructions" msgid="7350295932015220392">"SIM కార్డ్‌ని చొప్పించండి."</string>
-    <string name="keyguard_missing_sim_instructions_long" msgid="589889372883904477">"SIM కార్డ్ లేదు లేదా ఆమోదయోగ్యంగా లేదు. SIM కార్డ్‌ని చొప్పించండి."</string>
+    <string name="keyguard_missing_sim_instructions_long" msgid="589889372883904477">"SIM కార్డ్ లేదు లేదా ఆమోదయోగ్యం కాదు. SIM కార్డ్‌ని చొప్పించండి."</string>
     <string name="keyguard_permanent_disabled_sim_message_short" msgid="654102080186420706">"SIM కార్డ్ నిరుపయోగకరంగా మారింది."</string>
     <string name="keyguard_permanent_disabled_sim_instructions" msgid="4683178224791318347">"మీ SIM కార్డ్ శాశ్వతంగా నిలిపివేయబడింది.\n మరో SIM కార్డ్‌ని పొందడం కోసం మీ వైర్‌లెస్ సేవా ప్రదాతను సంప్రదించండి."</string>
     <string name="keyguard_sim_locked_message" msgid="953766009432168127">"SIM కార్డ్ లాక్ చేయబడింది."</string>
@@ -51,7 +51,7 @@
     <string name="keyguard_accessibility_sim_puk_area" msgid="136979425761438705">"SIM PUK ప్రాంతం"</string>
     <string name="keyguard_accessibility_next_alarm" msgid="5835196989158584991">"తదుపరి అలారం <xliff:g id="ALARM">%1$s</xliff:g>కి సెట్ చేయబడింది"</string>
     <string name="keyboardview_keycode_delete" msgid="6883116827512721630">"తొలగించు"</string>
-    <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"నమోదు చేయండి"</string>
+    <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"నమూనాను మర్చిపోయాను"</string>
     <string name="kg_wrong_pattern" msgid="7620081431514773802">"నమూనా తప్పు"</string>
     <string name="kg_wrong_password" msgid="4580683060277329277">"పాస్‌వర్డ్ తప్పు"</string>
diff --git a/packages/SystemUI/res-keyguard/values-th/strings.xml b/packages/SystemUI/res-keyguard/values-th/strings.xml
index 65d7d30..6e8f965 100644
--- a/packages/SystemUI/res-keyguard/values-th/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-th/strings.xml
@@ -24,7 +24,7 @@
     <string name="keyguard_password_enter_pin_code" msgid="3420548423949593123">"พิมพ์รหัส PIN"</string>
     <string name="keyguard_password_enter_puk_code" msgid="670683628782925409">"พิมพ์ PUK ของซิมและรหัส PIN ใหม่"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="3747778500166059332">"รหัส PUK ของซิม"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="8188243197504453830">"รหัส PIN ของซิมใหม่"</string>
+    <string name="keyguard_password_enter_pin_prompt" msgid="8188243197504453830">"รหัส PIN ใหม่ของซิม"</string>
     <string name="keyguard_password_entry_touch_hint" msgid="5790410752696806482"><font size="17">"แตะเพื่อพิมพ์รหัสผ่าน"</font></string>
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"พิมพ์รหัสผ่านเพื่อปลดล็อก"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"พิมพ์ PIN เพื่อปลดล็อก"</string>
@@ -35,7 +35,7 @@
     <string name="keyguard_plugged_in_charging_slowly" msgid="6637043106038550407">"กำลังชาร์จอย่างช้าๆ"</string>
     <string name="keyguard_low_battery" msgid="9218432555787624490">"เสียบที่ชาร์จของคุณ"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8566679946700751371">"กด \"เมนู\" เพื่อปลดล็อก"</string>
-    <string name="keyguard_network_locked_message" msgid="6743537524631420759">"ล็อกเครือข่ายแล้ว"</string>
+    <string name="keyguard_network_locked_message" msgid="6743537524631420759">"เครือข่ายถูกล็อก"</string>
     <string name="keyguard_missing_sim_message_short" msgid="6327533369959764518">"ไม่มีซิมการ์ด"</string>
     <string name="keyguard_missing_sim_message" product="tablet" msgid="4550152848200783542">"ไม่มีซิมการ์ดในแท็บเล็ต"</string>
     <string name="keyguard_missing_sim_message" product="default" msgid="6585414237800161146">"ไม่มีซิมการ์ดในโทรศัพท์"</string>
@@ -72,19 +72,19 @@
     <string name="kg_invalid_puk" msgid="5399287873762592502">"ใส่รหัส PUK ที่ถูกต้องอีกครั้ง การพยายามซ้ำหลายครั้งจะทำให้ซิมการ์ดถูกปิดใช้งานอย่างถาวร"</string>
     <string name="kg_invalid_confirm_pin_hint" product="default" msgid="5672736555427444330">"รหัส PIN ไม่ตรง"</string>
     <string name="kg_login_too_many_attempts" msgid="6604574268387867255">"ลองหลายรูปแบบมากเกินไป"</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8637788033282252027">"คุณพิมพ์ PIN ไม่ถูกต้องไป <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้งแล้ว \n\nโปรดลองอีกครั้งใน <xliff:g id="NUMBER_1">%2$d</xliff:g> วินาที"</string>
-    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7724148763268377734">"คุณพิมพ์รหัสผ่านไม่ถูกต้องไป <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้งแล้ว \n\nโปรดลองอีกครั้งใน <xliff:g id="NUMBER_1">%2$d</xliff:g> วินาที"</string>
-    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4820967667848302092">"คุณวาดรูปแบบการปลดล็อกไม่ถูกต้องไป <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้งแล้ว \n\nโปรดลองอีกครั้งในอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> วินาที"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8637788033282252027">"คุณพิมพ์ PIN ไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้งแล้ว \n\nโปรดลองอีกครั้งใน <xliff:g id="NUMBER_1">%2$d</xliff:g> วินาที"</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7724148763268377734">"คุณพิมพ์รหัสผ่านไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้งแล้ว \n\nโปรดลองอีกครั้งใน <xliff:g id="NUMBER_1">%2$d</xliff:g> วินาที"</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4820967667848302092">"คุณวาดรูปแบบการปลดล็อกไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้งแล้ว \n\nโปรดลองอีกครั้งในอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> วินาที"</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1629351522209932316">"คุณปลดล็อกแท็บเล็ตไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้ง หากพยายามไม่สำเร็จอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> ครั้ง ระบบจะรีเซ็ตแท็บเล็ตเครื่องนี้ ซึ่งจะเป็นการลบข้อมูลทั้งหมดในเครื่อง"</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="3921998703529189931">"คุณปลดล็อกโทรศัพท์ไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้ง หากพยายามไม่สำเร็จอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> ครั้ง ระบบจะรีเซ็ตโทรศัพท์เครื่องนี้ ซึ่งจะเป็นการลบข้อมูลทั้งหมดในเครื่อง"</string>
     <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="4694232971224663735">"คุณปลดล็อกแท็บเล็ตไม่ถูกต้อง <xliff:g id="NUMBER">%d</xliff:g> ครั้ง ระบบจะรีเซ็ตแท็บเล็ตเครื่องนี้ ซึ่งจะเป็นการลบข้อมูลทั้งหมดในเครื่อง"</string>
     <string name="kg_failed_attempts_now_wiping" product="default" msgid="2365964340830006961">"คุณปลดล็อกโทรศัพท์ไม่ถูกต้อง <xliff:g id="NUMBER">%d</xliff:g> ครั้ง ระบบจะรีเซ็ตโทรศัพท์เครื่องนี้ ซึ่งจะเป็นการลบข้อมูลทั้งหมดในเครื่อง"</string>
-    <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="1365418870560228936">"คุณปลดล็อกแท็บเล็ตไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้ง หากพยายามไม่สำเร็จอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> ครั้ง ระบบจะนำผู้ใช้รายนี้ออก ซึ่งจะเป็นการลบข้อมูลผู้ใช้ทั้งหมด"</string>
-    <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="2151286957817486128">"คุณปลดล็อกโทรศัพท์ไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้ง หากพยายามไม่สำเร็จอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> ครั้ง ระบบจะนำผู้ใช้รายนี้ออก ซึ่งจะเป็นการลบข้อมูลผู้ใช้ทั้งหมด"</string>
-    <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="5464020754932560928">"คุณปลดล็อกแท็บเล็ตไม่ถูกต้อง <xliff:g id="NUMBER">%d</xliff:g> ครั้ง ระบบจะนำผู้ใช้รายนี้ออก ซึ่งจะเป็นการลบข้อมูลผู้ใช้ทั้งหมด"</string>
-    <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="6171564974118059">"คุณปลดล็อกโทรศัพท์ไม่ถูกต้อง <xliff:g id="NUMBER">%d</xliff:g> ครั้ง ระบบจะนำผู้ใช้รายนี้ออก ซึ่งจะเป็นการลบข้อมูลผู้ใช้ทั้งหมด"</string>
-    <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="9154513795928824239">"คุณปลดล็อกแท็บเล็ตไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้ง หากพยายามไม่สำเร็จอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> ครั้ง ระบบจะนำโปรไฟล์งานออก ซึ่งจะเป็นการลบข้อมูลโปรไฟล์ทั้งหมด"</string>
-    <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="2162434417489128282">"คุณปลดล็อกโทรศัพท์ไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้ง หากพยายามไม่สำเร็จอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> ครั้ง ระบบจะนำโปรไฟล์งานออก ซึ่งจะเป็นการลบข้อมูลโปรไฟล์ทั้งหมด"</string>
+    <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="1365418870560228936">"คุณปลดล็อกแท็บเล็ตไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้ง หากพยายามไม่สำเร็จอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> ครั้ง ระบบจะนำผู้ใช้รายนี้ออก ซึ่งจะเป็นการลบข้อมูลทั้งหมดของผู้ใช้"</string>
+    <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="2151286957817486128">"คุณปลดล็อกโทรศัพท์ไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้ง หากพยายามไม่สำเร็จอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> ครั้ง ระบบจะนำผู้ใช้รายนี้ออก ซึ่งจะเป็นการลบข้อมูลทั้งหมดของผู้ใช้"</string>
+    <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="5464020754932560928">"คุณปลดล็อกแท็บเล็ตไม่ถูกต้อง <xliff:g id="NUMBER">%d</xliff:g> ครั้ง ระบบจะนำผู้ใช้รายนี้ออก ซึ่งจะเป็นการลบข้อมูลทั้งหมดของผู้ใช้"</string>
+    <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="6171564974118059">"คุณปลดล็อกโทรศัพท์ไม่ถูกต้อง <xliff:g id="NUMBER">%d</xliff:g> ครั้ง ระบบจะนำผู้ใช้รายนี้ออก ซึ่งจะเป็นการลบข้อมูลทั้งหมดของผู้ใช้"</string>
+    <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="9154513795928824239">"คุณปลดล็อกแท็บเล็ตไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้ง หากพยายามไม่สำเร็จอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> ครั้ง ระบบจะนำโปรไฟล์งานออก ซึ่งจะเป็นการลบข้อมูลทั้งหมดของโปรไฟล์"</string>
+    <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="2162434417489128282">"คุณปลดล็อกโทรศัพท์ไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้ง หากพยายามไม่สำเร็จอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> ครั้ง ระบบจะนำโปรไฟล์งานออก ซึ่งจะเป็นการลบข้อมูลทั้งหมดของโปรไฟล์"</string>
     <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="8966727588974691544">"คุณปลดล็อกแท็บเล็ตไม่ถูกต้อง <xliff:g id="NUMBER">%d</xliff:g> ครั้ง ระบบจะนำโปรไฟล์งานออก ซึ่งจะเป็นการลบข้อมูลโปรไฟล์ทั้งหมด"</string>
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="8476407539834855">"คุณปลดล็อกโทรศัพท์ไม่ถูกต้อง <xliff:g id="NUMBER">%d</xliff:g> ครั้ง ระบบจะนำโปรไฟล์งานออก ซึ่งจะเป็นการลบข้อมูลโปรไฟล์ทั้งหมด"</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="956706236554092172">"คุณวาดรูปแบบการปลดล็อกไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้ง หากพยายามไม่สำเร็จอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> ครั้ง ระบบจะขอให้คุณปลดล็อกแท็บเล็ตโดยใช้บัญชีอีเมล\n\n โปรดลองอีกครั้งในอีก <xliff:g id="NUMBER_2">%3$d</xliff:g> วินาที"</string>
@@ -117,16 +117,16 @@
     <string name="kg_prompt_reason_device_admin" msgid="2438626748767361010">"ผู้ดูแลอุปกรณ์ล็อกอุปกรณ์ไว้"</string>
     <string name="kg_prompt_reason_user_request" msgid="8236951765212462286">"มีการล็อกอุปกรณ์ด้วยตัวเอง"</string>
     <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="71299470072448533">
-      <item quantity="other">ไม่มีการปลดล็อกอุปกรณ์เป็นเวลา <xliff:g id="NUMBER_1">%d</xliff:g> ชั่วโมง ยืนยันรูปแบบ</item>
-      <item quantity="one">ไม่มีการปลดล็อกอุปกรณ์เป็นเวลา <xliff:g id="NUMBER_0">%d</xliff:g> ชั่วโมง ยืนยันรูปแบบ</item>
+      <item quantity="other">ไม่มีการปลดล็อกอุปกรณ์มา <xliff:g id="NUMBER_1">%d</xliff:g> ชั่วโมงแล้ว ยืนยันรูปแบบ</item>
+      <item quantity="one">ไม่มีการปลดล็อกอุปกรณ์มา <xliff:g id="NUMBER_0">%d</xliff:g> ชั่วโมงแล้ว ยืนยันรูปแบบ</item>
     </plurals>
     <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="34586942088144385">
-      <item quantity="other">ไม่มีการปลดล็อกอุปกรณ์เป็นเวลา <xliff:g id="NUMBER_1">%d</xliff:g> ชั่วโมง ยืนยัน PIN</item>
-      <item quantity="one">ไม่มีการปลดล็อกอุปกรณ์เป็นเวลา <xliff:g id="NUMBER_0">%d</xliff:g> ชั่วโมง ยืนยัน PIN</item>
+      <item quantity="other">ไม่มีการปลดล็อกอุปกรณ์มา <xliff:g id="NUMBER_1">%d</xliff:g> ชั่วโมงแล้ว ยืนยัน PIN</item>
+      <item quantity="one">ไม่มีการปลดล็อกอุปกรณ์มา <xliff:g id="NUMBER_0">%d</xliff:g> ชั่วโมงแล้ว ยืนยัน PIN</item>
     </plurals>
     <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="257297696215346527">
-      <item quantity="other">ไม่มีการปลดล็อกอุปกรณ์เป็นเวลา <xliff:g id="NUMBER_1">%d</xliff:g> ชั่วโมง ยืนยันรหัสผ่าน</item>
-      <item quantity="one">ไม่มีการปลดล็อกอุปกรณ์เป็นเวลา <xliff:g id="NUMBER_0">%d</xliff:g> ชั่วโมง ยืนยันรหัสผ่าน</item>
+      <item quantity="other">ไม่มีการปลดล็อกอุปกรณ์มา <xliff:g id="NUMBER_1">%d</xliff:g> ชั่วโมงแล้ว ยืนยันรหัสผ่าน</item>
+      <item quantity="one">ไม่มีการปลดล็อกอุปกรณ์มา <xliff:g id="NUMBER_0">%d</xliff:g> ชั่วโมงแล้ว ยืนยันรหัสผ่าน</item>
     </plurals>
     <string name="fingerprint_not_recognized" msgid="348813995267914625">"ไม่รู้จัก"</string>
 </resources>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
index ba3e9de..dd31862 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
@@ -62,8 +62,8 @@
     <string name="kg_sim_pin_instructions_multi" msgid="1586316574649150223">"輸入「<xliff:g id="CARRIER">%1$s</xliff:g>」的 SIM 卡 PIN 碼"</string>
     <string name="kg_pin_instructions" msgid="4069609316644030034">"輸入 PIN 碼"</string>
     <string name="kg_password_instructions" msgid="136952397352976538">"輸入密碼"</string>
-    <string name="kg_puk_enter_puk_hint" msgid="2288964170039899277">"SIM 卡已遭停用,輸入 PUK 碼即可繼續使用。如需瞭解詳情,請與行動通訊業者聯絡。"</string>
-    <string name="kg_puk_enter_puk_hint_multi" msgid="1373131883510840794">"SIM 卡「<xliff:g id="CARRIER">%1$s</xliff:g>」現已遭停用,輸入 PUK 碼即可繼續使用。如需瞭解詳情,請與行動通訊業者聯絡。"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="2288964170039899277">"SIM 卡已遭停用,輸入 PUK 碼即可繼續使用。如需瞭解詳情,請與電信業者聯絡。"</string>
+    <string name="kg_puk_enter_puk_hint_multi" msgid="1373131883510840794">"SIM 卡「<xliff:g id="CARRIER">%1$s</xliff:g>」現已遭停用,輸入 PUK 碼即可繼續使用。如需瞭解詳情,請與電信業者聯絡。"</string>
     <string name="kg_puk_enter_pin_hint" msgid="3137789674920391087">"輸入所需的 PIN 碼"</string>
     <string name="kg_enter_confirm_pin_hint" msgid="3089485999116759671">"確認所需的 PIN 碼"</string>
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4471738151810900114">"正在解除 SIM 卡鎖定…"</string>
@@ -89,12 +89,12 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="8476407539834855">"你嘗試解鎖手機已失敗 <xliff:g id="NUMBER">%d</xliff:g> 次。你的 Work 設定檔將遭到移除,所有設定檔資料也會一併遭到刪除。"</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="956706236554092172">"你的解鎖圖案已畫錯 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次,目前還剩 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次機會。如果失敗次數超過限制,系統就會要求你透過電子郵件帳戶解鎖平板電腦。\n\n請在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒後再試一次。"</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="8364140853305528449">"你的解鎖圖案已畫錯 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次,目前還剩 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次機會。如果失敗次數超過限制,系統就會要求你透過電子郵件帳戶解鎖手機。\n\n請在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒後再試一次。"</string>
-    <string name="kg_password_wrong_pin_code_pukked" msgid="3389829202093674267">"SIM 卡的 PIN 碼輸入錯誤,你現在必須請行動通訊業者為裝置解鎖。"</string>
+    <string name="kg_password_wrong_pin_code_pukked" msgid="3389829202093674267">"SIM 卡的 PIN 碼輸入錯誤,你現在必須請電信業者為裝置解鎖。"</string>
     <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="4314341367727055967">
       <item quantity="other">SIM 卡的 PIN 碼輸入錯誤,你還可以再試 <xliff:g id="NUMBER_1">%d</xliff:g> 次。</item>
-      <item quantity="one">SIM 卡的 PIN 碼輸入錯誤,你還可以再試 <xliff:g id="NUMBER_0">%d</xliff:g> 次。如果仍然失敗,就必須請行動通訊業者為裝置解鎖。</item>
+      <item quantity="one">SIM 卡的 PIN 碼輸入錯誤,你還可以再試 <xliff:g id="NUMBER_0">%d</xliff:g> 次。如果仍然失敗,就必須請電信業者為裝置解鎖。</item>
     </plurals>
-    <string name="kg_password_wrong_puk_code_dead" msgid="3329017604125179374">"SIM 卡無法使用,請與你的行動通訊業者聯絡。"</string>
+    <string name="kg_password_wrong_puk_code_dead" msgid="3329017604125179374">"SIM 卡無法使用,請與你的電信業者聯絡。"</string>
     <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="2287504898931957513">
       <item quantity="other">SIM 卡的 PUK 碼輸入錯誤,你還可以再試 <xliff:g id="NUMBER_1">%d</xliff:g> 次。如果仍然失敗,SIM 卡將永久無法使用。</item>
       <item quantity="one">SIM 卡的 PUK 碼輸入錯誤,你還可以再試 <xliff:g id="NUMBER_0">%d</xliff:g> 次。如果仍然失敗,SIM 卡將永久無法使用。</item>
diff --git a/packages/SystemUI/res/drawable/clipboard_empty.xml b/packages/SystemUI/res/drawable/clipboard_empty.xml
index 14a5ad2..33cd58c 100644
--- a/packages/SystemUI/res/drawable/clipboard_empty.xml
+++ b/packages/SystemUI/res/drawable/clipboard_empty.xml
@@ -1,25 +1,24 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+    Copyright (C) 2017 The Android Open Source Project
 
-    Licensed under the Apache License, Version 2.0 (the License);
+    Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
     You may obtain a copy of the License at
 
          http://www.apache.org/licenses/LICENSE-2.0
 
     Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an AS IS BASIS,
+    distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24.0dp"
-        android:height="24.0dp"
+        android:width="18.0dp"
+        android:height="18.0dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M19.0,2.0l-4.18,0.0C14.0,0.84 13.3,0.0 12.0,0.0c-1.3,0.0 -2.0,0.84 -2.82,2.0L5.0,2.0c-1.1,0.0 -2.0,0.9 -2.0,2.0l0.0,16.0c0.0,1.0 0.9,2.0 2.0,2.0l14.0,0.0c1.1,0.0 2.0,-0.9 2.0,-2.0L21.0,4.0c0.0,-1.1 -0.9,-2.0 -2.0,-2.0zm-7.0,0.0c0.55,0.0 1.0,0.45 1.0,1.0s-0.45,1.0 -1.0,1.0 -1.0,-0.45 -1.0,-1.0 0.45,-1.0 1.0,-1.0zm7.0,18.0L5.0,20.0L5.0,4.0l2.0,0.0l0.0,3.0l10.0,0.0L17.0,4.0l2.0,0.0l0.0,16.0z" />
+        android:pathData="M16.0,1.0L4.0,1.0c-1.1,0.0 -2.0,0.9 -2.0,2.0l0.0,14.0l2.0,0.0L4.0,3.0l12.0,0.0L16.0,1.0zm3.0,4.0L8.0,5.0c-1.1,0.0 -2.0,0.9 -2.0,2.0l0.0,14.0c0.0,1.0 0.9,2.0 2.0,2.0l11.0,0.0c1.1,0.0 2.0,-0.9 2.0,-2.0L21.0,7.0c0.0,-1.1 -0.9,-2.0 -2.0,-2.0zm0.0,16.0L8.0,21.0L8.0,7.0l11.0,0.0l0.0,14.0z"/>
 </vector>
-
diff --git a/packages/SystemUI/res/drawable/clipboard_full.xml b/packages/SystemUI/res/drawable/clipboard_full.xml
index 2d46870..cb056da 100644
--- a/packages/SystemUI/res/drawable/clipboard_full.xml
+++ b/packages/SystemUI/res/drawable/clipboard_full.xml
@@ -1,25 +1,24 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+    Copyright (C) 2017 The Android Open Source Project
 
-    Licensed under the Apache License, Version 2.0 (the License);
+    Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
     You may obtain a copy of the License at
 
          http://www.apache.org/licenses/LICENSE-2.0
 
     Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an AS IS BASIS,
+    distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24.0dp"
-    android:height="24.0dp"
-    android:viewportWidth="24.0"
-    android:viewportHeight="24.0">
+        android:width="18.0dp"
+        android:height="18.0dp"
+        android:viewportWidth="18.0"
+        android:viewportHeight="18.0">
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M19.0,2.0l-4.18,0.0C14.0,0.84 13.3,0.0 12.0,0.0c-1.3,0.0 -2.0,0.84 -2.82,2.0L5.0,2.0c-1.1,0.0 -2.0,0.9 -2.0,2.0l0.0,16.0c0.0,1.0 0.9,2.0 2.0,2.0l14.0,0.0c1.1,0.0 2.0,-0.9 2.0,-2.0L21.0,4.0c0.0,-1.1 -0.9,-2.0 -2.0,-2.0zm-7.0,0.0c0.55,0.0 1.0,0.45 1.0,1.0s-0.45,1.0 -1.0,1.0 -1.0,-0.45 -1.0,-1.0 0.45,-1.0 1.0,-1.0zm7.0,18.0L5.0,20.0L5.0,4.0l2.0,0.0l0.0,3.0l10.0,0.0L17.0,4.0l2.0,0.0l0.0,16.0z M 6,8 l 12,0 l 0,11 l -12,0 l 0,-11z" />
+        android:pathData="M12.0,0.75L3.0,0.75c-0.82,0.0 -1.5,0.67 -1.5,1.5l0.0,10.5L3.0,12.75L3.0,2.25l9.0,0.0L12.0,0.75zM14.25,3.75L6.0,3.75c-0.83,0.0 -1.5,0.67 -1.5,1.5l0.0,10.5c0.0,0.83 0.67,1.5 1.5,1.5l8.25,0.0c0.83,0.0 1.5,-0.67 1.5,-1.5L15.75,5.25C15.75,4.42 15.08,3.75 14.25,3.75zM7.25,6.5l5.74,0.0l0.0,1.75L7.25,8.25L7.25,6.5zM11.76,14.5l-4.5,0.0l0.0,-1.75l4.5,0.0L11.76,14.5zM13.0,11.38L7.26,11.38L7.26,9.62L13.0,9.62L13.0,11.38z"
+        android:fillColor="#FFFFFF"/>
 </vector>
-
diff --git a/packages/SystemUI/res/drawable/ic_fingerprint_error.xml b/packages/SystemUI/res/drawable/ic_fingerprint_error.xml
index 11e83a1..a7fb1a1 100644
--- a/packages/SystemUI/res/drawable/ic_fingerprint_error.xml
+++ b/packages/SystemUI/res/drawable/ic_fingerprint_error.xml
@@ -19,12 +19,12 @@
         android:viewportWidth="32.0"
         android:viewportHeight="32.0">
     <path
-        android:fillColor="@color/system_warning_color"
+        android:fillColor="?android:attr/colorError"
         android:pathData="M15.99,2.5C8.53,2.5 2.5,8.54 2.5,16.0s6.03,13.5 13.49,13.5S29.5,23.46 29.5,16.0S23.45,2.5 15.99,2.5zM16.0,26.8c-5.97,0.0 -10.8,-4.83 -10.8,-10.8S10.03,5.2 16.0,5.2S26.8,10.03 26.8,16.0S21.97,26.8 16.0,26.8z"/>
     <path
-        android:fillColor="@color/system_warning_color"
+        android:fillColor="?android:attr/colorError"
         android:pathData="M14.65,20.05l2.7,0.0l0.0,2.7l-2.7,0.0z"/>
     <path
-        android:fillColor="@color/system_warning_color"
+        android:fillColor="?android:attr/colorError"
         android:pathData="M14.65,9.25l2.7,0.0l0.0,8.1l-2.7,0.0z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_network_logging.xml b/packages/SystemUI/res/drawable/ic_qs_network_logging.xml
index 87b5a14..7bdf50c 100644
--- a/packages/SystemUI/res/drawable/ic_qs_network_logging.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_network_logging.xml
@@ -20,8 +20,7 @@
   android:width="12.0dp"
   android:height="12.0dp"
   android:viewportWidth="24.0"
-  android:viewportHeight="24.0"
-  android:tint="#4DFFFFFF" >
+  android:viewportHeight="24.0">
     <path
       android:fillColor="#FFFFFFFF"
       android:pathData="M2,24v-4h12v4H2z M2,16v-4h20v4H2z M5,7 12,0 19,7 14,7 14,15 10,15 10,7z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml b/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml
index 54c52bf..782fbe4 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml
@@ -16,8 +16,8 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:width="32.0dp"
         android:height="32.0dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
+        android:viewportWidth="19.0"
+        android:viewportHeight="19.0">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M4.6,7.8l0.7,0.0l0.0,1.3L4.6,9.1L4.6,11.0L3.0,11.0L3.0,9.2L0.1,9.2L0.0,8.2l3.0,-5.7l1.7,0.0L4.6,7.8L4.6,7.8zM1.7,7.8L3.0,7.8l0.0,-3.0L2.9,5.0L1.7,7.8z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_e.xml b/packages/SystemUI/res/drawable/ic_qs_signal_e.xml
index dd0f271..4232126 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_e.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_e.xml
@@ -16,9 +16,12 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:width="32dp"
         android:height="32dp"
-        android:viewportWidth="5.0"
-        android:viewportHeight="5.0">
+        android:viewportWidth="13.0"
+        android:viewportHeight="13.0">
+  <group
+    android:translateX="3.5" >
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M4.400000,7.300000L1.700000,7.300000l0.000000,2.400000l3.300000,0.000000L5.000000,11.000000L0.000000,11.000000L0.000000,2.500000l4.900000,0.000000l0.000000,1.300000L1.700000,3.800000l0.000000,2.100000l2.800000,0.000000L4.500000,7.300000z"/>
+      android:fillColor="#FFFFFFFF"
+      android:pathData="M4.400000,7.300000L1.700000,7.300000l0.000000,2.400000l3.300000,0.000000L5.000000,11.000000L0.000000,11.000000L0.000000,2.500000l4.900000,0.000000l0.000000,1.300000L1.700000,3.800000l0.000000,2.100000l2.800000,0.000000L4.500000,7.300000z"/>
+  </group>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_g.xml b/packages/SystemUI/res/drawable/ic_qs_signal_g.xml
index 3b47c0d..0c512d7 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_g.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_g.xml
@@ -16,9 +16,11 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:width="32dp"
         android:height="32dp"
-        android:viewportWidth="7.0"
-        android:viewportHeight="7.0">
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M6.500000,9.900000c-0.200000,0.400000 -0.600000,0.700000 -1.000000,0.900000s-1.000000,0.400000 -1.800000,0.400000c-0.900000,0.000000 -1.700000,-0.300000 -2.200000,-0.800000S0.700000,9.000000 0.700000,7.900000L0.700000,5.600000c0.000000,-1.100000 0.300000,-1.900000 0.800000,-2.400000s1.200000,-0.800000 2.100000,-0.800000c1.000000,0.000000 1.700000,0.200000 2.100000,0.700000s0.700000,1.200000 0.700000,2.100000L4.700000,5.200000c0.000000,-0.500000 -0.100000,-0.900000 -0.200000,-1.100000S4.000000,3.700000 3.600000,3.700000c-0.400000,0.000000 -0.700000,0.200000 -0.900000,0.500000S2.300000,5.000000 2.300000,5.600000l0.000000,2.300000c0.000000,0.700000 0.100000,1.100000 0.300000,1.400000s0.600000,0.500000 1.000000,0.500000c0.300000,0.000000 0.600000,0.000000 0.700000,-0.100000s0.300000,-0.200000 0.400000,-0.300000L4.700000,7.800000L3.500000,7.800000L3.500000,6.600000l2.900000,0.000000L6.400000,9.900000z"/>
+        android:viewportWidth="13.0"
+        android:viewportHeight="13.0">
+    <group android:translateX="3.5" >
+      <path
+          android:fillColor="#FFFFFFFF"
+          android:pathData="M6.500000,9.900000c-0.200000,0.400000 -0.600000,0.700000 -1.000000,0.900000s-1.000000,0.400000 -1.800000,0.400000c-0.900000,0.000000 -1.700000,-0.300000 -2.200000,-0.800000S0.700000,9.000000 0.700000,7.900000L0.700000,5.600000c0.000000,-1.100000 0.300000,-1.900000 0.800000,-2.400000s1.200000,-0.800000 2.100000,-0.800000c1.000000,0.000000 1.700000,0.200000 2.100000,0.700000s0.700000,1.200000 0.700000,2.100000L4.700000,5.200000c0.000000,-0.500000 -0.100000,-0.900000 -0.200000,-1.100000S4.000000,3.700000 3.600000,3.700000c-0.400000,0.000000 -0.700000,0.200000 -0.900000,0.500000S2.300000,5.000000 2.300000,5.600000l0.000000,2.300000c0.000000,0.700000 0.100000,1.100000 0.300000,1.400000s0.600000,0.500000 1.000000,0.500000c0.300000,0.000000 0.600000,0.000000 0.700000,-0.100000s0.300000,-0.200000 0.400000,-0.300000L4.700000,7.800000L3.500000,7.800000L3.500000,6.600000l2.900000,0.000000L6.400000,9.900000z"/>
+    </group>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_h.xml b/packages/SystemUI/res/drawable/ic_qs_signal_h.xml
index d694e61..b9572b2 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_h.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_h.xml
@@ -14,11 +14,14 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="32.0dp"
+        android:width="32dp"
         android:height="32dp"
-        android:viewportWidth="6.0"
-        android:viewportHeight="6.0">
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M6.000000,11.000000L4.400000,11.000000L4.400000,7.500000L1.700000,7.500000L1.700000,11.000000L0.000000,11.000000L0.000000,2.500000l1.700000,0.000000l0.000000,3.700000l2.700000,0.000000L4.400000,2.500000L6.000000,2.500000L6.000000,11.000000z"/>
+        android:viewportWidth="13.0"
+        android:viewportHeight="13.0">
+      <group
+        android:translateX="3.5" >
+        <path
+            android:fillColor="#FFFFFFFF"
+            android:pathData="M6.000000,11.000000L4.400000,11.000000L4.400000,7.500000L1.700000,7.500000L1.700000,11.000000L0.000000,11.000000L0.000000,2.500000l1.700000,0.000000l0.000000,3.700000l2.700000,0.000000L4.400000,2.500000L6.000000,2.500000L6.000000,11.000000z"/>
+      </group>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_settings_20dp.xml b/packages/SystemUI/res/drawable/ic_settings_16dp.xml
similarity index 96%
rename from packages/SystemUI/res/drawable/ic_settings_20dp.xml
rename to packages/SystemUI/res/drawable/ic_settings_16dp.xml
index 3170f86..c21b60c 100644
--- a/packages/SystemUI/res/drawable/ic_settings_20dp.xml
+++ b/packages/SystemUI/res/drawable/ic_settings_16dp.xml
@@ -14,8 +14,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="20dp"
-    android:height="20dp"
+    android:width="16dp"
+    android:height="16dp"
     android:viewportWidth="24.0"
     android:viewportHeight="24.0">
     <path
diff --git a/packages/SystemUI/res/drawable/ic_sim.xml b/packages/SystemUI/res/drawable/ic_sim.xml
new file mode 100644
index 0000000..983c1d0
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_sim.xml
@@ -0,0 +1,27 @@
+<!--
+    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="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:pathData="M0 0h24v24H0z"
+        android:fillColor="#00000000"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M18.0,2.0l-8.0,0.0L4.02,8.0 4.0,20.0c0.0,1.0 0.9,2.0 2.0,2.0l12.0,0.0c1.1,0.0 2.0,-0.9 2.0,-2.0L20.0,4.0c0.0,-1.1 -0.9,-2.0 -2.0,-2.0z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/lockscreen_fingerprint_error_state_to_fp.xml b/packages/SystemUI/res/drawable/lockscreen_fingerprint_error_state_to_fp.xml
index e207cb3..3af2f7f 100644
--- a/packages/SystemUI/res/drawable/lockscreen_fingerprint_error_state_to_fp.xml
+++ b/packages/SystemUI/res/drawable/lockscreen_fingerprint_error_state_to_fp.xml
@@ -98,11 +98,11 @@
             <path
                 android:name="path_2"
                 android:pathData="M 1.35900878906,6.76104736328 c 0.0,0.0 -2.69998168945,0.0 -2.69998168945,0.0 c 0.0,0.0 0.0,-2.69995117188 0.0,-2.69995117188 c 0.0,0.0 2.69998168945,0.0 2.69998168945,0.0 c 0.0,0.0 0.0,2.69995117188 0.0,2.69995117188 Z"
-                android:fillColor="@*android:color/system_error" />
+                android:fillColor="?android:attr/colorError" />
             <path
                 android:name="path_1"
                 android:pathData="M 1.35363769531,1.36633300781 c 0.0,0.0 -2.69998168945,0.0 -2.69998168945,0.0 c 0.0,0.0 0.0,-8.09997558594 0.0,-8.09997558594 c 0.0,0.0 2.69998168945,0.0 2.69998168945,0.0 c 0.0,0.0 0.0,8.09997558594 0.0,8.09997558594 Z"
-                android:fillColor="@*android:color/system_error" />
+                android:fillColor="?android:attr/colorError" />
         </group>
     </group>
     <group
@@ -117,7 +117,7 @@
             <path
                 android:name="path_3"
                 android:pathData="M 0.0101470947266,10.8087768555 c -5.96701049805,0.0 -10.8000183105,-4.8330078125 -10.8000183105,-10.8000488281 c 0.0,-5.96691894531 4.8330078125,-10.7999267578 10.8000183105,-10.7999267578 c 5.96697998047,0.0 10.799987793,4.8330078125 10.799987793,10.7999267578 c 0.0,5.96704101562 -4.8330078125,10.8000488281 -10.799987793,10.8000488281 Z"
-                android:strokeColor="@*android:color/system_error"
+                android:strokeColor="?android:attr/colorError"
                 android:strokeWidth="2"
                 android:trimPathStart="0"
                 android:trimPathEnd="1" />
diff --git a/packages/SystemUI/res/drawable/lockscreen_fingerprint_fp_to_error_state.xml b/packages/SystemUI/res/drawable/lockscreen_fingerprint_fp_to_error_state.xml
index 2b4babc..a577afc 100644
--- a/packages/SystemUI/res/drawable/lockscreen_fingerprint_fp_to_error_state.xml
+++ b/packages/SystemUI/res/drawable/lockscreen_fingerprint_fp_to_error_state.xml
@@ -96,7 +96,7 @@
                 <path
                     android:name="ridge_5_path_0"
                     android:pathData="M -25.3591003418,-24.4138946533 c -0.569000244141,0.106399536133 -1.12660217285,0.140594482422 -1.45460510254,0.140594482422 c -1.29689025879,0.0 -2.53239440918,-0.343307495117 -3.62019348145,-1.12400817871 c -1.67700195312,-1.20349121094 -2.76950073242,-3.17008972168 -2.76950073242,-5.39189147949"
-                    android:strokeColor="@*android:color/system_error"
+                    android:strokeColor="?android:attr/colorError"
                     android:strokeWidth="1.45"
                     android:strokeLineCap="round"
                     android:trimPathEnd="0" />
@@ -106,7 +106,7 @@
                 <path
                     android:name="ridge_7_path_0"
                     android:pathData="M -36.1409912109,-21.7843475342 c -1.00540161133,-1.19300842285 -1.57499694824,-1.9181060791 -2.36520385742,-3.50170898438 c -0.827560424805,-1.65869140625 -1.31352233887,-3.49159240723 -1.31352233887,-5.48489379883 c 0.0,-3.66279602051 2.96932983398,-6.63220214844 6.63221740723,-6.63220214844 c 3.6628112793,0.0 6.63220214844,2.96940612793 6.63220214844,6.63220214844"
-                    android:strokeColor="@*android:color/system_error"
+                    android:strokeColor="?android:attr/colorError"
                     android:strokeWidth="1.45"
                     android:strokeLineCap="round"
                     android:trimPathEnd="0" />
@@ -116,7 +116,7 @@
                 <path
                     android:name="ridge_6_path_0"
                     android:pathData="M -42.1907958984,-25.6756896973 c -0.758117675781,-2.14370727539 -0.896545410156,-3.86891174316 -0.896545410156,-5.12921142578 c 0.0,-1.46069335938 0.249176025391,-2.84799194336 0.814682006836,-4.09748840332 c 1.56153869629,-3.45030212402 5.03434753418,-5.85076904297 9.0679473877,-5.85076904297 c 5.49430847168,0.0 9.94830322266,4.4539642334 9.94830322266,9.94825744629 c 0.0,1.83151245117 -1.48460388184,3.31610107422 -3.31610107422,3.31610107422 c -1.83149719238,0.0 -3.31610107422,-1.48469543457 -3.31610107422,-3.31610107422 c 0.0,-1.83139038086 -1.48458862305,-3.31610107422 -3.31610107422,-3.31610107422 c -1.83149719238,0.0 -3.31610107422,1.48471069336 -3.31610107422,3.31610107422 c 0.0,2.57020568848 0.989517211914,4.88710021973 2.60510253906,6.5865020752 c 1.22210693359,1.28550720215 2.43139648438,2.09950256348 4.47590637207,2.69030761719"
-                    android:strokeColor="@*android:color/system_error"
+                    android:strokeColor="?android:attr/colorError"
                     android:strokeWidth="1.45"
                     android:strokeLineCap="round"
                     android:trimPathEnd="0" />
@@ -126,7 +126,7 @@
                 <path
                     android:name="ridge_2_path_0"
                     android:pathData="M -44.0646514893,-38.1672973633 c 1.19026184082,-1.77430725098 2.67503356934,-3.24531555176 4.55902099609,-4.27278137207 c 1.88395690918,-1.0274810791 4.04466247559,-1.61137390137 6.34175109863,-1.61137390137 c 2.28761291504,0.0 4.43991088867,0.579071044922 6.31831359863,1.59861755371 c 1.8784942627,1.01954650879 3.36059570312,2.4796295166 4.55279541016,4.24153137207"
-                    android:strokeColor="@*android:color/system_error"
+                    android:strokeColor="?android:attr/colorError"
                     android:strokeWidth="1.45"
                     android:strokeLineCap="round"
                     android:trimPathStart="1" />
@@ -138,7 +138,7 @@
                 <path
                     android:name="ridge_1_path_0"
                     android:pathData="M 71.7812347412,97.0507202148 c -2.27149963379,-1.31344604492 -4.71360778809,-2.07006835938 -7.56221008301,-2.07006835938 c -2.84869384766,0.0 -5.23320007324,0.779556274414 -7.34411621094,2.07006835938"
-                    android:strokeColor="@*android:color/system_error"
+                    android:strokeColor="?android:attr/colorError"
                     android:strokeWidth="1.45"
                     android:strokeLineCap="round"
                     android:trimPathEnd="0" />
@@ -157,11 +157,11 @@
             <path
                 android:name="path_2"
                 android:pathData="M -1.3705291748,4.06730651855 c 0.0,0.0 0.036376953125,-0.0102386474609 0.036376953125,-0.0102386474609 c 0.0,0.0 -0.00682067871094,0.0040283203125 -0.00682067871093,0.0040283203125 c 0.0,0.0 -0.0161437988281,0.00479125976562 -0.0161437988281,0.00479125976563 c 0.0,0.0 -0.0134124755859,0.00141906738281 -0.0134124755859,0.00141906738281 Z"
-                android:fillColor="@*android:color/system_error" />
+                android:fillColor="?android:attr/colorError" />
             <path
                 android:name="path_1"
                 android:pathData="M -1.3737487793,-6.77532958984 c 0.0,0.0 0.00604248046875,0.0166625976562 0.00604248046876,0.0166625976562 c 0.0,0.0 0.0213623046875,0.0250244140625 0.0213623046875,0.0250244140625 c 0.0,0.0 -0.00604248046875,-0.0166625976562 -0.00604248046876,-0.0166625976562 c 0.0,0.0 -0.0213623046875,-0.0250244140625 -0.0213623046875,-0.0250244140625 Z"
-                android:fillColor="@*android:color/system_error" />
+                android:fillColor="?android:attr/colorError" />
         </group>
     </group>
     <group
@@ -176,7 +176,7 @@
             <path
                 android:name="path_3"
                 android:pathData="M 0.0101470947266,10.8087768555 c -5.96701049805,0.0 -10.8000183105,-4.8330078125 -10.8000183105,-10.8000488281 c 0.0,-5.96691894531 4.8330078125,-10.7999267578 10.8000183105,-10.7999267578 c 5.96697998047,0.0 10.799987793,4.8330078125 10.799987793,10.7999267578 c 0.0,5.96704101562 -4.8330078125,10.8000488281 -10.799987793,10.8000488281 Z"
-                android:strokeColor="@*android:color/system_error"
+                android:strokeColor="?android:attr/colorError"
                 android:strokeWidth="2"
                 android:trimPathStart="1" />
         </group>
diff --git a/packages/SystemUI/res/drawable/pip_expand.xml b/packages/SystemUI/res/drawable/pip_expand.xml
new file mode 100644
index 0000000..e34a95d
--- /dev/null
+++ b/packages/SystemUI/res/drawable/pip_expand.xml
@@ -0,0 +1,38 @@
+<?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="60dp"
+    android:height="60dp"
+    android:viewportWidth="60"
+    android:viewportHeight="60">
+
+    <path
+        android:fillColor="#FFFFFF"
+        android:pathData="M8,7.5v45c0,2.75,2.25,5,5,5h34.05c2.75,0,4.95-2.25,4.95-5v-45c0-2.75-2.2-5-4.95-5H13
+C10.25,2.5,8,4.75,8,7.5z
+M13,6.5h34c0.55,0,1,0.45,1,1v45c0,0.55-0.45,1-1,1H13c-0.55,0-1-0.45-1-1v-45C12,6.95,12.45,6.5,13,6.5z" />
+    <path
+        android:pathData="M60,0L0,0l0,60h60V0z" />
+    <path
+        android:fillColor="#FFFFFF"
+        android:pathData="M20.86,35h-2c-0.55,0-1,0.45-1,1v10.5c0,0.55,0.45,1,1,1h10.5c0.55,0,1-0.45,1-1v-2c0-0.55-0.45-1-1-1h-7.5
+V36C21.86,35.45,21.41,35,20.86,35z" />
+    <path
+        android:fillColor="#FFFFFF"
+        android:pathData="M29.64,13.5v2c0,0.55,0.45,1,1,1h7.5V24c0,0.55,0.45,1,1,1h2c0.55,0,1-0.45,1-1V13.5c0-0.55-0.45-1-1-1
+h-10.5C30.09,12.5,29.64,12.95,29.64,13.5z" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/qs_ic_wifi_lock.xml b/packages/SystemUI/res/drawable/qs_ic_wifi_lock.xml
index b7da30b..bf405fa 100644
--- a/packages/SystemUI/res/drawable/qs_ic_wifi_lock.xml
+++ b/packages/SystemUI/res/drawable/qs_ic_wifi_lock.xml
@@ -20,10 +20,10 @@
     android:viewportHeight="72.0"
     android:tint="?android:attr/textColorPrimary">
     <group
-        android:translateX="52.0"
-        android:translateY="42.0" >
+        android:translateX="28.0"
+        android:translateY="10.5" >
         <path
-            android:fillColor="#FFFFFFFF"
-            android:pathData="M18.0,8.0l-1.0,0.0L17.0,6.0c0.0,-2.76 -2.24,-5.0 -5.0,-5.0S7.0,3.24 7.0,6.0l0.0,2.0L6.0,8.0c-1.1,0.0 -2.0,0.9 -2.0,2.0l0.0,10.0c0.0,1.0 0.9,2.0 2.0,2.0l12.0,0.0c1.1,0.0 2.0,-0.9 2.0,-2.0L20.0,10.0c0.0,-1.1 -0.9,-2.0 -2.0,-2.0zm-6.0,9.0c-1.1,0.0 -2.0,-0.9 -2.0,-2.0s0.9,-2.0 2.0,-2.0 2.0,0.9 2.0,2.0 -0.9,2.0 -2.0,2.0zm3.1,-9.0L8.9,8.0L8.9,6.0c0.0,-1.71 1.39,-3.1 3.1,-3.1 1.71,0.0 3.1,1.39 3.1,3.1l0.0,2.0z"/>
+            android:pathData="M36 16l-2 0 0 -4C34 6.48 29.52 2 24 2 18.48 2 14 6.48 14 12l0 4 -2 0c-2.21 0 -4 1.79 -4 4l0 20c0 2.21 1.79 4 4 4l24 0c2.21 0 4 -1.79 4 -4l0 -20c0 -2.21 -1.79 -4 -4 -4zM24 34c-2.21 0 -4 -1.79 -4 -4 0 -2.21 1.79 -4 4 -4 2.21 0 4 1.79 4 4 0 2.21 -1.79 4 -4 4zm6.2 -18l-12.4 0 0 -4c0 -3.42 2.78 -6.2 6.2 -6.2 3.42 0 6.2 2.78 6.2 6.2l0 4z"
+            android:fillColor="#FFFFFF" />
     </group>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_in.xml b/packages/SystemUI/res/drawable/stat_sys_signal_in.xml
new file mode 100644
index 0000000..7e6e09b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_in.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:autoMirrored="true"
+        android:width="17dp"
+        android:height="17dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:name="in"
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M8.7,12.2l-2.0,3.5l-2.0,-3.5z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_inout.xml b/packages/SystemUI/res/drawable/stat_sys_signal_inout.xml
new file mode 100644
index 0000000..b7b6f0f
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_inout.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:autoMirrored="true"
+        android:width="17dp"
+        android:height="17dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:name="in"
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M8.7,12.2l-2.0,3.5l-2.0,-3.5z" />
+    <path
+        android:name="out"
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M0.5,15.7l2.0,-3.5l2.0,3.5z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_out.xml b/packages/SystemUI/res/drawable/stat_sys_signal_out.xml
new file mode 100644
index 0000000..910c035
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_out.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:autoMirrored="true"
+        android:width="17dp"
+        android:height="17dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:name="out"
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M0.5,15.7l2.0,-3.5l2.0,3.5z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_in.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_in.xml
new file mode 100644
index 0000000..666127b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_in.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:autoMirrored="true"
+        android:width="18.41dp"
+        android:height="17dp"
+        android:viewportWidth="26.0"
+        android:viewportHeight="24.0">
+    <path
+        android:name="in"
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M8.7,18.3l-2.0,3.5l-2.0,-3.5z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_inout.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_inout.xml
new file mode 100644
index 0000000..eeba030
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_inout.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:autoMirrored="true"
+        android:width="18.41dp"
+        android:height="17dp"
+        android:viewportWidth="26.0"
+        android:viewportHeight="24.0">
+    <path
+        android:name="in"
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M8.7,18.3l-2.0,3.5l-2.0,-3.5z" />
+    <path
+        android:name="out"
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M0.5,21.8l2.0,-3.5l2.0,3.5z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_out.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_out.xml
new file mode 100644
index 0000000..d577d1a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_out.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:autoMirrored="true"
+        android:width="18.41dp"
+        android:height="17dp"
+        android:viewportWidth="26.0"
+        android:viewportHeight="24.0">
+    <path
+        android:name="out"
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M0.5,21.8l2.0,-3.5l2.0,3.5z" />
+</vector>
diff --git a/packages/SystemUI/res/layout-sw410dp/status_bar_alarm_group.xml b/packages/SystemUI/res/layout-sw410dp/status_bar_alarm_group.xml
deleted file mode 100644
index 46c761a..0000000
--- a/packages/SystemUI/res/layout-sw410dp/status_bar_alarm_group.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2016 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:systemui="http://schemas.android.com/apk/res-auto"
-    android:id="@+id/date_time_alarm_group"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:layout_marginTop="16dp"
-    android:layout_marginStart="16dp"
-    android:gravity="start"
-    android:orientation="vertical">
-    <LinearLayout
-        android:id="@+id/date_time_group"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:orientation="horizontal"
-        android:focusable="true" >
-
-        <include layout="@layout/split_clock_view"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:id="@+id/clock" />
-
-        <com.android.systemui.statusbar.policy.DateView
-            android:id="@+id/date"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginStart="6dp"
-            android:drawableStart="@drawable/header_dot"
-            android:drawablePadding="6dp"
-            android:singleLine="true"
-            android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Clock"
-            android:textSize="@dimen/qs_time_collapsed_size"
-            android:gravity="top"
-            systemui:datePattern="@string/abbrev_wday_month_day_no_year_alarm" />
-
-        <com.android.systemui.statusbar.AlphaOptimizedImageView
-            android:id="@+id/alarm_status_collapsed"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:src="@drawable/ic_access_alarms_small"
-            android:paddingStart="6dp"
-            android:gravity="center"
-            android:visibility="gone" />
-    </LinearLayout>
-
-    <com.android.systemui.statusbar.AlphaOptimizedButton
-        android:id="@+id/alarm_status"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:minHeight="20dp"
-        android:paddingTop="3dp"
-        android:drawablePadding="8dp"
-        android:drawableStart="@drawable/ic_access_alarms_small"
-        android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
-        android:gravity="top"
-        android:background="?android:attr/selectableItemBackground"
-        android:visibility="gone" />
-
-</LinearLayout>
diff --git a/packages/SystemUI/res/layout/battery_percentage_view.xml b/packages/SystemUI/res/layout/battery_percentage_view.xml
index acae9f5..f5c3d40 100644
--- a/packages/SystemUI/res/layout/battery_percentage_view.xml
+++ b/packages/SystemUI/res/layout/battery_percentage_view.xml
@@ -25,5 +25,5 @@
         android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Clock"
         android:textColor="?android:attr/textColorPrimary"
         android:gravity="center_vertical|start"
-        android:paddingStart="4dp"
+        android:paddingStart="@dimen/battery_level_padding_start"
         />
diff --git a/packages/SystemUI/res/layout/keyguard_status_bar.xml b/packages/SystemUI/res/layout/keyguard_status_bar.xml
index a2dfc0d..c5f2f4a 100644
--- a/packages/SystemUI/res/layout/keyguard_status_bar.xml
+++ b/packages/SystemUI/res/layout/keyguard_status_bar.xml
@@ -52,16 +52,6 @@
             >
             <include layout="@layout/system_icons" />
         </FrameLayout>
-        <TextView android:id="@+id/battery_level"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center_vertical"
-            android:layout_marginStart="@dimen/header_battery_margin_keyguard"
-            android:paddingEnd="@dimen/battery_level_padding_end"
-            android:textColor="#ffffff"
-            android:visibility="gone"
-            android:textSize="@dimen/battery_level_text_size"
-            android:importantForAccessibility="noHideDescendants"/>
     </LinearLayout>
 
     <com.android.keyguard.CarrierText
diff --git a/packages/SystemUI/res/layout/mobile_signal_group.xml b/packages/SystemUI/res/layout/mobile_signal_group.xml
index 8b10074..d988acc 100644
--- a/packages/SystemUI/res/layout/mobile_signal_group.xml
+++ b/packages/SystemUI/res/layout/mobile_signal_group.xml
@@ -54,4 +54,10 @@
         android:src="@drawable/stat_sys_roaming"
         android:contentDescription="@string/accessibility_data_connection_roaming"
         android:visibility="gone" />
+    <ImageView
+        android:id="@+id/mobile_inout"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:visibility="gone"
+        />
 </FrameLayout>
diff --git a/packages/SystemUI/res/layout/pip_menu_activity.xml b/packages/SystemUI/res/layout/pip_menu_activity.xml
index 0f5ca9b..f38c8ff 100644
--- a/packages/SystemUI/res/layout/pip_menu_activity.xml
+++ b/packages/SystemUI/res/layout/pip_menu_activity.xml
@@ -32,19 +32,32 @@
         android:background="?android:selectableItemBackgroundBorderless" />
 
     <FrameLayout
+        android:id="@+id/expand_container"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+        <ImageView
+            android:layout_width="64dp"
+            android:layout_height="64dp"
+            android:layout_gravity="center"
+            android:contentDescription="@string/pip_phone_expand"
+            android:src="@drawable/pip_expand"
+            android:background="?android:selectableItemBackgroundBorderless" />
+    </FrameLayout>
+
+    <FrameLayout
         android:id="@+id/actions_container"
         android:layout_width="match_parent"
         android:layout_height="48dp"
         android:layout_gravity="bottom"
-        android:paddingStart="24dp"
-        android:paddingEnd="24dp"
         android:background="#66000000"
         android:visibility="invisible">
         <LinearLayout
-            android:id="@+id/actions"
+            android:id="@+id/actions_group"
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
             android:layout_gravity="center_horizontal"
-            android:orientation="horizontal" />
+            android:orientation="horizontal"
+            android:divider="@android:color/transparent"
+            android:showDividers="middle" />
     </FrameLayout>
 </FrameLayout>
diff --git a/packages/SystemUI/res/layout/qs_detail_item.xml b/packages/SystemUI/res/layout/qs_detail_item.xml
index 6edf135..6544f0d 100644
--- a/packages/SystemUI/res/layout/qs_detail_item.xml
+++ b/packages/SystemUI/res/layout/qs_detail_item.xml
@@ -63,7 +63,6 @@
         android:focusable="true"
         android:scaleType="center"
         android:contentDescription="@*android:string/media_route_controller_disconnect"
-        android:tint="?android:attr/textColorPrimary"
-        android:src="@drawable/ic_qs_cancel" />
+        android:tint="?android:attr/textColorPrimary" />
 
 </LinearLayout>
diff --git a/packages/SystemUI/res/layout/qs_divider.xml b/packages/SystemUI/res/layout/qs_divider.xml
new file mode 100644
index 0000000..660e4af
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_divider.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+<View xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="1dp"
+    android:layout_marginStart="16dp"
+    android:layout_marginEnd="16dp"
+    android:background="?android:attr/colorForeground" />
diff --git a/packages/SystemUI/res/layout/qs_footer.xml b/packages/SystemUI/res/layout/qs_footer.xml
new file mode 100644
index 0000000..82e1ae7
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_footer.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+-->
+
+<!-- Extends RelativeLayout -->
+<com.android.systemui.qs.QSFooter
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/header"
+    android:layout_width="match_parent"
+    android:layout_height="48dp"
+    android:baselineAligned="false"
+    android:clickable="false"
+    android:clipChildren="false"
+    android:clipToPadding="false"
+    android:paddingTop="0dp"
+    android:paddingEnd="8dp"
+    android:paddingStart="16dp"
+    android:gravity="center_vertical"
+    android:orientation="horizontal">
+
+    <include
+        android:id="@+id/date_time_alarm_group"
+        layout="@layout/status_bar_alarm_group"
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="1" />
+
+    <com.android.systemui.statusbar.phone.MultiUserSwitch
+        android:id="@+id/multi_user_switch"
+        android:layout_width="48dp"
+        android:layout_height="48dp"
+        android:layout_alignParentEnd="true"
+        android:background="@drawable/ripple_drawable"
+        android:focusable="true">
+
+        <ImageView
+            android:id="@+id/multi_user_avatar"
+            android:layout_width="@dimen/multi_user_avatar_expanded_size"
+            android:layout_height="@dimen/multi_user_avatar_expanded_size"
+            android:layout_gravity="center"
+            android:scaleType="centerInside"/>
+    </com.android.systemui.statusbar.phone.MultiUserSwitch>
+
+    <com.android.systemui.statusbar.AlphaOptimizedImageView
+        android:id="@android:id/edit"
+        android:layout_width="48dp"
+        android:layout_height="48dp"
+        android:background="?android:attr/selectableItemBackgroundBorderless"
+        android:clickable="true"
+        android:clipToPadding="false"
+        android:contentDescription="@string/accessibility_quick_settings_edit"
+        android:focusable="true"
+        android:padding="16dp"
+        android:src="@drawable/ic_mode_edit"
+        android:tint="?android:attr/colorForeground"/>
+
+    <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
+        android:id="@+id/settings_button_container"
+        android:layout_width="48dp"
+        android:layout_height="48dp"
+        android:clipChildren="false"
+        android:clipToPadding="false">
+
+        <com.android.systemui.statusbar.phone.SettingsButton
+            android:id="@+id/settings_button"
+            style="@android:style/Widget.Material.Button.Borderless"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:background="@drawable/ripple_drawable"
+            android:contentDescription="@string/accessibility_quick_settings_settings"
+            android:src="@drawable/ic_settings_16dp"
+            android:tint="?android:attr/colorForeground"/>
+
+        <com.android.systemui.statusbar.AlphaOptimizedImageView
+            android:id="@+id/tuner_icon"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:paddingStart="36dp"
+            android:paddingEnd="4dp"
+            android:src="@drawable/tuner"
+            android:tint="?android:attr/textColorTertiary"
+            android:visibility="invisible"/>
+
+    </com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
+
+    <com.android.systemui.statusbar.phone.ExpandableIndicator
+        android:id="@+id/expand_indicator"
+        android:layout_width="48dp"
+        android:layout_height="48dp"
+        android:clipToPadding="false"
+        android:clickable="true"
+        android:focusable="true"
+        android:background="?android:attr/selectableItemBackgroundBorderless"
+        android:contentDescription="@string/accessibility_quick_settings_expand"
+        android:padding="14dp" />
+
+</com.android.systemui.qs.QSFooter>
diff --git a/packages/SystemUI/res/layout/qs_panel.xml b/packages/SystemUI/res/layout/qs_panel.xml
index 895185b..3658313 100644
--- a/packages/SystemUI/res/layout/qs_panel.xml
+++ b/packages/SystemUI/res/layout/qs_panel.xml
@@ -26,12 +26,16 @@
     <com.android.systemui.qs.QSPanel
             android:id="@+id/quick_settings_panel"
             android:background="#0000"
-            android:layout_marginTop="52dp"
+            android:layout_marginTop="28dp"
             android:layout_width="match_parent"
-            android:layout_height="wrap_content" />
+            android:layout_height="wrap_content"
+            android:layout_marginBottom="48dp" />
 
     <include layout="@layout/quick_status_bar_expanded_header" />
 
+    <include android:id="@+id/qs_footer"
+        layout="@layout/qs_footer" />
+
     <include android:id="@+id/qs_detail" layout="@layout/qs_detail" />
 
     <include android:id="@+id/qs_customize" layout="@layout/qs_customize_panel"
diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
index 78d4bdd..520dab4 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -16,8 +16,9 @@
 -->
 
 <!-- Extends RelativeLayout -->
-<com.android.systemui.statusbar.phone.QuickStatusBarHeader
+<com.android.systemui.qs.QuickStatusBarHeader
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:id="@+id/header"
     android:layout_width="match_parent"
     android:layout_height="@dimen/status_bar_header_height"
@@ -26,147 +27,71 @@
     android:clickable="false"
     android:clipChildren="false"
     android:clipToPadding="false"
+    android:paddingBottom="48dp"
     android:paddingTop="0dp"
     android:paddingEnd="0dp"
     android:paddingStart="0dp">
 
     <LinearLayout
-        android:layout_width="wrap_content"
-        android:layout_height="48dp"
+        android:layout_width="match_parent"
+        android:layout_height="24dp"
         android:layout_alignParentEnd="true"
         android:clipChildren="false"
         android:clipToPadding="false"
         android:gravity="center"
-        android:paddingEnd="4dp"
+        android:paddingStart="8dp"
+        android:paddingEnd="8dp"
         android:orientation="horizontal">
 
-        <com.android.systemui.statusbar.phone.MultiUserSwitch
-            android:id="@+id/multi_user_switch"
-            android:layout_width="48dp"
-            android:layout_height="48dp"
-            android:layout_alignParentEnd="true"
-            android:background="@drawable/ripple_drawable"
-            android:focusable="true">
 
-            <ImageView
-                android:id="@+id/multi_user_avatar"
-                android:layout_width="@dimen/multi_user_avatar_expanded_size"
-                android:layout_height="@dimen/multi_user_avatar_expanded_size"
-                android:layout_gravity="center"
-                android:scaleType="centerInside"/>
-        </com.android.systemui.statusbar.phone.MultiUserSwitch>
+        <com.android.keyguard.CarrierText
+            android:id="@+id/qs_carrier_text"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:gravity="center_vertical|start"
+            android:ellipsize="marquee"
+            android:textAppearance="?android:attr/textAppearanceSmall"
+            android:textColor="?android:attr/textColorPrimary"
+            android:singleLine="true" />
 
-        <com.android.systemui.statusbar.AlphaOptimizedImageView
-            android:id="@android:id/edit"
-            android:layout_width="48dp"
-            android:layout_height="48dp"
-            android:background="?android:attr/selectableItemBackgroundBorderless"
-            android:clickable="true"
-            android:clipToPadding="false"
-            android:contentDescription="@string/accessibility_quick_settings_edit"
-            android:focusable="true"
-            android:padding="14dp"
-            android:src="@drawable/ic_mode_edit"
-            android:tint="?android:attr/colorForeground"/>
-
-        <LinearLayout
-            android:id="@+id/system_icons_super_container"
+        <FrameLayout
+            android:id="@+id/system_icons_container"
             android:layout_width="wrap_content"
-            android:layout_height="@dimen/status_bar_header_height"
-            android:layout_alignWithParentIfMissing="true"
-            android:layout_toStartOf="@id/multi_user_switch"
-            android:background="@drawable/ripple_drawable">
+            android:layout_height="match_parent"
+            android:layout_gravity="center_vertical">
 
-            <FrameLayout
-                android:id="@+id/system_icons_container"
-                android:layout_width="wrap_content"
-                android:layout_height="24dp"
-                android:layout_gravity="center_vertical">
+            <include layout="@layout/system_icons" />
 
-                <include layout="@layout/system_icons" />
-            </FrameLayout>
-        </LinearLayout>
+        </FrameLayout>
 
-        <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
-            android:id="@+id/settings_button_container"
-            android:layout_width="48dp"
-            android:layout_height="48dp"
-            android:clipChildren="false"
-            android:clipToPadding="false">
-
-            <com.android.systemui.statusbar.phone.SettingsButton
-                android:id="@+id/settings_button"
-                style="@android:style/Widget.Material.Button.Borderless"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:background="@drawable/ripple_drawable"
-                android:contentDescription="@string/accessibility_quick_settings_settings"
-                android:src="@drawable/ic_settings_20dp"
-                android:tint="?android:attr/colorForeground"/>
-
-            <com.android.systemui.statusbar.AlphaOptimizedImageView
-                android:id="@+id/tuner_icon"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:paddingStart="36dp"
-                android:src="@drawable/tuner"
-                android:tint="?android:attr/textColorTertiary"
-                android:visibility="invisible"/>
-
-        </com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
-
-        <com.android.systemui.statusbar.phone.ExpandableIndicator
-            android:id="@+id/expand_indicator"
-            android:layout_width="48dp"
-            android:layout_height="48dp"
-            android:clipToPadding="false"
-            android:clickable="true"
-            android:focusable="true"
-            android:background="?android:attr/selectableItemBackgroundBorderless"
-            android:contentDescription="@string/accessibility_quick_settings_expand"
-            android:padding="12dp" />
-
+        <com.android.systemui.statusbar.policy.Clock
+            android:id="@+id/clock"
+            android:textAppearance="@style/TextAppearance.StatusBar.Clock"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:singleLine="true"
+            android:paddingStart="@dimen/status_bar_clock_starting_padding"
+            android:paddingEnd="@dimen/status_bar_clock_end_padding"
+            android:gravity="center_vertical|start"
+            systemui:showDark="false"
+            />
     </LinearLayout>
 
-    <TextView
-        android:id="@+id/header_emergency_calls_only"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_alignParentStart="true"
-        android:layout_alignParentTop="true"
-        android:focusable="true"
-        android:gravity="center_vertical"
-        android:paddingStart="16dp"
-        android:paddingTop="6dp"
-        android:singleLine="true"
-        android:text="@*android:string/emergency_calls_only"
-        android:textAppearance="@style/TextAppearance.StatusBar.Expanded.EmergencyCallsOnly"
-        android:visibility="gone"/>
-
-    <include
-        android:id="@+id/date_time_alarm_group"
-        layout="@layout/status_bar_alarm_group"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="16dp"
-        android:layout_marginTop="12dp"
-        android:layout_alignParentStart="true"
-        android:layout_alignParentTop="true" />
-
     <com.android.systemui.qs.QuickQSPanel
         android:id="@+id/quick_qs_panel"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_alignParentEnd="true"
-        android:layout_marginTop="54dp"
-        android:layout_marginBottom="24dp"
+        android:layout_marginTop="36dp"
+        android:layout_marginBottom="8dp"
         android:layout_alignParentTop="true"
         android:accessibilityTraversalAfter="@+id/date_time_group"
         android:accessibilityTraversalBefore="@id/expand_indicator"
         android:clipChildren="false"
         android:clipToPadding="false"
-        android:layout_marginStart="16dp"
-        android:layout_marginEnd="16dp"
+        android:layout_marginStart="8dp"
+        android:layout_marginEnd="8dp"
         android:focusable="true"
         android:importantForAccessibility="yes"
         android:paddingTop="0dp"/>
@@ -192,4 +117,4 @@
         android:textStyle="bold"
         android:visibility="invisible"/>
 
-</com.android.systemui.statusbar.phone.QuickStatusBarHeader>
+</com.android.systemui.qs.QuickStatusBarHeader>
diff --git a/packages/SystemUI/res/layout/signal_cluster_view.xml b/packages/SystemUI/res/layout/signal_cluster_view.xml
index 222a31d..4d03f0f 100644
--- a/packages/SystemUI/res/layout/signal_cluster_view.xml
+++ b/packages/SystemUI/res/layout/signal_cluster_view.xml
@@ -70,6 +70,11 @@
             android:layout_width="wrap_content"
             android:alpha="0.0"
             />
+        <ImageView
+            android:id="@+id/wifi_inout"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            />
     </FrameLayout>
     <View
         android:id="@+id/wifi_signal_spacer"
diff --git a/packages/SystemUI/res/layout/status_bar_alarm_group.xml b/packages/SystemUI/res/layout/status_bar_alarm_group.xml
index 745320e..7a5b6dc 100644
--- a/packages/SystemUI/res/layout/status_bar_alarm_group.xml
+++ b/packages/SystemUI/res/layout/status_bar_alarm_group.xml
@@ -18,57 +18,42 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:id="@+id/date_time_alarm_group"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:layout_marginTop="16dp"
-    android:layout_marginStart="16dp"
-    android:gravity="start"
-    android:orientation="vertical">
-    <LinearLayout
-        android:id="@+id/date_time_group"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:orientation="horizontal"
-        android:focusable="true" >
-
-        <include layout="@layout/split_clock_view"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:id="@+id/clock" />
-
-        <com.android.systemui.statusbar.AlphaOptimizedImageView
-            android:id="@+id/alarm_status_collapsed"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:src="@drawable/ic_access_alarms_small"
-            android:tint="?android:attr/textColorPrimary"
-            android:paddingStart="6dp"
-            android:gravity="center"
-            android:visibility="gone" />
-    </LinearLayout>
+    android:layout_width="0dp"
+    android:layout_height="48dp"
+    android:layout_weight="1"
+    android:gravity="center_vertical"
+    android:orientation="horizontal"
+    android:background="?android:attr/selectableItemBackground">
 
     <com.android.systemui.statusbar.policy.DateView
         android:id="@+id/date"
         android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
+        android:layout_height="match_parent"
         android:singleLine="true"
-        android:layout_marginTop="-4dp"
         android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Clock"
         android:textSize="@dimen/qs_time_collapsed_size"
-        android:gravity="top"
+        android:gravity="center_vertical"
         systemui:datePattern="@string/abbrev_wday_month_day_no_year_alarm" />
 
+    <com.android.systemui.statusbar.AlphaOptimizedImageView
+        android:id="@+id/alarm_status_collapsed"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:src="@drawable/ic_access_alarms_small"
+        android:tint="?android:attr/textColorPrimary"
+        android:paddingStart="6dp"
+        android:paddingEnd="6dp"
+        android:gravity="center"
+        android:visibility="gone" />
+
     <com.android.systemui.statusbar.AlphaOptimizedButton
         android:id="@+id/alarm_status"
         android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:minHeight="20dp"
-        android:paddingTop="3dp"
-        android:drawablePadding="8dp"
-        android:drawableStart="@drawable/ic_access_alarms_small"
-        android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
-        android:gravity="top"
-        android:background="?android:attr/selectableItemBackground"
+        android:layout_height="match_parent"
+        android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Clock"
+        android:gravity="center_vertical"
+        android:background="@null"
+        android:clickable="false"
         android:visibility="gone" />
 
 </LinearLayout>
diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml
index b3ff5d6..18ffd0f 100644
--- a/packages/SystemUI/res/layout/volume_dialog.xml
+++ b/packages/SystemUI/res/layout/volume_dialog.xml
@@ -20,6 +20,7 @@
     android:layout_height="wrap_content"
     android:layout_marginBottom="@dimen/volume_dialog_margin_bottom"
     android:background="@drawable/volume_dialog_background"
+    android:paddingTop="@dimen/volume_dialog_padding_top"
     android:translationZ="4dp" >
 
     <LinearLayout
@@ -29,16 +30,11 @@
         android:orientation="vertical" >
 
         <LinearLayout
-                android:id="@+id/volume_dialog_rows"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:paddingEnd="@dimen/volume_button_size"
-                android:paddingTop="@dimen/volume_dialog_collapsed_padding_top"
-                android:orientation="vertical" >
-            <View android:id="@+id/spacer"
-                  android:layout_width="match_parent"
-                  android:layout_height="@dimen/volume_dialog_expanded_spacer"
-                  android:visibility="gone"/>
+            android:id="@+id/volume_dialog_rows"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingEnd="@dimen/volume_button_size"
+            android:orientation="vertical" >
             <!-- volume rows added and removed here! :-) -->
         </LinearLayout>
 
@@ -48,7 +44,21 @@
         <include layout="@layout/tuner_zen_mode_panel" />
     </LinearLayout>
 
-    <com.android.keyguard.AlphaOptimizedImageButton
+    <LinearLayout
+        android:id="@+id/volume_dialog_content"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:layout_alignParentEnd="true"
+        android:layout_alignParentTop="true"
+        android:layout_marginEnd="@dimen/volume_expander_margin_end" >
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:ellipsize="end"
+            android:maxLines="1"
+            android:textAppearance="@style/TextAppearance.Volume.Header" />
+        <com.android.keyguard.AlphaOptimizedImageButton
             xmlns:android="http://schemas.android.com/apk/res/android"
             xmlns:tools="http://schemas.android.com/tools"
             android:id="@+id/volume_expand_button"
@@ -60,9 +70,7 @@
             android:src="@drawable/ic_volume_collapse_animation"
             android:background="@drawable/ripple_drawable"
             tools:ignore="RtlHardcoded"
-            android:layout_alignParentEnd="true"
-            android:layout_alignParentTop="true"
-            android:layout_marginTop="@dimen/volume_expander_margin_top"
-            android:layout_marginEnd="@dimen/volume_expander_margin_end"/>
+            />
 
+    </LinearLayout>
 </RelativeLayout>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index e3d5d7a..c6231df 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -692,4 +692,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Skermkiekies"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Algemene boodskappe"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Berging"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Kitsprogramme"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Kitsprogramme hoef nie geïnstalleer te word nie."</string>
+    <string name="app_info" msgid="6856026610594615344">"Programinligting"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index c2c6739..3fca840 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -516,9 +516,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"በኃይል ማሳወቂያ መቆጣጠሪያዎች አማካኝነት የአንድ መተግበሪያ ማሳወቂያዎች የአስፈላጊነት ደረጃ ከ0 እስከ 5 ድረስ ማዘጋጀት ይችላሉ። \n\n"<b>"ደረጃ 5"</b>" \n- በማሳወቂያ ዝርዝሩ አናት ላይ አሳይ \n- የሙሉ ማያ ገጽ ማቋረጥን ፍቀድ \n- ሁልጊዜ አጮልቀው ይመልከቱ \n\n"<b>"ደረጃ 4"</b>" \n- የሙሉ ማያ ገጽ ማቋረጥን ከልክል \n- ሁልጊዜ አጮልቀው ይመልከቱ \n\n"<b>"ደረጃ 3"</b>" \n- የሙሉ ማያ ገጽ ማቋረጥን ከልክል \n- በፍጹም አጮልቀው አይምልከቱ \n\n"<b>"ደረጃ 2"</b>" \n- የሙሉ ማያ ገጽ ማቋረጥን ይከልክሉ \n- በፍጹም አጮልቀው አይመልከቱ \n- ድምፅ እና ንዝረትን በፍጹም አይኑር \n\n"<b>"ደረጃ 1"</b>" \n- የሙሉ ማያ ገጽ ማቋረጥን ይከልክሉ \n- በፍጹም አጮልቀው አይመልከቱ \n- ድምፅ ወይም ንዝረትን በፍጹም አያደርጉ \n- ከመቆለፊያ ገጽ እና የሁኔታ አሞሌ ይደብቁ \n- በማሳወቂያ ዝርዝር ግርጌ ላይ አሳይ \n\n"<b>"ደረጃ 0"</b>" \n- ሁሉንም የመተግበሪያው ማሳወቂያዎች ያግዱ"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"ማሳወቂያዎች"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"እነዚህን ማሳወቂያዎች ከእንግዲህ አያግኙዋቸውም።"</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="one">1 ከ<xliff:g id="NUMBER_1">%d</xliff:g> ምድቦች ከዚህ መተግበሪያ</item>
+      <item quantity="other">1 ከ<xliff:g id="NUMBER_1">%d</xliff:g> ምድቦች ከዚህ መተግበሪያ</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"ሁሉም ምድቦች"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"ተጨማሪ ቅንብሮች"</string>
     <string name="notification_done" msgid="5279426047273930175">"ተከናውኗል"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -592,31 +594,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"ጠፍቷል"</string>
     <string name="nav_bar" msgid="1993221402773877607">"የአሰሳ አሞሌ"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"አቀማመጥ"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"ተጨማሪ የግራ አዝራር ዓይነት"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"ተጨማሪ የቀኝ አዝራር ዓይነት"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(ነባሪ)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"የቅንጥብ ሰሌዳ"</item>
+    <item msgid="5742013440802239414">"የቁልፍ ኮድ"</item>
+    <item msgid="8802889973626281575">"የቁልፍ ሰሌዳ መቀየሪያ"</item>
+    <item msgid="8175437057325747277">"ምንም የለም"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"መደበኛ"</item>
+    <item msgid="8256205964297588988">"እምቅ"</item>
+    <item msgid="8719936228094005878">"ወደ ግራ ያዘነበለ"</item>
+    <item msgid="586019486955594690">"ወደ ቀኝ ያዘነበለ"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"የቁልፍ ሰሌዳ መቀየሪያ"</string>
     <string name="save" msgid="2311877285724540644">"አስቀምጥ"</string>
     <string name="reset" msgid="2448168080964209908">"ዳግም አስጀምር"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"የአዝራር ስፋት አስተካክል"</string>
     <string name="clipboard" msgid="1313879395099896312">"የቅንጥብ ሰሌዳ"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"ብጁ የአሰሳ አዝራር"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"የግራ ቁልፍ ኮድ"</string>
+    <string name="right_keycode" msgid="708447961000848163">"የቀኝ ቁልፍ ኮድ"</string>
+    <string name="left_icon" msgid="3096287125959387541">"የግራ አዶ"</string>
+    <string name="right_icon" msgid="3952104823293824311">"የቀኝ አዶ"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"ሰቆችን ለማከል ይጎትቱ"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"ለማስወገድ ወደዚህ ይጎትቱ"</string>
     <string name="qs_edit" msgid="2232596095725105230">"አርትዕ"</string>
@@ -665,44 +667,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"የ<xliff:g id="ID_1">%s</xliff:g> ቅንብሮችን ክፈት።"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"የቅንብሮድ ቅደም-ተከተል አርትዕ።"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"ገጽ <xliff:g id="ID_1">%1$d</xliff:g> ከ <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"ማያ ገጽ ቁልፍ"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"ዘርጋ"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"አሳንስ"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"ዝጋ"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"ስልኩ እየሞቀ ነው"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"ስልኩ እየቀዘቀዘ ሳለ አንዳንድ ባህሪዎች ይገደባሉ"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"የእርስዎ ስልክ በራስ-ሰር ለመቀዝቀዝ ይሞክራል። አሁንም ስልክዎን መጠቀም ይችላሉ፣ ነገር ግን ሊንቀራፈፍ ይችላል።\n\nአንዴ ስልክዎ ከቀዘቀዘ በኋላ በመደበኝነት ያሄዳል።"</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"የግራ አቋራጭ"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"የቀኝ አቋራጭ"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"የግራ አቋራጭ እንዲሁም ይከፍታል"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"ቀኝ አቋራጭ እንዲሁም ይከፍታል"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"ምንም የለም"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"<xliff:g id="APP">%1$s</xliff:g>ን ያስጀምሩ"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"ሌሎች መተግበሪያዎች"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"ክብ"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"ፐላስ"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"ሲቀነስ"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"ግራ"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"ቀኝ"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"ምናሌ"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"የ<xliff:g id="APP">%1$s</xliff:g> መተግበሪያ"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"ማንቂያዎች"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"ቅጽበታዊ ገጽ እይታዎች"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"አጠቃላይ መልዕክቶች"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"ማከማቻ"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"የቅጽበት መተግበሪያዎች"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"ቅጽበታዊ መተግበሪያዎች መጫን አያስፈልጋቸውም።"</string>
+    <string name="app_info" msgid="6856026610594615344">"የመተግበሪያ መረጃ"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 931a92e..1de61c2 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -704,4 +704,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"لقطات الشاشة"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"رسائل عامة"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"سعة التخزين"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"التطبيقات الفورية"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"لا تتطلب التطبيقات الفورية إجراء التثبيت."</string>
+    <string name="app_info" msgid="6856026610594615344">"معلومات عن التطبيق"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index a547e40..0694c3f 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -516,9 +516,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Enerji bildiriş nəzarəti ilə, tətbiq bildirişləri üçün əhəmiyyət səviyyəsini 0-dan 5-ə kimi ayarlaya bilərsiniz. \n\n"<b>"Səviyyə 5"</b>" \n- Bildiriş siyahısının yuxarı hissəsində göstərin \n- Tam ekran kəsintisinə icazə verin \n- Hər zaman izləyin \n\n"<b>"Səviyyə 4"</b>" \n- Tam ekran kəsintisinin qarşısını alın \n- Hər zaman izləyin \n\n"<b>"Level 3"</b>" \n- Tam ekran kəsintisinin qarşısını alın \n- Heç vaxt izləməyin \n\n"<b>"Level 2"</b>" \n- Tam ekran kəsintisinin qarşısını alın \n- Heç vaxt izləməyin \n- Heç vaxt səsliyə və ya vibrasiyaya qoymayın \n\n"<b>"Səviyyə 1"</b>" \n- Prevent full screen interruption \n- Heç vaxt izləməyin \n- Heç vaxt səsliyə və ya vibrasiyaya qoymayın \n- Ekran kilidi və ya status panelindən gizlədin \n- Bildiriş siyahısının yuxarı hissəsində göstərin \n\n"<b>"Səviyyə 0"</b>" \n- Bütün bildirişləri tətbiqdən blok edin"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Bildirişlər"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"Bu bildirişlər daha sizə göndərilməyəcək."</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="other">Bu tətbiqin <xliff:g id="NUMBER_1">%d</xliff:g> kateqoriyasından 1 kanal</item>
+      <item quantity="one">Bu tətbiqin <xliff:g id="NUMBER_0">%d</xliff:g> kateqoriyasından 1 kanal</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"Bütün Kateqoriyalar"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Daha çox ayar"</string>
     <string name="notification_done" msgid="5279426047273930175">"Hazırdır"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -592,31 +594,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"Deaktiv"</string>
     <string name="nav_bar" msgid="1993221402773877607">"Naviqasiya paneli"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"Tərtibat"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"Əlavə sol düymə növü"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"Əlavə sağ düymə növü"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(defolt)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"Mübadilə buferi"</item>
+    <item msgid="5742013440802239414">"Açar kodu"</item>
+    <item msgid="8802889973626281575">"Klaviatura dəyişdirici"</item>
+    <item msgid="8175437057325747277">"Heç bir"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"Normal"</item>
+    <item msgid="8256205964297588988">"Yığcam"</item>
+    <item msgid="8719936228094005878">"Sola əyilmiş"</item>
+    <item msgid="586019486955594690">"Sağa əyilmiş"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"Klaviatura dəyişdirici"</string>
     <string name="save" msgid="2311877285724540644">"Saxlayın"</string>
     <string name="reset" msgid="2448168080964209908">"Sıfırlayın"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"Düymənin enini nizamlayın"</string>
     <string name="clipboard" msgid="1313879395099896312">"Pano"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"Fərdi naviqasiya düyməsi"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"Sol açar kodu"</string>
+    <string name="right_keycode" msgid="708447961000848163">"Sağ açar kodu"</string>
+    <string name="left_icon" msgid="3096287125959387541">"Sol ikona"</string>
+    <string name="right_icon" msgid="3952104823293824311">"Sağ ikona"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"Xanalar əlavə etmək üçün sürüşdürün"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Silmək üçün bura sürüşdürün"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Redaktə edin"</string>
@@ -665,44 +667,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> ayarlarını açın."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Ayarların sıralanmasını redaktə edin."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> səhifədən <xliff:g id="ID_1">%1$d</xliff:g> səhifə"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"Ekran kilidi"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"Genişləndirin"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Kiçildin"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Bağlayın"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"Telefon qızmağa başlayır"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"Telefon soyuyana kimi bəzi funksiyalar məhdudlaşdırılır"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefonunuz avtomatik olaraq soyumağa başlayacaq. Telefon istifadəsinə davam edə bilərsiniz, lakin sürəti yavaşlaya bilər.\n\nTelefonunuz soyuduqdan sonra normal işləyəcək."</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"Sol qısayol"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"Sağ qısayol"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"Sol qısayol kiliddən çıxır"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"Sağ qısayol kiliddən çıxır"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"Heç biri"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"<xliff:g id="APP">%1$s</xliff:g> tətbiqini başladın"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"Digər tətbiqlər"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"Çevrə"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"Plyus"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"Minus"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"Sol"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"Sağ"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"Menyu"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> tətbiqi"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Siqnallar"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Skrinşotlar"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Ümumi Mesajlar"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Yaddaş"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Ani Tətbiqlər"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Ani tətbiqlər quraşdırma tələb etmir."</string>
+    <string name="app_info" msgid="6856026610594615344">"Tətbiq məlumatı"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 6e82774..2751eb8 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -695,4 +695,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Snimci ekrana"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Opšte poruke"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Memorijski prostor"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Instant aplikacije"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Instant aplikacije ne zahtevaju instalaciju."</string>
+    <string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index b7ae16c..148ba31 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -700,4 +700,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Здымкі экрана"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Агульныя паведамленні"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Захоўванне"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Імгненныя праграмы"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Імгненныя праграмы не патрабуюць усталёўкі."</string>
+    <string name="app_info" msgid="6856026610594615344">"Інфармацыя пра праграму"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index defbdf8..993595a 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -516,9 +516,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"С помощта на контролите за известията можете да зададете ниво на важност от 0 до 5 за известията от дадено приложение. \n\n"<b>"Ниво 5"</b>" \n– Показване най-горе в списъка с известия. \n– Разрешаване на прекъсването на цял екран. \n– Известията винаги се показват мимолетно. \n\n"<b>"Ниво 4"</b>" \n– Предотвратяване на прекъсването на цял екран. \n– Известията винаги се показват мимолетно. \n\n"<b>"Ниво 3"</b>" \n– Предотвратяване на прекъсването на цял екран. \n– Известията никога не се показват мимолетно. \n\n"<b>"Ниво 2"</b>" \n– Предотвратяване на прекъсването на цял екран. \n– Известията никога не се показват мимолетно. \n– Без издаване на звуков сигнал и вибриране. \n\n"<b>"Ниво 1"</b>" \n– Предотвратяване на прекъсването на цял екран. \n– Известията никога не се показват мимолетно. \n– Без издаване на звуков сигнал и вибриране. \n– Скриване от заключения екран и лентата на състоянието. \n– Показване най-долу в списъка с известия. \n\n"<b>"Ниво 0"</b>" \n– Блокиране на всички известия от приложението."</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Известия"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"Вече няма да получавате тези известия."</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="other">1 от <xliff:g id="NUMBER_1">%d</xliff:g> категории от това приложение</item>
+      <item quantity="one">1 от <xliff:g id="NUMBER_0">%d</xliff:g> категория от това приложение</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"Всички категории"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Още настройки"</string>
     <string name="notification_done" msgid="5279426047273930175">"Готово"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g> от <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -592,31 +594,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"Изкл."</string>
     <string name="nav_bar" msgid="1993221402773877607">"Лента за навигация"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"Оформление"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"Тип на допълнителния ляв бутон"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"Тип на допълнителния десен бутон"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(по подразбиране)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"Буферна памет"</item>
+    <item msgid="5742013440802239414">"Клавишен код"</item>
+    <item msgid="8802889973626281575">"Превключвател на клавиатурата"</item>
+    <item msgid="8175437057325747277">"Няма"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"Нормално"</item>
+    <item msgid="8256205964297588988">"Компактно"</item>
+    <item msgid="8719936228094005878">"Лява ориентация"</item>
+    <item msgid="586019486955594690">"Дясна ориентация"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"Превключвател на клавиатурата"</string>
     <string name="save" msgid="2311877285724540644">"Запазване"</string>
     <string name="reset" msgid="2448168080964209908">"Повторно задаване"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"Коригиране на ширината на бутона"</string>
     <string name="clipboard" msgid="1313879395099896312">"Буферна памет"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"Персонализиран бутон за навигация"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"Ляв бутон за клавишен код"</string>
+    <string name="right_keycode" msgid="708447961000848163">"Десен бутон за клавишен код"</string>
+    <string name="left_icon" msgid="3096287125959387541">"Лява икона"</string>
+    <string name="right_icon" msgid="3952104823293824311">"Дясна икона"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"Преместете с плъзгане, за да добавите плочки"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Преместете тук с плъзгане за премахване"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Редактиране"</string>
@@ -665,44 +667,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Отваряне на настройките за <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Редактиране на подредбата на настройките."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Страница <xliff:g id="ID_1">%1$d</xliff:g> от <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"Заключен екран"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"Разгъване"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Намаляване"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Затваряне"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"Телефонът загрява"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"Някои функции са ограничени, докато телефонът се охлажда"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"Телефонът ви автоматично ще направи опит за охлаждане. Пак можете да го използвате, но той може да работи по-бавно.\n\nСлед като се охлади, ще работи нормално."</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"Ляв пряк път"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"Десен пряк път"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"Левият пряк път също служи за отключване"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"Десният пряк път също служи за отключване"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"Няма"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"Стартиране на <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"Други приложения"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"Кръг"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"Плюс"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"Минус"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"Стрелка за наляво"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"Стрелка за надясно"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"Меню"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"Приложение <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Сигнали"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Екранни снимки"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Общи съобщения"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Хранилище"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Мигновени приложения"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"За мигновените приложения не се изисква инсталиране."</string>
+    <string name="app_info" msgid="6856026610594615344">"Информация за приложението"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 9b7aee1..18e0396 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -64,7 +64,7 @@
     <string name="usb_debugging_message" msgid="2220143855912376496">"কম্পিউটারের RSA কী আঙ্গুলের ছাপ হল:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
     <string name="usb_debugging_always" msgid="303335496705863070">"এই কম্পিউটার থেকে সর্বদা অনুমতি দিন"</string>
     <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB ডিবাগিং অনুমোদিত নয়"</string>
-    <string name="usb_debugging_secondary_user_message" msgid="8572228137833020196">"ব্যবহারকারী বর্তমানে এই ডিভাইসটিতে প্রবেশ করুন করেছেন তাই USB ডিবাগিং চালু করা যাবে না। এই বৈশিষ্ট্যটি ব্যবহার করতে, অনুগ্রহ করে প্রশাসক ব্যবহারকারীতে পাল্টান।"</string>
+    <string name="usb_debugging_secondary_user_message" msgid="8572228137833020196">"ব্যবহারকারী বর্তমানে এই ডিভাইসটিতে প্রবেশ করেছেন তাই USB ডিবাগিং চালু করা যাবে না। এই বৈশিষ্ট্যটি ব্যবহার করতে, অনুগ্রহ করে প্রশাসক ব্যবহারকারীতে পাল্টান।"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"স্ক্রীণ পূরণ করতে জুম করুন"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"পূর্ণ স্ক্রীণে প্রসারিত করুন"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"স্ক্রীনশট সংরক্ষণ করা হচ্ছে..."</string>
@@ -516,9 +516,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"পাওয়ার বিজ্ঞপ্তির নিয়ন্ত্রণগুলি ব্যহবার করে, আপনি কোনো অ্যাপ্লিকেশানের বিজ্ঞপ্তির জন্য ০ থেকে ৫ পর্যন্ত একটি গুরুত্বের লেভেলকে সেট করতে পারবেন৷ \n\n"<b>"লেভেল ৫"</b>" \n- বিজ্ঞপ্তি তালিকার শীর্ষে দেখায় \n- পূর্ণ স্ক্রীনের বাধাকে অনুমতি দেয় \n- সর্বদা স্ক্রীনে উপস্থিত হয় \n\n"<b>"লেভেল ৪"</b>" \n- পূর্ণ স্ক্রীনের বাধাকে আটকায় \n- সর্বদা স্ক্রীনে উপস্থিত হয় \n\n"<b>"লেভেল ৩"</b>" \n- পূর্ণ স্ক্রীনের বাধাকে আটকায় \n- কখনই স্ক্রীনে উপস্থিত হয় না \n\n"<b>"লেভেল ২"</b>" \n- পূর্ণ স্ক্রীনের বাধাকে আটকায় \n- কখনই স্ক্রীনে উপস্থিত হয় না \n- কখনই শব্দ এবং কম্পন করে না \n\n"<b>"লেভেল ১"</b>" \n- পূর্ণ স্ক্রীনের বাধাকে আটকায় \n- কখনই স্ক্রীনে উপস্থিত হয় না \n- কখনই শব্দ এবং কম্পন করে না \n- লক স্ক্রীন এবং স্থিতি দন্ড থেকে লুকায় \n- বিজ্ঞপ্তি তালিকার নীচের দিকে দেখায় \n\n"<b>"লেভেল ০"</b>" \n- অ্যাপ্লিকেশান থেকে সমস্ত বিজ্ঞপ্তিকে অবরূদ্ধ করে"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"বিজ্ঞপ্তি"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"আপনি আর এই বিজ্ঞপ্তিগুলি পাবেন না।"</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="one">এই অ্যাপের <xliff:g id="NUMBER_1">%d</xliff:g>টি বিভাগের মধ্যে ১</item>
+      <item quantity="other">এই অ্যাপের <xliff:g id="NUMBER_1">%d</xliff:g>টি বিভাগের মধ্যে ১</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"সকল বিভাগ"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"আরো সেটিংস"</string>
     <string name="notification_done" msgid="5279426047273930175">"সম্পন্ন"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -592,31 +594,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"বন্ধ আছে"</string>
     <string name="nav_bar" msgid="1993221402773877607">"নেভিগেশন দন্ড"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"লেআউট"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"অতিরিক্ত বাঁদিকের বোতামের ধরণ"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"অতিরিক্ত ডানদিকের বোতামের ধরণ"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(ডিফল্ট)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"ক্লিপবোর্ড"</item>
+    <item msgid="5742013440802239414">"কীকোড"</item>
+    <item msgid="8802889973626281575">"কিবোর্ড স্যুইচার"</item>
+    <item msgid="8175437057325747277">"কোনো কিছুই নয়"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"সাধারণ"</item>
+    <item msgid="8256205964297588988">"নিবিড়"</item>
+    <item msgid="8719936228094005878">"বাঁদিক ঘেঁষা"</item>
+    <item msgid="586019486955594690">"ডানদিক ঘেঁষা"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"কিবোর্ড স্যুইচার"</string>
     <string name="save" msgid="2311877285724540644">"সংরক্ষণ করুন"</string>
     <string name="reset" msgid="2448168080964209908">"আবার সেট করুন"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"বোতামের প্রস্থ সমন্বয় করুন"</string>
     <string name="clipboard" msgid="1313879395099896312">"ক্লিপবোর্ড"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"কাস্টম নেভিগেশান বোতাম"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"বাঁদিকের কিকোড"</string>
+    <string name="right_keycode" msgid="708447961000848163">"ডানদিকের কিকোড"</string>
+    <string name="left_icon" msgid="3096287125959387541">"বাঁ দিকের আইকন"</string>
+    <string name="right_icon" msgid="3952104823293824311">"ডানদিকের আইকন"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"টাইলগুলি যোগ করার জন্য টেনে আনুন"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"সরানোর জন্য এখানে টেনে আনুন"</string>
     <string name="qs_edit" msgid="2232596095725105230">"সম্পাদনা করুন"</string>
@@ -659,50 +661,40 @@
     <string name="accessibility_quick_settings_expand" msgid="2375165227880477530">"দ্রুত সেটিংস খুলুন৷"</string>
     <string name="accessibility_quick_settings_collapse" msgid="1792625797142648105">"দ্রুত সেটিংস বন্ধ করুন৷"</string>
     <string name="accessibility_quick_settings_alarm_set" msgid="1863000242431528676">"অ্যালার্ম সেট করা হয়েছে৷"</string>
-    <string name="accessibility_quick_settings_user" msgid="1567445362870421770">"<xliff:g id="ID_1">%s</xliff:g> হিসেবে প্রবেশ করুন রয়েছেন"</string>
+    <string name="accessibility_quick_settings_user" msgid="1567445362870421770">"<xliff:g id="ID_1">%s</xliff:g> হিসেবে প্রবেশ করে রয়েছেন"</string>
     <string name="accessibility_quick_settings_no_internet" msgid="31890692343084075">"কোন ইন্টারনেট নেই৷"</string>
     <string name="accessibility_quick_settings_open_details" msgid="4230931801728005194">"বিশদ বিবরণ খুলুন৷"</string>
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> সেটিংস খুলুন৷"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"ক্রম বা সেটিংস সম্পাদনা করুন৷"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g>টির মধ্যে <xliff:g id="ID_1">%1$d</xliff:g> নং পৃষ্ঠা"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"লক স্ক্রিন"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"প্রসারিত করুন"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"ছোটো করুন"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"বন্ধ করুন"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"ফোনটি গরম হচ্ছে"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"ফোনটি ঠান্ডা হওয়ার সময় কিছু বৈশিষ্ট্য সীমিত হতে পারে"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"আপনার ফোনটি নিজে থেকেই ঠান্ডা হওয়ার চেষ্টা করবে৷ আপনি তবুও আপনার ফোন ব্যবহার করতে পারেন, কিন্তু এটি একটু ধীরে চলতে পারে৷\n\nআপনার ফোনটি পুরোপুরি ঠান্ডা হয়ে গেলে এটি স্বাভাবিকভাবে চলবে৷"</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"বাঁদিকের শর্টকাট"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"ডানদিকের শর্টকাট"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"বাঁদিকের শর্টকাট দিয়েও আনলক করা যায়"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"ডানদিকের শর্টকাট দিয়েও আনলক করা যায়"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"কোনোটিই নয়"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"<xliff:g id="APP">%1$s</xliff:g> লঞ্চ করুন"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"অন্যান্য অ্যাপ"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"চেনাশোনা"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"যোগ"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"বিয়োগ"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"বাঁদিক"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"ডান"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"মেনু"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> অ্যাপ"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"সতর্কতাগুলি"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"স্ক্রীনশটস"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"সাধারণ বার্তাগুলি"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"সঞ্চয়স্থান"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"ঝটপট অ্যাপ"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"ঝটপট অ্যাপ ইনস্টল করার প্রয়োজন হয় না।"</string>
+    <string name="app_info" msgid="6856026610594615344">"অ্যাপ্লিকেশানের তথ্য"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 65f3003..10d3aa5 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -520,9 +520,12 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Uz kontrolu obavještenja o napajanju, možete postaviti nivo značaja obavještenja iz aplikacije, i to od nivoa 0 do 5. \n\n"<b>"Nivo 5"</b>" \n- Prikaži na vrhu liste obavještenja \n- Dopusti prekid prikaza cijelog ekrana \n- Uvijek izviruj \n\n"<b>"Nvio 4"</b>" \n- Spriječi prekid prikaza cijelog ekrana \n- Uvijek izviruj \n\n"<b>"Nivo 3"</b>" \n- Spriječi prekid prikaza cijelog ekrana \n- Nikad ne izviruj \n\n"<b>"Nivo 2"</b>" \n- Spriječi prekid prikaza cijelog ekrana \n- Nikad ne izviruj \n- Nikada ne puštaj zvuk ili vibraciju \n\n"<b>"Nivo 1"</b>" \n- Spriječi prekid prikaza cijelog ekrana \n- Nikada ne izviruj \n- Nikada ne puštaj zvuk ili vibraciju \n- Sakrij sa ekrana za zaključavanje i statusne trake \n- Prikaži na dnu liste obavještenja \n\n"<b>"Nivo 0"</b>" \n- Blokiraj sva obavještenja iz aplikacije"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Obavještenja"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"Nećete više primati ova obavještenja."</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="one">1 od <xliff:g id="NUMBER_1">%d</xliff:g> kategorije iz ove aplikacije</item>
+      <item quantity="few">1 od <xliff:g id="NUMBER_1">%d</xliff:g> kategorije iz ove aplikacije</item>
+      <item quantity="other">1 od <xliff:g id="NUMBER_1">%d</xliff:g> kategorija iz ove aplikacije</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"Sve kategorije"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Više postavki"</string>
     <string name="notification_done" msgid="5279426047273930175">"Gotovo"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -596,31 +599,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"Isključi"</string>
     <string name="nav_bar" msgid="1993221402773877607">"Navigaciona traka"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"Raspored"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"Dodatni tip dugmeta lijevo"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"Dodatni tip dugmeta desno"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(zadano)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"Međumemorija"</item>
+    <item msgid="5742013440802239414">"Kôd tipke"</item>
+    <item msgid="8802889973626281575">"Prebacivač tastatura"</item>
+    <item msgid="8175437057325747277">"Nema"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"Normalna"</item>
+    <item msgid="8256205964297588988">"Kompaktna"</item>
+    <item msgid="8719936228094005878">"Ulijevo"</item>
+    <item msgid="586019486955594690">"Udesno"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"Prebacivač tastatura"</string>
     <string name="save" msgid="2311877285724540644">"Sačuvaj"</string>
     <string name="reset" msgid="2448168080964209908">"Ponovno pokretanje"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"Podesite širinu dugmeta"</string>
     <string name="clipboard" msgid="1313879395099896312">"Međumemorija"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"Prilagođeno dugme za navigaciju"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"Kôd tipke lijevo"</string>
+    <string name="right_keycode" msgid="708447961000848163">"Kôd tipke desno"</string>
+    <string name="left_icon" msgid="3096287125959387541">"Ikona lijevo"</string>
+    <string name="right_icon" msgid="3952104823293824311">"Ikona desno"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"Povucite da dodate polja"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Prevucite ovdje za uklanjanje"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Uredi"</string>
@@ -669,44 +672,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Otvori postavke za: <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Urediti raspored postavki."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Stranica <xliff:g id="ID_1">%1$d</xliff:g> od <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"Zaključavanje ekrana"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"Proširi"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Umanji"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Zatvori"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"Telefon se pregrijava"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"Neke funkcije su ograničene dok se telefon hladi"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"Vaš telefon će se automatski pokušati ohladiti. I dalje možete koristi telefon, ali će možda raditi sporije.\n\nNakon što se ohladi, telefon će normalno raditi."</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"Prečica lijevo"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"Prečica desno"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"Prečica lijevo također otključava"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"Prečica desno također otključava"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"Ništa"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"Pokrenite aplikaciju <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"Druge aplikacije"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"Krug"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"Plus"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"Minus"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"Lijevo"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"Desno"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"Meni"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"Aplikacija <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Upozorenja"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Snimci ekrana"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Općenite poruke"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Pohrana"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Instant-aplikacije"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Za instant aplikacije nije potrebna instalacija"</string>
+    <string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 0f7a003..82a4c0e 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -516,9 +516,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Amb els controls de notificació millorats, pots establir un nivell d\'importància d\'entre 0 i 5 per a les notificacions d\'una aplicació. \n\n"<b>"Nivell 5"</b>" \n- Mostra les notificacions a la part superior de la llista \n- Permet la interrupció de la pantalla completa \n- Permet sempre la previsualització \n\n"<b>"Nivell 4"</b>" \n- No permet la interrupció de la pantalla completa \n- Permet sempre la previsualització \n\n"<b>"Nivell 3"</b>" \n- No permet la interrupció de la pantalla completa \n- No permet mai la previsualització \n\n"<b>"Nivell 2"</b>" \n- No permet la interrupció de la pantalla completa \n- No permet mai la previsualització \n- Les notificacions no poden emetre sons ni vibracions \n\n"<b>"Nivell 1"</b>" \n- No permet la interrupció de la pantalla completa \n- No permet mai la previsualització \n- No activa mai el so ni la vibració \n- Amaga les notificacions de la pantalla de bloqueig i de la barra d\'estat \n- Mostra les notificacions a la part inferior de la llista \n\n"<b>"Nivell 0"</b>" \n- Bloqueja totes les notificacions de l\'aplicació"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notificacions"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"Ja no rebràs aquestes notificacions."</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="other">1 categoria per a aquesta aplicació (<xliff:g id="NUMBER_1">%d</xliff:g> en total)</item>
+      <item quantity="one">1 categoria per a aquesta aplicació (<xliff:g id="NUMBER_0">%d</xliff:g> en total)</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"Totes les categories"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Més opcions"</string>
     <string name="notification_done" msgid="5279426047273930175">"Fet"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -592,31 +594,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"Desactivat"</string>
     <string name="nav_bar" msgid="1993221402773877607">"Barra de navegació"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"Disseny"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"Tipus de botó addicional de l\'esquerra"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"Tipus de botó addicional de la dreta"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(predeterminat)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"Porta-retalls"</item>
+    <item msgid="5742013440802239414">"Codi de tecla"</item>
+    <item msgid="8802889973626281575">"Commutador del teclat"</item>
+    <item msgid="8175437057325747277">"Cap"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"Normal"</item>
+    <item msgid="8256205964297588988">"Compacte"</item>
+    <item msgid="8719936228094005878">"Cap a l\'esquerra"</item>
+    <item msgid="586019486955594690">"Cap a la dreta"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"Commutador del teclat"</string>
     <string name="save" msgid="2311877285724540644">"Desa"</string>
     <string name="reset" msgid="2448168080964209908">"Restableix"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"Ajusta l\'amplada del botó"</string>
     <string name="clipboard" msgid="1313879395099896312">"Porta-retalls"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"Botó de navegació personalitzat"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"Codi de tecla de l\'esquerra"</string>
+    <string name="right_keycode" msgid="708447961000848163">"Codi de tecla de la dreta"</string>
+    <string name="left_icon" msgid="3096287125959387541">"Icona de l\'esquerra"</string>
+    <string name="right_icon" msgid="3952104823293824311">"Icona de la dreta"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"Arrossega per afegir funcions"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Arrossega aquí per suprimir una funció"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Edita"</string>
@@ -665,44 +667,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Obre la configuració per a <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Edita l\'ordre de la configuració."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Pàgina <xliff:g id="ID_1">%1$d</xliff:g> (<xliff:g id="ID_2">%2$d</xliff:g> en total)"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"Pantalla de bloqueig"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"Desplega"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimitza"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Tanca"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"El telèfon s\'està escalfant"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"Algunes funcions estaran limitades mentre el telèfon es refreda"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"El telèfon provarà de refredar-se automàticament. Podràs continuar utilitzant-lo, però és possible que funcioni més lentament.\n\nUn cop s\'hagi refredat, funcionarà amb normalitat."</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"Drecera de l\'esquerra"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"Drecera de la dreta"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"La drecera de l\'esquerra també desbloqueja el dispositiu"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"La drecera de la dreta també desbloqueja el dispositiu"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"Cap"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"Inicia <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"Altres aplicacions"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"Cercle"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"Més"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"Menys"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"Esquerra"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"Dreta"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"Menú"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"Aplicació <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertes"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Captures de pantalla"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Missatges generals"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Emmagatzematge"</string>
+    <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>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 5fd428a..ff33ba6 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -700,4 +700,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Snímky obrazovek"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Všeobecné zprávy"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Úložiště"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Okamžité aplikace"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Okamžité aplikace není třeba instalovat."</string>
+    <string name="app_info" msgid="6856026610594615344">"Informace o aplikaci"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 3c60752..04b3faf 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -692,4 +692,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshots"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Generelle meddelelser"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Lagerplads"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Instant apps kræver ingen installation."</string>
+    <string name="app_info" msgid="6856026610594615344">"Oplysninger om appen"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index bdc9193..cc5bb73 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -694,4 +694,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshots"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Nachrichten"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Speicher"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Instant-Apps"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Bei Instant-Apps ist keine vorherige Installation erforderlich."</string>
+    <string name="app_info" msgid="6856026610594615344">"App-Informationen"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 155a736..dde7ed4 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -692,4 +692,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Στιγμιότυπα οθόνης"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Γενικά μηνύματα"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Αποθηκευτικός χώρος"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Instant Εφαρμογές"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Οι Instant Εφαρμογές δεν απαιτούν εγκατάσταση."</string>
+    <string name="app_info" msgid="6856026610594615344">"Πληροφορίες εφαρμογής"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 73c8480..a1c3bea 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -692,4 +692,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshots"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"General Messages"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Storage"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Instant apps don\'t require installation."</string>
+    <string name="app_info" msgid="6856026610594615344">"App info"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 73c8480..a1c3bea 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -692,4 +692,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshots"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"General Messages"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Storage"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Instant apps don\'t require installation."</string>
+    <string name="app_info" msgid="6856026610594615344">"App info"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 73c8480..a1c3bea 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -692,4 +692,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshots"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"General Messages"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Storage"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Instant apps don\'t require installation."</string>
+    <string name="app_info" msgid="6856026610594615344">"App info"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index a6aa331..a8774c5 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -518,9 +518,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Con los controles de activación de notificaciones, puedes establecer un nivel de importancia para las notificaciones de una app. \n\n"<b>"Nivel 5"</b>" \n- Mostrar en la parte superior de la lista de notificaciones. \n- Permitir interrupción en la pantalla completa. \n- Mostrar siempre. \n\n"<b>"Nivel 4"</b>" \n- No permitir interrupción en la pantalla completa. \n- Mostrar siempre. \n\n"<b>"Nivel 3"</b>" \n- No permitir interrupción en la pantalla completa. \n- No mostrar. \n\n"<b>"Nivel 2"</b>" \n- No permitir interrupción en la pantalla completa. \n- No mostrar. \n- No sonar ni vibrar. \n\n"<b>"Nivel 1"</b>" \n- No permitir interrupción en la pantalla completa. \n- No mostrar. \n- No sonar ni vibrar. \n- Ocultar de la pantalla bloqueada y la barra de estado. \n- Mostrar al final de la lista de notificaciones. \n\n"<b>"Nivel 0"</b>" \n- Bloquear todas las notificaciones de la app."</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notificaciones"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"Ya no recibirás estas notificaciones."</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="other">1 de <xliff:g id="NUMBER_1">%d</xliff:g> categorías de esta app</item>
+      <item quantity="one">1 de <xliff:g id="NUMBER_0">%d</xliff:g> categoría de esta app</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"Todas las categorías"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Más opciones de configuración"</string>
     <string name="notification_done" msgid="5279426047273930175">"Listo"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g> de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -594,31 +596,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"Desactivado"</string>
     <string name="nav_bar" msgid="1993221402773877607">"Barra de navegación"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"Diseño"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"Tipo de botón izquierdo adicional"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"Tipo de botón derecho adicional"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(predeterminada)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"Portapapeles"</item>
+    <item msgid="5742013440802239414">"Clave de código"</item>
+    <item msgid="8802889973626281575">"Cambio de teclado"</item>
+    <item msgid="8175437057325747277">"Ninguno"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"Normal"</item>
+    <item msgid="8256205964297588988">"Compacto"</item>
+    <item msgid="8719936228094005878">"Hacia la izquierda"</item>
+    <item msgid="586019486955594690">"Hacia la derecha"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"Cambio de teclado"</string>
     <string name="save" msgid="2311877285724540644">"Guardar"</string>
     <string name="reset" msgid="2448168080964209908">"Restablecer"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"Ajustar ancho del botón"</string>
     <string name="clipboard" msgid="1313879395099896312">"Portapapeles"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"Botón de navegación personalizado"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"Clave de código izquierdo"</string>
+    <string name="right_keycode" msgid="708447961000848163">"Clave de código derecho"</string>
+    <string name="left_icon" msgid="3096287125959387541">"Ícono izquierdo"</string>
+    <string name="right_icon" msgid="3952104823293824311">"Ícono derecho"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"Arrastra los mosaicos para agregarlos"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Arrastra aquí para quitar"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Editar"</string>
@@ -667,44 +669,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Abrir configuración de <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Editar orden de configuración"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Página <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"Pantalla bloqueada"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"Expandir"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Cerrar"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"El teléfono se está calentando"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"Se limitarán algunas funciones mientras se enfría el teléfono"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"Tu teléfono intentará enfriarse automáticamente. Podrás usarlo, pero es posible que funcione más lento.\n\nUna vez que se haya enfriado, volverá a funcionar correctamente."</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"Acceso directo izquierdo"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"Acceso directo derecho"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"El acceso directo izquierdo también lo desbloquea"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"El acceso directo derecho también lo desbloquea"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"Ninguno"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"Iniciar <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"Otras apps"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"Círculo"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"Más"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"Menos"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"Izquierda"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"Derecha"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"Menú"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"App de <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturas de pantalla"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Mensajes generales"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Almacenamiento"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Apps instantáneas"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Las Apps instantáneas no requieren instalación."</string>
+    <string name="app_info" msgid="6856026610594615344">"Información de la app"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index df3c697..5892ac8 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -694,4 +694,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturas de pantalla"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Mensajes generales"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Almacenamiento"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Aplicaciones Instantáneas"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"No es necesario instalar las Aplicaciones Instantáneas."</string>
+    <string name="app_info" msgid="6856026610594615344">"Información de la aplicación"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 60bcbbc..561486e 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -518,9 +518,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Toite märguannete juhtnuppudega saate määrata rakenduse märguannete tähtsuse taseme vahemikus 0–5. \n\n"<b>"5. tase"</b>" \n- Kuva märguannete loendi ülaosas\n- Luba täisekraanil häirimine \n- Kuva alati ekraani servas \n\n"<b>"4. tase"</b>" \n- Keela täisekraanil häirimine \n- Kuva alati ekraani servas \n\n"<b>"3. tase"</b>" \n- Keela täisekraanil häirimine \n- Ära kunagi kuva ekraani servas \n\n"<b>"2. tase"</b>" \n- Keela täisekraanil häirimine \n- Ära kunagi kuva ekraani servas \n- Ära kunagi helise ega vibreeri \n\n"<b>"1. tase"</b>" \n- Keela täisekraanil häirimine \n- Ära kunagi kuva ekraani servas \n- Ära kunagi helise ega vibreeri \n- Peida lukustuskuval ja olekuribal \n- Kuva märguannete loendi allosas \n\n"<b>"Tase 0"</b>" \n- Blokeeri kõik rakenduse märguanded"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Märguanded"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"Te ei saa enam neid märguandeid."</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="other">1 selle rakenduse <xliff:g id="NUMBER_1">%d</xliff:g>-st kategooriast</item>
+      <item quantity="one">1 selle rakenduse <xliff:g id="NUMBER_0">%d</xliff:g>-st kategooriast</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"Kõik kategooriad"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Rohkem seadeid"</string>
     <string name="notification_done" msgid="5279426047273930175">"Valmis"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -594,31 +596,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"Väljas"</string>
     <string name="nav_bar" msgid="1993221402773877607">"Navigeerimisriba"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"Paigutus"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"Täiendava vasaku nupu tüüp"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"Täiendava parema nupu tüüp"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(vaikeseade)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"Lõikelaud"</item>
+    <item msgid="5742013440802239414">"Võtmekood"</item>
+    <item msgid="8802889973626281575">"Klaviatuuri vahetaja"</item>
+    <item msgid="8175437057325747277">"Mitte ükski"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"Tavaline"</item>
+    <item msgid="8256205964297588988">"Kompaktne"</item>
+    <item msgid="8719936228094005878">"Vasakule kaldu"</item>
+    <item msgid="586019486955594690">"Paremale kaldu"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"Klaviatuuri vahetaja"</string>
     <string name="save" msgid="2311877285724540644">"Salvesta"</string>
     <string name="reset" msgid="2448168080964209908">"Lähtesta"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"Nupu laiuse reguleerimine"</string>
     <string name="clipboard" msgid="1313879395099896312">"Lõikelaud"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"Kohandatud navigeerimisnupp"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"Vasak võtmekood"</string>
+    <string name="right_keycode" msgid="708447961000848163">"Parem võtmekood"</string>
+    <string name="left_icon" msgid="3096287125959387541">"Vasak ikoon"</string>
+    <string name="right_icon" msgid="3952104823293824311">"Parem ikoon"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"Lohistage paanide lisamiseks"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Lohistage eemaldamiseks siia"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Muutmine"</string>
@@ -667,44 +669,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Ava teenuse <xliff:g id="ID_1">%s</xliff:g> seaded."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Muuda seadete järjestust."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Leht <xliff:g id="ID_1">%1$d</xliff:g>/<xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"Lukustuskuva"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"Laiendamine"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimeeri"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Sule"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"Telefon soojeneb"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"Mõned funktsioonid on piiratud, kuni telefon jahtub"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"Teie telefon proovib automaatselt maha jahtuda. Saate telefoni ikka kasutada, kuid see võib olla aeglasem.\n\nKui telefon on jahtunud, töötab see tavapäraselt."</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"Vasak otsetee"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"Parem otsetee"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"Vasak otsetee avab ka"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"Parem otsetee avab ka"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"Mitte ükski"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"Rakenduse <xliff:g id="APP">%1$s</xliff:g> käivitamine"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"Muud rakendused"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"Ring"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"Pluss"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"Miinus"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"Vasak"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"Parem"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"Menüü"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"Rakendus <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Teatised"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Ekraanipildid"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Üldised sõnumid"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Salvestusruum"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Installimata avatavad rakendused"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Installimata avatavaid rakendusi pole vaja installida."</string>
+    <string name="app_info" msgid="6856026610594615344">"Rakenduse teave"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 8743d05..c123c50 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -620,7 +620,7 @@
     <string name="left_keycode" msgid="2010948862498918135">"Ezkerreko teklaren kodea"</string>
     <string name="right_keycode" msgid="708447961000848163">"Eskuineko teklaren kodea"</string>
     <string name="left_icon" msgid="3096287125959387541">"Ezkerreko ikonoa"</string>
-    <string name="right_icon" msgid="3952104823293824311">"Ezkerreko ikonoa"</string>
+    <string name="right_icon" msgid="3952104823293824311">"Eskuineko ikonoa"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"Arrastatu lauzak hemen gehitzeko"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Kentzeko, arrastatu hona"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Editatu"</string>
@@ -694,4 +694,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Pantaila-argazkiak"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Mezu orokorrak"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Memoria"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Zuzeneko aplikazioak"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Zuzeneko aplikazioak ez dira instalatu behar."</string>
+    <string name="app_info" msgid="6856026610594615344">"Aplikazioari buruzko informazioa"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 528415c..642fd43 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -516,9 +516,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"با کنترل‌های قدرتمند اعلان می‌توانید سطح اهمیت اعلان‌های هر برنامه را از ۰ تا ۵ تعیین کنید. \n\n"<b>"سطح ۵"</b>" \n- در صدر فهرست اعلان‌ها نشان داده می‌شود \n- وقفه برای نمایش تمام‌صفحه مجاز است \n- همیشه اجمالی نشان داده می‌شود \n\n"<b>"سطح ۴"</b>" \n- وقفه برای نمایش تمام‌صفحه مجاز نیست \n- همیشه اجمالی نشان داده می‌شود \n\n"<b>"سطح ۳"</b>" \n- وقفه برای نمایش تمام‌صفحه مجاز نیست \n- هیچ‌وقت اجمالی نشان داده نمی‌شود \n\n"<b>"سطح ۲"</b>" \n- وقفه برای نمایش تمام‌صفحه مجاز نیست \n- هیچ‌وقت اجمالی نشان داده نمی‌شود \n- هیچ‌وقت صدا و لرزش ایجاد نمی‌کند \n\n"<b>"سطح ۱"</b>" \n- نمایش تمام صفحه مجاز نیست \n- هیچ‌وقت اجمالی نشان داده نمی‌شود \n- هیچ‌وقت صدا یا لرزش ایجاد نمی‌کند \n- در قفل صفحه و نوار وضعیت پنهان است \n- در پایین فهرست اعلان‌ها نشان داده می‌شود \n\n"<b>"سطح ۰"</b>" \n- همه اعلان‌های این برنامه مسدود است"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"اعلان‌ها"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"دیگر این اعلان‌ها را دریافت نخواهید کرد."</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="one">یکی از <xliff:g id="NUMBER_1">%d</xliff:g> دسته این برنامه</item>
+      <item quantity="other">یکی از <xliff:g id="NUMBER_1">%d</xliff:g> دسته این برنامه</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"‏همه دسته‎ها"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"تنظیمات بیشتر"</string>
     <string name="notification_done" msgid="5279426047273930175">"تمام"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -592,31 +594,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"خاموش"</string>
     <string name="nav_bar" msgid="1993221402773877607">"نوار پیمایش"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"طرح‌بندی"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"نوع دکمه منتهی‌الیه چپ"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"نوع دکمه منتهی‌الیه راست"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(پیش‌فرض)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"کلیپ‌بورد"</item>
+    <item msgid="5742013440802239414">"کد کلید"</item>
+    <item msgid="8802889973626281575">"تغییردهنده صفحه‌کلید"</item>
+    <item msgid="8175437057325747277">"هیچ‌کدام"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"معمولی"</item>
+    <item msgid="8256205964297588988">"فشرده"</item>
+    <item msgid="8719936228094005878">"متمایل به چپ"</item>
+    <item msgid="586019486955594690">"متمایل به راست"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"تغییردهنده صفحه‌کلید"</string>
     <string name="save" msgid="2311877285724540644">"ذخیره کردن"</string>
     <string name="reset" msgid="2448168080964209908">"بازنشانی"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"تنظیم پهنای دکمه"</string>
     <string name="clipboard" msgid="1313879395099896312">"کلیپ‌بورد"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"دکمه پیمایش سفارشی"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"کدکلید چپ"</string>
+    <string name="right_keycode" msgid="708447961000848163">"کدکلید راست"</string>
+    <string name="left_icon" msgid="3096287125959387541">"نماد چپ"</string>
+    <string name="right_icon" msgid="3952104823293824311">"نماد راست"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"برای افزودن کاشی، بکشید"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"برای حذف، به اینجا بکشید"</string>
     <string name="qs_edit" msgid="2232596095725105230">"ویرایش"</string>
@@ -665,44 +667,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"باز کردن تنظیمات <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"ویرایش ترتیب تنظیمات."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"صفحه <xliff:g id="ID_1">%1$d</xliff:g> از <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"قفل صفحه"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"بزرگ کردن"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"کوچک کردن"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"بستن"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"تلفن درحال گرم شدن است"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"وقتی تلفن درحال خنک شدن است، بعضی از قابلیت‌ها محدود می‌شوند"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"تلفنتان به‌طور خودکار سعی می‌کند خنک شود. همچنان می‌توانید از تلفنتان استفاده کنید، اما ممکن است کندتر عمل کند.\n\nوقتی تلفن خنک شد، عملکرد عادی‌اش از سرگرفته می‌شود."</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"میان‌بر چپ"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"میان‌بر راست"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"قفل میان‌بر چپ هم باز می‌شود"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"قفل میان‌بر راست هم باز می‌شود"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"هیچ‌کدام"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"راه‌اندازی <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"سایر برنامه‌ها"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"دایره"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"جمع"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"تفریق"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"چپ"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"راست"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"منو"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> برنامه"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"هشدارها"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"عکس‌های صفحه‌نمایش"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"پیام‌های عمومی"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"فضای ذخیره‌سازی"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"برنامه‌های فوری"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"برنامه‌های فوری نیاز به نصب ندارند."</string>
+    <string name="app_info" msgid="6856026610594615344">"اطلاعات برنامه"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 5f44434..e3fc32c 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -692,4 +692,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Kuvakaappaukset"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Yleiset viestit"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Tallennustila"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Pikasovelluksia ei tarvitse asentaa."</string>
+    <string name="app_info" msgid="6856026610594615344">"Sovelluksen tiedot"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 139a1de..afec321 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -518,9 +518,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Avec les réglages avancés des notifications, vous pouvez définir un degré d\'importance de 0 à 5 pour les notifications d\'une application. \n\n"<b>"Niveau 5"</b>" \n- Afficher dans le haut de la liste des notifications \n- Autoriser les interruptions en mode plein écran \n- Toujours afficher les aperçus \n\n"<b>"Niveau 4"</b>" \n- Empêcher les interruptions en mode plein écran \n- Toujours afficher les aperçus \n\n"<b>"Niveau 3"</b>" \n- Empêcher les interruptions en mode plein écran \n- Ne jamais afficher les aperçus \n\n"<b>"Niveau 2"</b>" \n- Empêcher les interruptions en mode plein écran \n- Ne jamais afficher les aperçus \n- Ne pas autoriser les sons et les vibrations \n\n"<b>"Niveau 1"</b>" \n- Empêcher les interruptions en mode plein écran \n- Ne jamais afficher les aperçus \n- Ne pas autoriser les sons et les vibrations \n- Masquer de l\'écran de verrouillage et de la barre d\'état status bar \n- Afficher dans le bas de la liste des notifications \n\n"<b>"Level 0"</b>" \n- Bloquer toutes les notifications de l\'application"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notifications"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"Vous ne recevrez plus ces notifications."</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="one">1 catégorie sur <xliff:g id="NUMBER_1">%d</xliff:g> pour cette application</item>
+      <item quantity="other">1 catégories sur <xliff:g id="NUMBER_1">%d</xliff:g> pour cette application</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"Toutes les catégories"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Plus de paramètres"</string>
     <string name="notification_done" msgid="5279426047273930175">"Terminé"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -594,31 +596,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"Désactivé"</string>
     <string name="nav_bar" msgid="1993221402773877607">"Barre de navigation"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"Disposition"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"Type de bouton gauche supplémentaire"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"Type de bouton droit supplémentaire"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(par défaut)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"Presse-papiers"</item>
+    <item msgid="5742013440802239414">"Code de touche"</item>
+    <item msgid="8802889973626281575">"Sélecteur de clavier"</item>
+    <item msgid="8175437057325747277">"Aucun"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"Normale"</item>
+    <item msgid="8256205964297588988">"Compacte"</item>
+    <item msgid="8719936228094005878">"Alignée à gauche"</item>
+    <item msgid="586019486955594690">"Alignée à droite"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"Sélecteur de clavier"</string>
     <string name="save" msgid="2311877285724540644">"Enregistrer"</string>
     <string name="reset" msgid="2448168080964209908">"Réinitialiser"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"Ajuster la largeur du bouton"</string>
     <string name="clipboard" msgid="1313879395099896312">"Presse-papiers"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"Bouton de navigation personnalisé"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"Code de touche gauche"</string>
+    <string name="right_keycode" msgid="708447961000848163">"Code de touche droit"</string>
+    <string name="left_icon" msgid="3096287125959387541">"Icône à gauche"</string>
+    <string name="right_icon" msgid="3952104823293824311">"Icône droite"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"Faites glisser des tuiles pour les ajouter"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Faites glisser les tuiles ici pour les supprimer"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Modifier"</string>
@@ -667,44 +669,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Ouvrir les paramètres <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Modifier l\'ordre des paramètres."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Page <xliff:g id="ID_1">%1$d</xliff:g> sur <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"Écran de verrouillage"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"Développer"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Réduire"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Fermer"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"Le téléphone commence à chauffer"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"Les fonctionnalités sont limitées pendant que le téléphone refroidit"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"Votre téléphone va essayer de se refroidir automatiquement. Vous pouvez toujours l\'utiliser, mais il risque d\'être plus lent.\n\nUne fois refroidi, il fonctionnera normalement."</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"Raccourci gauche"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"Raccourci droit"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"Le raccourci gauche déverrouille aussi :"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"Le raccourci droit déverrouille aussi :"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"Aucun"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"Lancer l\'application <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"Autres applications"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"Cercle"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"Plus"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"Moins"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"Gauche"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"Droite"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"Menu"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"Application <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertes"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Saisies d\'écran"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Messages généraux"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Stockage"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Applications instantanées"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Les applications instantanées ne nécessitent pas d\'installation."</string>
+    <string name="app_info" msgid="6856026610594615344">"Détails de l\'application"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index e33155b..a4983ac 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -518,9 +518,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Grâce aux commandes de gestion des notifications, vous pouvez définir le niveau d\'importance (compris entre 0 et 5) des notifications d\'une application. \n\n"<b>"Niveau 5"</b>" \n- Afficher en haut de la liste des notifications \n- Autoriser l\'interruption en plein écran \n- Toujours en aperçu \n\n"<b>"Niveau 4"</b>" \n- Empêcher l\'interruption en plein écran \n- Toujours en aperçu \n\n"<b>"Niveau 3"</b>" \n- Empêcher l\'interruption en plein écran \n- Jamais en aperçu \n\n"<b>"Niveau 2"</b>" \n- Empêcher l\'interruption en plein écran \n- Jamais en aperçu \n- Ne jamais émettre de signal sonore ni déclencher le vibreur \n\n"<b>"Niveau 1"</b>" \n- Empêcher l\'interruption en plein écran \n- Jamais en aperçu \n- Ne jamais émettre de signal sonore ni déclencher le vibreur \n- Masquer les notifications dans l\'écran de verrouillage et la barre d\'état \n- Afficher au bas de la liste des notifications \n\n"<b>"Niveau 0"</b>" \n- Bloquer toutes les notifications de l\'application"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notifications"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"Vous ne recevrez plus ces notifications."</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="one">1 catégorie sur <xliff:g id="NUMBER_1">%d</xliff:g> pour cette application</item>
+      <item quantity="other">1 catégorie sur <xliff:g id="NUMBER_1">%d</xliff:g> pour cette application</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"Toutes les catégories"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Plus de paramètres"</string>
     <string name="notification_done" msgid="5279426047273930175">"Terminé"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> : <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -594,31 +596,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"Désactivé"</string>
     <string name="nav_bar" msgid="1993221402773877607">"Barre de navigation"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"Disposition"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"Type de bouton gauche supplémentaire"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"Type de bouton droit supplémentaire"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(par défaut)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"Presse-papiers"</item>
+    <item msgid="5742013440802239414">"Code de touche"</item>
+    <item msgid="8802889973626281575">"Sélecteur clavier"</item>
+    <item msgid="8175437057325747277">"Aucun"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"Normale"</item>
+    <item msgid="8256205964297588988">"Compacte"</item>
+    <item msgid="8719936228094005878">"Alignée à gauche"</item>
+    <item msgid="586019486955594690">"Alignée à droite"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"Sélecteur clavier"</string>
     <string name="save" msgid="2311877285724540644">"Enregistrer"</string>
     <string name="reset" msgid="2448168080964209908">"Réinitialiser"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"Ajuster la largeur du bouton"</string>
     <string name="clipboard" msgid="1313879395099896312">"Presse-papiers"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"Bouton de navigation personnalisé"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"Code de touche gauche"</string>
+    <string name="right_keycode" msgid="708447961000848163">"Code de touche droit"</string>
+    <string name="left_icon" msgid="3096287125959387541">"Icône gauche"</string>
+    <string name="right_icon" msgid="3952104823293824311">"Icône droite"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"Faites glisser des tuiles ici pour les ajouter"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Faites glisser les tuiles ici pour les supprimer."</string>
     <string name="qs_edit" msgid="2232596095725105230">"Modifier"</string>
@@ -667,44 +669,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Ouvrir les paramètres <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Modifier l\'ordre des paramètres."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Page <xliff:g id="ID_1">%1$d</xliff:g> sur <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"Écran de verrouillage"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"Développer"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Réduire"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Fermer"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"Le téléphone chauffe"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"Fonctionnalités limitées pendant le refroidissement du téléphone"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"Votre téléphone va essayer de se refroidir automatiquement. Vous pouvez toujours l\'utiliser, mais il risque d\'être plus lent.\n\nUne fois refroidi, il fonctionnera normalement."</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"Raccourci gauche"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"Raccourci droit"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"Le raccourci gauche déverrouille également"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"Le raccourci droit déverrouille également"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"Aucun"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"Lancer <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"Autres applications"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"Cercle"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"Plus"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"Moins"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"Gauche"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"Droite"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"Menu"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"Application <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertes"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Captures d\'écran"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Nouveaux messages"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Espace de stockage"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Applis instantanées"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Les applis instantanées ne nécessitent pas d\'installation."</string>
+    <string name="app_info" msgid="6856026610594615344">"Infos sur l\'appli"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 9b738bd..5bbdf60 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -518,9 +518,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Cos controis de notificacións mellorados, podes asignarlles un nivel de importancia comprendido entre 0 e 5 ás notificacións dunha aplicación determinada. \n\n"<b>"Nivel 5"</b>" \n- Mostrar na parte superior da lista de notificacións. \n- Permitir interrupcións no modo de pantalla completa. \n- Mostrar sempre. \n\n"<b>"Nivel 4"</b>" \n- Impedir interrupcións no modo de pantalla completa. \n- Mostrar sempre. \n\n"<b>"Nivel 3"</b>" \n- Impedir interrupcións no modo de pantalla completa. \n- Non mostrar nunca. \n\n"<b>"Nivel 2"</b>" \n- Impedir interrupcións no modo de pantalla completa. \n- Non mostrar nunca. \n- Non soar nin vibrar nunca. \n\n"<b>"Nivel 1"</b>" \n- Impedir interrupcións no modo de pantalla completa. \n- Non mostrar nunca. \n- Non soar nin vibrar nunca. \n- Ocultar na pantalla de bloqueo e na barra de estado. \n- Mostrar na parte inferior da lista de notificacións. \n\n"<b>"Nivel 0"</b>" \n- Bloquear todas as notificacións da aplicación."</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notificacións"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"Deixarás de recibir estas notificacións."</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="other">1 de <xliff:g id="NUMBER_1">%d</xliff:g> categorías desta aplicación</item>
+      <item quantity="one">1 de <xliff:g id="NUMBER_0">%d</xliff:g> categoría desta aplicación</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"Todas as categorías"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Máis opcións"</string>
     <string name="notification_done" msgid="5279426047273930175">"Feito"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g> de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -594,31 +596,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"Desactivar"</string>
     <string name="nav_bar" msgid="1993221402773877607">"Barra de navegación"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"Deseño"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"Tipo de botón adicional á esquerda"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"Tipo de botón adicional á dereita"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(predeterminado)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"Portapapeis"</item>
+    <item msgid="5742013440802239414">"Código de teclas"</item>
+    <item msgid="8802889973626281575">"Conmutador do teclado"</item>
+    <item msgid="8175437057325747277">"Ningún"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"Normal"</item>
+    <item msgid="8256205964297588988">"Compacto"</item>
+    <item msgid="8719936228094005878">"Á esquerda"</item>
+    <item msgid="586019486955594690">"Á dereita"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"Conmutador do teclado"</string>
     <string name="save" msgid="2311877285724540644">"Gardar"</string>
     <string name="reset" msgid="2448168080964209908">"Restablecer"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"Axustar o ancho do botón"</string>
     <string name="clipboard" msgid="1313879395099896312">"Portapapeis"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"Botón de navegación personalizada"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"Código de teclas á esquerda"</string>
+    <string name="right_keycode" msgid="708447961000848163">"Código de teclas á dereita"</string>
+    <string name="left_icon" msgid="3096287125959387541">"Icona á esquerda"</string>
+    <string name="right_icon" msgid="3952104823293824311">"Icona á dereita"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"Arrastrar para engadir funcións"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Arrastra o elemento ata aquí para eliminalo"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Editar"</string>
@@ -667,44 +669,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Abrir a configuración de <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Editar a orde das opcións de configuración."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Páxina <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"Pantalla de bloqueo"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"Despregar"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Pechar"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"O teléfono está quentando"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"O uso dalgunhas funcións é limitado mentres o teléfono arrefría"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"O teléfono tentará arrefriar automaticamente. Podes utilizalo, pero é probable que funcione máis lento.\n\nUnha vez que arrefríe, funcionará con normalidade."</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"Atallo á esquerda"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"Atallo á dereita"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"O atallo á esquerda tamén desbloquea o dispositivo"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"O atallo á dereita tamén desbloquea o dispositivo"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"Ningún"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"Iniciar <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"Outras aplicacións"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"Círculo"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"Máis"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"Menos"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"Esquerda"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"Dereita"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"Menú"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"Aplicación <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturas de pantalla"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Mensaxes xerais"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Almacenamento"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Aplicacións instantáneas"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"As aplicacións instantáneas non precisan instalación."</string>
+    <string name="app_info" msgid="6856026610594615344">"Información da aplicación"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index bc82be9..e63390a 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -516,9 +516,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"પાવર સૂચના નિયંત્રણો સાથે, તમે ઍપ્લિકેશનની સૂચનાઓ માટે 0 થી 5 સુધીના મહત્વના સ્તરને સેટ કરી શકો છો. \n\n"<b>"સ્તર 5"</b>" \n- સૂચના સૂચિની ટોચ પર બતાવો \n- પૂર્ણ સ્ક્રીન અવરોધની મંજૂરી આપો \n- હંમેશાં ત્વરિત દૃષ્ટિ કરો \n\n"<b>"સ્તર 4"</b>" \n- પૂર્ણ સ્ક્રીન અવરોધ અટકાવો \n- હંમેશાં ત્વરિત દૃષ્ટિ કરો \n\n"<b>"સ્તર 3"</b>" \n- પૂર્ણ સ્ક્રીન અવરોધ અટકાવો \n- ક્યારેય ત્વરિત દૃષ્ટિ કરશો નહીં \n\n"<b>"સ્તર 2"</b>" \n- પૂર્ણ સ્ક્રીન અવરોધ અટકાવો \n- ક્યારેય ત્વરિત દૃષ્ટિ કરશો નહીં \n- ક્યારેય અવાજ અને વાઇબ્રેશન કરશો નહીં \n\n"<b>"સ્તર 1"</b>" \n- પૂર્ણ સ્ક્રીન અવરોધ અટકાવો \n- ક્યારેય ત્વરિત દૃષ્ટિ કરશો નહીં \n- ક્યારેય અવાજ અથવા વાઇબ્રેટ કરશો નહીં \n- લૉક સ્ક્રીન અને સ્થિતિ બારથી છુપાવો \n- સૂચના સૂચિના તળિયા પર બતાવો \n\n"<b>"સ્તર 0"</b>" \n- ઍપ્લિકેશનની તમામ સૂચનાઓને અવરોધિત કરો"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"સૂચનાઓ"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"તમને હવે આ સૂચનાઓ મળશે નહીં."</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="one">આ ઍપ્લિકેશન તરફથી <xliff:g id="NUMBER_1">%d</xliff:g> માંથી 1 કૅટેગરી</item>
+      <item quantity="other">આ ઍપ્લિકેશન તરફથી <xliff:g id="NUMBER_1">%d</xliff:g> માંથી 1 કૅટેગરી</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"બધી કૅટેગરી"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"વધુ સેટિંગ્સ"</string>
     <string name="notification_done" msgid="5279426047273930175">"થઈ ગયું"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -592,31 +594,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"બંધ"</string>
     <string name="nav_bar" msgid="1993221402773877607">"નેવિગેશન બાર"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"લેઆઉટ"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"અતિરિક્ત ડાબો બટન પ્રકાર"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"અતિરિક્ત જમણો બટન પ્રકાર"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(ડિફૉલ્ટ)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"ક્લિપબોર્ડ"</item>
+    <item msgid="5742013440802239414">"કીકોડ"</item>
+    <item msgid="8802889973626281575">"કીબોર્ડ સ્વિચર"</item>
+    <item msgid="8175437057325747277">"કોઈ નહીં"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"સામાન્ય"</item>
+    <item msgid="8256205964297588988">"નિબિડ"</item>
+    <item msgid="8719936228094005878">"ડાબી બાજુએ ઢળતું"</item>
+    <item msgid="586019486955594690">"જમણી બાજુએ ઢળતું"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"કીબોર્ડ સ્વિચર"</string>
     <string name="save" msgid="2311877285724540644">"સાચવો"</string>
     <string name="reset" msgid="2448168080964209908">"ફરીથી સેટ કરો"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"બટનની પહોળાઈ સમાયોજિત કરો"</string>
     <string name="clipboard" msgid="1313879395099896312">"ક્લિપબોર્ડ"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"કસ્ટમ નેવિગેશન બટન"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"ડાબો કીકોડ"</string>
+    <string name="right_keycode" msgid="708447961000848163">"જમણો કીકોડ"</string>
+    <string name="left_icon" msgid="3096287125959387541">"ડાબું આઇકન"</string>
+    <string name="right_icon" msgid="3952104823293824311">"જમણું આઇકન"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"ટાઇલ્સ ઉમેરવા માટે ખેંચો"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"દૂર કરવા માટે અહીં ખેંચો"</string>
     <string name="qs_edit" msgid="2232596095725105230">"સંપાદિત કરો"</string>
@@ -665,44 +667,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> સેટિંગ્સ ખોલો."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"સેટિંગ્સનો ક્રમ સંપાદિત કરો."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> માંથી <xliff:g id="ID_1">%1$d</xliff:g> પૃષ્ઠ"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"લૉક સ્ક્રીન"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"વિસ્તૃત કરો"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"નાનું કરો"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"બંધ કરો"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"ફોન ગરમ થઈ રહ્યો છે"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"ફોન ઠંડો થાય ત્યાં સુધી કેટલીક સુવિધાઓ મર્યાદિત હોય છે"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"તમારો ફોન આપમેળે ઠંડો થવાનો પ્રયાસ કરશે. તમે હજી પણ તમારા ફોનનો ઉપયોગ કરી શકો છો, પરંતુ તે કદાચ થોડો ધીમો ચાલે.\n\nતમારો ફોન ઠંડો થઈ જવા પર, તે સામાન્ય રીતે ચાલશે."</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"ડાબો શૉર્ટકટ"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"જમણો શૉર્ટકટ"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"ડાબો શૉર્ટકટ પણ અનલૉક કરે છે"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"જમણો શૉર્ટકટ પણ અનલૉક કરે છે"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"કોઈ નહીં"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"<xliff:g id="APP">%1$s</xliff:g> લૉન્ચ કરો"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"અન્ય ઍપ્લિકેશનો"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"વર્તુળ"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"સરવાળો"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"બાદબાકી"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"ડાબે"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"જમણે"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"મેનૂ"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> ઍપ્લિકેશન"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"ચેતવણીઓ"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"સ્ક્રીનશૉટ"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"સામાન્ય સંદેશા"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"સ્ટોરેજ"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"ઝટપટ ઍપ્લિકેશનો"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"ઝટપટ ઍપ્લિકેશનો માટે ઇન્સ્ટૉલેશનની જરૂર નથી."</string>
+    <string name="app_info" msgid="6856026610594615344">"ઍપ્લિકેશન માહિતી"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 6b9050e..f1d4545 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -682,8 +682,8 @@
     <string name="tuner_launch_app" msgid="1527264114781925348">"<xliff:g id="APP">%1$s</xliff:g> लॉन्च करें"</string>
     <string name="tuner_other_apps" msgid="4726596850501162493">"दूसरे ऐप"</string>
     <string name="tuner_circle" msgid="2340998864056901350">"मंडली"</string>
-    <string name="tuner_plus" msgid="6792960658533229675">"धन का चिह्न"</string>
-    <string name="tuner_minus" msgid="4806116839519226809">"ऋण का चिह्न"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"जोड़ का चिह्न"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"घटाने का चिह्न"</string>
     <string name="tuner_left" msgid="8404287986475034806">"बायां"</string>
     <string name="tuner_right" msgid="6222734772467850156">"दायां"</string>
     <string name="tuner_menu" msgid="191640047241552081">"मेनू"</string>
@@ -692,4 +692,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"स्‍क्रीनशॉट"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"सामान्य संदेश"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"जगह"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"झटपट ऐप्स"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"झटपट ऐप्स के लिए इंस्टॉलेशन ज़रूरी नहीं है."</string>
+    <string name="app_info" msgid="6856026610594615344">"ऐप की जानकारी"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 02b6dae..a8fe4b1 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -695,4 +695,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Snimke zaslona"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Općenite poruke"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Pohrana"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Instant aplikacije"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Instant aplikacije nije potrebno instalirati."</string>
+    <string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 647369b..0bd7fd0 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -516,9 +516,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Az értesítési beállítások révén 0-tól 5-ig állíthatja be a fontossági szintet az alkalmazás értesítéseinél. \n\n"<b>"5. szint"</b>" \n– Megjelenítés az értesítési lista tetején \n– Teljes képernyő megszakításának engedélyezése \n– Mindig felugrik \n\n"<b>"4. szint"</b>" \n– Teljes képernyő megszakításának megakadályozása \n– Mindig felugrik \n\n"<b>"3. szint"</b>" \n– Teljes képernyő megszakításának megakadályozása \n– Soha nem ugrik fel \n\n"<b>"2. szint"</b>" \n– Teljes képernyő megszakításának megakadályozása \n– Soha nem ugrik fel \n– Soha nincs hangjelzés és rezgés \n\n"<b>"1. szint"</b>" \n– Teljes képernyő megszakításának megakadályozása \n– Soha nem ugrik fel \n– Soha nincs hangjelzés vagy rezgés \n– Elrejtés a lezárási képernyőről és az állapotsávról \n– Megjelenítés az értesítési lista alján \n\n"<b>"0. szint"</b>" \n– Az alkalmazás összes értesítésének letiltása"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Értesítések"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"Többé nem jelennek meg ezek az értesítések."</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="other">1 az alkalmazás <xliff:g id="NUMBER_1">%d</xliff:g> kategóriájából</item>
+      <item quantity="one">1 az alkalmazás <xliff:g id="NUMBER_0">%d</xliff:g> kategóriájából</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"Minden kategória"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"További beállítások"</string>
     <string name="notification_done" msgid="5279426047273930175">"Kész"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> – <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -592,31 +594,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"Ki"</string>
     <string name="nav_bar" msgid="1993221402773877607">"Navigációs sáv"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"Elrendezés"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"További bal oldali gombtípus"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"További jobb oldali gombtípus"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(alapértelmezett)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"Vágólap"</item>
+    <item msgid="5742013440802239414">"Billentyűkód"</item>
+    <item msgid="8802889973626281575">"Billentyűzetváltó"</item>
+    <item msgid="8175437057325747277">"Nincs"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"Normál"</item>
+    <item msgid="8256205964297588988">"Kompakt"</item>
+    <item msgid="8719936228094005878">"Bal oldali"</item>
+    <item msgid="586019486955594690">"Jobb oldali"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"Billentyűzetváltó"</string>
     <string name="save" msgid="2311877285724540644">"Mentés"</string>
     <string name="reset" msgid="2448168080964209908">"Alaphelyzet"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"Gombszélesség beállítása"</string>
     <string name="clipboard" msgid="1313879395099896312">"Vágólap"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"Személyre szabott navigációs gomb"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"Bal oldali billentyűkód"</string>
+    <string name="right_keycode" msgid="708447961000848163">"Jobb oldali billentyűkód"</string>
+    <string name="left_icon" msgid="3096287125959387541">"Bal oldali ikon"</string>
+    <string name="right_icon" msgid="3952104823293824311">"Jobb oldali ikon"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"Húzza csempe hozzáadásához"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Húzza ide az eltávolításhoz"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Szerkesztés"</string>
@@ -665,44 +667,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"A(z) <xliff:g id="ID_1">%s</xliff:g> beállításainak megnyitása."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Beállítások sorrendjének szerkesztése."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>. oldal, összesen: <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"Lezárási képernyő"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"Kibontás"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Kis méret"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Bezárás"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"A telefon melegszik"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"Bizonyos funkciók korlátozottan működnek a telefon hűlése közben"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"A telefon automatikusan megpróbál lehűlni. Továbbra is tudja használni a telefont, de elképzelhető, hogy működése lelassul.\n\nAmint a telefon lehűl, újra a szokásos módon működik majd."</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"Bal oldali parancsikon"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"Jobb oldali parancsikon"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"A bal oldali parancsikon szintén feloldja a zárolást"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"A jobb oldali parancsikon szintén feloldja a zárolást"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"Nincs"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"A(z) <xliff:g id="APP">%1$s</xliff:g> alkalmazás indítása"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"Egyéb alkalmazások"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"Kör"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"Plusz"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"Mínusz"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"Bal"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"Jobb"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"Menü"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> alkalmazás"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Értesítések"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Képernyőképek"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Általános üzenetek"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Tárhely"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Azonnali alkalmazások"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Az azonnali alkalmazásokat nem kell telepíteni."</string>
+    <string name="app_info" msgid="6856026610594615344">"Alkalmazásinformáció"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 1f05d8a..63882e6 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -692,4 +692,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Էկրանի պատկերներ"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Ընդհանուր հաղորդագրություններ"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Հիշողություն"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Ակնթարթորեն գործարկվող հավելվածներ"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Ակնթարթորեն գործարկվող հավելվածները տեղադրում չեն պահանջում։"</string>
+    <string name="app_info" msgid="6856026610594615344">"Հավելվածի տվյալներ"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index e323b73..2be8a4d 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -155,7 +155,7 @@
     <string name="accessibility_cell_data" msgid="7080312242791850520">"Data Seluler"</string>
     <string name="accessibility_cell_data_on" msgid="4310018593519761767">"Data Seluler Aktif"</string>
     <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Data Seluler Nonaktif"</string>
-    <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Penambatan bluetooth."</string>
+    <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Tethering bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Mode pesawat."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Tidak ada kartu SIM."</string>
     <string name="accessibility_carrier_network_change_mode" msgid="4017301580441304305">"Jaringan operator berubah."</string>
@@ -692,4 +692,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshot"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Pesan Umum"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Penyimpanan"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Aplikasi Instan"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Aplikasi instan tidak perlu diinstal."</string>
+    <string name="app_info" msgid="6856026610594615344">"Info aplikasi"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index cb60752..04ae68d 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -692,4 +692,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Skjámyndir"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Almenn skilaboð"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Geymslurými"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Skyndiforrit"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Skyndiforrit þurfa ekki uppsetningu."</string>
+    <string name="app_info" msgid="6856026610594615344">"Forritsupplýsingar"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 6e887c8..2766dd4 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -694,4 +694,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshot"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Messaggi generali"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Spazio di archiviazione"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"App istantanee"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Le app istantanee non richiedono l\'installazione."</string>
+    <string name="app_info" msgid="6856026610594615344">"Informazioni app"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index d2b0fb9..e9719ba 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -520,9 +520,13 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"בעזרת פקדים של הודעות הפעלה, תוכל להגדיר רמת חשיבות מ-0 עד 5 להודעות אפליקציה. \n\n"<b>"רמה 5"</b>" \n- הצג בראש רשימת ההודעות \n- אפשר הפרעה במסך מלא \n- תמיד אפשר הצצה \n\n"<b>"רמה 4"</b>" \n- מנע הפרעה במסך מלא \n- תמיד אפשר הצצה \n\n"<b>"רמה 3"</b>" \n- מנע הפרעה במסך מלא \n- אף פעם אל תאפשר הצצה \n\n"<b>"רמה 2"</b>" \n- מנע הפרעה במסך מלא \n- אף פעם אל תאפשר הצצה \n- אף פעם אל תאפשר קול ורטט \n\n"<b>"רמה 1"</b>" \n- מנע הפרעה במסך מלא \n- אף פעם אל תאפשר הצצה \n- אף פעם אל תאפשר קול ורטט \n- הסתר ממסך הנעילה ומשורת הסטטוס \n- הצג בתחתית רשימת ההודעות \n\n"<b>"רמה 0"</b>" \n- חסום את כל ההודעות מהאפליקציה"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"הודעות"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"לא תקבל את ההודעות האלה יותר."</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="two">1 מתוך <xliff:g id="NUMBER_1">%d</xliff:g> קטגוריות מאפליקציה זו</item>
+      <item quantity="many">1 מתוך <xliff:g id="NUMBER_1">%d</xliff:g> קטגוריות מאפליקציה זו</item>
+      <item quantity="other">1 מתוך <xliff:g id="NUMBER_1">%d</xliff:g> קטגוריות מאפליקציה זו</item>
+      <item quantity="one">1 קטגוריה מתוך <xliff:g id="NUMBER_0">%d</xliff:g> מאפליקציה זו</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"כל הקטגוריות"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"הגדרות נוספות"</string>
     <string name="notification_done" msgid="5279426047273930175">"סיום"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -596,31 +600,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"כבוי"</string>
     <string name="nav_bar" msgid="1993221402773877607">"סרגל ניווט"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"פריסה"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"סוג נוסף של לחצן שמאלי"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"סוג נוסף של לחצן ימני"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(ברירת מחדל)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"לוח"</item>
+    <item msgid="5742013440802239414">"קוד מפתח"</item>
+    <item msgid="8802889973626281575">"מחליף מקלדת"</item>
+    <item msgid="8175437057325747277">"ללא"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"רגילה"</item>
+    <item msgid="8256205964297588988">"קומפקטית"</item>
+    <item msgid="8719936228094005878">"נטייה שמאלה"</item>
+    <item msgid="586019486955594690">"נטייה ימינה"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"מחליף מקלדת"</string>
     <string name="save" msgid="2311877285724540644">"שמור"</string>
     <string name="reset" msgid="2448168080964209908">"איפוס"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"שינוי של רוחב לחצן"</string>
     <string name="clipboard" msgid="1313879395099896312">"לוח"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"לחצן לניווט מותאם אישית"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"קוד מפתח שמאלי"</string>
+    <string name="right_keycode" msgid="708447961000848163">"קוד מפתח ימני"</string>
+    <string name="left_icon" msgid="3096287125959387541">"סמל שמאלי"</string>
+    <string name="right_icon" msgid="3952104823293824311">"סמל ימני"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"גרור כדי להוסיף משבצות"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"גרור לכאן כדי להסיר"</string>
     <string name="qs_edit" msgid="2232596095725105230">"ערוך"</string>
@@ -669,44 +673,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"פתיחת הגדרות של <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"עריכת סדר ההגדרות."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"דף <xliff:g id="ID_1">%1$d</xliff:g> מתוך <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"מסך נעילה"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"הרחב"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"מזער"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"סגור"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"הטלפון מתחמם"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"חלק מהתכונות מוגבלות כל עוד הטלפון מתקרר"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"קירור הטלפון ייעשה באופן אוטומטי. תוכל עדיין להשתמש בטלפון, אבל ייתכן שהוא יפעל לאט יותר.\n\nהטלפון יחזור לפעול כרגיל לאחר שיתקרר."</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"קיצור דרך שמאלי"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"קיצור דרך ימני"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"קיצור דרך שמאלי גם מבטל נעילה"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"קיצור דרך ימני גם מבטל נעילה"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"ללא"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"הפעל את האפליקציה <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"אפליקציות אחרות"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"מעגל"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"פלוס"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"מינוס"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"שמאלה"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"ימינה"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"תפריט"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"האפליקציה <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"התראות"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"צילומי מסך"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"הודעות כלליות"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"אחסון"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"אפליקציות אינסטנט"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"אפליקציות אינסטנט לא דורשות התקנה."</string>
+    <string name="app_info" msgid="6856026610594615344">"פרטי אפליקציה"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 6603a77..968c437 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -518,9 +518,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"電源通知管理では、アプリの通知の重要度をレベル 0~5 で設定できます。\n\n"<b>"レベル 5"</b>" \n- 通知リストの一番上に表示する \n- 全画面表示を許可する \n- 常にポップアップする \n\n"<b>"レベル 4"</b>" \n- 全画面表示しない \n- 常にポップアップする \n\n"<b>"レベル 3"</b>" \n- 全画面表示しない \n- ポップアップしない \n\n"<b>"レベル 2"</b>" \n- 全画面表示しない \n- ポップアップしない \n- 音やバイブレーションを使用しない \n\n"<b>"レベル 1"</b>" \n- 全画面表示しない \n- ポップアップしない \n- 音やバイブレーションを使用しない \n- ロック画面やステータスバーに表示しない \n- 通知リストの一番下に表示する \n\n"<b>"レベル 0"</b>" \n- アプリからのすべての通知をブロックする"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"通知"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"今後、この通知は配信されません。"</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="other">このアプリのカテゴリ <xliff:g id="NUMBER_1">%d</xliff:g> 件中 1 件</item>
+      <item quantity="one">このアプリのカテゴリ <xliff:g id="NUMBER_0">%d</xliff:g> 件中 1 件</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"すべてのカテゴリ"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"詳細設定"</string>
     <string name="notification_done" msgid="5279426047273930175">"完了"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -594,31 +596,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"OFF"</string>
     <string name="nav_bar" msgid="1993221402773877607">"ナビゲーション バー"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"レイアウト"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"その他の左ボタンタイプ"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"その他の右ボタンタイプ"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(デフォルト)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"クリップボード"</item>
+    <item msgid="5742013440802239414">"キーコード"</item>
+    <item msgid="8802889973626281575">"キーボードを切り替え"</item>
+    <item msgid="8175437057325747277">"なし"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"標準"</item>
+    <item msgid="8256205964297588988">"コンパクト"</item>
+    <item msgid="8719936228094005878">"左寄り"</item>
+    <item msgid="586019486955594690">"右寄り"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"キーボードを切り替え"</string>
     <string name="save" msgid="2311877285724540644">"保存"</string>
     <string name="reset" msgid="2448168080964209908">"リセット"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"ボタンの幅の調整"</string>
     <string name="clipboard" msgid="1313879395099896312">"クリップボード"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"カスタム ナビゲーション ボタン"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"左キーコード"</string>
+    <string name="right_keycode" msgid="708447961000848163">"右キーコード"</string>
+    <string name="left_icon" msgid="3096287125959387541">"左アイコン"</string>
+    <string name="right_icon" msgid="3952104823293824311">"右アイコン"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"タイルを追加するにはドラッグしてください"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"削除するにはここにドラッグ"</string>
     <string name="qs_edit" msgid="2232596095725105230">"編集"</string>
@@ -667,44 +669,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> の設定を開きます。"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"設定の順序を編集します。"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"ページ <xliff:g id="ID_1">%1$d</xliff:g>/<xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"ロック画面"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"展開"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"最小化"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"閉じる"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"スマートフォンの温度が上昇中"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"スマートフォンのクールダウン中は一部の機能が制限されます"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"スマートフォンは自動的にクールダウンを行います。その間もスマートフォンを使用できますが、動作が遅くなる可能性があります。\n\nクールダウンが完了すると、通常どおり動作します。"</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"左ショートカット"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"右ショートカット"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"左ショートカットでもロックを解除"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"右ショートカットでもロックを解除"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"なし"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"<xliff:g id="APP">%1$s</xliff:g> を起動"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"その他のアプリ"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"サークル"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"プラス"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"マイナス"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"左"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"右"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"メニュー"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> アプリ"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"通知"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"スクリーンショット"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"一般メッセージ"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"ストレージ"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Instant Apps はインストールせずに利用できます。"</string>
+    <string name="app_info" msgid="6856026610594615344">"アプリ情報"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index fb08e93..258f447 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -692,4 +692,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"ეკრანის ანაბეჭდები"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"ზოგადი შეტყობინებები"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"მეხსიერება"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"მყისიერი აპები"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"მყისიერი აპები ინსტალაციას არ საჭიროებს."</string>
+    <string name="app_info" msgid="6856026610594615344">"აპის შესახებ"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 111f1a7..66f3ea7 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -692,4 +692,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Скриншоттар"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Жалпы хабарлар"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Жад"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Лездік қолданбаларды орнатудың қажеті жоқ."</string>
+    <string name="app_info" msgid="6856026610594615344">"Қолданба ақпараты"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 402b42f..a5c724b 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -516,9 +516,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"ជាមួយអង្គគ្រប់គ្រងការជូនដំណឹងថាមពល អ្នកអាចកំណត់កម្រិតសំខាន់ពី 0 ទៅ 5 សម្រាប់ការជូនដំណឹងរបស់កម្មវិធី។ \n\n"<b>"កម្រិត 5"</b>" \n- បង្ហាញនៅផ្នែកខាងលើបញ្ជីជូនដំណឹង \n- អនុញ្ញាតការរំខានលើអេក្រង់ពេញ \n- លោតឡើងជានិច្ច \n\n"<b>"កម្រិត 4"</b>" \n- រារាំងការរំខានលើអេក្រង់ពេញ \n- លោតឡើងជានិច្ច \n\n"<b>"កម្រិត 3"</b>" \n- រារាំងការរំខានលើអេក្រង់ពេញ \n- លោតឡើងជានិច្ច \n\n"<b>"កម្រិត 2"</b>" \n- រារាំងការរំខានលើអេក្រង់ពេញ \n- លោតឡើងជានិច្ច \n- មិនបន្លឺសំឡេង ឬញ័រ \n\n"<b>"កម្រិត 1"</b>" \n- រារាំងការរំខានលើអេក្រង់ពេញ \n- លោតឡើងជានិច្ច \n- មិនបន្លឺសំឡេង ឬញ័រ \n- លាក់ពីអេក្រង់ចាក់សោ និងរបារស្ថានភាព \n- បង្ហាញនៅផ្នែកខាងក្រោមបញ្ជីជូនដំណឹង \n\n"<b>"កម្រិត 0"</b>" \n- រារាំងការជូនដំណឹងទាំងអស់ពីកម្មវិធី"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"ការ​ជូនដំណឹង"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"អ្នក​នឹង​មិន​ទទួល​បាន​ការ​ជូនដំណឹង​ទាំងនេះ​ទៀត​ទេ។"</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="other">ប្រភេទ 1 ក្នុង​ចំណោម​ប្រភេទ <xliff:g id="NUMBER_1">%d</xliff:g> ពី​កម្មវិធី​នេះ</item>
+      <item quantity="one">ប្រភេទ 1 ក្នុង​ចំណោម​ប្រភេទ <xliff:g id="NUMBER_0">%d</xliff:g> ពី​កម្មវិធី​នេះ</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"ប្រភេទ​ទាំងអស់"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"ការកំណត់ច្រើនទៀត"</string>
     <string name="notification_done" msgid="5279426047273930175">"រួចរាល់"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -592,31 +594,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"បិទ"</string>
     <string name="nav_bar" msgid="1993221402773877607">"របាររុករក"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"ប្លង់"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"ប្រភេទ​ប៊ូតុង​ខាង​ឆ្វេង​បន្ថែម"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"ប្រភេទ​ប៊ូតុង​ខាង​ស្តាំ​បន្ថែម"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(លំនាំដើម)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"អង្គចងចាំ"</item>
+    <item msgid="5742013440802239414">"លេខកូដ​គ្រាប់ចុច"</item>
+    <item msgid="8802889973626281575">"កម្មវិធី​ប្តូរក្តារ​ចុច"</item>
+    <item msgid="8175437057325747277">"គ្មាន"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"ធម្មតា"</item>
+    <item msgid="8256205964297588988">"តូច"</item>
+    <item msgid="8719936228094005878">"ផ្អៀង​ទៅ​ឆ្វេង"</item>
+    <item msgid="586019486955594690">"ផ្អៀង​ទៅ​ស្តាំ"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"កម្មវិធី​ប្តូរក្តារ​ចុច"</string>
     <string name="save" msgid="2311877285724540644">"រក្សាទុក"</string>
     <string name="reset" msgid="2448168080964209908">"កំណត់​ឡើងវិញ"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"កែសម្រួលទទឹងប៊ូតុង"</string>
     <string name="clipboard" msgid="1313879395099896312">"ក្ដារ​តម្បៀត​ខ្ទាស់"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"ប៊ូតុងរុករកផ្ទាល់ខ្លួន"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"កូដ​គ្រាប់ចុច​ខាង​ឆ្វេង"</string>
+    <string name="right_keycode" msgid="708447961000848163">"កូដ​គ្រាប់ចុច​ខាង​ស្តាំ"</string>
+    <string name="left_icon" msgid="3096287125959387541">"រូបតំណាង​ខាង​ឆ្វេង"</string>
+    <string name="right_icon" msgid="3952104823293824311">"រូបតំណាង​ខាង​ស្ដាំ"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"អូសដើម្បីបន្ថែមប្រអប់"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"អូសទីនេះដើម្បីយកចេញ"</string>
     <string name="qs_edit" msgid="2232596095725105230">"កែសម្រួល"</string>
@@ -665,44 +667,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"បើការកំណត់ <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"កែលំដាប់ការកំណត់"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"ទំព័រ <xliff:g id="ID_1">%1$d</xliff:g> នៃ <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"អេក្រង់​ចាក់សោ"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"ពង្រីក"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"បង្រួម"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"បិទ"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"ទូរសព្ទ​នេះ​កំពុង​កើន​កម្តៅ"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"មុខងារ​មួយ​ចំនួន​នឹង​មិន​អាច​ប្រើ​បាន​ពេញលេញ​នោះ​ទេ ខណៈពេល​ដែល​ទូរសព្ទ​កំពុង​បញ្ចុះ​កម្តៅ"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"ទូរសព្ទ​របស់អ្នក​នឹង​ព្យាយាម​បញ្ចុះ​កម្តៅ​ដោយ​ស្វ័យប្រវត្តិ។ អ្នក​នៅតែ​អាច​ប្រើ​ទូរសព្ទ​របស់អ្នក​បាន​ដដែល​ ប៉ុន្តែ​វា​នឹង​ដំណើរ​ការ​យឺត​ជាង​មុន។\n\nបន្ទាប់​ពី​ទូរសព្ទ​របស់អ្នក​ត្រជាក់​ជាង​មុន​ហើយ វា​នឹង​ដំណើរការ​ដូច​ធម្មតា។"</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"ផ្លូវកាត់​ខាង​ឆ្វេង"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"ផ្លូវកាត់​ខាង​ស្តាំ"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"ផ្លូវកាត់​ខាង​ឆ្វេង​ក៏​ដោះសោ​ដែរ"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"ផ្លូវកាត់​ខាង​ស្តាំ​ក៏​ដោះសោ​ដែរ"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"គ្មាន"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"ចាប់​ផ្តើម <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"កម្មវិធី​ផ្សេង​ទៀត"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"រង្វង់"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"បូក"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"ដក"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"ឆ្វេង"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"ស្ដាំ"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"ម៉ឺនុយ"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"កម្មវិធី <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"ការ​ជូនដំណឹង"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"រូបថត​អេក្រង់"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"សារ​ទូទៅ"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"ទំហំផ្ទុក"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"កម្មវិធី​ប្រើ​ភ្លាមៗ"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"កម្មវិធី​ប្រើ​ភ្លាមៗ​មិន​តម្រូវ​ឲ្យ​មានការ​ដំឡើង​ទេ។"</string>
+    <string name="app_info" msgid="6856026610594615344">"ព័ត៌មាន​កម្មវិធី"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 8ea08b9..f4ce3bf 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -516,9 +516,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"ಪವರ್ ಅಧಿಸೂಚನೆ ನಿಯಂತ್ರಣಗಳ ಮೂಲಕ, ನೀವು ಅಪ್ಲಿಕೇಶನ್‌ಗಳ ಅಧಿಸೂಚನೆಗಳನ್ನು 0 ರಿಂದ 5 ರವರೆಗಿನ ಹಂತಗಳ ಪ್ರಾಮುಖ್ಯತೆಯನ್ನು ಹೊಂದಿಸಬಹುದು. \n\n"<b>"ಹಂತ 5"</b>" \n- ಮೇಲಿನ ಅಧಿಸೂಚನೆ ಪಟ್ಟಿಯನ್ನು ತೋರಿಸಿ \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ಅನುಮತಿಸಿ \n- ಯಾವಾಗಲು ಇಣುಕು ನೋಟ \n\n"<b>"ಹಂತ 4"</b>" \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ತಡೆಯಿರಿ \n- ಯಾವಾಗಲು ಇಣುಕು ನೋಟ\n\n"<b>"ಹಂತ 3"</b>" \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ತಡೆಯಿರಿ \n- ಎಂದಿಗೂ ಇಣುಕು ನೋಟ ಬೇಡ \n\n"<b>"ಹಂತ 2"</b>" \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ತಡೆಯಿರಿ \n- ಎಂದಿಗೂ ಇಣುಕು ನೋಟ ಬೇಡ \n- ಶಬ್ದ ಮತ್ತು ವೈಬ್ರೇಷನ್ ಎಂದಿಗೂ ಮಾಡಬೇಡಿ \n\n"<b>"ಹಂತ 1"</b>" \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ತಡೆಯಿರಿ \n- ಎಂದಿಗೂ ಇಣುಕು ನೋಟ ಬೇಡ \n- ಶಬ್ದ ಮತ್ತು ವೈಬ್ರೇಷನ್ ಎಂದಿಗೂ ಮಾಡಬೇಡಿ \n- ಸ್ಥಿತಿ ಪಟ್ಟಿ ಮತ್ತು ಲಾಕ್ ಪರದೆಯಿಂದ ಮರೆಮಾಡಿ \n- ಕೆಳಗಿನ ಅಧಿಸೂಚನೆ ಪಟ್ಟಿಯನ್ನು ತೋರಿಸಿ \n\n"<b>"ಹಂತ 0"</b>" \n- ಅಪ್ಲಿಕೇಶನ್‌ನಿಂದ ಎಲ್ಲಾ ಅಧಿಸೂಚನೆಗಳನ್ನು ನಿರ್ಬಂಧಿಸಿ"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"ಅಧಿಸೂಚನೆಗಳು"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"ನೀವು ಇನ್ನು ಮುಂದೆ ಈ ಅಧಿಸೂಚನೆಗಳನ್ನು ಪಡೆಯುವುದಿಲ್ಲ."</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="one">ಈ ಅಪ್ಲಿಕೇಶನ್‌ನಿಂದ <xliff:g id="NUMBER_1">%d</xliff:g> ವರ್ಗಗಳಲ್ಲಿ 1</item>
+      <item quantity="other">ಈ ಅಪ್ಲಿಕೇಶನ್‌ನಿಂದ <xliff:g id="NUMBER_1">%d</xliff:g> ವರ್ಗಗಳಲ್ಲಿ 1</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"ಎಲ್ಲ ವರ್ಗಗಳು"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"ಹೆಚ್ಚಿನ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
     <string name="notification_done" msgid="5279426047273930175">"ಮುಗಿದಿದೆ"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -592,31 +594,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"ಆಫ್"</string>
     <string name="nav_bar" msgid="1993221402773877607">"ನ್ಯಾವಿಗೇಷನ್ ಬಾರ್"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"ಲೇಔಟ್"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"ಹೆಚ್ಚುವರಿ ಎಡ ಬಟನ್ ವಿಧ"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"ಹೆಚ್ಚುವರಿ ಬಲ ಬಟನ್ ವಿಧ"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(ಡಿಫಾಲ್ಟ್‌)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"ಕ್ಲಿಪ್‌ಬೋರ್ಡ್"</item>
+    <item msgid="5742013440802239414">"ಕೀಕೋಡ್"</item>
+    <item msgid="8802889973626281575">"ಕೀಬೋರ್ಡ್ ಬದಲಾಯಿಸುವಿಕೆ"</item>
+    <item msgid="8175437057325747277">"ಯಾವುದೂ ಅಲ್ಲ"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"ಸಾಮಾನ್ಯ"</item>
+    <item msgid="8256205964297588988">"ಕಾಂಪ್ಯಾಕ್ಟ್‌"</item>
+    <item msgid="8719936228094005878">"ಎಡ-ಬಾಗುವಿಕೆ"</item>
+    <item msgid="586019486955594690">"ಬಲ-ಬಾಗುವಿಕೆ"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"ಕೀಬೋರ್ಡ್ ಬದಲಾಯಿಸುವಿಕೆ"</string>
     <string name="save" msgid="2311877285724540644">"ಉಳಿಸು"</string>
     <string name="reset" msgid="2448168080964209908">"ಮರುಹೊಂದಿಸು"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"ಬಟನ್ ಅಳತೆ ಹೊಂದಿಸು"</string>
     <string name="clipboard" msgid="1313879395099896312">"ಕ್ಲಿಪ್‌ಬೋರ್ಡ್"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"ಕಸ್ಟಮ್ ನ್ಯಾವಿಗೇಷನ್ ಬಟನ್"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"ಎಡ ಕೀಕೋಡ್"</string>
+    <string name="right_keycode" msgid="708447961000848163">"ಬಲ ಕೀಕೋಡ್"</string>
+    <string name="left_icon" msgid="3096287125959387541">"ಎಡ ಐಕಾನ್"</string>
+    <string name="right_icon" msgid="3952104823293824311">"ಬಲ ಐಕಾನ್"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"ಟೈಲ್‌ಗಳನ್ನು ಸೇರಿಸಲು ಡ್ರ್ಯಾಗ್ ಮಾಡಿ"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"ತೆಗೆದುಹಾಕಲು ಇಲ್ಲಿ ಡ್ರ್ಯಾಗ್‌ ಮಾಡಿ"</string>
     <string name="qs_edit" msgid="2232596095725105230">"ಎಡಿಟ್"</string>
@@ -665,44 +667,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ತೆರೆಯಿರಿ."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"ಸೆಟ್ಟಿಂಗ್‌ಗಳ ಕ್ರಮವನ್ನು ಎಡಿಟ್ ಮಾಡಿ."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> ರಲ್ಲಿ <xliff:g id="ID_1">%1$d</xliff:g> ಪುಟ"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"ಲಾಕ್ ಪರದೆ"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"ವಿಸ್ತೃತಗೊಳಿಸು"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"ಕುಗ್ಗಿಸಿ"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"ಮುಚ್ಚಿ"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"ಫೋನ್ ಬಿಸಿಯಾಗುತ್ತಿದೆ"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"ಫೋನ್ ತಣ್ಣಗಾಗುವವರೆಗೂ ಕೆಲವು ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಸೀಮಿತಗೊಳಿಸುತ್ತದೆ"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"ನಿಮ್ಮ ಫೋನ್ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ತಣ್ಣಗಾಗಲು ಪ್ರಯತ್ನಿಸುತ್ತದೆ. ನಿಮ್ಮ ಫೋನ್ ಅನ್ನು ನೀವು ಈಗಲೂ ಬಳಸಬಹುದಾಗಿರುತ್ತದೆ, ಆದರೆ ಇದು ನಿಧಾನವಾಗಿರಬಹುದು.\n\nಒಮ್ಮೆ ನಿಮ್ಮ ಫೋನ್ ತಣ್ಣಗಾದ ನಂತರ ಇದು ಸಾಮಾನ್ಯ ರೀತಿಯಲ್ಲಿ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ."</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"ಎಡ ಶಾರ್ಟ್‌ಕಟ್"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"ಬಲ ಶಾರ್ಟ್‌ಕಟ್"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"ಎಡ ಶಾರ್ಟ್‌ಕಟ್ ಕೂಡ ಅನ್‌ಲಾಕ್ ಮಾಡುತ್ತದೆ"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"ಬಲ ಶಾರ್ಟ್‌ಕಟ್ ಕೂಡ ಅನ್‌ಲಾಕ್ ಮಾಡುತ್ತದೆ"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"ಯಾವುದೂ ಅಲ್ಲ"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"<xliff:g id="APP">%1$s</xliff:g> ಪ್ರಾರಂಭಿಸಿ"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"ಇತರ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"ವಲಯ"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"ಪ್ಲಸ್"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"ಮೈನಸ್"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"ಎಡ"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"ಬಲ"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"ಮೆನು"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> ಅಪ್ಲಿಕೇಶನ್"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"ಎಚ್ಚರಿಕೆಗಳು"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ಗಳು"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"ಸಾಮಾನ್ಯ ಸಂದೇಶಗಳು"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"ಸಂಗ್ರಹಣೆ"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"ತತ್‌ಕ್ಷಣ ಆಪ್‌ಗಳು"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"ತತ್‌ಕ್ಷಣ ಆಪ್‌ಗಳಿಗೆ ಸ್ಥಾಪನೆಯ ಅಗತ್ಯವಿಲ್ಲ."</string>
+    <string name="app_info" msgid="6856026610594615344">"ಅಪ್ಲಿಕೇಶನ್ ಮಾಹಿತಿ"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index d2a6a77..b624b58 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -518,9 +518,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"전원 알림 컨트롤을 사용하면 앱 알림 관련 중요도를 0부터 5까지로 설정할 수 있습니다. \n\n"<b>"레벨 5"</b>" \n- 알림 목록 상단에 표시 \n- 전체 화면일 경우 알림 표시 허용 \n- 항상 엿보기 표시 \n\n"<b>"레벨 4"</b>" \n- 전체 화면에 알림 표시 금지 \n- 항상 엿보기 표시 \n\n"<b>"레벨 3"</b>" \n- 전체 화면에 알림 표시 금지 \n- 엿보기 표시 안함 \n\n"<b>"레벨 2"</b>" \n- 전체 화면에 알림 표시 금지 \n- 엿보기 표시 안함 \n- 소리나 진동으로 알리지 않음 \n\n"<b>"레벨 1"</b>" \n- 전체 화면에 알림 표시 금지 \n- 엿보기 표시 안함 \n- 소리나 진동으로 알리지 않음 \n- 잠금 화면 및 상태 표시줄에서 숨김 \n- 알림 목록 하단에 표시 \n\n"<b>"레벨 0"</b>" \n- 앱의 모든 알림 차단"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"알림"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"더 이상 다음의 알림을 받지 않습니다."</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="other">이 앱의 카테고리 <xliff:g id="NUMBER_1">%d</xliff:g>개 중 1개</item>
+      <item quantity="one">이 앱의 카테고리 <xliff:g id="NUMBER_0">%d</xliff:g>개 중 1개</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"전체 카테고리"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"설정 더보기"</string>
     <string name="notification_done" msgid="5279426047273930175">"완료"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -594,31 +596,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"사용 안함"</string>
     <string name="nav_bar" msgid="1993221402773877607">"탐색 메뉴"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"레이아웃"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"추가 왼쪽 버튼 유형"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"추가 오른쪽 버튼 유형"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(기본)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"클립보드"</item>
+    <item msgid="5742013440802239414">"키 코드"</item>
+    <item msgid="8802889973626281575">"키보드 전환 도구"</item>
+    <item msgid="8175437057325747277">"없음"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"보통"</item>
+    <item msgid="8256205964297588988">"작게"</item>
+    <item msgid="8719936228094005878">"왼쪽으로 기울기"</item>
+    <item msgid="586019486955594690">"오른쪽으로 기울기"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"키보드 전환 도구"</string>
     <string name="save" msgid="2311877285724540644">"저장"</string>
     <string name="reset" msgid="2448168080964209908">"초기화"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"버튼 너비 조정"</string>
     <string name="clipboard" msgid="1313879395099896312">"클립보드"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"맞춤 탐색 버튼"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"왼쪽 키 코드"</string>
+    <string name="right_keycode" msgid="708447961000848163">"오른쪽 키 코드"</string>
+    <string name="left_icon" msgid="3096287125959387541">"왼쪽 아이콘"</string>
+    <string name="right_icon" msgid="3952104823293824311">"오른쪽 아이콘"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"드래그하여 타일 추가"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"삭제하려면 여기를 드래그"</string>
     <string name="qs_edit" msgid="2232596095725105230">"수정"</string>
@@ -667,44 +669,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> 설정 열기"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"설정 순서 수정"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g>페이지 중 <xliff:g id="ID_1">%1$d</xliff:g>페이지"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"잠금 화면"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"펼치기"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"최소화"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"닫기"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"휴대전화 온도가 높음"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"휴대전화 온도를 낮추는 동안 일부 기능이 제한됩니다."</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"휴대전화 온도를 자동으로 낮추려고 시도합니다. 휴대전화를 계속 사용할 수는 있지만 작동이 느려질 수도 있습니다.\n\n휴대전화 온도가 낮아지면 정상적으로 작동됩니다."</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"왼쪽 바로가기"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"오른쪽 바로가기"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"왼쪽 바로가기도 잠금 해제 가능"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"오른쪽 바로가기도 잠금 해제 가능"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"없음"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"<xliff:g id="APP">%1$s</xliff:g> 실행"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"기타 앱"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"원"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"더하기 기호"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"빼기 기호"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"왼쪽 화살표"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"오른쪽 화살표"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"메뉴"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> 앱"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"알림"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"스크린샷"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"일반 메시지"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"저장소"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"빠른 실행 앱"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"빠른 실행 앱은 설치가 필요하지 않습니다."</string>
+    <string name="app_info" msgid="6856026610594615344">"앱 정보"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 8124220..c56d9bb 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -692,4 +692,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Скриншоттор"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Жалпы билдирүүлөр"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Сактагыч"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Ыкчам ачылуучу колдонмолор"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Ыкчам ачылуучу колдонмолорду орнотуу талап кылынбайт."</string>
+    <string name="app_info" msgid="6856026610594615344">"Колдонмо тууралуу"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index c40797c..ca05240 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -19,9 +19,6 @@
     <!-- thickness (width) of the navigation bar on phones that require it -->
     <dimen name="navigation_bar_size">@*android:dimen/navigation_bar_width</dimen>
 
-    <!-- Standard notification gravity -->
-    <integer name="notification_panel_layout_gravity">@integer/standard_notification_panel_layout_gravity</integer>
-
     <dimen name="docked_divider_handle_width">2dp</dimen>
     <dimen name="docked_divider_handle_height">16dp</dimen>
 
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 7ae971e..05e4e57 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -692,4 +692,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"ຮູບຖ່າຍໜ້າຈໍ"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"ຂໍ້ຄວາມທົ່ວໄປ"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"ບ່ອນເກັບຂໍ້ມູນ"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"ອິນສະແຕນແອັບ"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"ອິນສະແຕນແອັບບໍ່ຈຳເປັນຕ້ອງມີການຕິດຕັ້ງ."</string>
+    <string name="app_info" msgid="6856026610594615344">"ຂໍ້ມູນແອັບ"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index e98b7f7..095ae2f 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -520,9 +520,13 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Naudodami pranešimų valdiklius galite nustatyti programos pranešimų svarbos lygį nuo 0 iki 5. \n\n"<b>"5 lygis"</b>" \n– Rodyti pranešimų sąrašo viršuje \n– Leisti pertraukti, kai veikia viso ekrano režimas \n– Visada rodyti pranešimus \n\n"<b>"4 lygis"</b>" \n– Neleisti pertraukti viso ekrano režimo \n– Visada rodyti pranešimus \n\n"<b>"3 lygis"</b>" \n– Neleisti pertraukti viso ekrano režimo \n– Niekada nerodyti pranešimų \n\n"<b>"2 lygis"</b>" \n– Neleisti pertraukti viso ekrano režimo \n– Niekada nerodyti pranešimų \n– Niekada neleisti garso ir nevibruoti \n\n"<b>"1 lygis"</b>" \n– Neleisti pertraukti viso ekrano režimo \n– Niekada nerodyti pranešimų \n– Niekada neleisti garso ir nevibruoti \n– Slėpti užrakinimo ekrane ir būsenos juostoje \n– Rodyti pranešimų sąrašo apačioje \n\n"<b>"0 lygis"</b>" \n– Blokuoti visus programos pranešimus"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Pranešimai"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"Nebegausite šių pranešimų."</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="one">1 iš <xliff:g id="NUMBER_1">%d</xliff:g> kategorijos (iš šios programos)</item>
+      <item quantity="few">1 iš <xliff:g id="NUMBER_1">%d</xliff:g> kategorijų (iš šios programos)</item>
+      <item quantity="many">1 iš <xliff:g id="NUMBER_1">%d</xliff:g> kategorijos (iš šios programos)</item>
+      <item quantity="other">1 iš <xliff:g id="NUMBER_1">%d</xliff:g> kategorijų (iš šios programos)</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"Visos kategorijos"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Daugiau nustatymų"</string>
     <string name="notification_done" msgid="5279426047273930175">"Atlikta"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -596,31 +600,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"Išjungta"</string>
     <string name="nav_bar" msgid="1993221402773877607">"Naršymo juosta"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"Išdėstymas"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"Papildomo mygtuko kairėje tipas"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"Papildomo mygtuko dešinėje tipas"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(numatytoji)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"Iškarpinė"</item>
+    <item msgid="5742013440802239414">"Klavišo kodas"</item>
+    <item msgid="8802889973626281575">"Klaviatūros perjungiklis"</item>
+    <item msgid="8175437057325747277">"Nėra"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"Įprastas"</item>
+    <item msgid="8256205964297588988">"Kompaktiškas"</item>
+    <item msgid="8719936228094005878">"Kairėje"</item>
+    <item msgid="586019486955594690">"Dešinėje"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"Klaviatūros perjungiklis"</string>
     <string name="save" msgid="2311877285724540644">"Išsaugoti"</string>
     <string name="reset" msgid="2448168080964209908">"Atstatyti"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"Mygtuko pločio koregavimas"</string>
     <string name="clipboard" msgid="1313879395099896312">"Iškarpinė"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"Tinkintas naršymo mygtukas"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"Klavišo kodas kairėje"</string>
+    <string name="right_keycode" msgid="708447961000848163">"Klavišo kodas dešinėje"</string>
+    <string name="left_icon" msgid="3096287125959387541">"Piktograma kairėje"</string>
+    <string name="right_icon" msgid="3952104823293824311">"Piktograma dešinėje"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"Nuvilkite, kad pridėtumėte išklotinės elementų"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Vilkite čia, jei norite pašalinti"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Redaguoti"</string>
@@ -669,44 +673,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Atidaryti „<xliff:g id="ID_1">%s</xliff:g>“ nustatymus."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Redaguoti nustatymų tvarką."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g> psl. iš <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"Užrakinimo ekranas"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"Išskleisti"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Sumažinti"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Uždaryti"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"Telefonas kaista"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"Kai kurios funkcijos gali neveikti, kol telefonas vėsta"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefonas automatiškai bandys atvėsti. Telefoną vis tiek galėsite naudoti, tačiau jis gali veikti lėčiau.\n\nKai telefonas atvės, jis veiks įprastai."</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"Spartusis klavišas kairėje"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"Spartusis klavišas dešinėje"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"Spartusis klavišas kairėje taip pat atrakina"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"Spartusis klavišas dešinėje taip pat atrakina"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"Nėra"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"Paleisti programą „<xliff:g id="APP">%1$s</xliff:g>“"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"Kitos programos"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"Draugų ratas"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"Pliusas"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"Minusas"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"Kairėje"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"Dešinėje"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"Meniu"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"Programa „<xliff:g id="APP">%1$s</xliff:g>“"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Įspėjimai"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Ekrano kopijos"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Bendrieji pranešimai"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Saugykla"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Akimirksniu įkeliamos programėlės"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Akimirksniu įkeliamų programėlių nereikia įdiegti."</string>
+    <string name="app_info" msgid="6856026610594615344">"Programos informacija"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index c55d7a8..9eff144 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -518,9 +518,12 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Izmantojot barošanas paziņojumu vadīklas, varat lietotnes paziņojumiem iestatīt svarīguma līmeni (no 0 līdz 5). \n\n"<b>"5. līmenis"</b>" \n- Tiek rādīts paziņojumu saraksta augšdaļā \n- Tiek atļauta pilnekrāna režīma pārtraukšana \n- Ieskats vienmēr atļauts \n\n"<b>"4. līmenis"</b>" \n- Tiek novērsta pilnekrāna režīma pārtraukšana \n- Ieskats vienmēr atļauts \n\n"<b>"3. līmenis"</b>" \n- Tiek novērsta pilnekrāna režīma pārtraukšana \n- Ieskats nav atļauts \n\n"<b>"2. līmenis"</b>" \n- Tiek novērsta pilnekrāna režīma pārtraukšana \n- Ieskats nav atļauts \n- Nav atļautas skaņas un vibrosignāls \n\n"<b>"1. līmenis"</b>" \n- Tiek novērsta pilnekrāna režīma pārtraukšana \n- Ieskats nav atļauts \n- Nav atļautas skaņas un vibrosignāls \n- Paziņojumi tiek paslēpti bloķēšanas ekrānā un statusa joslā \n- Paziņojumi tiek rādīti paziņojumu saraksta apakšdaļā \n\n"<b>"0. līmenis"</b>" \n- Visi lietotnes paziņojumi tiek bloķēti"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Paziņojumi"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"Jūs vairs nesaņemsiet šos paziņojumus."</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="zero">1 no <xliff:g id="NUMBER_1">%d</xliff:g> kategorijām šai lietotnei</item>
+      <item quantity="one">1 no <xliff:g id="NUMBER_1">%d</xliff:g> kategorijas šai lietotnei</item>
+      <item quantity="other">1 no <xliff:g id="NUMBER_1">%d</xliff:g> kategorijām šai lietotnei</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"Visas kategorijas"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Citi iestatījumi"</string>
     <string name="notification_done" msgid="5279426047273930175">"Gatavs"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -594,31 +597,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"Izslēgts"</string>
     <string name="nav_bar" msgid="1993221402773877607">"Navigācijas josla"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"Izkārtojums"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"Kreisās puses papildu pogas veids"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"Labās puses papildu pogas veids"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(noklusējums)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"Starpliktuve"</item>
+    <item msgid="5742013440802239414">"Taustiņu kods"</item>
+    <item msgid="8802889973626281575">"Tastatūras pārslēdzējs"</item>
+    <item msgid="8175437057325747277">"Neviens"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"Normāls"</item>
+    <item msgid="8256205964297588988">"Kompakts"</item>
+    <item msgid="8719936228094005878">"Novirzīts pa kreisi"</item>
+    <item msgid="586019486955594690">"Novirzīts pa labi"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"Tastatūras pārslēdzējs"</string>
     <string name="save" msgid="2311877285724540644">"Saglabāt"</string>
     <string name="reset" msgid="2448168080964209908">"Atiestatīt"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"Pogas platuma pielāgošana"</string>
     <string name="clipboard" msgid="1313879395099896312">"Starpliktuve"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"Pielāgota navigācijas poga"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"Taustiņu kods kreisajā pusē"</string>
+    <string name="right_keycode" msgid="708447961000848163">"Taustiņu kods labajā pusē"</string>
+    <string name="left_icon" msgid="3096287125959387541">"Ikona kreisajā pusē"</string>
+    <string name="right_icon" msgid="3952104823293824311">"Ikona labajā pusē"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"Velciet elementus, lai tos pievienotu"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Lai noņemtu vienumus, velciet tos šeit."</string>
     <string name="qs_edit" msgid="2232596095725105230">"Rediģēt"</string>
@@ -667,44 +670,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Atvērt <xliff:g id="ID_1">%s</xliff:g> iestatījumus."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Rediģēt iestatījumu secību."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>. lpp. no <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"Bloķēšanas ekrāns"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"Izvērst"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizēt"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Aizvērt"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"Tālrunis kļūst silts"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"Dažas funkcijas ir ierobežotas, kamēr tālrunis mēģina atdzist"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"Jūsu tālrunis automātiski mēģinās atdzist. Jūs joprojām varat izmantot tālruni, taču tas, iespējams, darbosies lēnāk.\n\nTiklīdz tālrunis būs atdzisis, tas darbosies normāli."</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"Saīsne kreisajā pusē"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"Saīsne labajā pusē"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"Saīsne kreisajā pusē arī atbloķē"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"Saīsne labajā pusē arī atbloķē"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"Nav"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"Palaist <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"Citas lietotnes"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"Loks"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"Pluss"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"Mīnuss"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"Pa kreisi"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"Pa labi"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"Izvēlne"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> lietotne"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Brīdinājumi"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Ekrānuzņēmumi"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Vispārīgi ziņojumi"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Krātuve"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Tūlītējās lietotnes"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Tūlītējām lietotnēm nav nepieciešama instalēšana."</string>
+    <string name="app_info" msgid="6856026610594615344">"Lietotnes informācija"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index f5378c5..e384ae3 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -692,4 +692,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Слики од екранот"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Општи пораки"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Меморија"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Инстант апликации"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Инстант апликациите нема потреба да се инсталираат."</string>
+    <string name="app_info" msgid="6856026610594615344">"Информации за апликација"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 0d92c3b..427430f 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -516,9 +516,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"പവർ അറിയിപ്പ് നിയന്ത്രണം ഉപയോഗിച്ച്, ഒരു ആപ്പിനായുള്ള അറിയിപ്പുകൾക്ക് 0 മുതൽ 5 വരെയുള്ള പ്രാധാന്യ ലെവലുകളിലൊന്ന് നിങ്ങൾക്ക് സജ്ജമാക്കാവുന്നതാണ്. \n\n"<b>"ലെവൽ 5"</b>" \n- അറിയിപ്പ് ലിസ്റ്റിന്റെ മുകളിൽ കാണിക്കുക \n- മുഴുവൻ സ്ക്രീൻ തടസ്സം അനുവദിക്കുക \n- എല്ലായ്പ്പോഴും ദൃശ്യമാക്കുക \n\n"<b>"ലെവൽ 4"</b>" \n- മുഴുവൻ സ്ക്രീൻ തടസ്സം തടയുക \n- എല്ലായ്പ്പോഴും ദൃശ്യമാക്കുക \n\n"<b>"ലെവൽ 3"</b>" \n- മുഴുവൻ സ്ക്രീൻ തടസ്സം തടയുക \n- ഒരിക്കലും സൃശ്യമാക്കരുത് \n\n"<b>"ലെവൽ 2"</b>" \n- മുഴുവൻ സ്ക്രീൻ തടസ്സം തടയുക \n- ഒരിക്കലും ദൃശ്യമാക്കരുത് \n- ഒരിക്കലും ശബ്ദവും വൈബ്രേഷനും ഉണ്ടാക്കരുത് \n\n"<b>"ലെവൽ 1"</b>" \n- മുഴുവൻ സ്ക്രീൻ തടസ്സം തടയുക \n- ഒരിക്കലും ദൃശ്യമാക്കരുത് \n- ഒരിക്കലും ശബ്ദവും വൈബ്രേഷനും ഉണ്ടാക്കരുത് \n- ലോക്ക് സ്ക്രീനിൽ നിന്നും സ്റ്റാറ്റസ് ബാറിൽ നിന്നും മറയ്ക്കുക \n- അറിയിപ്പ് ലിസ്റ്റിന്റെ അടിയിൽ കാണിക്കുക \n\n"<b>"ലെവൽ 0"</b>" \n- ആപ്പിൽ നിന്നുള്ള എല്ലാ അറിയിപ്പുകളും ബ്ലോക്കുചെയ്യുക"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"അറിയിപ്പുകൾ"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"നിങ്ങൾക്ക് ഈ അറിയിപ്പുകൾ ഇനിയങ്ങോട്ട് ലഭിക്കില്ല."</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="other">ഈ ആപ്പിൽ നിന്നുള്ള 1 / <xliff:g id="NUMBER_1">%d</xliff:g> വിഭാഗങ്ങൾ</item>
+      <item quantity="one">ഈ ആപ്പിൽ നിന്നുള്ള 1 / <xliff:g id="NUMBER_0">%d</xliff:g> വിഭാഗം</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"എല്ലാ വിഭാഗങ്ങളും"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"കൂടുതൽ ക്രമീകരണം"</string>
     <string name="notification_done" msgid="5279426047273930175">"പൂർത്തിയായി"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -592,31 +594,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"ഓഫ്"</string>
     <string name="nav_bar" msgid="1993221402773877607">"നാവിഗേഷൻ ബാർ"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"ലേ‌ഔട്ട്"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"അധിക ഇടത് ബട്ടൺ തരം"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"അധിക വലത് ബട്ടൺ തരം"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(ഡിഫോൾട്ട്)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"ക്ലിപ്പ്ബോർഡ്"</item>
+    <item msgid="5742013440802239414">"കീകോഡ്"</item>
+    <item msgid="8802889973626281575">"കീബോർഡ് സ്വിച്ചർ"</item>
+    <item msgid="8175437057325747277">"ഒന്നുമില്ല"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"സാധാരണ വേഗത്തിൽ"</item>
+    <item msgid="8256205964297588988">"ഒതുക്കമുള്ളത്"</item>
+    <item msgid="8719936228094005878">"ഇടത്തേക്ക് ചാഞ്ഞിരിക്കുന്നത്"</item>
+    <item msgid="586019486955594690">"വലത്തേക്ക് ചാഞ്ഞിരിക്കുന്നത്"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"കീബോർഡ് സ്വിച്ചർ"</string>
     <string name="save" msgid="2311877285724540644">"സംരക്ഷിക്കുക"</string>
     <string name="reset" msgid="2448168080964209908">"പുനഃസജ്ജമാക്കുക"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"ബട്ടൺ വീതി ക്രമീകരിക്കുക"</string>
     <string name="clipboard" msgid="1313879395099896312">"ക്ലിപ്പ്ബോർഡ്"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"ഇഷ്ടാനുസൃത നാവിഗേഷൻ ബട്ടൺ"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"ഇടതുവശത്തെ കീകോഡ്"</string>
+    <string name="right_keycode" msgid="708447961000848163">"വലതുവശത്തെ കീകോഡ്"</string>
+    <string name="left_icon" msgid="3096287125959387541">"ഇടതുവശത്തെ ചിഹ്നം"</string>
+    <string name="right_icon" msgid="3952104823293824311">"വലതുവശത്തെ ചിഹ്നം"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"ടൈലുകൾ ചേർക്കുന്നതിന് വലിച്ചിടുക"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"നീക്കംചെയ്യുന്നതിന് ഇവിടെ വലിച്ചിടുക"</string>
     <string name="qs_edit" msgid="2232596095725105230">"എഡിറ്റുചെയ്യുക"</string>
@@ -665,44 +667,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> ക്രമീകരണം തുറക്കുക."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"ക്രമീകരണ ക്രമം എഡിറ്റുചെയ്യുക."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"പേജ് <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"ലോക്ക് സ്‌ക്രീൻ"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"വികസിപ്പിക്കുക"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"ചെറുതാക്കുക‍"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"അടയ്‌ക്കുക"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"ഫോൺ ചൂടായിക്കൊണ്ടിരിക്കുന്നു"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"ഫോൺ തണുത്തുകൊണ്ടിരിക്കുമ്പോൾ ചില ഫീച്ചറുകൾ പരിമിതപ്പെടുത്തപ്പെടും"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"നിങ്ങളുടെ ഫോൺ സ്വയമേവ തണുക്കാൻ ശ്രമിക്കും. നിങ്ങൾക്ക് അപ്പോഴും ഫോൺ ഉപയോഗിക്കാമെങ്കിലും പ്രവർത്തനം മന്ദഗതിയിലായിരിക്കും.\n\nതണുത്തുകഴിഞ്ഞാൽ, ഫോൺ സാധാരണ ഗതിയിൽ പ്രവർത്തിക്കും."</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"ഇടത് കുറുക്കുവഴി"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"വലത് കുറുക്കുവഴി"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"ഇടത് കുറുക്കുവഴിയും അൺലോക്കുചെയ്യുന്നു"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"വലത് കുറുക്കുവഴിയും അൺലോക്കുചെയ്യുന്നു"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"ഒന്നുമില്ല"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"<xliff:g id="APP">%1$s</xliff:g> സമാരംഭിക്കുക"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"മറ്റ് ആപ്‌സ്"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"സർക്കിൾ"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"അധികചിഹ്നം"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"ന്യൂനം"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"ഇടത്"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"വലത്"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"മെനു"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> ആപ്പ്"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"അലേർട്ടുകൾ"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"സ്‌ക്രീൻഷോട്ടുകൾ"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"പൊതുവായ സന്ദേശങ്ങൾ"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"സ്റ്റോറേജ്"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"ഇൻസ്റ്റന്റ് ആപ്പ്"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"ഇൻസ്‌റ്റ‌ന്റ് ആപ്പിന് ഇൻസ്‌റ്റലേഷൻ ആവശ്യമില്ല."</string>
+    <string name="app_info" msgid="6856026610594615344">"ആപ്പ് വിവരം"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 0bf02c8..08d10d1 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -516,9 +516,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Тэжээлийн мэдэгдлийн удирдлагын тусламжтайгаар та апп-н мэдэгдэлд 0-5 хүртэлх ач холбогдлын түвшин тогтоох боломжтой. \n\n"<b>"5-р түвшин"</b>" \n- Мэдэгдлийн жагсаалтын хамгийн дээр харуулна \n- Бүтэн дэлгэцэд саад болно \n- Дэлгэцэд тогтмол гарч ирнэ \n\n"<b>"4-р түвшин"</b>" \n- Бүтэн дэлгэцэд саад болохоос сэргийлнэ \n- Дэлгэцэд тогтмол гарч ирнэ \n\n"<b>"3-р түвшин"</b>" \n- Бүтэн дэлгэцэд саад болохоос сэргийлнэ \n- Дэлгэцэд хэзээ ч гарч ирэхгүй \n\n"<b>"2-р түвшин"</b>" \n- Бүтэн дэлгэцэд саад болохоос сэргийлнэ \n- Дэлгэцэд хэзээ ч гарч ирэхгүй \n- Дуу болон чичиргээ хэзээ ч гаргахгүй \n\n"<b>"1-р түвшин"</b>" \n- Бүтэн дэлгэцэд саад болохоос сэргийлнэ \n- Дэлгэцэд хэзээ ч гарч ирэхгүй \n- Дуу болон чичиргээ хэзээ ч гаргахгүй \n- Түгжигдсэн дэлгэц болон статусын самбараас нууна \n- Мэдэгдлийн жагсаалтын доор харуулна \n\n"<b>"0-р түвшин"</b>" \n- Энэ апп-н бүх мэдэгдлийг блоклоно"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Мэдэгдэл"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"Ta цаашид мэдэгдэл авахгүй."</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="other">энэ аппын <xliff:g id="NUMBER_1">%d</xliff:g>-с 1 ангилал</item>
+      <item quantity="one">энэ аппын <xliff:g id="NUMBER_0">%d</xliff:g>-с 1 ангилал</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"Бүх ангилал"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Бусад тохиргоо"</string>
     <string name="notification_done" msgid="5279426047273930175">"Дууссан"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -592,31 +594,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"Идэвхгүй"</string>
     <string name="nav_bar" msgid="1993221402773877607">"Навигацийн самбар"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"Бүдүүвч"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"Нэмэлт зүүн товчлуураар шивэх"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"Нэмэлт баруун товчлуураар шивэх"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(өгөгдмөл)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"Түр санах ой"</item>
+    <item msgid="5742013440802239414">"Түлхүүр код"</item>
+    <item msgid="8802889973626281575">"Гар солигч"</item>
+    <item msgid="8175437057325747277">"Хоосон"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"Энгийн"</item>
+    <item msgid="8256205964297588988">"Нягтшил сайтай"</item>
+    <item msgid="8719936228094005878">"Зүүн налуу"</item>
+    <item msgid="586019486955594690">"Баруун налуу"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"Гар солигч"</string>
     <string name="save" msgid="2311877285724540644">"Хадгалах"</string>
     <string name="reset" msgid="2448168080964209908">"Бүгдийг цэвэрлэх"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"Товчлуурын өргөнг тохируулах"</string>
     <string name="clipboard" msgid="1313879395099896312">"Түр санах ой"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"Навигацийн товчлуурыг өөрчлөх"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"Зүүн түлхүүрийн код"</string>
+    <string name="right_keycode" msgid="708447961000848163">"Баруун түлхүүрийн код"</string>
+    <string name="left_icon" msgid="3096287125959387541">"Зүүн дүрс тэмдэг"</string>
+    <string name="right_icon" msgid="3952104823293824311">"Баруун дүрс тэмдэг"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"Дөрвөлж нэмэхийн тулд чирнэ үү"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Устгахын тулд энд зөөнө үү"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Засах"</string>
@@ -665,44 +667,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> тохиргоог нээнэ үү."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Тохиргооны дарааллыг өөрчилнө үү."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g>-н <xliff:g id="ID_1">%1$d</xliff:g>-р хуудас"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"Түгжигдсэн дэлгэц"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"Дэлгэх"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Багасгах"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Хаах"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"Утас халж эхэлж байна"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"Таны утас хөрж байх зуур зарим онцлогийг хязгаарласан"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"Таны утас автоматаар хөрөх болно. Та утсаа ашиглаж болох хэдий ч удаан ажиллаж болзошгүй.\n\nТаны утас хөрсний дараагаар хэвийн ажиллана."</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"Зүүн товчлол"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"Баруун товчлол"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"Зүүн товчлол нь мөн түгжээг тайлдаг"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"Баруун товчлол нь мөн түгжээг тайлдаг"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"Хоосон"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"<xliff:g id="APP">%1$s</xliff:g>-г эхлүүлэх"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"Бусад апп"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"Хүрээлэл"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"Нэмэх"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"Хасах"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"Зүүн"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"Баруун"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"Цэс"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> апп"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Сануулга"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Дэлгэцийн зураг дарах"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Энгийн зурвас"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Хадгалах сан"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Шуурхай апп"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Шуурхай аппыг суулгах шаардлагагүй."</string>
+    <string name="app_info" msgid="6856026610594615344">"Апп-н мэдээлэл"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index e48c136..2d6dd89 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -516,9 +516,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"उर्जा सूचना नियंत्रणांसह, आपण अॅपच्या सूचनांसाठी महत्त्व स्तर 0 ते 5 पर्यंत सेट करू शकता. \n\n"<b>"स्तर 5"</b>" \n- सूचना सूचीच्या शीर्षस्थानी दर्शवा \n- पूर्ण स्क्रीन व्यत्ययास अनुमती द्या \n- नेहमी डोकावून पहा \n\n"<b>"स्तर 4"</b>" \n- पूर्ण स्क्रीन व्यत्ययास प्रतिबंधित करा \n- नेहमी डोकावून पहा \n\n"<b>"स्तर 3"</b>" \n- पूर्ण स्क्रीन व्यत्ययास प्रतिबंधित करा \n- कधीही डोकावून पाहू नका \n\n"<b>"स्तर 2"</b>" \n- पूर्ण स्क्रीन व्यत्ययास प्रतिबंधित करा \n- कधीही डोकावून पाहू नका \n- कधीही ध्वनी किंवा कंपन करू नका \n\n"<b>"स्तर 1"</b>" \n- पूर्ण स्क्रीन व्यत्ययास प्रतिबंधित करा \n- कधीही डोकावून पाहू नका \n- कधीही ध्वनी किंवा कंपन करू नका \n- लॉक स्क्रीन आणि स्टेटस बार मधून लपवा \n- सूचना सूचीच्या तळाशी दर्शवा \n\n"<b>"स्तर 0"</b>" \n- अॅपमधील सर्व सूचना अवरोधित करा"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"सूचना"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"आपल्याला यापुढे या सूचना प्राप्त होणार नाहीत."</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="one">या अ‍ॅपवरून <xliff:g id="NUMBER_1">%d</xliff:g> श्रेणीपैकी 1</item>
+      <item quantity="other">या अ‍ॅपवरून <xliff:g id="NUMBER_1">%d</xliff:g> श्रेण्यांपैकी 1</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"सर्व श्रेण्या"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"अधिक सेटिंग्ज"</string>
     <string name="notification_done" msgid="5279426047273930175">"पूर्ण झाले"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -592,31 +594,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"बंद"</string>
     <string name="nav_bar" msgid="1993221402773877607">"नॅव्हिगेशन बार"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"लेआउट"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"अतिरिक्त डाव्या बटणाचा प्रकार"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"अतिरिक्त उजव्या बटणाचा प्रकार"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(डीफॉल्ट)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"क्लिपबोर्ड"</item>
+    <item msgid="5742013440802239414">"कीकोड"</item>
+    <item msgid="8802889973626281575">"कीबोर्ड स्विचर"</item>
+    <item msgid="8175437057325747277">"काहीही नाही"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"सामान्य"</item>
+    <item msgid="8256205964297588988">"संक्षिप्त"</item>
+    <item msgid="8719936228094005878">"डावीकडे कललेले"</item>
+    <item msgid="586019486955594690">"उजवीकडे कललेले"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"कीबोर्ड स्विचर"</string>
     <string name="save" msgid="2311877285724540644">"जतन करा"</string>
     <string name="reset" msgid="2448168080964209908">"रीसेट करा"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"बटण रूंदी समायोजित करा"</string>
     <string name="clipboard" msgid="1313879395099896312">"क्लिपबोर्ड"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"सानुकूल नेव्हिगेशन बटण"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"डावा कीकोड"</string>
+    <string name="right_keycode" msgid="708447961000848163">"उजवा कीकोड"</string>
+    <string name="left_icon" msgid="3096287125959387541">"डावे चिन्ह"</string>
+    <string name="right_icon" msgid="3952104823293824311">"उजवे चिन्ह"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"टाइल जोडण्यासाठी ड्रॅग करा"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"काढण्यासाठी येथे ड्रॅग करा"</string>
     <string name="qs_edit" msgid="2232596095725105230">"संपादित करा"</string>
@@ -665,44 +667,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> सेटिंग्ज उघडा."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"सेटिंग्जचा क्रम संपादित करा."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"पृष्ठ <xliff:g id="ID_2">%2$d</xliff:g> पैकी <xliff:g id="ID_1">%1$d</xliff:g>"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"लॉक स्‍क्रीन"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"विस्तृत करा"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"लहान करा"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"बंद करा"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"फोन ऊष्ण होत आहे"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"फोन थंड होत असताना काही वैशिष्‍ट्ये मर्यादित असतात"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"आपला फोन स्वयंचलितपणे थंड होईल. आपण अद्यापही आपला फोन वापरू शकता परंतु तो कदाचित धीमेपणे कार्य करेल.\n\nआपला फोन एकदा थंड झाला की, तो सामान्यपणे कार्य करेल."</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"डावा शॉर्टकट"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"उजवा शॉर्टकट"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"डावा शॉर्टकट देखील अनलॉक करतो"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"उजवा शॉर्टकट देखील अनलॉक करतो"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"काहीही नाही"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"<xliff:g id="APP">%1$s</xliff:g> लाँच करा"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"इतर अॅप्स"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"मंडळ"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"अधिक चिन्ह"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"उणे चिन्ह"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"डावा"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"उजवा"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"मेनू"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> अ‍ॅप"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"सूचना"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"स्क्रीनशॉट"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"सर्वसाधारण संदेश"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"संचय"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"इन्सटंट अ‍ॅप्स"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"इन्सटंट अॅप्सना स्थापनेची आवश्यकता नसते."</string>
+    <string name="app_info" msgid="6856026610594615344">"अॅप माहिती"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index b07e07e..b043460 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -516,9 +516,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Dengan kawalan pemberitahuan berkuasa, anda boleh menetapkan tahap kepentingan dari 0 hingga 5 untuk pemberitahuan apl. \n\n"<b>"Tahap 5"</b>" \n- Tunjukkan pada bahagian atas senarai pemberitahuan \n- Benarkan gangguan skrin penuh \n- Sentiasa intai \n\n"<b>"Tahap 4"</b>" \n- Halang gangguan skrin penuh \n- Sentiasa intai \n\n"<b>"Tahap 3"</b>" \n- Halang gangguan skrin penuh \n- Jangan intai \n\n"<b>"Tahap 2"</b>" \n- Halang gangguan skrin penuh \n- Jangan intai \n- Jangan berbunyi dan bergetar \n\n"<b>"Tahap 1"</b>" \n- Halang gangguan skrin penuh \n- Jangan intai \n- Jangan berbunyi atau bergetar \n- Sembunyikan daripada skrin kunci dan bar status \n- Tunjukkan di bahagian bawah senarai pemberitahuan \n\n"<b>"Tahap 0"</b>" \n- Sekat semua pemberitahuan daripada apl"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Pemberitahuan"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"Anda tidak akan menerima pemberitahuan ini lagi."</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="other">1 daripada <xliff:g id="NUMBER_1">%d</xliff:g> kategori daripada apl ini</item>
+      <item quantity="one">1 daripada <xliff:g id="NUMBER_0">%d</xliff:g> kategori daripada apl ini</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"Semua Kategori"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Lagi tetapan"</string>
     <string name="notification_done" msgid="5279426047273930175">"Selesai"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -592,31 +594,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"Mati"</string>
     <string name="nav_bar" msgid="1993221402773877607">"Bar navigasi"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"Reka letak"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"Jenis butang kiri tambahan"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"Jenis butang kanan tambahan"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(lalai)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"Papan Keratan"</item>
+    <item msgid="5742013440802239414">"Kod Kunci"</item>
+    <item msgid="8802889973626281575">"Penukar papan kekunci"</item>
+    <item msgid="8175437057325747277">"Tiada"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"Biasa"</item>
+    <item msgid="8256205964297588988">"Sarat"</item>
+    <item msgid="8719936228094005878">"Jajar ke kiri"</item>
+    <item msgid="586019486955594690">"Jajar ke kanan"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"Penukar papan kekunci"</string>
     <string name="save" msgid="2311877285724540644">"Simpan"</string>
     <string name="reset" msgid="2448168080964209908">"Tetapkan semula"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"Laraskan lebar butang"</string>
     <string name="clipboard" msgid="1313879395099896312">"Papan Keratan"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"Butang navigasi tersuai"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"Kod kunci kiri"</string>
+    <string name="right_keycode" msgid="708447961000848163">"Kod kunci kanan"</string>
+    <string name="left_icon" msgid="3096287125959387541">"Ikon kiri"</string>
+    <string name="right_icon" msgid="3952104823293824311">"Ikon kanan"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"Seret untuk menambahkan jubin"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Seret ke sini untuk mengalih keluar"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Edit"</string>
@@ -665,44 +667,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Buka tetapan <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Edit susunan tetapan."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Halaman <xliff:g id="ID_1">%1$d</xliff:g> daripada <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"Kunci skrin"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"Kembangkan"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimumkan"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Tutup"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"Telefon semakin panas"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"Sesetengah ciri adalah terhad semasa telefon menyejuk"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefon anda akan cuba menyejuk secara automatik. Anda masih dapat menggunakan telefon itu tetapi telefon tersebut mungkin berjalan lebih perlahan.\n\nSetelah telefon anda sejuk, telefon itu akan berjalan seperti biasa."</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"Pintasan kiri"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"Pintasan kanan"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"Pintasan kiri juga membuka kunci"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"Pintasan kanan juga membuka kunci"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"Tiada"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"Lancarkan <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"Apl lain"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"Bulatan"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"Tambah"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"Tolak"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"Kiri"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"Kanan"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"Menu"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"Apl <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Makluman"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Tangkapan skrin"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Mesej Am"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Storan"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Apl Segera"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Apl segera tidak memerlukan pemasangan."</string>
+    <string name="app_info" msgid="6856026610594615344">"Maklumat apl"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index d5332a0..3fefa6d 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -517,8 +517,8 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"အကြောင်းကြားချက်များ"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"သင်သည် ဤအကြောင်းကြားချက်များကို လက်ခံရရှိတော့မည် မဟုတ်ပါ။"</string>
     <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
-      <item quantity="other">ဤအက်ပ်ရှိ အုပ်စု <xliff:g id="NUMBER_1">%d</xliff:g> ခုအနက်မှ ၁ ခု</item>
-      <item quantity="one">ဤအက်ပ်ရှိ အုပ်စု <xliff:g id="NUMBER_0">%d</xliff:g> ခုအနက်မှ ၁ ခု</item>
+      <item quantity="other">ဤအက်ပ်က အုပ်စု <xliff:g id="NUMBER_1">%d</xliff:g> ခုအနက်မှ ၁ ခု</item>
+      <item quantity="one">ဤအက်ပ်က အုပ်စု <xliff:g id="NUMBER_0">%d</xliff:g> ခုအနက်မှ ၁ ခု</item>
     </plurals>
     <string name="notification_all_categories" msgid="5407190218055113282">"အုပ်စုအားလုံး"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"နောက်ထပ် ဆက်တင်များ"</string>
@@ -606,8 +606,8 @@
   <string-array name="nav_bar_layouts">
     <item msgid="8077901629964902399">"ပုံမှန်"</item>
     <item msgid="8256205964297588988">"ကျစ်ကျစ်လစ်လစ်"</item>
-    <item msgid="8719936228094005878">"လက်ဝဲယိမ်း"</item>
-    <item msgid="586019486955594690">"လက်ယာယိမ်း"</item>
+    <item msgid="8719936228094005878">"လက်ဝဲဖက် ကပ်လျက်"</item>
+    <item msgid="586019486955594690">"လက်ယာဖက် ကပ်လျက်"</item>
   </string-array>
     <string name="menu_ime" msgid="4998010205321292416">"ကီးဘုတ် ပြောင်းလဲပေးသည့်စနစ်"</string>
     <string name="save" msgid="2311877285724540644">"သိမ်းရန်"</string>
@@ -692,4 +692,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"မျက်နှာပြင်ဓာတ်ပုံများ"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"အထွေထွေ မက်ဆေ့ဂျ်များ"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"သိုလှောင်မှုများ"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"ချက်ခြင်းသုံးအက်ပ်များကို ထည့်သွင်းစရာမလိုပါ။"</string>
+    <string name="app_info" msgid="6856026610594615344">"အက်ပ်အချက်အလက်"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 1ded359..bf081e4 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -516,9 +516,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Med effektive varselinnstillinger kan du angi viktighetsnivåer fra 0 til 5 for appvarsler. \n\n"<b>"Nivå 5"</b>" \n– Vis øverst på varsellisten \n– Tillat forstyrrelser ved fullskjermmodus \n– Vis alltid raskt \n\n"<b>"Nivå 4"</b>" \n– Forhindre forstyrrelser ved fullskjermmodus \n– Vis alltid raskt \n\n"<b>"Nivå 3"</b>" \n– Forhindre forstyrrelser ved fullskjermmodus \n– Vis aldri raskt \n\n"<b>"Nivå 2"</b>" \n– Forhindre forstyrrelser ved fullskjermmodus \n– Vis aldri fort \n– Tillat aldri lyder eller vibrering \n\n"<b>"Nivå 1"</b>" \n– Forhindre forstyrrelser ved fullskjermmodus \n– Vis aldri raskt \n– Tillat aldri lyder eller vibrering \n– Skjul fra låseskjermen og statusfeltet \n– Vis nederst på varsellisten \n\n"<b>"Nivå 0"</b>" \n– Blokkér alle varsler fra appen"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Varsler"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"Du får ikke disse varslene lenger."</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="other">1 av <xliff:g id="NUMBER_1">%d</xliff:g> kategorier fra denne appen</item>
+      <item quantity="one">1 av <xliff:g id="NUMBER_0">%d</xliff:g> kategori fra denne appen</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"Alle kategorier"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Flere innstillinger"</string>
     <string name="notification_done" msgid="5279426047273930175">"Ferdig"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -592,31 +594,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"Av"</string>
     <string name="nav_bar" msgid="1993221402773877607">"Navigasjonsrad"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"Oppsett"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"Ekstra venstre-knapptype"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"Ekstra høyre-knapptype"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(standard)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"Utklippstavle"</item>
+    <item msgid="5742013440802239414">"Nøkkelkode"</item>
+    <item msgid="8802889973626281575">"Bytteknapp for tastatur"</item>
+    <item msgid="8175437057325747277">"Ingen"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"Normal"</item>
+    <item msgid="8256205964297588988">"Kompakt"</item>
+    <item msgid="8719936228094005878">"Lent mot venstre"</item>
+    <item msgid="586019486955594690">"Lent mot høyre"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"Bytteknapp for tastatur"</string>
     <string name="save" msgid="2311877285724540644">"Lagre"</string>
     <string name="reset" msgid="2448168080964209908">"Tilbakestill"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"Juster bredden på knappen"</string>
     <string name="clipboard" msgid="1313879395099896312">"Utklippstavle"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"Spesialtilpasset navigasjonsknapp"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"Venstre-nøkkelkode"</string>
+    <string name="right_keycode" msgid="708447961000848163">"Høyre-nøkkelkode"</string>
+    <string name="left_icon" msgid="3096287125959387541">"Venstre-ikon"</string>
+    <string name="right_icon" msgid="3952104823293824311">"Høyre-ikon"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"Dra for å legge til fliser"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Dra hit for å fjerne"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Endre"</string>
@@ -665,44 +667,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Åpne <xliff:g id="ID_1">%s</xliff:g>-innstillingene."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Endre rekkefølgen på innstillingene."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Side <xliff:g id="ID_1">%1$d</xliff:g> av <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"Låseskjerm"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"Vis"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimer"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Lukk"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"Telefonen begynner å bli varm"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"Enkelte funksjoner er begrenset mens telefonen kjøles ned"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefonen din kommer til å prøve å kjøle seg ned automatisk. Du kan fremdeles bruke telefonen, men den kjører muligens saktere.\n\nTelefonen kommer til å kjøre som normalt, når den har kjølt seg ned."</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"Venstre hurtigtast"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"Høyre hurtigtast"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"Venstre hurtigtast låser også opp"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"Høyre hurtigtast låser også opp"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"Ingen"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"Start <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"Andre apper"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"Sirkel"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"Pluss"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"Minus"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"Venstre"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"Høyre"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"Meny"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g>-appen"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Varsler"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Skjermdumper"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Generelle meldinger"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Lagring"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Du trenger ikke å installere instant-apper."</string>
+    <string name="app_info" msgid="6856026610594615344">"Info om appen"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 126d071..bfcaf16 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -516,9 +516,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"सशक्त सूचना नियन्त्रणहरू मार्फत तपाईं अनुप्रयाेगका सूचनाहरूका लागि ० देखि ५ सम्मको महत्व सम्बन्धी स्तर सेट गर्न सक्नुहुन्छ। \n\n"<b>"स्तर ५"</b>" \n- सूचनाको सूचीको माथिल्लो भागमा देखाउने \n- पूर्ण स्क्रिनमा अवरोधका लागि अनुमति दिने \n- सधैँ चियाउने \n\n"<b>"स्तर ४"</b>" \n- पूर्ण स्क्रिनमा अवरोधलाई रोक्ने \n- सधैँ चियाउने \n\n"<b>"स्तर ३"</b>" \n- पूर्ण स्क्रिनमा अवरोधलाई रोक्ने \n- कहिल्यै नचियाउने \n\n"<b>"स्तर २"</b>" \n- पूर्ण स्क्रिनमा अवरोधलाई रोक्ने \n- कहिल्यै नचियाउने \n- कहिल्यै पनि आवाज ननिकाल्ने र कम्पन नगर्ने \n\n"<b>"स्तर १"</b>" \n- पूर्ण स्क्रिनमा अवरोध रोक्ने \n- कहिल्यै नचियाउने \n- कहिल्यै पनि आवाज ननिकाल्ने वा कम्पन नगर्ने \n- लक स्क्रिन र वस्तुस्थिति पट्टीबाट लुकाउने \n- सूचनाको सूचीको तल्लो भागमा देखाउने \n\n"<b>"स्तर ०"</b>" \n- अनुप्रयोगका सबै सूचनाहरूलाई रोक्ने"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"सूचनाहरू"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"तपाईंले अबदेखि यी सूचनाहरू प्राप्त गर्नुहुने छैन।"</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="other">यस अनुप्रयोगका <xliff:g id="NUMBER_1">%d</xliff:g> कोटिहरू मध्ये १</item>
+      <item quantity="one">यस अनुप्रयोगको <xliff:g id="NUMBER_0">%d</xliff:g> कोटि मध्ये १</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"सबै कोटिहरू"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"थप सेटिङहरू"</string>
     <string name="notification_done" msgid="5279426047273930175">"सम्पन्‍न भयो"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -592,31 +594,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"निष्क्रिय"</string>
     <string name="nav_bar" msgid="1993221402773877607">"नेभिगेशन पट्टी"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"लेआउट"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"अतिरिक्त बायाँतिरको बटनको प्रकार"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"अतिरिक्त दायाँतिरको बटनको प्रकार"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(पूर्वनिर्धारित)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"क्लिपबोर्ड"</item>
+    <item msgid="5742013440802239414">"किकोड"</item>
+    <item msgid="8802889973626281575">"किबोर्ड स्विचर"</item>
+    <item msgid="8175437057325747277">"कुनै पनि होइन"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"साधारण"</item>
+    <item msgid="8256205964297588988">"खँदिलो"</item>
+    <item msgid="8719936228094005878">"बायाँतिर लैजानुहोस्"</item>
+    <item msgid="586019486955594690">"दायाँतिर लैजानुहोस्"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"किबोर्ड स्विचर"</string>
     <string name="save" msgid="2311877285724540644">"सुरक्षित गर्नुहोस्"</string>
     <string name="reset" msgid="2448168080964209908">"पुनःसेट गर्नु"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"बटनको चौडाइ समायोजन गर्नुहोस्"</string>
     <string name="clipboard" msgid="1313879395099896312">"क्लिपबोर्ड"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"अनुकूलनको नेभिगेशन बटन"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"बायाँतिरको किकोड"</string>
+    <string name="right_keycode" msgid="708447961000848163">"दायाँतिरको किकोड"</string>
+    <string name="left_icon" msgid="3096287125959387541">"बायाँतिर देखाउने आइकन"</string>
+    <string name="right_icon" msgid="3952104823293824311">"दायाँतिरको आइकन"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"टाइलहरू थप्न तान्नुहोस्"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"हटाउनका लागि यहाँ तान्नुहोस्"</string>
     <string name="qs_edit" msgid="2232596095725105230">"सम्पादन गर्नुहोस्"</string>
@@ -665,44 +667,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> सम्बन्धी सेटिङहरूलाई खोल्नुहोस्।"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"सेटिङहरूको क्रमलाई सम्पादन गर्नुहोस्।"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> मध्ये पृष्ठ <xliff:g id="ID_1">%1$d</xliff:g>"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"लक स्क्रिन"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"विस्तृत गर्नुहोस्"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"सानो बनाउनुहोस्"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"बन्द गर्नुहोस्"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"फोन तातो भइरहेको छ"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"फोन चिसो हुँदै गर्दा केही विशेषताहरूलाई सीमित गरिन्छ"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"तपाईंको फोन स्वतः चिसो हुने प्रयास गर्नेछ। तपाईं अझै पनि आफ्नो फोनको प्रयोग गर्न सक्नुहुन्छ तर त्यो अझ ढिलो चल्न सक्छ।\n\nचिसो भएपछि तपाईंको फोन सामान्य गतिमा चल्नेछ।"</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"बायाँतिरको सर्टकट"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"दायाँतिरको सर्टकट"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"बायाँतिरको सर्टकटले पनि अनलक गर्छ"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"दायाँतिरको सर्टकटले पनि अनलक गर्छ"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"कुनै पनि होइन"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"<xliff:g id="APP">%1$s</xliff:g> सुरु गर्नुहोस्"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"अन्य अनुप्रयोगहरू"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"सर्कल"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"प्लस चिन्ह"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"माइनस चिन्ह"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"बायाँ"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"दायाँ"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"मेनु"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> अनुप्रयोग"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"अलर्टहरू"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"स्क्रिनशटहरू"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"सामान्य सन्देशहरू"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"भण्डारण"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"तात्कालिक अनुप्रयोगहरू"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"तात्कालिक अनुप्रयोगहरूलाई स्थापना गर्नु पर्दैन|"</string>
+    <string name="app_info" msgid="6856026610594615344">"अनुप्रयोगका बारे जानकारी"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index e178147..4ec7528 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -692,4 +692,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshots"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Algemene berichten"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Opslag"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Instant-apps"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Instant-apps hoeven niet te worden geïnstalleerd."</string>
+    <string name="app_info" msgid="6856026610594615344">"App-info"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 5bb3813..9b28995 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -516,9 +516,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"ਪਾਵਰ ਸੂਚਨਾ ਕੰਟਰੋਲਾਂ ਨਾਲ, ਤੁਸੀਂ ਕਿਸੇ ਐਪ ਦੀਆਂ ਸੂਚਨਾਵਾਂ ਲਈ ਮਹੱਤਤਾ ਪੱਧਰ ਨੂੰ 0 ਤੋਂ 5 ਤੱਕ ਸੈੱਟ ਕਰ ਸਕਦੇ ਹੋ। \n\n"<b>"ਪੱਧਰ 5"</b>" \n- ਸੂਚਨਾ ਸੂਚੀ ਦੇ ਸਿਖਰ \'ਤੇ ਵਿਖਾਓ \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਦੀ ਆਗਿਆ ਦਿਓ \n- ਹਮੇਸ਼ਾਂ ਝਲਕ ਵਿਖਾਓ \n\n"<b>"ਪੱਧਰ 4"</b>" \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਨੂੰ ਰੋਕੋ \n- ਹਮੇਸ਼ਾਂ ਝਲਕ ਵਿਖਾਓ \n\n"<b>"ਪੱਧਰ 3"</b>" \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਨੂੰ ਰੋਕੋ \n- ਕਦੇ ਝਲਕ ਨਾ ਵਿਖਾਓ \n\n"<b>"ਪੱਧਰ 2"</b>" \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਰੋਕੋ \n- ਕਦੇ ਝਲਕ ਨਾ ਵਿਖਾਓ \n- ਕਦੇ ਵੀ ਧੁਨੀ ਜਾਂ ਥਰਥਰਾਹਟ ਨਾ ਕਰੋ \n\n"<b>"ਪੱੱਧਰ 1"</b>" \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਨੂੰ ਰੋਕੋ \n- ਕਦੇ ਝਲਕ ਨਾ ਵਿਖਾਓ \n- ਕਦੇ ਧੁਨੀ ਜਾਂ ਥਰਥਰਾਹਟ ਨਾ ਕਰੋ \n- ਲੌਕ ਸਕ੍ਰੀਨ ਅਤੇ ਸਥਿਤੀ ਪੱਟੀ ਤੋਂ ਲੁਕਾਓ \n- ਸੂਚਨਾ ਸੂਚੀ ਦੇ ਹੇਠਾਂ ਵਿਖਾਓ \n\n"<b>"ਪੱਧਰ 0"</b>" \n- ਐਪ ਤੋਂ ਸਾਰੀਆਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਬਲੌਕ ਕਰੋ"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"ਸੂਚਨਾਵਾਂ"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"ਤੁਸੀਂ ਹੁਣ ਇਹ ਸੂਚਨਾਵਾਂ ਪ੍ਰਾਪਤ ਨਹੀਂ ਕਰੋਂਗੇ।"</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="one">ਇਸ ਐਪ ਤੋਂ <xliff:g id="NUMBER_1">%d</xliff:g> ਸ਼੍ਰੇਣੀ ਵਿੱਚੋਂ 1</item>
+      <item quantity="other">ਇਸ ਐਪ ਤੋਂ <xliff:g id="NUMBER_1">%d</xliff:g> ਸ਼੍ਰੇਣੀਆਂ ਵਿੱਚੋਂ 1</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"ਸਭ ਸ਼੍ਰੇਣੀਆਂ"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"ਹੋਰ ਸੈਟਿੰਗਾਂ"</string>
     <string name="notification_done" msgid="5279426047273930175">"ਹੋ ਗਿਆ"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -592,31 +594,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"ਬੰਦ"</string>
     <string name="nav_bar" msgid="1993221402773877607">"ਆਵਾਗੌਣ ਪੱਟੀ"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"ਖਾਕਾ"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"ਵਧੇਰੇ ਖੱਬੇ ਬਟਨ ਕਿਸਮ"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"ਵਧੇਰੇ ਸੱਜੇ ਬਟਨ ਕਿਸਮ"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(ਪੂਰਵ-ਨਿਰਧਾਰਤ)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"ਕਲਿੱਪਬੋਰਡ"</item>
+    <item msgid="5742013440802239414">"ਕੀ-ਕੋਡ"</item>
+    <item msgid="8802889973626281575">"ਕੀ-ਬੋਰਡ ਸਵਿੱਚਰ"</item>
+    <item msgid="8175437057325747277">"ਕੋਈ ਨਹੀਂ"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"ਸਧਾਰਨ"</item>
+    <item msgid="8256205964297588988">"ਸੰਖੇਪ"</item>
+    <item msgid="8719936228094005878">"ਖੱਬੇ-ਉਲਾਰ"</item>
+    <item msgid="586019486955594690">"ਸੱਜੇ-ਉਲਾਰ"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"ਕੀ-ਬੋਰਡ ਸਵਿੱਚਰ"</string>
     <string name="save" msgid="2311877285724540644">"ਰੱਖਿਅਤ ਕਰੋ"</string>
     <string name="reset" msgid="2448168080964209908">"ਰੀਸੈੱਟ ਕਰੋ"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"ਬਟਨ ਚੁੜਾਈ ਵਿਵਸਥਿਤ ਕਰੋ"</string>
     <string name="clipboard" msgid="1313879395099896312">"ਕਲਿੱਪਬੋਰਡ"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ ਆਵਾਗੌਣ ਬਟਨ"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"ਖੱਬਾ ਕੀ-ਕੋਡ"</string>
+    <string name="right_keycode" msgid="708447961000848163">"ਸੱਜਾ ਕੀ-ਕੋਡ"</string>
+    <string name="left_icon" msgid="3096287125959387541">"ਖੱਬਾ ਪ੍ਰਤੀਕ"</string>
+    <string name="right_icon" msgid="3952104823293824311">"ਸੱਜਾ ਪ੍ਰਤੀਕ"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"ਟਾਇਲਾਂ ਨੂੰ ਸ਼ਾਮਲ ਕਰਨ ਲਈ ਘਸੀਟੋ"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"ਹਟਾਉਣ ਲਈ ਇੱਥੇ ਘਸੀਟੋ"</string>
     <string name="qs_edit" msgid="2232596095725105230">"ਸੰਪਾਦਨ ਕਰੋ"</string>
@@ -665,44 +667,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> ਸੈਟਿੰਗਾਂ ਖੋਲ੍ਹੋ।"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"ਸੈਟਿੰਗਾਂ ਦੇ ਕ੍ਰਮ ਦਾ ਸੰਪਾਦਨ ਕਰੋ।"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> ਦਾ <xliff:g id="ID_1">%1$d</xliff:g> ਪੰਨਾ"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"ਲੌਕ ਸਕ੍ਰੀਨ"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"ਵਿਸਤਾਰ ਕਰੋ"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"ਛੋਟਾ ਕਰੋ"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"ਬੰਦ ਕਰੋ"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"ਫ਼ੋਨ ਗਰਮ ਹੋ ਰਿਹਾ ਹੈ"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"ਫ਼ੋਨ ਦੇ ਠੰਡਾ ਹੋਣ ਦੇ ਦੌਰਾਨ ਕੁਝ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਸੀਮਿਤ ਹੁੰਦੀਆਂ ਹਨ"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"ਤੁਹਾਡਾ ਫ਼ੋਨ ਸਵੈਚਲਿਤ ਰੂਪ ਵਿੱਚ ਠੰਡਾ ਹੋਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੇਗਾ। ਤੁਸੀਂ ਹਾਲੇ ਵੀ ਆਪਣੇ ਫ਼ੋਨ ਨੂੰ ਵਰਤ ਸਕਦੇ ਹੋ, ਪਰੰਤੂ ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਇਹ ਵਧੇਰੇ ਹੌਲੀ ਚੱਲੇ।\n\nਇੱਕ ਵਾਰ ਠੰਡਾ ਹੋਣ ਤੋਂ ਬਾਅਦ ਤੁਹਾਡਾ ਫ਼ੋਨ ਸਧਾਰਨ ਤੌਰ \'ਤੇ ਚੱਲੇਗਾ।"</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"ਖੱਬਾ ਸ਼ਾਰਟਕੱਟ"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"ਸੱਜਾ ਸ਼ਾਰਟਕੱਟ"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"ਖੱਬੇ ਸ਼ਾਰਟਕੱਟ ਨਾਲ ਵੀ ਅਨਲੌਕ ਹੁੰਦੀ ਹੈ"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"ਸੱਜੇ ਸ਼ਾਰਟਕੱਟ ਨਾਲ ਵੀ ਅਨਲੌਕ ਹੁੰਦੀ ਹੈ"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"ਕੋਈ ਨਹੀਂ"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"<xliff:g id="APP">%1$s</xliff:g> ਲਾਂਚ ਕਰੋ"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"ਹੋਰ ਐਪਾਂ"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"ਚੱਕਰ"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"ਜੋੜ-ਚਿੰਨ੍ਹ"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"ਘਟਾਓ-ਚਿੰਨ੍ਹ"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"ਖੱਬਾ"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"ਸੱਜਾ"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"ਮੀਨੂ"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> ਐਪ"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"ਸੁਚੇਤਨਾਵਾਂ"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"ਸਕ੍ਰੀਨਸ਼ਾਟ"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"ਆਮ ਸੁਨੇਹੇ"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"ਸਟੋਰੇਜ"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"ਤਤਕਾਲ ਐਪਾਂ"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"ਤਤਕਾਲ ਐਪਾਂ ਨੂੰ ਸਥਾਪਨਾ ਦੀ ਲੋੜ ਨਹੀਂ ਹੈ।"</string>
+    <string name="app_info" msgid="6856026610594615344">"ਐਪ ਜਾਣਕਾਰੀ"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index cbab708..b6e8252 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -698,4 +698,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Zrzuty ekranu"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Wiadomości"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Miejsce"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Aplikacje błyskawiczne"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Aplikacji błyskawicznych nie trzeba instalować."</string>
+    <string name="app_info" msgid="6856026610594615344">"O aplikacji"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 4a0ad2d..5279bea 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -694,4 +694,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturas de tela"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Mensagens gerais"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Armazenamento"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Os Instant Apps não requerem instalação."</string>
+    <string name="app_info" msgid="6856026610594615344">"Informações do app"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 17a97b7..83801d3 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -692,4 +692,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturas de ecrã"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Mensagens gerais"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Armazenamento"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Aplicações instantâneas"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"As Aplicações instantâneas não requerem instalação."</string>
+    <string name="app_info" msgid="6856026610594615344">"Informações da aplicação"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 4a0ad2d..5279bea 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -694,4 +694,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturas de tela"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Mensagens gerais"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Armazenamento"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Os Instant Apps não requerem instalação."</string>
+    <string name="app_info" msgid="6856026610594615344">"Informações do app"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 0073c65..1812a75 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -697,4 +697,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturi de ecran"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Mesaje generale"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Stocare"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Aplicații instantanee"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Aplicațiile instantanee nu necesită instalare."</string>
+    <string name="app_info" msgid="6856026610594615344">"Informații despre aplicație"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index a00bcb0..e2302d8 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -522,9 +522,13 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"С помощью этой функции вы можете устанавливать уровень важности уведомлений от 0 до 5 для каждого приложения.\n\n"<b>"Уровень 5"</b>\n"‒ Помещать уведомления в начало списка.\n‒ Показывать полноэкранные уведомления.\n‒ Показывать всплывающие уведомления.\nУровень 4\n"<b></b>\n"‒ Не показывать полноэкранные уведомления.\n‒ Показывать всплывающие уведомления.\nУровень 3\n"<b></b>\n"‒ Не показывать полноэкранные уведомления.\n‒ Не показывать всплывающие уведомления.\nУровень 2\n"<b></b>\n"‒ Не показывать полноэкранные уведомления.\n‒ Не показывать всплывающие уведомления.\n‒ Не использовать звук и вибрацию.\nУровень 1\n"<b></b>\n"‒ Не показывать полноэкранные уведомления.\n‒ Не показывать всплывающие уведомления.\n‒ Не использовать звук и вибрацию.\n‒ Не показывать на экране блокировки и в строке состояния.\n‒ Помещать уведомления в конец списка.\nУровень 0\n"<b></b>\n"‒ Блокировать все уведомления приложения."</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Уведомления"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"Вы больше не будете получать эти уведомления."</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="one">1 из <xliff:g id="NUMBER_1">%d</xliff:g> категории в этом приложении</item>
+      <item quantity="few">1 из <xliff:g id="NUMBER_1">%d</xliff:g> категорий в этом приложении</item>
+      <item quantity="many">1 из <xliff:g id="NUMBER_1">%d</xliff:g> категорий в этом приложении</item>
+      <item quantity="other">1 из <xliff:g id="NUMBER_1">%d</xliff:g> категорий в этом приложении</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"Все категории"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Другие настройки"</string>
     <string name="notification_done" msgid="5279426047273930175">"Готово"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g>: <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -598,31 +602,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"Отключено"</string>
     <string name="nav_bar" msgid="1993221402773877607">"Панель навигации"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"Раскладка"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"Дополнительный тип кнопки \"Влево\""</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"Дополнительный тип кнопки \"Вправо\""</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(по умолчанию)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"Буфер обмена"</item>
+    <item msgid="5742013440802239414">"Код клавиши"</item>
+    <item msgid="8802889973626281575">"Переключение раскладки"</item>
+    <item msgid="8175437057325747277">"Нет"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"Обычная"</item>
+    <item msgid="8256205964297588988">"Компактная"</item>
+    <item msgid="8719936228094005878">"С уклоном влево"</item>
+    <item msgid="586019486955594690">"С уклоном вправо"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"Переключение раскладки"</string>
     <string name="save" msgid="2311877285724540644">"Сохранить"</string>
     <string name="reset" msgid="2448168080964209908">"Сбросить"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"Выбор ширины кнопки"</string>
     <string name="clipboard" msgid="1313879395099896312">"Буфер обмена"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"Персонализированная кнопка навигации"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"Код клавиши \"Влево\""</string>
+    <string name="right_keycode" msgid="708447961000848163">"Код клавиши \"Вправо\""</string>
+    <string name="left_icon" msgid="3096287125959387541">"Значок \"Влево\""</string>
+    <string name="right_icon" msgid="3952104823293824311">"Значок \"Вправо\""</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"Перетащите нужные элементы"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Чтобы удалить, перетащите сюда"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Изменить"</string>
@@ -671,44 +675,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Открыть настройки <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Изменить порядок быстрых настроек."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Страница <xliff:g id="ID_1">%1$d</xliff:g> из <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"Заблокированный экран"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"Развернуть"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Свернуть"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Закрыть"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"Телефон нагревается"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"Пока телефон не остынет, некоторые функции могут быть недоступны."</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"Ваш телефон остынет автоматически.\n\nОбратите внимание, что до тех пор он может работать медленнее, чем обычно."</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"Ярлык \"Влево\""</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"Ярлык \"Вправо\""</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"Ярлык \"Влево\" также разблокирует экран"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"Ярлык \"Вправо\" также разблокирует экран"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"Нет"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"Запустить приложение \"<xliff:g id="APP">%1$s</xliff:g>\""</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"Другие приложения"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"Круг"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"Плюс"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"Минус"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"Влево"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"Вправо"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"Меню"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"Приложение \"<xliff:g id="APP">%1$s</xliff:g>\""</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Уведомления"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Скриншоты"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Сообщения"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Хранилище"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Приложения с мгновенным запуском"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Приложения с мгновенным запуском не требуется устанавливать."</string>
+    <string name="app_info" msgid="6856026610594615344">"О приложении"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 15a06bf..4962d4f 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -516,9 +516,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"බල දැනුම්දීම් පාලන සමගින්, ඔබට යෙදුමක දැනුම්දීම් සඳහා වැදගත්කම 0 සිට 5 දක්වා සැකසිය හැකිය. \n\n"<b>"5 මට්ටම"</b>" \n- දැනුම්දීම් ලැයිස්තුවේ ඉහළින්ම පෙන්වන්න \n- පූර්ණ තිර බාධාවට ඉඩ දෙන්න \n- සැම විට එබී බලන්න \n\n"<b>"4 මට්ටම"</b>" \n- පූර්ණ තිර බාධාව වළක්වන්න \n- සැම විට එබී බලන්න \n\n"<b>"3 මට්ටම"</b>" \n- පූර්ණ තිර බාධාව වළක්වන්න \n- කිසි විටක එබී නොබලන්න \n\n"<b>"2 මට්ටම"</b>" \n- පූර්ණ තිර බාධාව වළක්වන්න \n- කිසි විටක එබී නොබලන්න \n- කිසි විටක හඬ සහ කම්පනය සිදු නොකරන්න \n\n"<b>"1 මට්ටම"</b>" \n- පූර්ණ තිර බාධාව වළක්වන්න \n- කිසි විටක එබී නොබලන්න \n- කිසි විටක හඬ සහ කම්පනය සිදු නොකරන්න \n- අගුලු තිරය සහ තත්ත්ව තීරුව වෙතින් සඟවන්න \n- දැනුම්දීම් ලැයිස්තුවේ පහළින්ම පෙන්වන්න \n\n"<b>"0 මට්ටම"</b>" \n- යෙදුම වෙතින් වන සියලු දැනුම් දීම් සඟවන්න."</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"දැනුම් දීම්"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"ඔබ තවදුරටත් මෙම දැනුම්දීම් නොලැබෙනු ඇත."</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="one">මෙම යෙදුමෙන් ප්‍රවර්ග <xliff:g id="NUMBER_1">%d</xliff:g>කින් 1</item>
+      <item quantity="other">මෙම යෙදුමෙන් ප්‍රවර්ග <xliff:g id="NUMBER_1">%d</xliff:g>කින් 1</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"සියලු ප්‍රවර්ග"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"තව සැකසීම්"</string>
     <string name="notification_done" msgid="5279426047273930175">"නිමයි"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -592,31 +594,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"ක්‍රියාවිරහිතයි"</string>
     <string name="nav_bar" msgid="1993221402773877607">"සංචලන තීරුව"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"පිරිසැලසුම"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"අමතර වම් බොත්තම් වර්ගය"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"අමතර දකුණු බොත්තම් වර්ගය"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(පෙරනිමි)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"පසුරු පුවරුව"</item>
+    <item msgid="5742013440802239414">"යතුරු කේතය"</item>
+    <item msgid="8802889973626281575">"යතුරු පුවරු මාරුව"</item>
+    <item msgid="8175437057325747277">"කිසිවක් නැත"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"සාමාන්‍ය"</item>
+    <item msgid="8256205964297588988">"සංයුක්ත"</item>
+    <item msgid="8719936228094005878">"වමට-හැරුණු"</item>
+    <item msgid="586019486955594690">"දකුණට-හැරුණු"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"යතුරු පුවරු මාරුව"</string>
     <string name="save" msgid="2311877285724540644">"සුරකින්න"</string>
     <string name="reset" msgid="2448168080964209908">"යළි පිහිටුවන්න"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"බොත්තම් පළල සීරුමාරු කරන්න"</string>
     <string name="clipboard" msgid="1313879395099896312">"පසුරු පුවරුව"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"අභිරුචි සංචලන බොත්තම"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"දකුණු යතුරු කේතය"</string>
+    <string name="right_keycode" msgid="708447961000848163">"දකුණු යතුරු කේතය"</string>
+    <string name="left_icon" msgid="3096287125959387541">"වම් නිරූපකය"</string>
+    <string name="right_icon" msgid="3952104823293824311">"දකුණු නිරූපකය"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"ටයිල් එක් කිරීමට අදින්න"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"ඉවත් කිරීමට මෙතැනට අදින්න"</string>
     <string name="qs_edit" msgid="2232596095725105230">"සංස්කරණය"</string>
@@ -665,44 +667,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> සැකසීම් විවෘත කරන්න."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"සැකසීම්වල අනුපිළිවෙළ සංංස්කරණය කරන්න."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> න් <xliff:g id="ID_1">%1$d</xliff:g>"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"අගුලු තිරය"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"දිග හරින්න"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"කුඩා කරන්න"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"වසන්න"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"දුරකථනය උණුසුම් වෙමින්"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"දුරකථනය සිසිල් වන අතරතුර සමහර විශේෂාංග සීමිත විය හැකිය"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"ඔබගේ දුරකථනය ස්වයංක්‍රියව සිසිල් වීමට උත්සාහ කරනු ඇත. ඔබට තවම ඔබේ දුරකථනය භාවිත කළ හැකිය, නමුත් එය සෙමින් ධාවනය විය හැකිය.\n\nඔබේ දුරකථනය සිසිල් වූ පසු, එය සාමාන්‍ය ලෙස ධාවනය වනු ඇත."</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"වම් කෙටි මග"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"දකුණු කෙටි මග"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"වම් කෙටි මගද අගුලු හැරේ"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"දකුණු කෙටි මගද අගුලු හැරේ"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"කිසිවක් නැත"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"<xliff:g id="APP">%1$s</xliff:g> දියත් කරන්න"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"වෙනත් යෙදුම්"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"කවය"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"ධන"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"ඍණ"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"වම්"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"දකුණු"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"මෙනුව"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> යෙදුම"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"ඇඟවීම්"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"තිර රු"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"පොදු පණිවිඩ"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"ගබඩාව"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"ක්ෂණික යෙදුම්"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"ක්ෂණික යෙදුම් ස්ථාපනය කිරීම අවශ්‍ය නොවේ."</string>
+    <string name="app_info" msgid="6856026610594615344">"යෙදුම් තොරතුරු"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 2e24b90..716b22b 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -522,9 +522,13 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Pomocou ovládacích prvkov zobrazovania upozornení môžete nastaviť pre upozornenia aplikácie úroveň dôležitosti od 0 do 5. \n\n"<b>"Úroveň 5"</b>" \n– Zobrazovať v hornej časti zoznamu upozornení. \n– Povoliť prerušenia na celú obrazovku. \n– Vždy zobrazovať čiastočne. \n\n"<b>"Úroveň 4"</b>" \n– Zabrániť prerušeniam na celú obrazovku. \n– Vždy zobrazovať čiastočne. \n\n"<b>"Úroveň 3"</b>" \n– Zabrániť prerušeniam na celú obrazovku. \n– Nikdy nezobrazovať čiastočne. \n\n"<b>"Úroveň 2"</b>" \n– Zabrániť prerušeniam na celú obrazovku. \n– Nikdy nezobrazovať čiastočne. \n– Nikdy nespúšťať zvuk ani vibrácie. \n\n"<b>"Úroveň 1"</b>" \n– Zabrániť prerušeniam na celú obrazovku. \n– Nikdy nezobrazovať čiastočne. \n– Nikdy nespúšťať zvuk ani vibrácie. \n– Skryť na uzamknutej obrazovke a v stavovom riadku. \n– Zobraziť v dolnej časti zoznamu upozornení. \n\n"<b>"Úroveň 0"</b>" \n– Blokovať všetky upozornenia z aplikácie."</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Upozornenia"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"Takéto upozornenia už nebudete dostávať."</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="few">1 z <xliff:g id="NUMBER_1">%d</xliff:g> kategórií z tejto aplikácie</item>
+      <item quantity="many">1 z <xliff:g id="NUMBER_1">%d</xliff:g> kategórie z tejto aplikácie</item>
+      <item quantity="other">1 z <xliff:g id="NUMBER_1">%d</xliff:g> kategórií z tejto aplikácie</item>
+      <item quantity="one">1 z <xliff:g id="NUMBER_0">%d</xliff:g> kategórie z tejto aplikácie</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"Všetky kategórie"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Ďalšie nastavenia"</string>
     <string name="notification_done" msgid="5279426047273930175">"Hotovo"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -598,31 +602,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"Vypnuté"</string>
     <string name="nav_bar" msgid="1993221402773877607">"Navigačný panel"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"Rozloženie"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"Dodatočný typ ľavého tlačidla"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"Dodatočný typ pravého tlačidla"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(predvolené)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"Schránka"</item>
+    <item msgid="5742013440802239414">"Kód klávesnice"</item>
+    <item msgid="8802889973626281575">"Prepínač klávesnice"</item>
+    <item msgid="8175437057325747277">"Žiadne"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"Štandardná"</item>
+    <item msgid="8256205964297588988">"Kompaktná"</item>
+    <item msgid="8719936228094005878">"Naklonená doľava"</item>
+    <item msgid="586019486955594690">"Naklonená doprava"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"Prepínač klávesnice"</string>
     <string name="save" msgid="2311877285724540644">"Uložiť"</string>
     <string name="reset" msgid="2448168080964209908">"Obnoviť"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"Upraviť šírku tlačidla"</string>
     <string name="clipboard" msgid="1313879395099896312">"Schránka"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"Vlastné tlačidlo navigácie"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"Ľavý kód klávesnice"</string>
+    <string name="right_keycode" msgid="708447961000848163">"Pravý kód klávesnice"</string>
+    <string name="left_icon" msgid="3096287125959387541">"Ľavá ikona"</string>
+    <string name="right_icon" msgid="3952104823293824311">"Pravá ikona"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"Dlaždice pridáte presunutím"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Presunutím sem odstránite"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Upraviť"</string>
@@ -671,44 +675,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Otvoriť nastavenia <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Upraviť poradie nastavení"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Strana <xliff:g id="ID_1">%1$d</xliff:g> z <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"Uzamknutá obrazovka"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"Rozbaliť"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimalizovať"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Zavrieť"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"Teplota telefónu stúpa"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"Niektoré funkcie budú obmedzené, dokým neklesne teplota telefónu"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"Váš telefón sa automaticky pokúsi schladiť. Môžete ho naďalej používať, ale môže fungovať pomalšie.\n\nPo poklese teploty bude telefón fungovať ako normálne."</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"Ľavá skratka"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"Pravá skratka"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"Ľavá skratka tiež odomkne"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"Pravá skratka tiež odomkne"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"Žiadne"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"Spustiť aplikáciu <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"Ďalšie aplikácie"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"Kruh"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"Plus"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"Mínus"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"Doľava"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"Doprava"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"Ponuka"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"Aplikácia <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Upozornenia"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Snímky obrazovky"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Všeobecné správy"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Úložisko"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Okamžité aplikácie"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Okamžité aplikácie nevyžadujú inštaláciu."</string>
+    <string name="app_info" msgid="6856026610594615344">"Info o aplikácii"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 2bf8391..12592a8 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -522,9 +522,13 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"S kontrolniki za pomebnost obvestila je mogoče za obvestila aplikacije nastaviti stopnjo pomembnosti od 0 do 5. \n\n"<b>"Stopnja 5"</b>" \n– Prikaz na vrhu seznama obvestil \n– Omogočanje prekinitev v celozaslonskem načinu \n– Vedno prikaži hitre predoglede \n\n"<b>"Stopnja 4"</b>" \n– Preprečevanje prekinitev v celozaslonskem načinu \n– Vedno prikaži hitre predoglede \n\n"<b>"Stopnja 3"</b>" \n– Preprečevanje prekinitev v celozaslonskem načinu \n– Nikoli ne prikaži hitrih predogledov \n\n"<b>"Stopnja 2"</b>" \n– Preprečevanje prekinitev v celozaslonskem načinu \n– Nikoli ne prikaži hitrih predogledov \n– Nikoli ne uporabi zvoka in vibriranja \n\n"<b>"Stopnja 1"</b>" \n– Preprečevanje prekinitev v celozaslonskem načinu \n– Nikoli ne prikaži hitrih predogledov \n– Nikoli ne uporabi zvoka in vibriranja \n– Skrivanje na zaklenjenem zaslonu in v vrstici stanja \n– Prikaz na dnu seznama obvestil \n\n"<b>"Stopnja 0"</b>" \n– Blokiranje vseh obvestil aplikacije"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Obvestila"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"Teh obvestil ne boste več prejemali."</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="one">1 od <xliff:g id="NUMBER_1">%d</xliff:g> kategorije iz te aplikacije</item>
+      <item quantity="two">1 od <xliff:g id="NUMBER_1">%d</xliff:g> kategorij iz te aplikacije</item>
+      <item quantity="few">1 od <xliff:g id="NUMBER_1">%d</xliff:g> kategorij iz te aplikacije</item>
+      <item quantity="other">1 od <xliff:g id="NUMBER_1">%d</xliff:g> kategorij iz te aplikacije</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"Vse kategorije"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Več nastavitev"</string>
     <string name="notification_done" msgid="5279426047273930175">"Dokončano"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -598,31 +602,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"Izklop"</string>
     <string name="nav_bar" msgid="1993221402773877607">"Vrstica za krmarjenje"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"Postavitev"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"Vrsta dodatnega levega gumba"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"Vrsta dodatnega desnega gumba"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(privzeto)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"Odložišče"</item>
+    <item msgid="5742013440802239414">"Koda tipke"</item>
+    <item msgid="8802889973626281575">"Preklopnik tipkovnice"</item>
+    <item msgid="8175437057325747277">"Brez"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"Običajna"</item>
+    <item msgid="8256205964297588988">"Strnjena"</item>
+    <item msgid="8719936228094005878">"Nagnjena na levo"</item>
+    <item msgid="586019486955594690">"Nagnjena na desno"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"Preklopnik tipkovnice"</string>
     <string name="save" msgid="2311877285724540644">"Shrani"</string>
     <string name="reset" msgid="2448168080964209908">"Ponastavi"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"Prilagajanje širine gumba"</string>
     <string name="clipboard" msgid="1313879395099896312">"Odložišče"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"Gumb za krmarjenje po meri"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"Leva koda tipke"</string>
+    <string name="right_keycode" msgid="708447961000848163">"Desna koda tipke"</string>
+    <string name="left_icon" msgid="3096287125959387541">"Leva ikona"</string>
+    <string name="right_icon" msgid="3952104823293824311">"Desna ikona"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"Povlecite, če želite dodati ploščice"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Če želite odstraniti, povlecite sem"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Uredi"</string>
@@ -671,44 +675,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Odpri nastavitve za <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Uredi vrstni red nastavitev."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>. stran od <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"Zaklenjen zaslon"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"Razširi"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimiraj"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Zapri"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"Telefon se segreva"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"Nekatere funkcije bodo med ohlajanjem omejene."</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefon se bo samodejno poskusil ohladiti. Še naprej ga lahko uporabljate, vendar bo morda deloval počasneje.\n\nKo se telefon ohladi, bo zopet deloval kot običajno."</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"Leva bližnjica"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"Desna bližnjica"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"Levo bližnjico uporabi tudi za odklepanje"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"Desno bližnjico uporabi tudi za odklepanje"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"Ni izbrana"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"Zaženi aplikacijo <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"Druge aplikacije"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"Krog"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"Plus"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"Minus"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"Levo"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"Desno"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"Meni"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"Aplikacija <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Opozorila"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Posnetki zaslona"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Splošna sporočila"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Shramba"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Aplikacije brez nameščanja"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Aplikacij brez nameščanja ni treba namestiti."</string>
+    <string name="app_info" msgid="6856026610594615344">"Podatki o aplikaciji"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index d067d10..44e371e 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -692,4 +692,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Pamjet e ekranit"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Mesazhe të përgjithshme"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Hapësira ruajtëse"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Aplikacionet e çastit"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Aplikacionet e çastit nuk kërkojnë instalim."</string>
+    <string name="app_info" msgid="6856026610594615344">"Informacioni mbi aplikacionin"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 256fdbd..22953c1 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -695,4 +695,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Снимци екрана"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Опште поруке"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Меморијски простор"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Инстант апликације"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Инстант апликације не захтевају инсталацију."</string>
+    <string name="app_info" msgid="6856026610594615344">"Информације о апликацији"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 3dea01d..1c70e54 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -692,4 +692,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Skärmdumpar"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Allmänna meddelanden"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Lagring"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Snabbappar behöver inte installeras."</string>
+    <string name="app_info" msgid="6856026610594615344">"Info om appen"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 9084f83..d129771 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -516,9 +516,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Ukiwa na udhibiti wa arifa, unaweza kuweka kiwango cha umuhimu wa arifa za programu kuanzia 0 hadi 5. \n\n"<b>"Kiwango cha 5"</b>" \n- Onyesha katika sehemu ya juu ya orodha ya arifa \n- Ruhusu ukatizaji wa skrini nzima \n- Ruhusu arifa za kuchungulia kila wakati\n\n"<b>"Kiwango cha 4"</b>" \n- Zuia ukatizaji wa skrini nzima\n- Ruhusu arifa za kuchungulia kila wakati \n\n"<b>"Kiwango cha 3"</b>" \n- Zuia ukatizaji wa skrini nzima\n- Usiruhusu kamwe arifa za kuchungulia\n\n"<b>"Kiwango cha 2"</b>" \n- Zuia ukatizaji wa skrini nzima\n- Usiruhusu kamwe arifa za kuchungulia \n- Usiruhusu kamwe sauti au mtetemo \n\n"<b>"Kiwango cha 1"</b>" \n- Zuia ukatizaji wa skrini nzima \n- Usiruhusu kamwe arifa za kuchungulia \n- Usiruhusu kamwe sauti na mtetemo \n- Usionyeshe skrini iliyofungwa na sehemu ya arifa \n- Onyesha katika sehemu ya chini ya orodha ya arifa \n\n"<b>"Kiwango cha 0"</b>" \n- Zuia arifa zote kutoka programu"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Arifa"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"Hutapokea arifa hizi tena."</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="other">Aina 1 kati ya <xliff:g id="NUMBER_1">%d</xliff:g> kwenye programu hii</item>
+      <item quantity="one">Aina 1 kati ya <xliff:g id="NUMBER_0">%d</xliff:g> kwenye programu hii</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"Aina Zote"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Mipangilio zaidi"</string>
     <string name="notification_done" msgid="5279426047273930175">"Nimemaliza"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -592,31 +594,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"Imezimwa"</string>
     <string name="nav_bar" msgid="1993221402773877607">"Sehemu ya viungo muhimu"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"Mpangilio"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"Aina ya kitufe cha kushoto cha ziada"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"Aina ya kitufe cha kulia cha ziada"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(chaguo-msingi)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"Ubao wa kunakili"</item>
+    <item msgid="5742013440802239414">"Msimbo wa ufunguo"</item>
+    <item msgid="8802889973626281575">"Kibadilishaji cha kibodi"</item>
+    <item msgid="8175437057325747277">"Hamna"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"Ya Kawaida"</item>
+    <item msgid="8256205964297588988">"Kushikamana"</item>
+    <item msgid="8719936228094005878">"Inayoegemea kushoto"</item>
+    <item msgid="586019486955594690">"Inayoegemea kulia"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"Kibadilishaji cha kibodi"</string>
     <string name="save" msgid="2311877285724540644">"Hifadhi"</string>
     <string name="reset" msgid="2448168080964209908">"Weka upya"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"Rekebisha upana wa kitufe"</string>
     <string name="clipboard" msgid="1313879395099896312">"Ubao klipu"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"Kitufe maalum cha uelekezaji"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"Msimbo wa ufunguo wa kushoto"</string>
+    <string name="right_keycode" msgid="708447961000848163">"Msimbo wa ufunguo wa kulia"</string>
+    <string name="left_icon" msgid="3096287125959387541">"Aikoni ya kushoto"</string>
+    <string name="right_icon" msgid="3952104823293824311">"Aikoni ya kulia"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"Buruta ili uongeze vigae"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Buruta hapa ili uondoe"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Badilisha"</string>
@@ -665,44 +667,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Fungua mipangilio ya <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Badilisha orodha ya mipangilio."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Ukurasa wa <xliff:g id="ID_1">%1$d</xliff:g> kati ya <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"Skrini iliyofungwa"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"Panua"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Punguza"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Funga"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"Joto la simu linaongezeka"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"Baadhi ya vipengele havitatumika kwenye simu wakati inapoa"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"Simu yako itajaribu kupoa kiotomatiki. Bado unaweza kutumia simu yako, lakini huenda ikafanya kazi polepole. \n\nPindi simu yako itakapopoa, itaendelea kufanya kazi kama kawaida."</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"Njia ya mkato ya kushoto"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"Njia ya mkato ya kulia"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"Njia ya mkato ya kushoto pia inafungua"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"Njia ya mkato ya kulia pia inafungua"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"Hamna"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"Anzisha programu <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"Programu zingine"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"Mduara"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"Alama ya kuongeza"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"Alama ya kuondoa"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"Kushoto"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"Kulia"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"Menyu"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"Programu ya <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Arifa"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Picha za skrini"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Ujumbe wa Jumla"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Hifadhi"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Programu Zinazofunguka Papo Hapo"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Huhitaji kusakinisha programu zinazofunguka papo hapo."</string>
+    <string name="app_info" msgid="6856026610594615344">"Maelezo ya programu"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 7e63cbf..c8ffe8f 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -18,7 +18,6 @@
 <resources>
     <!-- Standard notification width + gravity -->
     <dimen name="notification_panel_width">@dimen/standard_notification_panel_width</dimen>
-    <integer name="notification_panel_layout_gravity">@integer/standard_notification_panel_layout_gravity</integer>
 
     <!-- Diameter of outer shape drawable shown in navbar search-->
     <dimen name="navbar_search_outerring_diameter">430dip</dimen>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 81261de..e4c4528 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -692,4 +692,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"ஸ்கிரீன் ஷாட்டுகள்"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"பொதுச் செய்திகள்"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"சேமிப்பிடம்"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"இன்ஸ்டண்ட் பயன்பாடுகள்"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"இன்ஸ்டண்ட் பயன்பாடுகளுக்கு நிறுவல் தேவையில்லை."</string>
+    <string name="app_info" msgid="6856026610594615344">"பயன்பாட்டுத் தகவல்"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index ae86bbb..3d625e1 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -516,9 +516,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"పవర్ నోటిఫికేషన్ నియంత్రణలతో, మీరు అనువర్తన నోటిఫికేషన్‌ల కోసం ప్రాముఖ్యత స్థాయిని 0 నుండి 5 వరకు సెట్ చేయవచ్చు. \n\n"<b>"స్థాయి 5"</b>" \n- నోటిఫికేషన్ జాబితా పైభాగంలో చూపబడతాయి \n- పూర్తి స్క్రీన్ అంతరాయం అనుమతించబడుతుంది \n- ఎల్లప్పుడూ త్వరిత వీక్షణ అందించబడుతుంది \n\n"<b>"స్థాయి 4"</b>" \n- పూర్తి స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎల్లప్పుడూ త్వరిత వీక్షణ అందించబడుతుంది \n\n"<b>"స్థాయి 3"</b>" \n- పూర్తి స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎప్పుడూ త్వరిత వీక్షణ అందించబడదు \n\n"<b>"స్థాయి 2"</b>" \n- పూర్తి స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎప్పుడూ త్వరిత వీక్షణ అందించబడదు \n- ఎప్పుడూ శబ్దం మరియు వైబ్రేషన్ చేయవు \n\n"<b>"స్థాయి 1"</b>" \n- పూర్తి స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎప్పుడూ త్వరిత వీక్షణ అందించబడదు \n- ఎప్పుడూ శబ్దం లేదా వైబ్రేట్ చేయవు \n- లాక్ స్క్రీన్ మరియు స్థితి పట్టీ నుండి దాచబడతాయి \n- నోటిఫికేషన్ జాబితా దిగువ భాగంలో చూపబడతాయి \n\n"<b>"స్థాయి 0"</b>" \n- అనువర్తనం నుండి అన్ని నోటిఫికేషన్‌లు బ్లాక్ చేయబడతాయి"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"నోటిఫికేషన్‌లు"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"మీరు ఇకపై ఈ నోటిఫికేషన్‌లను పొందరు."</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="other">ఈ అనువర్తనం నుండి <xliff:g id="NUMBER_1">%d</xliff:g> వర్గాలలో 1</item>
+      <item quantity="one">ఈ అనువర్తనం నుండి <xliff:g id="NUMBER_0">%d</xliff:g> వర్గంలో 1</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"అన్ని వర్గాలు"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"మరిన్ని సెట్టింగ్‌లు"</string>
     <string name="notification_done" msgid="5279426047273930175">"పూర్తయింది"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -592,31 +594,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"ఆఫ్ చేయి"</string>
     <string name="nav_bar" msgid="1993221402773877607">"నావిగేషన్ బార్"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"లేఅవుట్"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"అత్యంత ఎడమ వైపు ఉన్న బటన్ రకం"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"అత్యంత కుడివైపు ఉన్న బటన్ రకం"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(డిఫాల్ట్)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"క్లిప్‌బోర్డ్"</item>
+    <item msgid="5742013440802239414">"కీకోడ్"</item>
+    <item msgid="8802889973626281575">"కీబోర్డ్ స్విచర్"</item>
+    <item msgid="8175437057325747277">"ఏదీ వద్దు"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"సాధారణం"</item>
+    <item msgid="8256205964297588988">"సంక్షిప్తమైనది"</item>
+    <item msgid="8719936228094005878">"ఎడమవైపుకు వాలుగా"</item>
+    <item msgid="586019486955594690">"కుడివైపుకు వాలుగా"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"కీబోర్డ్ స్విచర్"</string>
     <string name="save" msgid="2311877285724540644">"సేవ్ చేయి"</string>
     <string name="reset" msgid="2448168080964209908">"రీసెట్ చేయి"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"బటన్ వెడల్పును సర్దుబాటు చేయండి"</string>
     <string name="clipboard" msgid="1313879395099896312">"క్లిప్‌బోర్డ్"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"అనుకూల నావిగేషన్ బటన్"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"ఎడమ వైపు కీకోడ్"</string>
+    <string name="right_keycode" msgid="708447961000848163">"కుడివైపు ఉన్న కీకోడ్"</string>
+    <string name="left_icon" msgid="3096287125959387541">"ఎడమ వైపు చిహ్నం"</string>
+    <string name="right_icon" msgid="3952104823293824311">"కుడివైపు ఉన్న చిహ్నం"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"టైల్‌లను జోడించడానికి లాగండి"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"తీసివేయడానికి ఇక్కడికి లాగండి"</string>
     <string name="qs_edit" msgid="2232596095725105230">"సవరించు"</string>
@@ -665,44 +667,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> సెట్టింగ్‌లను తెరవండి."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"సెట్టింగ్‌ల క్రమాన్ని సవరించండి."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g>లో <xliff:g id="ID_1">%1$d</xliff:g>వ పేజీ"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"లాక్ స్క్రీన్"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"విస్తరింపజేయి"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"కనిష్టీకరించు"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"మూసివేయి"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"ఫోన్ వేడెక్కుతోంది"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"ఫోన్‌ను చల్లబరిచే క్రమంలో కొన్ని లక్షణాలు పరిమితం చేయబడ్డాయి"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"మీ ఫోన్ స్వయంచాలకంగా చల్లబడటానికి ప్రయత్నిస్తుంది. మీరు ఇప్పటికీ మీ ఫోన్‌ను ఉపయోగించవచ్చు, కానీ దాని పనితీరు నెమ్మదిగా ఉండవచ్చు.\n\nమీ ఫోన్ చల్లబడిన తర్వాత, అది సాధారణ రీతిలో పని చేస్తుంది."</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"ఎడమవైపు సత్వరమార్గం"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"కుడివైపు సత్వరమార్గం"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"ఎడమవైపు సత్వరమార్గం కూడా అన్‌లాక్ చేస్తుంది"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"కుడివైపు సత్వరమార్గం కూడా అన్‌లాక్ చేస్తుంది"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"ఏదీ వద్దు"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"<xliff:g id="APP">%1$s</xliff:g>ని ప్రారంభించండి"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"ఇతర అనువర్తనాలు"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"సర్కిల్"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"కూడిక చిహ్నం"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"తీసివేత చిహ్నం"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"ఎడమ"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"కుడి"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"మెను"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> అనురవర్తనం"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"హెచ్చరికలు"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"స్క్రీన్‌షాట్‌లు"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"సాధారణ సందేశాలు"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"నిల్వ"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"తక్షణ అనువర్తనాలు"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"తక్షణ అనువర్తనాలకు ఇన్‌స్టాలేషన్ అవసరం లేదు."</string>
+    <string name="app_info" msgid="6856026610594615344">"అనువర్తన సమాచారం"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 902dfcc..8cc9388 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -516,9 +516,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"ส่วนควบคุมการแจ้งเตือนแบบเปิด/ปิดช่วยให้คุณตั้งค่าระดับความสำคัญสำหรับการแจ้งเตือนของแอปได้ตั้งแต่ระดับ 0-5 \n\n"<b>"ระดับ 5"</b>" \n- แสดงที่ด้านบนของรายการแจ้งเตือน \n- อนุญาตให้รบกวนแบบเต็มหน้าจอ \n- อนุญาตให้แสดงชั่วครู่ \n\n"<b>"ระดับ 4"</b>" \n- ป้องกันการรบกวนแบบเต็มหน้าจอ \n- แสดงชั่วครู่เสมอ \n\n"<b>"ระดับ 3"</b>" \n- ป้องกันการรบกวนแบบเต็มหน้าจอ \n- ไม่แสดงชั่วครู่เลย \n\n"<b>"ระดับ 2"</b>" \n- ป้องกันการรบกวนแบบเต็มหน้าจอ \n- ไม่แสดงชั่วครู่เลย \n- ไม่ส่งเสียงหรือสั่นเลย \n\n"<b>"ระดับ 1"</b>" \n- ป้องกันการรบกวนแบบเต็มหน้าจอ \n- ไม่แสดงชั่วครู่เลย \n- ไม่ส่งเสียงหรือสั่นเลย \n- ซ่อนจากหน้าจอล็อกและแถบสถานะ \n- แสดงที่ด้านล่างของรายการแจ้งเตือน \n\n"<b>"ระดับ 0"</b>" \n- บล็อกการแจ้งเตือนทั้งหมดจากแอป"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"การแจ้งเตือน"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"คุณจะไม่ได้รับการแจ้งเตือนเหล่านี้อีก"</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="other">1 จาก <xliff:g id="NUMBER_1">%d</xliff:g> หมวดหมู่ของแอปนี้</item>
+      <item quantity="one">1 จาก <xliff:g id="NUMBER_0">%d</xliff:g> หมวดหมู่ของแอปนี้</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"ทุกหมวดหมู่"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"การตั้งค่าเพิ่มเติม"</string>
     <string name="notification_done" msgid="5279426047273930175">"เสร็จสิ้น"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -592,31 +594,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"ปิด"</string>
     <string name="nav_bar" msgid="1993221402773877607">"แถบนำทาง"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"การจัดวาง"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"ประเภทปุ่มทางซ้ายเพิ่มเติม"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"ประเภทปุ่มทางขวาเพิ่มเติม"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(ค่าเริ่มต้น)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"คลิปบอร์ด"</item>
+    <item msgid="5742013440802239414">"Keycode"</item>
+    <item msgid="8802889973626281575">"ปุ่มสลับแป้นพิมพ์"</item>
+    <item msgid="8175437057325747277">"ไม่มี"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"ปกติ"</item>
+    <item msgid="8256205964297588988">"กะทัดรัด"</item>
+    <item msgid="8719936228094005878">"เอนไปทางซ้าย"</item>
+    <item msgid="586019486955594690">"เอนไปทางขวา"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"ปุ่มสลับแป้นพิมพ์"</string>
     <string name="save" msgid="2311877285724540644">"บันทึก"</string>
     <string name="reset" msgid="2448168080964209908">"รีเซ็ต"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"ปรับความกว้างของปุ่ม"</string>
     <string name="clipboard" msgid="1313879395099896312">"คลิปบอร์ด"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"ปุ่มนำทางที่กำหนดเอง"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"Keycode ทางซ้าย"</string>
+    <string name="right_keycode" msgid="708447961000848163">"Keycode ทางขวา"</string>
+    <string name="left_icon" msgid="3096287125959387541">"ไอคอนทางซ้าย"</string>
+    <string name="right_icon" msgid="3952104823293824311">"ไอคอนทางขวา"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"ลากเพื่อเพิ่มชิ้นส่วน"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"ลากมาที่นี่เพื่อนำออก"</string>
     <string name="qs_edit" msgid="2232596095725105230">"แก้ไข"</string>
@@ -665,44 +667,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"เปิดการตั้งค่า <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"แก้ไขลำดับการตั้งค่า"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"หน้า <xliff:g id="ID_1">%1$d</xliff:g> จาก <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"หน้าจอล็อก"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"ขยาย"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"ย่อเล็กสุด"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"ปิด"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"โทรศัพท์เริ่มเครื่องร้อน"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"คุณลักษณะบางอย่างจะใช้งานได้จำกัดขณะโทรศัพท์ลดอุณหภูมิลง"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"โทรศัพท์จะพยายามลดอุณหภูมิลงโดยอัตโนมัติ คุณยังสามารถใช้โทรศัพท์ได้ แต่โทรศัพท์อาจทำงานช้าลง\n\nโทรศัพท์จะทำงานตามปกติเมื่อเย็นลงแล้ว"</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"ทางลัดทางซ้าย"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"ทางลัดทางขวา"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"ทางลัดทางซ้ายปลดล็อกได้ด้วย"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"ทางลัดทางขวาปลดล็อกได้ด้วย"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"ไม่มี"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"เปิดแอป <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"แอปอื่นๆ"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"แวดวง"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"เครื่องหมายบวก"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"เครื่องหมายลบ"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"ซ้าย"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"ขวา"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"เมนู"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"แอป <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"การแจ้งเตือน"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"ภาพหน้าจอ"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"ข้อความทั่วไป"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"พื้นที่เก็บข้อมูล"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Instant App"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Instant Apps ไม่ต้องใช้การติดตั้ง"</string>
+    <string name="app_info" msgid="6856026610594615344">"ข้อมูลแอป"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 2de4e86..c2d5c74 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -516,9 +516,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Sa pamamagitan ng mga kontrol sa notification ng power, magagawa mong itakda ang antas ng kahalagahan ng mga notification ng isang app mula 0 hanggang 5. \n\n"<b>"Antas 5"</b>" \n- Ipakita sa itaas ng listahan ng notification \n- Payagan ang pag-istorbo kapag full screen \n- Palaging sumilip \n\n"<b>"Antas 4"</b>" \n- Pigilan ang pag-istorbo kapag full screen \n- Palaging sumilip \n\n"<b>"Antas 3"</b>" \n- Pigilan ang pag-istorbo kapag full screen \n- Huwag kailanman sumilip \n\n"<b>"Antas 2"</b>" \n- Pigilan ang pag-istorbo kapag full screen \n- Huwag kailanman sumilip \n- Huwag kailanman tumunog o mag-vibrate \n\n"<b>"Antas 1"</b>" \n- Pigilan ang pag-istorbo kapag full screen \n- Huwag kailanman sumilip \n- Huwag kailanman tumunog o mag-vibrate \n- Itago sa lock screen at status bar \n- Ipakita sa ibaba ng listahan ng notification \n\n"<b>"Antas 0"</b>" \n- I-block ang lahat ng notification mula sa app"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Mga Notification"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"Hindi mo na matatanggap ang mga notification na ito."</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="one">1 sa <xliff:g id="NUMBER_1">%d</xliff:g> kategorya mula sa app na ito</item>
+      <item quantity="other">1 sa <xliff:g id="NUMBER_1">%d</xliff:g> na kategorya mula sa app na ito</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"Lahat ng Kategorya"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Higit pang mga setting"</string>
     <string name="notification_done" msgid="5279426047273930175">"Tapos Na"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -592,31 +594,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"I-off"</string>
     <string name="nav_bar" msgid="1993221402773877607">"Navigation bar"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"Layout"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"Uri ng extra na button ng kaliwa"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"Uri ng extra na button ng kanan"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(default)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"Clipboard"</item>
+    <item msgid="5742013440802239414">"Keycode"</item>
+    <item msgid="8802889973626281575">"Keyboard switcher"</item>
+    <item msgid="8175437057325747277">"Wala"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"Karaniwan"</item>
+    <item msgid="8256205964297588988">"Compact"</item>
+    <item msgid="8719936228094005878">"Nakapanig sa kaliwa"</item>
+    <item msgid="586019486955594690">"Nakapanig sa kanan"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"Keyboard switcher"</string>
     <string name="save" msgid="2311877285724540644">"I-save"</string>
     <string name="reset" msgid="2448168080964209908">"I-reset"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"Isaayos ang lapad ng button"</string>
     <string name="clipboard" msgid="1313879395099896312">"Clipboard"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"Custom na button ng navigation"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"Kaliwang keycode"</string>
+    <string name="right_keycode" msgid="708447961000848163">"Kanang keycode"</string>
+    <string name="left_icon" msgid="3096287125959387541">"Icon ng kaliwa"</string>
+    <string name="right_icon" msgid="3952104823293824311">"Icon ng kanan"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"Mag-drag upang magdagdag ng mga tile"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"I-drag dito upang alisin"</string>
     <string name="qs_edit" msgid="2232596095725105230">"I-edit"</string>
@@ -665,44 +667,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Buksan ang mga setting ng <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"I-edit ang pagkakasunud-sunod ng mga setting."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Page <xliff:g id="ID_1">%1$d</xliff:g> ng <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"Lock screen"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"Palawakin"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"I-minimize"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Isara"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"Umiinit ang telepono"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"Limitado ang ilang feature habang nagku-cool down ang telepono"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"Awtomatikong susubukan ng iyong telepono na mag-cool down. Magagamit mo pa rin ang iyong telepono, ngunit maaaring mas mabagal ang paggana nito.\n\nKapag nakapag-cool down na ang iyong telepono, gagana na ito nang normal."</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"Kaliwang shortcut"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"Kanang shortcut"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"Ina-unlock din ng kaliwang shortcut ang"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"Ina-unlock din ng kanang shortcut ang"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"Wala"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"Ilunsad ang <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"Iba pang app"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"Circle"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"Plus"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"Minus"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"Kaliwa"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"Kanan"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"Menu"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> app"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Mga Alerto"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Mga Screenshot"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Mga Pangkalahatang Mensahe"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Storage"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Instant Apps"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Hindi kailangang i-install ang mga instant na app."</string>
+    <string name="app_info" msgid="6856026610594615344">"Impormasyon ng app"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 634ea9a..f7bdcc1 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -516,9 +516,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Güç bildirim kontrolleriyle, bir uygulamanın bildirimleri için 0 ile 5 arasında bir önem düzeyi ayarlayabilirsiniz. \n\n"<b>"5. Düzey"</b>" \n- Bildirim listesinin en üstünde gösterilsin \n- Tam ekran kesintisine izin verilsin \n- Ekranda her zaman kısaca belirsin \n\n"<b>"4. Düzey"</b>" \n- Tam ekran kesintisi engellensin \n- Ekranda her zaman kısaca belirsin \n\n"<b>"3. Düzey"</b>" \n- Tam ekran kesintisi engellensin \n- Ekranda hiçbir zaman kısaca belirmesin \n\n"<b>"2. Düzey"</b>" \n- Tam ekran kesintisi engellensin \n- Ekranda hiçbir zaman belirmesin \n- Hiçbir zaman ses çıkarmasın ve titreştirmesin \n\n"<b>"1. Düzey"</b>" \n- Tam ekran kesintisi engellensin \n- Ekranda hiçbir zaman kısaca belirmesin \n- Hiçbir zaman ses çıkarmasın veya titreştirmesin \n- Kilit ekranından ve durum çubuğundan gizlensin \n- Bildirim listesinin en altında gösterilsin \n\n"<b>"0. Düzey"</b>" \n- Uygulamadan gelen tüm bildirimler engellensin"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Bildirimler"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"Bu bildirimleri artık almayacaksınız."</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="other">Bu uygulamadan 1 / <xliff:g id="NUMBER_1">%d</xliff:g> kategori</item>
+      <item quantity="one">Bu uygulamadan 1 / <xliff:g id="NUMBER_0">%d</xliff:g> kategori</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"Tüm Kategoriler"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Diğer ayarlar"</string>
     <string name="notification_done" msgid="5279426047273930175">"Bitti"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -592,31 +594,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"Kapalı"</string>
     <string name="nav_bar" msgid="1993221402773877607">"Gezinme çubuğu"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"Düzen"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"Ekstra sol düğme türü"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"Ekstra sağ düğme türü"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(varsayılan)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"Pano"</item>
+    <item msgid="5742013440802239414">"Tuş kodu"</item>
+    <item msgid="8802889973626281575">"Klavye değiştirici"</item>
+    <item msgid="8175437057325747277">"Yok"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"Normal"</item>
+    <item msgid="8256205964297588988">"Küçük boyutlu"</item>
+    <item msgid="8719936228094005878">"Sola yaslanmış"</item>
+    <item msgid="586019486955594690">"Sağa yaslanmış"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"Klavye değiştirici"</string>
     <string name="save" msgid="2311877285724540644">"Kaydet"</string>
     <string name="reset" msgid="2448168080964209908">"Sıfırla"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"Düğme genişliğini düzenle"</string>
     <string name="clipboard" msgid="1313879395099896312">"Pano"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"Özel gezinme düğmesi"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"Sol tuş kodu"</string>
+    <string name="right_keycode" msgid="708447961000848163">"Sağ tuş kodu"</string>
+    <string name="left_icon" msgid="3096287125959387541">"Sol simge"</string>
+    <string name="right_icon" msgid="3952104823293824311">"Sağ simge"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"Blok eklemek için sürükleyin"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Kaldırmak için buraya sürükleyin"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Düzenle"</string>
@@ -665,44 +667,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> ayarlarını aç."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Ayarların sırasını düzenle."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Sayfa <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"Kilit ekranı"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"Genişlet"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Simge durumuna getir"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Kapat"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"Telefon ısınıyor"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"Telefon soğurken bazı özellikler sınırlı olarak kullanılabilir"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefonunuz otomatik olarak soğumaya çalışacak. Bu sırada telefonunuzu kullanmaya devam edebilirsiniz ancak uygulamalar daha yavaş çalışabilir.\n\nTelefonunuz soğuduktan sonra normal şekilde çalışacaktır."</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"Sol kısayol"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"Sağ kısayol"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"Sol kısayol aynı zamanda kilidi açar"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"Sağ kısayol aynı zamanda kilidi açar"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"Yok"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"<xliff:g id="APP">%1$s</xliff:g> uygulamasını başlat"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"Diğer uygulamalar"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"Daire"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"Artı"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"Eksi"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"Sol"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"Sağ"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"Menü"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> uygulaması"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Uyarılar"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Ekran görüntüleri"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Genel Mesajlar"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Depolama alanı"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Hazır Uygulamalar"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Hazır uygulamaların yüklenmesi gerekmez."</string>
+    <string name="app_info" msgid="6856026610594615344">"Uygulama bilgileri"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 4c9729d..47eb6ce 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -700,4 +700,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Знімки екрана"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Загальні повідомлення"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Пам’ять"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Додатки з миттєвим запуском"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Додатки з миттєвим запуском не потрібно встановлювати."</string>
+    <string name="app_info" msgid="6856026610594615344">"Про додаток"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 82793aa..ab96322 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -516,9 +516,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"پاور اطلاع کنٹرولز کے ساتھ آپ کسی ایپ کی اطلاعات کیلئے 0 سے 5 تک اہمیت کی سطح سیٹ کر سکتے ہیں۔ \n\n"<b>"سطح 5"</b>\n"- اطلاعات کی فہرست کے اوپر دکھائیں \n- پوری اسکرین کی مداخلت کی اجازت دیں \n- ہمیشہ جھانکنا\n\n"<b>"سطح 4"</b>\n"- پوری اسکرین کی مداخلت کو روکیں \n- ہمیشہ جھانکنا\n\n"<b>"سطح 3"</b>\n"- پوری اسکرین کی مداخلت کو روکیں \n- کبھی نہ جھانکنا \n\n"<b>"سطح 2"</b>\n"- پوری اسکرین کی مداخلت کو روکیں \n- کبھی نہ جھانکنا \n- کبھی آواز اور ارتعاش پیدا نہ کرنا \n\n"<b>" سطح 1"</b>\n"- پوری اسکرین کی مداخلت کو روکنا \n- کبھی نہ جھانکنا \n- کبھی بھی آواز یا ارتعاش پیدا نہ کرنا\n- مقفل اسکرین اور اسٹیٹس بار سے چھپانا \n - اطلاع کی فہرست کی نیچے دکھانا \n\n"<b>"سطح 0"</b>\n"- ایپ سے تمام اطلاعات مسدود کریں"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"اطلاعات"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"آپ کو یہ اطلاعات مزید نہیں ملیں گی۔"</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="other"> اس ایپ کے <xliff:g id="NUMBER_1">%d</xliff:g> زمروں میں سے 1</item>
+      <item quantity="one"> اس ایپ کے <xliff:g id="NUMBER_0">%d</xliff:g> زمرہ میں سے 1</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"سبھی زمرے"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"مزید ترتیبات"</string>
     <string name="notification_done" msgid="5279426047273930175">"ہوگیا"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -592,31 +594,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"آف"</string>
     <string name="nav_bar" msgid="1993221402773877607">"نیویگیشن بار"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"لے آؤٹ"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"بائيں جانب کی اضافی بٹن کی قسم"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"دائیں جانب کی اضافی بٹن کی قسم"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(ڈیفالٹ)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"کلپ بورڈ"</item>
+    <item msgid="5742013440802239414">"کی کوڈ"</item>
+    <item msgid="8802889973626281575">"کی بورڈ سوئچر"</item>
+    <item msgid="8175437057325747277">"کوئی نہیں"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"حسب معمول"</item>
+    <item msgid="8256205964297588988">"مختصر"</item>
+    <item msgid="8719936228094005878">"بائیں جانب جھکاؤ"</item>
+    <item msgid="586019486955594690">"دائیں جانب جھکاؤ"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"کی بورڈ سوئچر"</string>
     <string name="save" msgid="2311877285724540644">"محفوظ کریں"</string>
     <string name="reset" msgid="2448168080964209908">"دوبارہ ترتیب دیں"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"بٹن کی چوڑائی ایڈجسٹ کریں"</string>
     <string name="clipboard" msgid="1313879395099896312">"کلپ بورڈ"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"حسب ضرورت نیویگیشن بٹن"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"بائيں جانب کا کی کوڈ"</string>
+    <string name="right_keycode" msgid="708447961000848163">"دائيں جانب کا کی کوڈ"</string>
+    <string name="left_icon" msgid="3096287125959387541">"بائیں جانب کا آئیکن"</string>
+    <string name="right_icon" msgid="3952104823293824311">"دائيں جانب کا آئيکن"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"ٹائٹلز شامل کرنے کیلئے گھسیٹیں"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"ہٹانے کیلئے یہاں گھسیٹیں؟"</string>
     <string name="qs_edit" msgid="2232596095725105230">"ترمیم کریں"</string>
@@ -665,44 +667,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> ترتیبات کھولیں۔"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"ترتیبات کی ترتیب میں ترمیم کریں۔"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"صفحہ <xliff:g id="ID_1">%1$d</xliff:g> از <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"مقفل اسکرین"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"پھیلائیں"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"چھوٹی کریں"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"بند کریں"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"فون گرم ہو رہا ہے"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"فون کے ٹھنڈے ہو جانے تک کچھ خصوصیات محدود ہیں"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"آپ کا فون خودکار طور پر ٹھنڈا ہونے کی کوشش کرے گا۔ آپ ابھی بھی اپنا فون استعمال کر سکتے ہیں، مگر ہو سکتا ہے یہ سست چلے۔\n\nایک بار آپ کا فون ٹھنڈا ہوجائے تو یہ معمول کے مطابق چلے گا۔"</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"بائيں جانب کا شارٹ کٹ"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"دائیں جانب کا شارٹ کٹ"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"بائيں جانب کے شارٹ کٹ سے بھی غیرمقفل ہوتا ہے"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"دائيں جانب کے شارٹ کٹ سے بھی غیرمقفل ہو تا ہے"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"کوئی نہیں"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"<xliff:g id="APP">%1$s</xliff:g> شروع کریں"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"دیگر ایپس"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"حلقہ"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"جمع کا نشان"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"علامت تفریق"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"بائیں"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"دائیں"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"مینو"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> ایپ"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"الرٹس"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"اسکرین شاٹس"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"عمومی پیغامات"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"اسٹوریج"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"فوری ایپس"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"فوری ایپس کو انسٹالیشن کی ضرورت نہیں ہے۔"</string>
+    <string name="app_info" msgid="6856026610594615344">"ایپ کی معلومات"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 375ce70..3460961 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -596,8 +596,8 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"O‘chiq"</string>
     <string name="nav_bar" msgid="1993221402773877607">"Navigatsiya paneli"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"Sxema"</string>
-    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"Qo‘shimcha chap tugma turi"</string>
-    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"Qo‘shimcha o‘ng tugma turi"</string>
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"Qo‘shimcha Chapga tugmasi turi"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"Qo‘shimcha O‘ngga tugmasi turi"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(standart)"</string>
   <string-array name="nav_bar_buttons">
     <item msgid="1545641631806817203">"Vaqtinchalik xotira"</item>
@@ -608,8 +608,8 @@
   <string-array name="nav_bar_layouts">
     <item msgid="8077901629964902399">"Odatiy"</item>
     <item msgid="8256205964297588988">"Ixcham"</item>
-    <item msgid="8719936228094005878">"Chapga og‘ishgan"</item>
-    <item msgid="586019486955594690">"O‘ngga og‘ishgan"</item>
+    <item msgid="8719936228094005878">"Chap tomonga qiya"</item>
+    <item msgid="586019486955594690">"O‘ng tomonga qiya"</item>
   </string-array>
     <string name="menu_ime" msgid="4998010205321292416">"Klaviaturani almashtirish"</string>
     <string name="save" msgid="2311877285724540644">"Saqlash"</string>
@@ -617,10 +617,10 @@
     <string name="adjust_button_width" msgid="6138616087197632947">"Tugma enini moslashtiring"</string>
     <string name="clipboard" msgid="1313879395099896312">"Vaqtinchalik xotira"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"Maxsus navigatsiya tugmasi"</string>
-    <string name="left_keycode" msgid="2010948862498918135">"Chap tugma kodi"</string>
-    <string name="right_keycode" msgid="708447961000848163">"O‘ng tugma kodi"</string>
-    <string name="left_icon" msgid="3096287125959387541">"Chap nishoncha"</string>
-    <string name="right_icon" msgid="3952104823293824311">"O‘ng nishoncha"</string>
+    <string name="left_keycode" msgid="2010948862498918135">"Chapga tugmasi kodi"</string>
+    <string name="right_keycode" msgid="708447961000848163">"O‘ngga tugmasi kodi"</string>
+    <string name="left_icon" msgid="3096287125959387541">"Chapga belgisi"</string>
+    <string name="right_icon" msgid="3952104823293824311">"O‘ngga belgisi"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"Kerakli elementni tortib qo‘shing"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"O‘chirish uchun bu yerga torting"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Tahrirlash"</string>
@@ -676,22 +676,27 @@
     <string name="high_temp_title" msgid="4589508026407318374">"Telefon qizib ketdi"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"Telefon sovish paytida ayrim funksiyalar ishlamasligi mumkin"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefon avtomatik ravishda o‘zini sovitadi. Telefoningizdan foydalanishda davom etishingiz mumkin, lekin u sekinroq ishlashi mumkin.\n\nTelefon sovishi bilan normal holatda ishlashni boshlaydi."</string>
-    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"Chap tugma"</string>
-    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"O‘ng tugma"</string>
-    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"Chap tugma ham qulfdan chiqaradi"</string>
-    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"O‘ng tugma ham qulfdan chiqaradi"</string>
-    <string name="lockscreen_none" msgid="4783896034844841821">"Hech qaysi"</string>
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"Chapga yorlig‘i"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"O‘ngga yorlig‘i"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"Chapga tugmasi ham qulfdan chiqaradi"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"O‘ngga tugmasi ham qulfdan chiqaradi"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"Hech biri"</string>
     <string name="tuner_launch_app" msgid="1527264114781925348">"<xliff:g id="APP">%1$s</xliff:g> ilovasini ishga tushirish"</string>
     <string name="tuner_other_apps" msgid="4726596850501162493">"Boshqa ilovalar"</string>
     <string name="tuner_circle" msgid="2340998864056901350">"Aylana"</string>
     <string name="tuner_plus" msgid="6792960658533229675">"Plus"</string>
     <string name="tuner_minus" msgid="4806116839519226809">"Minus"</string>
-    <string name="tuner_left" msgid="8404287986475034806">"Chap"</string>
-    <string name="tuner_right" msgid="6222734772467850156">"O‘ng"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"Chapga"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"O‘ngga"</string>
     <string name="tuner_menu" msgid="191640047241552081">"Menyu"</string>
     <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> ilovasi"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Ogohlantirishlar"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Skrinshotlar"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Umumiy xabarlar"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Xotira"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Darhol ochiladigan ilovalar"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Darhol ochiladigan ilovalarni o‘rnatish shart emas."</string>
+    <string name="app_info" msgid="6856026610594615344">"Ilova haqida"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 0751a3e..8e7b7b0 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -518,9 +518,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Với các kiểm soát thông báo nguồn, bạn có thể đặt cấp độ quan trọng từ 0 đến 5 cho các thông báo của ứng dụng. \n\n"<b>"Cấp 5"</b>" \n- Hiển thị ở đầu danh sách thông báo \n- Cho phép gián đoạn ở chế độ toàn màn hình \n- Luôn xem nhanh \n\n"<b>"Cấp 4"</b>" \n- Ngăn gián đoạn ở chế độ toàn màn hình \n- Luôn xem nhanh \n\n"<b>"Cấp 3"</b>" \n- Ngăn gián đoạn ở chế độ toàn màn hình \n- Không bao giờ xem nhanh \n\n"<b>"Cấp 2"</b>" \n- Ngăn gián đoạn ở chế độ toàn màn hình \n- Không bao giờ xem nhanh \n- Không bao giờ có âm báo và rung \n\n"<b>"Cấp 1"</b>" \n- Ngăn gián đoạn ở chế độ toàn màn hình \n- Không bao giờ xem nhanh \n- Không bao giờ có âm báo và rung \n- Ẩn khỏi màn hình khóa và thanh trạng thái \n- Hiển thị ở cuối danh sách thông báo \n\n"<b>"Cấp 0"</b>" \n- Chặn tất cả các thông báo từ ứng dụng"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Thông báo"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"Bạn sẽ không nhận được những thông báo này nữa."</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="other">1 / <xliff:g id="NUMBER_1">%d</xliff:g> danh mục từ ứng dụng này</item>
+      <item quantity="one">1 / <xliff:g id="NUMBER_0">%d</xliff:g> danh mục từ ứng dụng này</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"Tất cả danh mục"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Cài đặt khác"</string>
     <string name="notification_done" msgid="5279426047273930175">"Xong"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -594,31 +596,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"Tắt"</string>
     <string name="nav_bar" msgid="1993221402773877607">"Thanh điều hướng"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"Bố cục"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"Loại nút bổ sung bên trái"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"Loại nút bổ sung bên phải"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(mặc định)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"Khay nhớ tạm"</item>
+    <item msgid="5742013440802239414">"Mã phím"</item>
+    <item msgid="8802889973626281575">"Trình chuyển đổi bàn phím"</item>
+    <item msgid="8175437057325747277">"Không có"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"Bình thường"</item>
+    <item msgid="8256205964297588988">"Cao"</item>
+    <item msgid="8719936228094005878">"Nghiêng sang trái"</item>
+    <item msgid="586019486955594690">"Nghiêng sang phải"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"Trình chuyển đổi bàn phím"</string>
     <string name="save" msgid="2311877285724540644">"Lưu"</string>
     <string name="reset" msgid="2448168080964209908">"Đặt lại"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"Điều chỉnh chiều rộng nút"</string>
     <string name="clipboard" msgid="1313879395099896312">"Khay nhớ tạm"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"Nút điều hướng tùy chỉnh"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"Mã phím bên trái"</string>
+    <string name="right_keycode" msgid="708447961000848163">"Mã phím bên phải"</string>
+    <string name="left_icon" msgid="3096287125959387541">"Biểu tượng bên trái"</string>
+    <string name="right_icon" msgid="3952104823293824311">"Biểu tượng bên phải"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"Kéo để thêm ô"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Kéo vào đây để xóa"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Chỉnh sửa"</string>
@@ -667,44 +669,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Mở cài đặt <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Chỉnh sửa thứ tự cài đặt."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Trang <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"Màn hình khóa"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"Mở rộng"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Thu nhỏ"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Đóng"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"Điện thoại đang nóng lên"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"Một số tính năng bị hạn chế trong khi điện thoại nguội dần"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"Điện thoại của bạn sẽ tự động nguội dần. Bạn vẫn có thể sử dụng điện thoại, nhưng điện thoại có thể chạy chậm hơn. \n\nSau khi đã nguội, điện thoại sẽ chạy bình thường."</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"Lối tắt bên trái"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"Lối tắt bên phải"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"Lối tắt bên trái cũng mở khóa"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"Lối tắt bên phải cũng mở khóa"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"Không có"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"Khởi chạy <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"Ứng dụng khác"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"Vòng kết nối"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"Dấu cộng"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"Dấu trừ"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"Bên trái"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"Bên phải"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"Menu"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"Ứng dụng <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Cảnh báo"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Ảnh chụp màn hình"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Thông báo chung"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Bộ nhớ"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Ứng dụng tức thì"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Ứng dụng tức thì không yêu cầu cài đặt."</string>
+    <string name="app_info" msgid="6856026610594615344">"Thông tin ứng dụng"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index b5ea880..be297be 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -516,9 +516,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"利用高级通知设置,您可以为应用通知设置从 0 级到 5 级的重要程度等级。\n\n"<b>"5 级"</b>" \n- 在通知列表顶部显示 \n- 允许全屏打扰 \n- 一律短暂显示通知 \n\n"<b>"4 级"</b>" \n- 禁止全屏打扰 \n- 一律短暂显示通知 \n\n"<b>"3 级"</b>" \n- 禁止全屏打扰 \n- 一律不短暂显示通知 \n\n"<b>"2 级"</b>" \n- 禁止全屏打扰 \n- 一律不短暂显示通知 \n- 一律不发出声音或振动 \n\n"<b>"1 级"</b>" \n- 禁止全屏打扰 \n- 一律不短暂显示通知 \n- 一律不发出声音或振动 \n- 不在锁定屏幕和状态栏中显示 \n- 在通知列表底部显示 \n\n"<b>"0 级"</b>" \n- 屏蔽应用的所有通知"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"通知"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"您将不会再收到这类通知。"</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="other">由此应用定义的 1 个类别(共 <xliff:g id="NUMBER_1">%d</xliff:g> 个)</item>
+      <item quantity="one">由此应用定义的 1 个类别(共 <xliff:g id="NUMBER_0">%d</xliff:g> 个)</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"所有类别"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"更多设置"</string>
     <string name="notification_done" msgid="5279426047273930175">"完成"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g><xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -592,31 +594,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"关闭"</string>
     <string name="nav_bar" msgid="1993221402773877607">"导航栏"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"布局"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"其他向左按钮类型"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"其他向右按钮类型"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(默认)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"剪贴板"</item>
+    <item msgid="5742013440802239414">"键码"</item>
+    <item msgid="8802889973626281575">"键盘切换器"</item>
+    <item msgid="8175437057325747277">"无"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"一般"</item>
+    <item msgid="8256205964297588988">"紧凑"</item>
+    <item msgid="8719936228094005878">"靠左"</item>
+    <item msgid="586019486955594690">"靠右"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"键盘切换器"</string>
     <string name="save" msgid="2311877285724540644">"保存"</string>
     <string name="reset" msgid="2448168080964209908">"重置"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"调整按钮宽度"</string>
     <string name="clipboard" msgid="1313879395099896312">"剪贴板"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"自定义导航按钮"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"向左键码"</string>
+    <string name="right_keycode" msgid="708447961000848163">"向右键码"</string>
+    <string name="left_icon" msgid="3096287125959387541">"向左图标"</string>
+    <string name="right_icon" msgid="3952104823293824311">"向右图标"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"拖动即可添加图块"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"拖动到此处即可移除"</string>
     <string name="qs_edit" msgid="2232596095725105230">"修改"</string>
@@ -665,44 +667,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"打开<xliff:g id="ID_1">%s</xliff:g>设置。"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"修改设置顺序。"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"第 <xliff:g id="ID_1">%1$d</xliff:g> 页,共 <xliff:g id="ID_2">%2$d</xliff:g> 页"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"锁定屏幕"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"展开"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"最小化"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"关闭"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"手机温度上升中"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"手机降温时,部分功能的使用会受限制"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"您的手机将自动尝试降温。您依然可以使用您的手机,但是手机运行速度可能会更慢。\n\n手机降温后,就会恢复正常的运行速度。"</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"向左快捷方式"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"向右快捷方式"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"向左快捷方式也可以解锁设备"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"向右快捷方式也可以解锁设备"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"无"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"启动<xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"其他应用"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"圆形"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"加号"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"减号"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"向左"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"向右"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"菜单"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g>应用"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"提醒"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"屏幕截图"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"常规消息"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"存储空间"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"免安装应用"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"免安装应用无需安装就能使用。"</string>
+    <string name="app_info" msgid="6856026610594615344">"应用信息"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index b7c347a..6906ead 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -518,9 +518,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"通知控制項讓您設定應用程式通知的重要性 (0 至 5 級)。\n\n"<b>"第 5 級"</b>" \n- 在通知清單頂部顯示 \n- 允許全螢幕騷擾 \n- 一律顯示通知 \n\n"<b>"第 4 級"</b>" \n- 阻止全螢幕騷擾 \n- 一律顯示通知 \n\n"<b>"第 3 級"</b>" \n- 阻止全螢幕騷擾 \n- 永不顯示通知 \n\n"<b>"第 2 級"</b>" \n- 阻止全螢幕騷擾 \n- 永不顯示通知 \n- 永不發出聲響和震動 \n\n"<b>"第 1 級"</b>" \n- 阻止全螢幕騷擾 \n- 永不顯示通知 \n- 永不發出聲響和震動 \n- 從上鎖畫面和狀態列中隱藏 \n- 在通知清單底部顯示 \n\n"<b>"第 0 級"</b>" \n- 封鎖所有應用程式通知"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"通知"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"您不會再收到這些通知。"</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="other">此應用程式的其中 1 個類別 (共 <xliff:g id="NUMBER_1">%d</xliff:g> 個)</item>
+      <item quantity="one">此應用程式的其中 1 個類別 (共 <xliff:g id="NUMBER_0">%d</xliff:g> 個)</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"所有類別"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"更多設定"</string>
     <string name="notification_done" msgid="5279426047273930175">"完成"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -594,31 +596,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"關閉"</string>
     <string name="nav_bar" msgid="1993221402773877607">"導覽列"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"配置"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"其他向左按鈕類型"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"其他向右按鈕類型"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(預設)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"剪貼簿"</item>
+    <item msgid="5742013440802239414">"按鍵碼"</item>
+    <item msgid="8802889973626281575">"鍵盤切換工具"</item>
+    <item msgid="8175437057325747277">"無"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"一般"</item>
+    <item msgid="8256205964297588988">"精簡"</item>
+    <item msgid="8719936228094005878">"靠左"</item>
+    <item msgid="586019486955594690">"靠右"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"鍵盤切換工具"</string>
     <string name="save" msgid="2311877285724540644">"儲存"</string>
     <string name="reset" msgid="2448168080964209908">"重設"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"調整按鈕寬度"</string>
     <string name="clipboard" msgid="1313879395099896312">"剪貼簿"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"自訂導覽按鈕"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"向左按鍵碼"</string>
+    <string name="right_keycode" msgid="708447961000848163">"向右按鍵碼"</string>
+    <string name="left_icon" msgid="3096287125959387541">"向左圖示"</string>
+    <string name="right_icon" msgid="3952104823293824311">"向右圖示"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"拖曳即可新增圖塊"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"拖曳這裡即可移除"</string>
     <string name="qs_edit" msgid="2232596095725105230">"編輯"</string>
@@ -667,44 +669,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"開啟<xliff:g id="ID_1">%s</xliff:g>設定頁面。"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"編輯設定次序。"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"第 <xliff:g id="ID_1">%1$d</xliff:g> 頁 (共 <xliff:g id="ID_2">%2$d</xliff:g> 頁)"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"螢幕鎖定"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"展開"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"最小化"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"關閉"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"手機溫度正在上升"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"手機降溫時,部分功能會受限制"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"手機會自動嘗試降溫。您仍可以使用手機,但手機的運作速度可能較慢。\n\n手機降溫後便會恢復正常。"</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"向左捷徑"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"向右捷徑"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"向左捷徑亦能將裝置解鎖"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"向右捷徑亦能將裝置解鎖"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"無"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"啟動「<xliff:g id="APP">%1$s</xliff:g>」"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"其他應用程式"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"圓形"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"加號"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"減號"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"向左"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"向右"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"選單"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"「<xliff:g id="APP">%1$s</xliff:g>」應用程式"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"通知"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"螢幕擷取畫面"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"一般訊息"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"儲存空間"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"即時應用程式"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"即時應用程式無需安裝即可使用。"</string>
+    <string name="app_info" msgid="6856026610594615344">"應用程式資料"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 494bd81..9aae1ad 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -158,7 +158,7 @@
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"藍牙網路共用"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"飛行模式。"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"沒有 SIM 卡。"</string>
-    <string name="accessibility_carrier_network_change_mode" msgid="4017301580441304305">"行動通訊業者網路正在變更。"</string>
+    <string name="accessibility_carrier_network_change_mode" msgid="4017301580441304305">"電信業者網路正在變更。"</string>
     <string name="accessibility_battery_details" msgid="7645516654955025422">"開啟電量詳細資料"</string>
     <string name="accessibility_battery_level" msgid="7451474187113371965">"電池電量為百分之 <xliff:g id="NUMBER">%d</xliff:g>。"</string>
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"充電中,已完成百分之 <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>。"</string>
@@ -516,9 +516,11 @@
     <string name="power_notification_controls_description" msgid="4372459941671353358">"只要使用電源通知控制項,您就能為應用程式通知設定從 0 到 5 的重要性等級。\n\n"<b>"等級 5"</b>" \n- 顯示在通知清單頂端 \n- 允許全螢幕通知 \n- 一律允許短暫顯示通知 \n\n"<b>"等級 4"</b>" \n- 禁止全螢幕通知 \n- 一律允許短暫顯示通知 \n\n"<b>"等級 3"</b>" \n- 禁止全螢幕通知 \n- 一律不允許短暫顯示通知 \n\n"<b>"等級 2"</b>" \n- 禁止全螢幕通知 \n- 一律不允許短暫顯示通知 \n- 一律不發出音效或震動 \n\n"<b>"等級 1"</b>" \n- 禁止全螢幕通知 \n- 一律不允許短暫顯示通知 \n- 一律不發出音效或震動 \n- 在鎖定畫面和狀態列中隱藏 \n- 顯示在通知清單底端 \n\n"<b>"等級 0"</b>" \n- 封鎖應用程式的所有通知"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"通知"</string>
     <string name="notification_channel_disabled" msgid="5805874247999578073">"你不會再收到這類通知。"</string>
-    <!-- no translation found for notification_num_channels_desc (8808748716499517938) -->
-    <!-- no translation found for notification_all_categories (5407190218055113282) -->
-    <skip />
+    <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
+      <item quantity="other">1 個類別是來自這個應用程式 (共 <xliff:g id="NUMBER_1">%d</xliff:g> 個類別)</item>
+      <item quantity="one">1 個類別是來自這個應用程式 (共 <xliff:g id="NUMBER_0">%d</xliff:g> 個類別)</item>
+    </plurals>
+    <string name="notification_all_categories" msgid="5407190218055113282">"所有類別"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"更多設定"</string>
     <string name="notification_done" msgid="5279426047273930175">"完成"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -592,31 +594,31 @@
     <string name="switch_bar_off" msgid="8803270596930432874">"關閉"</string>
     <string name="nav_bar" msgid="1993221402773877607">"導覽列"</string>
     <string name="nav_bar_layout" msgid="3664072994198772020">"配置"</string>
-    <!-- no translation found for left_nav_bar_button_type (8555981238887546528) -->
-    <skip />
-    <!-- no translation found for right_nav_bar_button_type (2481056627065649656) -->
-    <skip />
+    <string name="left_nav_bar_button_type" msgid="8555981238887546528">"其他向左按鈕類型"</string>
+    <string name="right_nav_bar_button_type" msgid="2481056627065649656">"其他向右按鈕類型"</string>
     <string name="nav_bar_default" msgid="8587114043070993007">"(預設)"</string>
-    <!-- no translation found for nav_bar_buttons:2 (8802889973626281575) -->
-    <!-- no translation found for nav_bar_layouts:0 (8077901629964902399) -->
-    <!-- no translation found for nav_bar_layouts:1 (8256205964297588988) -->
-    <!-- no translation found for nav_bar_layouts:2 (8719936228094005878) -->
-    <!-- no translation found for nav_bar_layouts:3 (586019486955594690) -->
-    <!-- no translation found for menu_ime (4998010205321292416) -->
-    <skip />
+  <string-array name="nav_bar_buttons">
+    <item msgid="1545641631806817203">"剪貼簿"</item>
+    <item msgid="5742013440802239414">"按鍵碼"</item>
+    <item msgid="8802889973626281575">"鍵盤切換工具"</item>
+    <item msgid="8175437057325747277">"無"</item>
+  </string-array>
+  <string-array name="nav_bar_layouts">
+    <item msgid="8077901629964902399">"一般"</item>
+    <item msgid="8256205964297588988">"精簡"</item>
+    <item msgid="8719936228094005878">"靠左"</item>
+    <item msgid="586019486955594690">"靠右"</item>
+  </string-array>
+    <string name="menu_ime" msgid="4998010205321292416">"鍵盤切換工具"</string>
     <string name="save" msgid="2311877285724540644">"儲存"</string>
     <string name="reset" msgid="2448168080964209908">"重設"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"調整按鈕寬度"</string>
     <string name="clipboard" msgid="1313879395099896312">"剪貼簿"</string>
     <string name="accessibility_key" msgid="5701989859305675896">"自訂導覽按鈕"</string>
-    <!-- no translation found for left_keycode (2010948862498918135) -->
-    <skip />
-    <!-- no translation found for right_keycode (708447961000848163) -->
-    <skip />
-    <!-- no translation found for left_icon (3096287125959387541) -->
-    <skip />
-    <!-- no translation found for right_icon (3952104823293824311) -->
-    <skip />
+    <string name="left_keycode" msgid="2010948862498918135">"向左按鍵碼"</string>
+    <string name="right_keycode" msgid="708447961000848163">"向右按鍵碼"</string>
+    <string name="left_icon" msgid="3096287125959387541">"向左圖示"</string>
+    <string name="right_icon" msgid="3952104823293824311">"向右圖示"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"拖曳即可新增圖塊"</string>
     <string name="drag_to_remove_tiles" msgid="3361212377437088062">"拖曳到這裡即可移除"</string>
     <string name="qs_edit" msgid="2232596095725105230">"編輯"</string>
@@ -665,44 +667,34 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"開啟「<xliff:g id="ID_1">%s</xliff:g>」設定。"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"編輯設定順序。"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"第 <xliff:g id="ID_1">%1$d</xliff:g> 頁,共 <xliff:g id="ID_2">%2$d</xliff:g> 頁"</string>
-    <!-- no translation found for tuner_lock_screen (5755818559638850294) -->
-    <skip />
+    <string name="tuner_lock_screen" msgid="5755818559638850294">"鎖定畫面"</string>
     <string name="pip_phone_expand" msgid="5889780005575693909">"展開"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"最小化"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"關閉"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"手機變熱"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"手機降溫時,部分功能會受限"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"手機會自動嘗試降溫。你仍可繼續使用手機,但是手機的運作速度可能會較慢。\n\n手機降溫完畢後,就會恢復正常的運作速度。"</string>
-    <!-- no translation found for lockscreen_shortcut_left (2182769107618938629) -->
-    <skip />
-    <!-- no translation found for lockscreen_shortcut_right (3328683699505226536) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_left (2043092136246951985) -->
-    <skip />
-    <!-- no translation found for lockscreen_unlock_right (1529992940510318775) -->
-    <skip />
-    <!-- no translation found for lockscreen_none (4783896034844841821) -->
-    <skip />
-    <!-- no translation found for tuner_launch_app (1527264114781925348) -->
-    <skip />
-    <!-- no translation found for tuner_other_apps (4726596850501162493) -->
-    <skip />
-    <!-- no translation found for tuner_circle (2340998864056901350) -->
-    <skip />
-    <!-- no translation found for tuner_plus (6792960658533229675) -->
-    <skip />
-    <!-- no translation found for tuner_minus (4806116839519226809) -->
-    <skip />
-    <!-- no translation found for tuner_left (8404287986475034806) -->
-    <skip />
-    <!-- no translation found for tuner_right (6222734772467850156) -->
-    <skip />
-    <!-- no translation found for tuner_menu (191640047241552081) -->
-    <skip />
-    <!-- no translation found for tuner_app (3507057938640108777) -->
-    <skip />
+    <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"向左快速鍵"</string>
+    <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"向右快速鍵"</string>
+    <string name="lockscreen_unlock_left" msgid="2043092136246951985">"向左快速鍵可一併解鎖裝置"</string>
+    <string name="lockscreen_unlock_right" msgid="1529992940510318775">"向右快速鍵可一併解鎖裝置"</string>
+    <string name="lockscreen_none" msgid="4783896034844841821">"無"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"啟動「<xliff:g id="APP">%1$s</xliff:g>」"</string>
+    <string name="tuner_other_apps" msgid="4726596850501162493">"其他應用程式"</string>
+    <string name="tuner_circle" msgid="2340998864056901350">"圓形"</string>
+    <string name="tuner_plus" msgid="6792960658533229675">"加號"</string>
+    <string name="tuner_minus" msgid="4806116839519226809">"減號"</string>
+    <string name="tuner_left" msgid="8404287986475034806">"向左"</string>
+    <string name="tuner_right" msgid="6222734772467850156">"向右"</string>
+    <string name="tuner_menu" msgid="191640047241552081">"選單"</string>
+    <string name="tuner_app" msgid="3507057938640108777">"「<xliff:g id="APP">%1$s</xliff:g>」應用程式"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"快訊"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"螢幕擷取畫面"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"一般訊息"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"儲存空間"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"免安裝應用程式"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"免安裝應用程式不必安裝就能使用。"</string>
+    <string name="app_info" msgid="6856026610594615344">"應用程式資訊"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index f119c00..c4a448f 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -692,4 +692,9 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Izithombe-skrini"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Imilayezo ejwayelekile"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Isitoreji"</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Izinhlelo zokusebenza ezisheshayo"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Izinhlelo zokusebenza ezisheshayo azidingi ukufakwa."</string>
+    <string name="app_info" msgid="6856026610594615344">"Ulwazi lohlelo lokusebenza"</string>
+    <!-- no translation found for mobile_data (7094582042819250762) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values/arrays_tv.xml b/packages/SystemUI/res/values/arrays_tv.xml
new file mode 100644
index 0000000..e52c5db
--- /dev/null
+++ b/packages/SystemUI/res/values/arrays_tv.xml
@@ -0,0 +1,35 @@
+<?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>
+    <!-- List of package names or class names which are considered as Settings,
+         so PIP location should be adjusted to the left of the side panel.
+         If it should be applied for all activities in a package, add the package name.
+         If it should be applied for an activity in a package, add its class name with package name.
+         The class name must follow format 'package_name/.class_name' ('/.' in between).
+         This can be overriden in an overlay.
+         -->
+    <string-array name="tv_pip_settings_class_name" translatable="false">
+        <item>com.android.tv.settings</item>
+        <item>com.google.android.leanbacklauncher/.settings.HomeScreenSettingsActivity</item>
+        <item>com.google.android.apps.mediashell/.settings.CastSettingsActivity</item>
+        <item>com.google.android.katniss.setting/.SpeechSettingsActivity</item>
+        <item>com.google.android.katniss.setting/.SearchSettingsActivity</item>
+        <item>com.google.android.gsf.notouch/.UsageDiagnosticsSettingActivity</item>
+    </string-array>
+</resources>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 7632f87..f405943 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -50,6 +50,7 @@
             <enum name="small" value="1" />
             <enum name="gone" value="2" />
         </attr>
+        <attr name="showDark" format="boolean" />
     </declare-styleable>
     <attr name="orientation">
         <enum name="horizontal" value="0" />
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 407cddf..f461bb3 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -27,7 +27,6 @@
     <color name="notification_list_shadow_top">#80000000</color>
     <drawable name="heads_up_notification_bg_pressed">#ff33B5E5</drawable>
     <color name="qs_batterymeter_frame_color">#FF404040</color>
-    <color name="system_warning_color">@*android:color/system_error</color>
     <color name="qs_tile_divider">#29ffffff</color><!-- 16% white -->
     <color name="qs_subhead">#99FFFFFF</color><!-- 60% white -->
     <color name="qs_detail_button">@*android:color/quaternary_device_default_settings</color>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 40d4d6f..f331d87 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -179,10 +179,10 @@
     <dimen name="close_handle_underlap">32dp</dimen>
 
     <!-- Height of the status bar header bar -->
-    <dimen name="status_bar_header_height">126dp</dimen>
+    <dimen name="status_bar_header_height">124dp</dimen>
 
     <!-- Height of the status bar header bar when expanded -->
-    <dimen name="status_bar_header_height_expanded">116dp</dimen>
+    <dimen name="status_bar_header_height_expanded">124dp</dimen>
 
     <!-- Height of the status bar header bar when on Keyguard -->
     <dimen name="status_bar_header_height_keyguard">40dp</dimen>
@@ -201,8 +201,7 @@
     <dimen name="volume_dialog_panel_width">@dimen/standard_notification_panel_width</dimen>
 
     <!-- Gravity for the notification panel -->
-    <integer name="standard_notification_panel_layout_gravity">0x31</integer><!-- top|center_horizontal -->
-    <integer name="notification_panel_layout_gravity">0x37</integer><!-- fill_horizontal|top -->
+    <integer name="notification_panel_layout_gravity">0x31</integer><!-- center_horizontal|top -->
 
     <!-- Height of the carrier/wifi name label -->
     <dimen name="carrier_label_height">24dp</dimen>
@@ -239,7 +238,7 @@
     <dimen name="qs_tile_padding_below_icon">12dp</dimen>
     <dimen name="qs_tile_padding_bottom">16dp</dimen>
     <dimen name="qs_tile_spacing">4dp</dimen>
-    <dimen name="qs_panel_padding_bottom">8dp</dimen>
+    <dimen name="qs_panel_padding_bottom">0dp</dimen>
     <dimen name="qs_detail_header_height">56dp</dimen>
     <dimen name="qs_detail_header_padding">0dp</dimen>
     <dimen name="qs_detail_header_bottom_padding">0dp</dimen>
@@ -429,7 +428,7 @@
     <dimen name="multi_user_avatar_keyguard_size">22dp</dimen>
 
     <!-- The width of user avatar when expanded -->
-    <dimen name="multi_user_avatar_expanded_size">24dp</dimen>
+    <dimen name="multi_user_avatar_expanded_size">16dp</dimen>
 
     <!-- The font size of the time when collapsed in QS -->
     <dimen name="qs_time_collapsed_size">14sp</dimen>
@@ -445,8 +444,8 @@
     <!-- Amount the date/time move when emergency calls only is present -->
     <dimen name="qs_date_time_translation">8dp</dimen>
 
-    <!-- Battery level text padding end when in expanded QS and on Keyguard -->
-    <dimen name="battery_level_padding_end">2dp</dimen>
+    <!-- Padding before battery level text in status bar, QS, and Keyguard -->
+    <dimen name="battery_level_padding_start">4dp</dimen>
 
     <!-- The top padding of the clear all button -->
     <dimen name="clear_all_padding_top">12dp</dimen>
@@ -600,8 +599,7 @@
 
     <!-- Volume dialog root view bottom margin, at rest -->
     <dimen name="volume_dialog_margin_bottom">4dp</dimen>
-    <dimen name="volume_dialog_collapsed_padding_top">8dp</dimen>
-    <dimen name="volume_dialog_expanded_spacer">14dp</dimen>
+    <dimen name="volume_dialog_padding_top">8dp</dimen>
     <dimen name="volume_dialog_padding_end">40dp</dimen>
 
     <dimen name="volume_row_padding_bottom">9.4dp</dimen>
@@ -733,4 +731,14 @@
     <!-- The size of the PIP drag-to-dismiss target. -->
     <dimen name="pip_dismiss_target_size">48dp</dimen>
 
+    <!-- The shortest-edge size of the expanded PiP. -->
+    <dimen name="pip_expanded_shortest_edge_size">160dp</dimen>
+
+    <!-- The padding between actions in the PiP in landscape  Note that the PiP does not reflect
+         the configuration of the device, so we can't use -land resources. -->
+    <dimen name="pip_between_action_padding_land">8dp</dimen>
+
+    <dimen name="default_gear_space">18dp</dimen>
+    <dimen name="cell_overlay_padding">18dp</dimen>
+
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 815c41f..93ae763 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1164,6 +1164,8 @@
     <string name="volume_stream_content_description_unmute">%1$s. Tap to unmute.</string>
     <string name="volume_stream_content_description_vibrate">%1$s. Tap to set to vibrate. Accessibility services may be muted.</string>
     <string name="volume_stream_content_description_mute">%1$s. Tap to mute. Accessibility services may be muted.</string>
+    <string name="volume_stream_content_description_vibrate_a11y">%1$s. Tap to set to vibrate.</string>
+    <string name="volume_stream_content_description_mute_a11y">%1$s. Tap to mute.</string>
 
     <string name="volume_dialog_accessibility_shown_message">%s volume controls shown. Swipe up to dismiss.</string>
     <string name="volume_dialog_accessibility_dismissed_message">Volume controls hidden</string>
@@ -1819,4 +1821,7 @@
     <!-- Action label for launching app info on the specified app [CHAR LIMIT=20] -->
     <string name="app_info">App info</string>
 
+    <!-- Quick settings tile for toggling mobile data [CHAR LIMIT=20] -->
+    <string name="mobile_data">Mobile data</string>
+
 </resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 48b7664..9168256 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -30,7 +30,7 @@
 
     <!-- Recents theme -->
     <style name="RecentsTheme.Wallpaper">
-        <item name="android:windowBackground">@color/transparent</item>
+        <item name="android:windowBackground">@*android:color/transparent</item>
         <item name="android:colorBackgroundCacheHint">@null</item>
         <item name="android:windowShowWallpaper">true</item>
         <item name="android:windowDisablePreview">true</item>
@@ -52,7 +52,7 @@
     <!-- Theme used for the activity that shows when the system forced an app to be resizable -->
     <style name="ForcedResizableTheme" parent="@android:style/Theme.Translucent.NoTitleBar">
         <item name="android:windowBackground">@drawable/forced_resizable_background</item>
-        <item name="android:statusBarColor">@color/transparent</item>
+        <item name="android:statusBarColor">@*android:color/transparent</item>
         <item name="android:windowAnimationStyle">@style/Animation.ForcedResizable</item>
     </style>
 
@@ -70,7 +70,7 @@
         <item name="android:windowContentOverlay">@null</item>
         <item name="android:windowBackground">@null</item>
         <item name="android:colorBackgroundCacheHint">@null</item>
-        <item name="android:statusBarColor">@color/transparent</item>
+        <item name="android:statusBarColor">@*android:color/transparent</item>
         <item name="android:windowAnimationStyle">@style/Animation.PipPhoneOverlayControl</item>
     </style>
 
@@ -164,7 +164,7 @@
 
     <style name="TextAppearance.QS.Warning">
         <item name="android:textSize">14sp</item>
-        <item name="android:textColor">@color/system_warning_color</item>
+        <item name="android:textColor">?android:attr/colorError</item>
     </style>
 
     <style name="TextAppearance.QS.DetailButton">
@@ -366,7 +366,7 @@
     </style>
 
     <style name="TextAppearance.NotificationGuts.SecondaryWarning">
-        <item name="android:textColor">@color/system_warning_color</item>
+        <item name="android:textColor">?android:attr/colorError</item>
         <item name="android:textSize">12sp</item>
     </style>
 
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index 85f12b5..bc3edd5 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -121,7 +121,6 @@
 
     </PreferenceScreen>
 
-    <!--
     <PreferenceScreen
       android:key="doze"
       android:title="@string/tuner_doze">
@@ -134,10 +133,9 @@
         <com.android.systemui.tuner.TunerSwitch
           android:key="doze_sensors_wake_up_fully"
           android:title="@string/tuner_doze_sensors_wake_up_fully"
-          sysui:defValue="false" />
+          sysui:defValue="true" />
 
     </PreferenceScreen>
-    -->
 
     <Preference
         android:key="nav_bar"
diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
index 1518bdc..45f1686 100644
--- a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
+++ b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
@@ -89,7 +89,6 @@
 
         setOnClickListener(mListener);
         setOnHoverListener(new LiftToActivateListener(context));
-        setAccessibilityDelegate(new ObscureSpeechDelegate(context));
 
         mEnableHaptics = new LockPatternUtils(context).isTactileFeedbackEnabled();
 
@@ -134,14 +133,6 @@
     }
 
     @Override
-    public void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
-
-        // Reset the "announced headset" flag when detached.
-        ObscureSpeechDelegate.sAnnouncedHeadset = false;
-    }
-
-    @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
         measureChildren(widthMeasureSpec, heightMeasureSpec);
diff --git a/packages/SystemUI/src/com/android/keyguard/ObscureSpeechDelegate.java b/packages/SystemUI/src/com/android/keyguard/ObscureSpeechDelegate.java
deleted file mode 100644
index 410a43a..0000000
--- a/packages/SystemUI/src/com/android/keyguard/ObscureSpeechDelegate.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.keyguard;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.media.AudioManager;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.view.View;
-import android.view.View.AccessibilityDelegate;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityNodeInfo;
-
-import com.android.internal.R;
-
-/**
- * Accessibility delegate that obscures speech for a view when the user has
- * not turned on the "speak passwords" preference and is not listening
- * through headphones.
- */
-class ObscureSpeechDelegate extends AccessibilityDelegate {
-    /** Whether any client has announced the "headset" notification. */
-    static boolean sAnnouncedHeadset = false;
-
-    private final ContentResolver mContentResolver;
-    private final AudioManager mAudioManager;
-
-    public ObscureSpeechDelegate(Context context) {
-        mContentResolver = context.getContentResolver();
-        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
-    }
-
-    @Override
-    public void sendAccessibilityEvent(View host, int eventType) {
-        super.sendAccessibilityEvent(host, eventType);
-
-        // Play the "headset required" announcement the first time the user
-        // places accessibility focus on a key.
-        if ((eventType == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED)
-                && !sAnnouncedHeadset && shouldObscureSpeech()) {
-            sAnnouncedHeadset = true;
-            host.announceForAccessibility(host.getContext().getString(
-                    R.string.keyboard_headset_required_to_hear_password));
-        }
-    }
-
-    @Override
-    public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
-        super.onPopulateAccessibilityEvent(host, event);
-
-        if ((event.getEventType() != AccessibilityEvent.TYPE_ANNOUNCEMENT)
-                && shouldObscureSpeech()) {
-            event.getText().clear();
-            event.setContentDescription(host.getContext().getString(
-                    R.string.keyboard_password_character_no_headset));
-        }
-    }
-
-    @Override
-    public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfo(host, info);
-
-        if (shouldObscureSpeech()) {
-            final Context ctx = host.getContext();
-            info.setText(null);
-            info.setContentDescription(
-                    ctx.getString(R.string.keyboard_password_character_no_headset));
-        }
-    }
-
-    @SuppressWarnings("deprecation")
-    private boolean shouldObscureSpeech() {
-        // The user can optionally force speaking passwords.
-        if (Settings.Secure.getIntForUser(mContentResolver,
-                Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD, 0, UserHandle.USER_CURRENT) != 0) {
-            return false;
-        }
-
-        // Always speak if the user is listening through headphones.
-        if (mAudioManager.isWiredHeadsetOn() || mAudioManager.isBluetoothA2dpOn()) {
-            return false;
-        }
-
-        // Don't speak since this key is used to type a password.
-        return true;
-    }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java b/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
index 48737f9..c43820d 100644
--- a/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
+++ b/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
@@ -40,6 +40,7 @@
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
+import android.widget.EditText;
 
 import java.util.ArrayList;
 import java.util.Stack;
@@ -306,9 +307,6 @@
                                                    int removedCount, int addedCount) {
         if (AccessibilityManager.getInstance(mContext).isEnabled() &&
                 (isFocused() || isSelected() && isShown())) {
-            if (!shouldSpeakPasswordsForAccessibility()) {
-                beforeText = null;
-            }
             AccessibilityEvent event =
                     AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
             event.setFromIndex(fromIndex);
@@ -324,48 +322,22 @@
     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
         super.onInitializeAccessibilityEvent(event);
 
-        event.setClassName(PasswordTextView.class.getName());
+        event.setClassName(EditText.class.getName());
         event.setPassword(true);
     }
 
     @Override
-    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
-        super.onPopulateAccessibilityEvent(event);
-
-        if (shouldSpeakPasswordsForAccessibility()) {
-            final CharSequence text = mText;
-            if (!TextUtils.isEmpty(text)) {
-                event.getText().add(text);
-            }
-        }
-    }
-
-    @Override
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfo(info);
 
         info.setClassName(PasswordTextView.class.getName());
         info.setPassword(true);
 
-        if (shouldSpeakPasswordsForAccessibility()) {
-            info.setText(mText);
-        }
-
         info.setEditable(true);
 
         info.setInputType(InputType.TYPE_NUMBER_VARIATION_PASSWORD);
     }
 
-    /**
-     * @return true if the user has explicitly allowed accessibility services
-     * to speak passwords.
-     */
-    private boolean shouldSpeakPasswordsForAccessibility() {
-        return (Settings.Secure.getIntForUser(mContext.getContentResolver(),
-                Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD, 0,
-                UserHandle.USER_CURRENT_OR_SELF) == 1);
-    }
-
     private class CharState {
         char whichChar;
         ValueAnimator textAnimator;
diff --git a/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java b/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java
index 14c67fe..e58538d 100644
--- a/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java
@@ -17,6 +17,8 @@
 import android.app.PendingIntent;
 import android.content.Intent;
 
+import com.android.systemui.plugins.ActivityStarter;
+
 /**
  * Single common instance of ActivityStarter that can be gotten and referenced from anywhere, but
  * delegates to an actual implementation such as StatusBar, assuming it exists.
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index bda4c95..ee8641b 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -16,7 +16,6 @@
 package com.android.systemui;
 
 import android.content.Context;
-import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Rect;
@@ -27,8 +26,6 @@
 import android.net.Uri;
 import android.os.Handler;
 import android.provider.Settings;
-import android.util.ArraySet;
-import android.util.AttributeSet;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -36,7 +33,6 @@
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 
-import android.widget.LinearLayout;
 import android.widget.TextView;
 import com.android.settingslib.graph.BatteryMeterDrawableBase;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -104,8 +100,8 @@
         updateShowPercent();
     }
 
-    public void forceShowPercent() {
-        mForceShowPercent = true;
+    public void setForceShowPercent(boolean show) {
+        mForceShowPercent = show;
         updateShowPercent();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index f1e7d53..bb7e19d 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -23,10 +23,12 @@
 import android.util.ArrayMap;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.app.NightDisplayController;
 import com.android.internal.util.Preconditions;
 import com.android.systemui.assist.AssistManager;
-import com.android.systemui.fragments.FragmentHostManager;
 import com.android.systemui.fragments.FragmentService;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.PluginDependencyProvider;
 import com.android.systemui.plugins.PluginManager;
 import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
 import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl;
@@ -47,6 +49,8 @@
 import com.android.systemui.statusbar.policy.DataSaverController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl;
+import com.android.systemui.statusbar.policy.ExtensionController;
+import com.android.systemui.statusbar.policy.ExtensionControllerImpl;
 import com.android.systemui.statusbar.policy.FlashlightController;
 import com.android.systemui.statusbar.policy.FlashlightControllerImpl;
 import com.android.systemui.statusbar.policy.HotspotController;
@@ -177,6 +181,9 @@
         mProviders.put(BatteryController.class, () ->
                 new BatteryControllerImpl(mContext));
 
+        mProviders.put(NightDisplayController.class, () ->
+                new NightDisplayController(mContext));
+
         mProviders.put(ManagedProfileController.class, () ->
                 new ManagedProfileControllerImpl(mContext));
 
@@ -233,6 +240,12 @@
         mProviders.put(FragmentService.class, () ->
                 new FragmentService(mContext));
 
+        mProviders.put(ExtensionController.class, () ->
+                new ExtensionControllerImpl());
+
+        mProviders.put(PluginDependencyProvider.class, () ->
+                new PluginDependencyProvider(get(PluginManager.class)));
+
         // Put all dependencies above here so the factory can override them if it wants.
         SystemUIFactory.getInstance().injectDependencies(mProviders, mContext);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index 8141b28..0b0ea720 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -571,6 +571,7 @@
                 public void onAnimationEnd(Animator animation) {
                     if (!mCancelled) {
                         mCallback.setUserExpandedChild(scaledView, expand);
+                        mScaler.setView(null);
                     } else {
                         mCallback.setExpansionCancelled(scaledView);
                     }
@@ -592,6 +593,7 @@
             }
             mCallback.setUserExpandedChild(mResizedView, nowExpanded);
             mCallback.setUserLockedChild(mResizedView, false);
+            mScaler.setView(null);
         }
 
         mExpanding = false;
diff --git a/packages/SystemUI/src/com/android/systemui/Prefs.java b/packages/SystemUI/src/com/android/systemui/Prefs.java
index b9ae585..e1aaaa3 100644
--- a/packages/SystemUI/src/com/android/systemui/Prefs.java
+++ b/packages/SystemUI/src/com/android/systemui/Prefs.java
@@ -47,6 +47,7 @@
         Key.QS_DATA_SAVER_DIALOG_SHOWN,
         Key.QS_INVERT_COLORS_ADDED,
         Key.QS_WORK_ADDED,
+        Key.QS_NIGHTDISPLAY_ADDED,
     })
     public @interface Key {
         @Deprecated
@@ -67,6 +68,7 @@
         String QS_DATA_SAVER_DIALOG_SHOWN = "QsDataSaverDialogShown";
         String QS_INVERT_COLORS_ADDED = "QsInvertColorsAdded";
         String QS_WORK_ADDED = "QsWorkAdded";
+        String QS_NIGHTDISPLAY_ADDED = "QsNightDisplayAdded";
     }
 
     public static boolean getBoolean(Context context, @Key String key, boolean defaultValue) {
diff --git a/packages/SystemUI/src/com/android/systemui/SystemBars.java b/packages/SystemUI/src/com/android/systemui/SystemBars.java
index 6623cabe..b5093b3 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemBars.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemBars.java
@@ -43,13 +43,6 @@
     }
 
     @Override
-    protected void onConfigurationChanged(Configuration newConfig) {
-        if (mStatusBar != null) {
-            mStatusBar.onConfigurationChanged(newConfig);
-        }
-    }
-
-    @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (mStatusBar != null) {
             mStatusBar.dump(fd, pw, args);
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 411fd3d..af7e9b4 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -35,7 +35,7 @@
 import com.android.systemui.statusbar.phone.LockscreenWallpaper;
 import com.android.systemui.statusbar.phone.NotificationIconAreaController;
 import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.statusbar.phone.QSTileHost;
+import com.android.systemui.qs.QSTileHost;
 import com.android.systemui.statusbar.phone.ScrimController;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index b3a0eb7..5d57daa 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -23,7 +23,6 @@
 import android.hardware.SensorManager;
 import android.os.Handler;
 import android.os.PowerManager;
-import android.os.SystemClock;
 
 import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.systemui.SystemUIApplication;
@@ -52,7 +51,10 @@
         DozeFactory.WakeLock wakeLock = new DozeFactory.WakeLock(powerManager.newWakeLock(
                 PowerManager.PARTIAL_WAKE_LOCK, "Doze"));
 
-        DozeMachine machine = new DozeMachine(dozeService, params, wakeLock);
+        DozeMachine machine = new DozeMachine(
+                DozeScreenStatePreventingAdapter.wrapIfNeeded(dozeService, params),
+                params,
+                wakeLock);
         machine.setParts(new DozeMachine.Part[]{
                 createDozeTriggers(context, sensorManager, host, config, params, handler, wakeLock,
                         machine),
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java
new file mode 100644
index 0000000..ad5897a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java
@@ -0,0 +1,66 @@
+/*
+ * 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.doze;
+
+import android.support.annotation.VisibleForTesting;
+import android.view.Display;
+
+import com.android.systemui.statusbar.phone.DozeParameters;
+
+/**
+ * Prevents usage of doze screen states on devices that don't support them.
+ */
+public class DozeScreenStatePreventingAdapter implements DozeMachine.Service {
+
+    private final DozeMachine.Service mInner;
+
+    @VisibleForTesting
+    DozeScreenStatePreventingAdapter(DozeMachine.Service inner) {
+        mInner = inner;
+    }
+
+    @Override
+    public void finish() {
+        mInner.finish();
+    }
+
+    @Override
+    public void setDozeScreenState(int state) {
+        if (state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND) {
+            state = Display.STATE_ON;
+        }
+        mInner.setDozeScreenState(state);
+    }
+
+    @Override
+    public void requestWakeUp() {
+        mInner.requestWakeUp();
+    }
+
+    /**
+     * If the device supports the doze display state, return {@code inner}. Otherwise
+     * return a new instance of {@link DozeScreenStatePreventingAdapter} wrapping {@code inner}.
+     */
+    public static DozeMachine.Service wrapIfNeeded(DozeMachine.Service inner,
+            DozeParameters params) {
+        return isNeeded(params) ? new DozeScreenStatePreventingAdapter(inner) : inner;
+    }
+
+    private static boolean isNeeded(DozeParameters params) {
+        return !params.getDisplayStateSupported();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/InputConsumerController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/InputConsumerController.java
new file mode 100644
index 0000000..7a1849e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/InputConsumerController.java
@@ -0,0 +1,123 @@
+/*
+ * 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.pip.phone;
+
+import static android.view.WindowManager.INPUT_CONSUMER_PIP;
+
+import android.os.Looper;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.InputChannel;
+import android.view.InputEvent;
+import android.view.InputEventReceiver;
+import android.view.IWindowManager;
+import android.view.MotionEvent;
+
+import java.io.PrintWriter;
+
+/**
+ * Manages the input consumer that allows the SystemUI to control the PiP.
+ */
+public class InputConsumerController {
+
+    private static final String TAG = InputConsumerController.class.getSimpleName();
+
+    /**
+     * Listener interface for callers to subscribe to touch events.
+     */
+    public interface TouchListener {
+        boolean onTouchEvent(MotionEvent ev);
+    }
+
+    /**
+     * Input handler used for the PiP input consumer.
+     */
+    private final class PipInputEventReceiver extends InputEventReceiver {
+
+        public PipInputEventReceiver(InputChannel inputChannel, Looper looper) {
+            super(inputChannel, looper);
+        }
+
+        @Override
+        public void onInputEvent(InputEvent event) {
+            boolean handled = true;
+            try {
+                // To be implemented for input handling over Pip windows
+                if (mListener != null && event instanceof MotionEvent) {
+                    MotionEvent ev = (MotionEvent) event;
+                    handled = mListener.onTouchEvent(ev);
+                }
+            } finally {
+                finishInputEvent(event, handled);
+            }
+        }
+    }
+
+    private IWindowManager mWindowManager;
+
+    private PipInputEventReceiver mInputEventReceiver;
+    private TouchListener mListener;
+
+    public InputConsumerController(IWindowManager windowManager) {
+        mWindowManager = windowManager;
+        registerInputConsumer();
+    }
+
+    /**
+     * Sets the touch listener.
+     */
+    public void setTouchListener(TouchListener listener) {
+        mListener = listener;
+    }
+
+    /**
+     * Registers the input consumer.
+     */
+    public void registerInputConsumer() {
+        if (mInputEventReceiver == null) {
+            final InputChannel inputChannel = new InputChannel();
+            try {
+                mWindowManager.destroyInputConsumer(INPUT_CONSUMER_PIP);
+                mWindowManager.createInputConsumer(INPUT_CONSUMER_PIP, inputChannel);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to create PIP input consumer", e);
+            }
+            mInputEventReceiver = new PipInputEventReceiver(inputChannel, Looper.myLooper());
+        }
+    }
+
+    /**
+     * Unregisters the input consumer.
+     */
+    public void unregisterInputConsumer() {
+        if (mInputEventReceiver != null) {
+            try {
+                mWindowManager.destroyInputConsumer(INPUT_CONSUMER_PIP);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to destroy PIP input consumer", e);
+            }
+            mInputEventReceiver.dispose();
+            mInputEventReceiver = null;
+        }
+    }
+
+    public void dump(PrintWriter pw, String prefix) {
+        final String innerPrefix = prefix + "  ";
+        pw.println(prefix + TAG);
+        pw.println(innerPrefix + "registered=" + (mInputEventReceiver != null));
+    }
+}
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 ae402ef..ecc2fad 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -53,6 +53,7 @@
 
     private final PinnedStackListener mPinnedStackListener = new PinnedStackListener();
 
+    private InputConsumerController mInputConsumerController;
     private PipMenuActivityController mMenuController;
     private PipMediaController mMediaController;
     private PipTouchHandler mTouchHandler;
@@ -68,35 +69,28 @@
             }
             mTouchHandler.onActivityPinned();
             mMediaController.onActivityPinned();
+            mMenuController.onActivityPinned();
+        }
+
+        @Override
+        public void onPinnedStackAnimationStarted() {
+            // Disable touches while the animation is running
+            mTouchHandler.setTouchEnabled(false);
         }
 
         @Override
         public void onPinnedStackAnimationEnded() {
-            // TODO(winsonc): Disable touch interaction with the PiP until the animation ends
+            // Re-enable touches after the animation completes
+            mTouchHandler.setTouchEnabled(true);
         }
 
         @Override
-        public void onPinnedActivityRestartAttempt(String launchedFromPackage) {
+        public void onPinnedActivityRestartAttempt() {
             if (!checkCurrentUserId(false /* debug */)) {
                 return;
             }
 
-            // Expand the activity back to fullscreen only if it was attempted to be restarted from
-            // another package than the top activity in the stack
-            boolean expandPipToFullscreen = true;
-            if (launchedFromPackage != null) {
-                ComponentName topActivity = PipUtils.getTopPinnedActivity(mContext,
-                        mActivityManager);
-                if (topActivity != null
-                        && topActivity.getPackageName().equals(launchedFromPackage)) {
-                    expandPipToFullscreen = false;
-                }
-            }
-            if (expandPipToFullscreen) {
-                mTouchHandler.getMotionHelper().expandPip();
-            } else {
-                Log.w(TAG, "Can not expand PiP to fullscreen via intent from the same package.");
-            }
+            mTouchHandler.getMotionHelper().expandPip();
         }
     };
 
@@ -128,9 +122,10 @@
 
         @Override
         public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds,
-                boolean fromImeAdjustement) {
+                Rect animatingBounds, boolean fromImeAdjustement) {
             mHandler.post(() -> {
-                mTouchHandler.onMovementBoundsChanged(insetBounds, normalBounds, fromImeAdjustement);
+                mTouchHandler.onMovementBoundsChanged(insetBounds, normalBounds, animatingBounds,
+                        fromImeAdjustement);
             });
         }
 
@@ -159,11 +154,12 @@
         }
         SystemServicesProxy.getInstance(mContext).registerTaskStackListener(mTaskStackListener);
 
+        mInputConsumerController = new InputConsumerController(mWindowManager);
         mMediaController = new PipMediaController(context, mActivityManager);
-        mMenuController = new PipMenuActivityController(context, mActivityManager, mWindowManager,
-                mMediaController);
-        mTouchHandler = new PipTouchHandler(context, mMenuController, mActivityManager,
-                mWindowManager);
+        mMenuController = new PipMenuActivityController(context, mActivityManager, mMediaController,
+                mInputConsumerController);
+        mTouchHandler = new PipTouchHandler(context, mActivityManager, mMenuController,
+                mInputConsumerController);
     }
 
     /**
@@ -186,6 +182,7 @@
     public void dump(PrintWriter pw) {
         final String innerPrefix = "  ";
         pw.println(TAG);
+        mInputConsumerController.dump(pw, innerPrefix);
         mMenuController.dump(pw, innerPrefix);
         mTouchHandler.dump(pw, innerPrefix);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index 9066977..65de22e 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -26,6 +26,7 @@
 import android.app.RemoteAction;
 import android.content.Intent;
 import android.content.pm.ParceledListSlice;
+import android.graphics.Color;
 import android.graphics.PointF;
 import android.os.Bundle;
 import android.os.Handler;
@@ -39,8 +40,9 @@
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.view.WindowManager.LayoutParams;
+import android.widget.FrameLayout;
 import android.widget.ImageView;
-import android.widget.TextView;
+import android.widget.LinearLayout;
 
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
@@ -56,8 +58,9 @@
     private static final String TAG = "PipMenuActivity";
 
     public static final int MESSAGE_SHOW_MENU = 1;
-    public static final int MESSAGE_HIDE_MENU = 2;
-    public static final int MESSAGE_UPDATE_ACTIONS = 3;
+    public static final int MESSAGE_POKE_MENU = 2;
+    public static final int MESSAGE_HIDE_MENU = 3;
+    public static final int MESSAGE_UPDATE_ACTIONS = 4;
 
     private static final long INITIAL_DISMISS_DELAY = 2000;
     private static final long POST_INTERACTION_DISMISS_DELAY = 1500;
@@ -66,7 +69,9 @@
     private boolean mMenuVisible;
     private final List<RemoteAction> mActions = new ArrayList<>();
     private View mMenuContainer;
+    private LinearLayout mActionsGroup;
     private View mDismissButton;
+    private int mBetweenActionPaddingLand;
 
     private ObjectAnimator mMenuContainerAnimator;
 
@@ -82,6 +87,9 @@
                 case MESSAGE_SHOW_MENU:
                     showMenu();
                     break;
+                case MESSAGE_POKE_MENU:
+                    cancelDelayedFinish();
+                    break;
                 case MESSAGE_HIDE_MENU:
                     hideMenu();
                     break;
@@ -126,6 +134,9 @@
         mDismissButton.setOnClickListener((v) -> {
             dismissPip();
         });
+        mActionsGroup = (LinearLayout) findViewById(R.id.actions_group);
+        mBetweenActionPaddingLand = getResources().getDimensionPixelSize(
+                R.dimen.pip_between_action_padding_land);
 
         notifyActivityCallback(mMessenger);
         showMenu();
@@ -138,6 +149,29 @@
     }
 
     @Override
+    public void onUserInteraction() {
+        repostDelayedFinish(POST_INTERACTION_DISMISS_DELAY);
+    }
+
+    @Override
+    protected void onUserLeaveHint() {
+        super.onUserLeaveHint();
+
+        // If another task is starting on top of the menu, then finish it so that it can be
+        // recreated on the top next time it starts
+        finish();
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+
+        // Fallback, if we are destroyed for any other reason (like when the task is being reset),
+        // also reset the callback.
+        notifyActivityCallback(null);
+    }
+
+    @Override
     public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
         if (!isInPictureInPictureMode) {
             finish();
@@ -145,11 +179,6 @@
     }
 
     @Override
-    public void onUserInteraction() {
-        repostDelayedFinish(POST_INTERACTION_DISMISS_DELAY);
-    }
-
-    @Override
     public boolean dispatchTouchEvent(MotionEvent ev) {
         // On the first action outside the window, hide the menu
         switch (ev.getAction()) {
@@ -158,13 +187,16 @@
                 break;
             case MotionEvent.ACTION_DOWN:
                 mDownPosition.set(ev.getX(), ev.getY());
+                mDownDelta.set(0f, 0f);
                 break;
             case MotionEvent.ACTION_MOVE:
                 mDownDelta.set(ev.getX() - mDownPosition.x, ev.getY() - mDownPosition.y);
                 if (mDownDelta.length() > mViewConfig.getScaledTouchSlop() && mMenuVisible) {
-                    hideMenu();
-                    mMenuVisible = false;
+                    // Restore the input consumer and let that drive the movement of this menu
+                    notifyRegisterInputConsumer();
+                    cancelDelayedFinish();
                 }
+                break;
         }
         return super.dispatchTouchEvent(ev);
     }
@@ -200,17 +232,21 @@
                 }
             });
             mMenuContainerAnimator.start();
+        } else {
+            repostDelayedFinish(POST_INTERACTION_DISMISS_DELAY);
         }
     }
 
     private void hideMenu() {
-        hideMenu(null /* animationFinishedRunnable */);
+        hideMenu(null /* animationFinishedRunnable */, true /* notifyMenuVisibility */);
     }
 
-    private void hideMenu(final Runnable animationFinishedRunnable) {
+    private void hideMenu(final Runnable animationFinishedRunnable, boolean notifyMenuVisibility) {
         if (mMenuVisible) {
             cancelDelayedFinish();
-            notifyMenuVisibility(false);
+            if (notifyMenuVisibility) {
+                notifyMenuVisibility(false);
+            }
             mMenuContainerAnimator = ObjectAnimator.ofFloat(mMenuContainer, View.ALPHA,
                     mMenuContainer.getAlpha(), 0f);
             mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_OUT);
@@ -234,27 +270,32 @@
     }
 
     private void updateActionViews() {
+        ViewGroup expandContainer = (ViewGroup) findViewById(R.id.expand_container);
         ViewGroup actionsContainer = (ViewGroup) findViewById(R.id.actions_container);
         actionsContainer.setOnTouchListener((v, ev) -> {
             // Do nothing, prevent click through to parent
             return true;
         });
 
+        int actionsContainerHeight = 0;
         if (mActions.isEmpty()) {
             actionsContainer.setVisibility(View.INVISIBLE);
         } else {
             actionsContainer.setVisibility(View.VISIBLE);
-            ViewGroup actionsGroup = (ViewGroup) findViewById(R.id.actions);
-            if (actionsGroup != null) {
-                actionsGroup.removeAllViews();
+            if (mActionsGroup != null) {
+                mActionsGroup.removeAllViews();
 
                 // Recreate the layout
+                final View decorView = getWindow().getDecorView();
+                final boolean isLandscapePip = decorView.getMeasuredWidth()
+                        > decorView.getMeasuredHeight();
                 final LayoutInflater inflater = LayoutInflater.from(this);
                 for (int i = 0; i < mActions.size(); i++) {
                     final RemoteAction action = mActions.get(i);
                     final ImageView actionView = (ImageView) inflater.inflate(
-                            R.layout.pip_menu_action, actionsGroup, false);
+                            R.layout.pip_menu_action, mActionsGroup, false);
                     action.getIcon().loadDrawableAsync(this, d -> {
+                        d.setTint(Color.WHITE);
                         actionView.setImageDrawable(d);
                     }, mHandler);
                     actionView.setContentDescription(action.getContentDescription());
@@ -265,10 +306,27 @@
                             Log.w(TAG, "Failed to send action", e);
                         }
                     });
-                    actionsGroup.addView(actionView);
+                    if (isLandscapePip && i > 0) {
+                        LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
+                                actionView.getLayoutParams();
+                        lp.leftMargin = mBetweenActionPaddingLand;
+                    }
+                    mActionsGroup.addView(actionView);
                 }
             }
+            actionsContainerHeight = actionsContainer.getLayoutParams().height;
         }
+
+        // Update the expand container margin to account for the existence of the action container
+        ((FrameLayout.LayoutParams) expandContainer.getLayoutParams()).bottomMargin =
+                actionsContainerHeight;
+        expandContainer.requestLayout();
+    }
+
+    private void notifyRegisterInputConsumer() {
+        Message m = Message.obtain();
+        m.what = PipMenuActivityController.MESSAGE_REGISTER_INPUT_CONSUMER;
+        sendMessage(m, "Could not notify controller to register input consumer");
     }
 
     private void notifyMenuVisibility(boolean visible) {
@@ -280,10 +338,12 @@
     }
 
     private void expandPip() {
+        // Do not notify menu visibility when hiding the menu, the controller will do this when it
+        // handles the message
         hideMenu(() -> {
             sendEmptyMessage(PipMenuActivityController.MESSAGE_EXPAND_PIP,
                     "Could not notify controller to expand PIP");
-        });
+        }, false /* notifyMenuVisibility */);
     }
 
     private void minimizePip() {
@@ -292,10 +352,12 @@
     }
 
     private void dismissPip() {
+        // Do not notify menu visibility when hiding the menu, the controller will do this when it
+        // handles the message
         hideMenu(() -> {
             sendEmptyMessage(PipMenuActivityController.MESSAGE_DISMISS_PIP,
                     "Could not notify controller to dismiss PIP");
-        });
+        }, false /* notifyMenuVisibility */);
     }
 
     private void notifyActivityCallback(Messenger callback) {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
index 91115d0..0b1c3ec 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
@@ -57,6 +57,7 @@
     public static final int MESSAGE_MINIMIZE_PIP = 102;
     public static final int MESSAGE_DISMISS_PIP = 103;
     public static final int MESSAGE_UPDATE_ACTIVITY_CALLBACK = 104;
+    public static final int MESSAGE_REGISTER_INPUT_CONSUMER = 105;
 
     /**
      * A listener interface to receive notification on changes in PIP.
@@ -64,8 +65,11 @@
     public interface Listener {
         /**
          * Called when the PIP menu visibility changes.
+         *
+         * @param menuVisible whether or not the menu is visible
+         * @param resize whether or not to resize the PiP with the visibility change
          */
-        void onPipMenuVisibilityChanged(boolean visible);
+        void onPipMenuVisibilityChanged(boolean menuVisible, boolean resize);
 
         /**
          * Called when the PIP requested to be expanded.
@@ -85,13 +89,13 @@
 
     private Context mContext;
     private IActivityManager mActivityManager;
-    private IWindowManager mWindowManager;
     private PipMediaController mMediaController;
+    private InputConsumerController mInputConsumerController;
 
     private ArrayList<Listener> mListeners = new ArrayList<>();
     private ParceledListSlice mAppActions;
     private ParceledListSlice mMediaActions;
-    private boolean mVisible;
+    private boolean mMenuVisible;
 
     private Messenger mToActivityMessenger;
     private Messenger mMessenger = new Messenger(new Handler() {
@@ -100,13 +104,14 @@
             switch (msg.what) {
                 case MESSAGE_MENU_VISIBILITY_CHANGED: {
                     boolean visible = msg.arg1 > 0;
-                    onMenuVisibilityChanged(visible);
+                    onMenuVisibilityChanged(visible, true /* resize */);
                     break;
                 }
                 case MESSAGE_EXPAND_PIP: {
                     mListeners.forEach(l -> l.onPipExpand());
-                    // Preemptively mark the menu as invisible once we expand the PiP
-                    onMenuVisibilityChanged(false);
+                    // Preemptively mark the menu as invisible once we expand the PiP, but don't
+                    // resize as we will be animating the stack
+                    onMenuVisibilityChanged(false, false /* resize */);
                     break;
                 }
                 case MESSAGE_MINIMIZE_PIP: {
@@ -115,15 +120,20 @@
                 }
                 case MESSAGE_DISMISS_PIP: {
                     mListeners.forEach(l -> l.onPipDismiss());
-                    // Preemptively mark the menu as invisible once we dismiss the PiP
-                    onMenuVisibilityChanged(false);
+                    // Preemptively mark the menu as invisible once we dismiss the PiP, but don't
+                    // resize as we'll be removing the stack in place
+                    onMenuVisibilityChanged(false, false /* resize */);
+                    break;
+                }
+                case MESSAGE_REGISTER_INPUT_CONSUMER: {
+                    mInputConsumerController.registerInputConsumer();
                     break;
                 }
                 case MESSAGE_UPDATE_ACTIVITY_CALLBACK: {
                     mToActivityMessenger = msg.replyTo;
                     // Mark the menu as invisible once the activity finishes as well
                     if (mToActivityMessenger == null) {
-                        onMenuVisibilityChanged(false);
+                        onMenuVisibilityChanged(false, true /* resize */);
                     }
                     break;
                 }
@@ -140,11 +150,19 @@
     };
 
     public PipMenuActivityController(Context context, IActivityManager activityManager,
-            IWindowManager windowManager, PipMediaController mediaController) {
+            PipMediaController mediaController, InputConsumerController inputConsumerController) {
         mContext = context;
         mActivityManager = activityManager;
-        mWindowManager = windowManager;
         mMediaController = mediaController;
+        mInputConsumerController = inputConsumerController;
+    }
+
+    public void onActivityPinned() {
+        if (!mMenuVisible) {
+            // If the menu is not visible, then re-register the input consumer if it is not already
+            // registered
+            mInputConsumerController.registerInputConsumer();
+        }
     }
 
     /**
@@ -192,6 +210,21 @@
     }
 
     /**
+     * Pokes the menu, indicating that the user is interacting with it.
+     */
+    public void pokeMenu() {
+        if (mToActivityMessenger != null) {
+            Message m = Message.obtain();
+            m.what = PipMenuActivity.MESSAGE_POKE_MENU;
+            try {
+                mToActivityMessenger.send(m);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Could not notify poke menu", e);
+            }
+        }
+    }
+
+    /**
      * Hides the menu activity.
      */
     public void hideMenu() {
@@ -207,6 +240,13 @@
     }
 
     /**
+     * @return whether the menu is currently visible.
+     */
+    public boolean isMenuVisible() {
+        return mMenuVisible;
+    }
+
+    /**
      * Sets the menu actions to the actions provided by the current PiP activity.
      */
     public void setAppActions(ParceledListSlice appActions) {
@@ -250,9 +290,14 @@
     /**
      * Handles changes in menu visibility.
      */
-    private void onMenuVisibilityChanged(boolean visible) {
-        mListeners.forEach(l -> l.onPipMenuVisibilityChanged(visible));
-        if (visible != mVisible) {
+    private void onMenuVisibilityChanged(boolean visible, boolean resize) {
+        if (visible) {
+            mInputConsumerController.unregisterInputConsumer();
+        } else {
+            mInputConsumerController.registerInputConsumer();
+        }
+        if (visible != mMenuVisible) {
+            mListeners.forEach(l -> l.onPipMenuVisibilityChanged(visible, resize));
             if (visible) {
                 // Once visible, start listening for media action changes. This call will trigger
                 // the menu actions to be updated again.
@@ -263,13 +308,13 @@
                 mMediaController.removeListener(mMediaActionListener);
             }
         }
-        mVisible = visible;
+        mMenuVisible = visible;
     }
 
     public void dump(PrintWriter pw, String prefix) {
         final String innerPrefix = prefix + "  ";
         pw.println(prefix + TAG);
-        pw.println(innerPrefix + "mVisible=" + mVisible);
+        pw.println(innerPrefix + "mMenuVisible=" + mMenuVisible);
         pw.println(innerPrefix + "mListeners=" + mListeners.size());
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
index ed0a37f..20c1136 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
@@ -57,10 +57,11 @@
     private static final int DEFAULT_MOVE_STACK_DURATION = 225;
     private static final int SNAP_STACK_DURATION = 225;
     private static final int DISMISS_STACK_DURATION = 375;
-    private static final int SHRINK_STACK_FROM_MENU_DURATION = 175;
-    private static final int EXPAND_STACK_TO_MENU_DURATION = 175;
-    private static final int EXPAND_STACK_TO_FULLSCREEN_DURATION = 225;
+    private static final int SHRINK_STACK_FROM_MENU_DURATION = 250;
+    private static final int EXPAND_STACK_TO_MENU_DURATION = 250;
+    private static final int EXPAND_STACK_TO_FULLSCREEN_DURATION = 300;
     private static final int MINIMIZE_STACK_MAX_DURATION = 200;
+    private static final int IME_SHIFT_DURATION = 300;
 
     // The fraction of the stack width that the user has to drag offscreen to minimize the PiP
     private static final float MINIMIZE_OFFSCREEN_FRACTION = 0.2f;
@@ -217,19 +218,12 @@
     /**
      * Animates the PiP to the minimized state, slightly offscreen.
      */
-    Rect animateToClosestMinimizedState(Rect movementBounds,
-            final PipMenuActivityController menuController) {
+    Rect animateToClosestMinimizedState(Rect movementBounds) {
         cancelAnimations();
         Rect toBounds = getClosestMinimizedBounds(mBounds, movementBounds);
         if (!mBounds.equals(toBounds)) {
             mBoundsAnimator = createAnimationToBounds(mBounds, toBounds,
                     MINIMIZE_STACK_MAX_DURATION, LINEAR_OUT_SLOW_IN, mUpdateBoundsListener);
-            mBoundsAnimator.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationStart(Animator animation) {
-                    menuController.hideMenu();
-                }
-            });
             mBoundsAnimator.start();
         }
         return toBounds;
@@ -274,9 +268,7 @@
             Rect expandedMovementBounds) {
         float savedSnapFraction = mSnapAlgorithm.getSnapFraction(new Rect(mBounds), movementBounds);
         mSnapAlgorithm.applySnapFraction(expandedBounds, expandedMovementBounds, savedSnapFraction);
-        mBoundsAnimator = createAnimationToBounds(mBounds, expandedBounds,
-                EXPAND_STACK_TO_MENU_DURATION, FAST_OUT_SLOW_IN, mUpdateBoundsListener);
-        mBoundsAnimator.start();
+        resizeAndAnimatePipUnchecked(expandedBounds, EXPAND_STACK_TO_MENU_DURATION);
         return savedSnapFraction;
     }
 
@@ -284,15 +276,25 @@
      * Animates the PiP from the expanded state to the normal state after the menu is hidden.
      */
     void animateToUnexpandedState(Rect normalBounds, float savedSnapFraction,
-            Rect normalMovementBounds) {
-        if (savedSnapFraction >= 0f) {
-            mSnapAlgorithm.applySnapFraction(normalBounds, normalMovementBounds, savedSnapFraction);
-            mBoundsAnimator = createAnimationToBounds(mBounds, normalBounds,
-                    SHRINK_STACK_FROM_MENU_DURATION, FAST_OUT_SLOW_IN, mUpdateBoundsListener);
-            mBoundsAnimator.start();
-        } else {
-            animateToClosestSnapTarget(normalMovementBounds);
+            Rect normalMovementBounds, Rect currentMovementBounds, boolean minimized) {
+        if (savedSnapFraction < 0f) {
+            // If there are no saved snap fractions, then just use the current bounds
+            savedSnapFraction = mSnapAlgorithm.getSnapFraction(new Rect(mBounds),
+                    currentMovementBounds);
         }
+        mSnapAlgorithm.applySnapFraction(normalBounds, normalMovementBounds, savedSnapFraction);
+        if (minimized) {
+            normalBounds = getClosestMinimizedBounds(normalBounds, normalMovementBounds);
+        }
+        resizeAndAnimatePipUnchecked(normalBounds, SHRINK_STACK_FROM_MENU_DURATION);
+    }
+
+    /**
+     * Animates the PiP to offset it from the IME.
+     */
+    void animateToIMEOffset(Rect toBounds) {
+        cancelAnimations();
+        resizeAndAnimatePipUnchecked(toBounds, IME_SHIFT_DURATION);
     }
 
     /**
@@ -317,18 +319,6 @@
     }
 
     /**
-     * Animates the PiP to some given bounds.
-     */
-    void animateToBounds(Rect toBounds) {
-        cancelAnimations();
-        if (!mBounds.equals(toBounds)) {
-            mBoundsAnimator = createAnimationToBounds(mBounds, toBounds,
-                    DEFAULT_MOVE_STACK_DURATION, FAST_OUT_LINEAR_IN, mUpdateBoundsListener);
-            mBoundsAnimator.start();
-        }
-    }
-
-    /**
      * Cancels all existing animations.
      */
     void cancelAnimations() {
@@ -365,7 +355,32 @@
                     mActivityManager.resizePinnedStack(toBounds, null /* tempPinnedTaskBounds */);
                     mBounds.set(toBounds);
                 } catch (RemoteException e) {
-                    Log.e(TAG, "Could not move pinned stack to bounds: " + toBounds, e);
+                    Log.e(TAG, "Could not resize pinned stack to bounds: " + toBounds, e);
+                }
+            });
+        }
+    }
+
+    /**
+     * Directly resizes the PiP to the given {@param bounds}.
+     */
+    private void resizeAndAnimatePipUnchecked(Rect toBounds, int duration) {
+        if (!toBounds.equals(mBounds)) {
+            mHandler.post(() -> {
+                try {
+                    StackInfo stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
+                    if (stackInfo == null) {
+                        // In the case where we've already re-expanded or dismissed the PiP, then
+                        // just skip the resize
+                        return;
+                    }
+
+                    mActivityManager.resizeStack(PINNED_STACK_ID, toBounds,
+                            false /* allowResizeInDockedMode */, true /* preserveWindows */,
+                            true /* animate */, duration);
+                    mBounds.set(toBounds);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Could not animate resize pinned stack to bounds: " + toBounds, e);
                 }
             });
         }
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 d832810..010522d 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -16,27 +16,24 @@
 
 package com.android.systemui.pip.phone;
 
-import static android.view.WindowManager.INPUT_CONSUMER_PIP;
-
 import android.app.IActivityManager;
 import android.content.Context;
+import android.graphics.Point;
 import android.graphics.PointF;
 import android.graphics.Rect;
 import android.os.Handler;
-import android.os.Looper;
 import android.os.RemoteException;
 import android.util.Log;
+import android.util.Size;
 import android.view.IPinnedStackController;
 import android.view.IWindowManager;
-import android.view.InputChannel;
-import android.view.InputEvent;
-import android.view.InputEventReceiver;
 import android.view.MotionEvent;
 import android.view.ViewConfiguration;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.policy.PipSnapAlgorithm;
+import com.android.systemui.R;
 import com.android.systemui.statusbar.FlingAnimationUtils;
 
 import java.io.PrintWriter;
@@ -59,12 +56,10 @@
 
     private final Context mContext;
     private final IActivityManager mActivityManager;
-    private final IWindowManager mWindowManager;
     private final ViewConfiguration mViewConfig;
     private final PipMenuListener mMenuListener = new PipMenuListener();
     private IPinnedStackController mPinnedStackController;
 
-    private PipInputEventReceiver mInputEventReceiver;
     private final PipMenuActivityController mMenuController;
     private final PipDismissViewController mDismissViewController;
     private final PipSnapAlgorithm mSnapAlgorithm;
@@ -77,6 +72,7 @@
     private Rect mNormalMovementBounds = new Rect();
     private Rect mExpandedBounds = new Rect();
     private Rect mExpandedMovementBounds = new Rect();
+    private int mExpandedShortestEdgeSize;
 
     private Handler mHandler = new Handler();
     private Runnable mShowDismissAffordance = new Runnable() {
@@ -89,9 +85,8 @@
     };
 
     // Behaviour states
-    private boolean mIsTappingThrough;
-    private boolean mIsMinimized;
     private boolean mIsMenuVisible;
+    private boolean mIsMinimized;
     private boolean mIsImeShowing;
     private int mImeHeight;
     private float mSavedSnapFraction = -1f;
@@ -106,36 +101,12 @@
     private final Rect mTmpBounds = new Rect();
 
     /**
-     * Input handler used for Pip windows.
-     */
-    private final class PipInputEventReceiver extends InputEventReceiver {
-
-        public PipInputEventReceiver(InputChannel inputChannel, Looper looper) {
-            super(inputChannel, looper);
-        }
-
-        @Override
-        public void onInputEvent(InputEvent event) {
-            boolean handled = true;
-            try {
-                // To be implemented for input handling over Pip windows
-                if (event instanceof MotionEvent) {
-                    MotionEvent ev = (MotionEvent) event;
-                    handled = handleTouchEvent(ev);
-                }
-            } finally {
-                finishInputEvent(event, handled);
-            }
-        }
-    }
-
-    /**
      * A listener for the PIP menu activity.
      */
     private class PipMenuListener implements PipMenuActivityController.Listener {
         @Override
-        public void onPipMenuVisibilityChanged(boolean visible) {
-            setMenuVisibilityState(visible);
+        public void onPipMenuVisibilityChanged(boolean menuVisible, boolean resize) {
+            setMenuVisibilityState(menuVisible, resize);
         }
 
         @Override
@@ -148,7 +119,7 @@
         @Override
         public void onPipMinimize() {
             setMinimizedStateInternal(true);
-            mMotionHelper.animateToClosestMinimizedState(mMovementBounds, mMenuController);
+            mMotionHelper.animateToClosestMinimizedState(mMovementBounds);
         }
 
         @Override
@@ -159,13 +130,13 @@
         }
     }
 
-    public PipTouchHandler(Context context, PipMenuActivityController menuController,
-            IActivityManager activityManager, IWindowManager windowManager) {
+    public PipTouchHandler(Context context, IActivityManager activityManager,
+            PipMenuActivityController menuController,
+            InputConsumerController inputConsumerController) {
 
         // Initialize the Pip input consumer
         mContext = context;
         mActivityManager = activityManager;
-        mWindowManager = windowManager;
         mViewConfig = ViewConfiguration.get(context);
         mMenuController = menuController;
         mMenuController.addListener(mMenuListener);
@@ -178,14 +149,21 @@
         };
         mMotionHelper = new PipMotionHelper(mContext, mActivityManager, mSnapAlgorithm,
                 mFlingAnimationUtils);
-        registerInputConsumer();
+        mExpandedShortestEdgeSize = context.getResources().getDimensionPixelSize(
+                R.dimen.pip_expanded_shortest_edge_size);
+
+        // Register the listener for input consumer touch events
+        inputConsumerController.setTouchListener(this::handleTouchEvent);
+    }
+
+    public void setTouchEnabled(boolean enabled) {
+        mTouchState.setAllowTouches(enabled);
     }
 
     public void onActivityPinned() {
         // Reset some states once we are pinned
-        if (mIsTappingThrough) {
-            mIsTappingThrough = false;
-            registerInputConsumer();
+        if (mIsMenuVisible) {
+            mIsMenuVisible = false;
         }
         if (mIsMinimized) {
             setMinimizedStateInternal(false);
@@ -202,15 +180,21 @@
         mImeHeight = imeHeight;
     }
 
-    public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds,
+    public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds, Rect animatingBounds,
             boolean fromImeAdjustement) {
         // Re-calculate the expanded bounds
         mNormalBounds = normalBounds;
         Rect normalMovementBounds = new Rect();
         mSnapAlgorithm.getMovementBounds(mNormalBounds, insetBounds, normalMovementBounds,
                 mIsImeShowing ? mImeHeight : 0);
-        // TODO: Figure out the expanded size policy
-        mExpandedBounds = new Rect(normalBounds);
+
+        // Calculate the expanded size
+        float aspectRatio = (float) normalBounds.width() / normalBounds.height();
+        Point displaySize = new Point();
+        mContext.getDisplay().getRealSize(displaySize);
+        Size expandedSize = mSnapAlgorithm.getSizeForAspectRatio(aspectRatio,
+                mExpandedShortestEdgeSize, displaySize.x, displaySize.y);
+        mExpandedBounds.set(0, 0, expandedSize.getWidth(), expandedSize.getHeight());
         Rect expandedMovementBounds = new Rect();
         mSnapAlgorithm.getMovementBounds(mExpandedBounds, insetBounds, expandedMovementBounds,
                 mIsImeShowing ? mImeHeight : 0);
@@ -223,7 +207,7 @@
                 // Defer the update of the current movement bounds until after the user finishes
                 // touching the screen
             } else {
-                final Rect bounds = new Rect(mMotionHelper.getBounds());
+                final Rect bounds = new Rect(animatingBounds);
                 final Rect toMovementBounds = mIsMenuVisible
                         ? expandedMovementBounds
                         : normalMovementBounds;
@@ -243,7 +227,7 @@
                         bounds.offsetTo(bounds.left, toMovementBounds.bottom);
                     }
                 }
-                mMotionHelper.animateToBounds(bounds);
+                mMotionHelper.animateToIMEOffset(bounds);
             }
         }
 
@@ -251,7 +235,7 @@
         // above
         mNormalMovementBounds = normalMovementBounds;
         mExpandedMovementBounds = expandedMovementBounds;
-        updateMovementBounds();
+        updateMovementBounds(mIsMenuVisible);
     }
 
     private boolean handleTouchEvent(MotionEvent ev) {
@@ -283,7 +267,7 @@
             case MotionEvent.ACTION_UP: {
                 // Update the movement bounds again if the state has changed since the user started
                 // dragging (ie. when the IME shows)
-                updateMovementBounds();
+                updateMovementBounds(mIsMenuVisible);
 
                 for (PipTouchGesture gesture : mGestures) {
                     if (gesture.onUp(mTouchState)) {
@@ -294,41 +278,11 @@
                 // Fall through to clean up
             }
             case MotionEvent.ACTION_CANCEL: {
+                mTouchState.reset();
                 break;
             }
         }
-        return !mIsTappingThrough;
-    }
-
-    /**
-     * Registers the input consumer.
-     */
-    private void registerInputConsumer() {
-        if (mInputEventReceiver == null) {
-            final InputChannel inputChannel = new InputChannel();
-            try {
-                mWindowManager.destroyInputConsumer(INPUT_CONSUMER_PIP);
-                mWindowManager.createInputConsumer(INPUT_CONSUMER_PIP, inputChannel);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to create PIP input consumer", e);
-            }
-            mInputEventReceiver = new PipInputEventReceiver(inputChannel, Looper.myLooper());
-        }
-    }
-
-    /**
-     * Unregisters the input consumer.
-     */
-    private void unregisterInputConsumer() {
-        if (mInputEventReceiver != null) {
-            try {
-                mWindowManager.destroyInputConsumer(INPUT_CONSUMER_PIP);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to destroy PIP input consumer", e);
-            }
-            mInputEventReceiver.dispose();
-            mInputEventReceiver = null;
-        }
+        return !mIsMenuVisible;
     }
 
     /**
@@ -374,34 +328,30 @@
     /**
      * Sets the menu visibility.
      */
-    void setMenuVisibilityState(boolean isMenuVisible) {
-        if (!isMenuVisible) {
-            mIsTappingThrough = false;
-            registerInputConsumer();
-        } else {
-            unregisterInputConsumer();
-        }
-        MetricsLogger.visibility(mContext, MetricsEvent.ACTION_PICTURE_IN_PICTURE_MENU,
-                isMenuVisible);
-
-        if (isMenuVisible != mIsMenuVisible) {
-            if (isMenuVisible) {
-                // Save the current snap fraction and if we do not drag or move the PiP, then
-                // we store back to this snap fraction.  Otherwise, we'll reset the snap
-                // fraction and snap to the closest edge
-                Rect expandedBounds = new Rect(mExpandedBounds);
+    void setMenuVisibilityState(boolean menuVisible, boolean resize) {
+        if (menuVisible) {
+            // Save the current snap fraction and if we do not drag or move the PiP, then
+            // we store back to this snap fraction.  Otherwise, we'll reset the snap
+            // fraction and snap to the closest edge
+            Rect expandedBounds = new Rect(mExpandedBounds);
+            if (resize) {
                 mSavedSnapFraction = mMotionHelper.animateToExpandedState(expandedBounds,
                         mMovementBounds, mExpandedMovementBounds);
-            } else {
-                // Try and restore the PiP to the closest edge, using the saved snap fraction
-                // if possible
+            }
+        } else {
+            // Try and restore the PiP to the closest edge, using the saved snap fraction
+            // if possible
+            if (resize) {
                 Rect normalBounds = new Rect(mNormalBounds);
                 mMotionHelper.animateToUnexpandedState(normalBounds, mSavedSnapFraction,
-                        mNormalMovementBounds);
+                        mNormalMovementBounds, mMovementBounds, mIsMinimized);
             }
-            mIsMenuVisible = isMenuVisible;
-            updateMovementBounds();
+            mSavedSnapFraction = -1f;
         }
+        mIsMenuVisible = menuVisible;
+        updateMovementBounds(menuVisible);
+        MetricsLogger.visibility(mContext, MetricsEvent.ACTION_PICTURE_IN_PICTURE_MENU,
+                menuVisible);
     }
 
     /**
@@ -418,6 +368,16 @@
 
         @Override
         public void onDown(PipTouchState touchState) {
+            if (!touchState.isUserInteracting()) {
+                return;
+            }
+
+            // If the menu is still visible, and we aren't minimized, then just poke the menu
+            // so that it will timeout after the user stops touching it
+            if (mMenuController.isMenuVisible() && !mIsMinimized) {
+                mMenuController.pokeMenu();
+            }
+
             if (ENABLE_DRAG_TO_DISMISS) {
                 mDismissViewController.createDismissTarget();
                 mHandler.postDelayed(mShowDismissAffordance, SHOW_DISMISS_AFFORDANCE_DELAY);
@@ -426,6 +386,10 @@
 
         @Override
         boolean onMove(PipTouchState touchState) {
+            if (!touchState.isUserInteracting()) {
+                return false;
+            }
+
             if (touchState.startedDragging()) {
                 mSavedSnapFraction = -1f;
             }
@@ -458,6 +422,10 @@
 
         @Override
         public boolean onUp(PipTouchState touchState) {
+            if (!touchState.isUserInteracting()) {
+                return false;
+            }
+
             try {
                 if (ENABLE_DRAG_TO_DISMISS) {
                     mHandler.removeCallbacks(mShowDismissAffordance);
@@ -478,21 +446,35 @@
             } finally {
                 mDismissViewController.destroyDismissTarget();
             }
+
             if (touchState.isDragging()) {
                 PointF vel = mTouchState.getVelocity();
                 if (!mIsMinimized && (mMotionHelper.shouldMinimizePip()
                         || isHorizontalFlingTowardsCurrentEdge(vel))) {
                     // Pip should be minimized
                     setMinimizedStateInternal(true);
-                    mMotionHelper.animateToClosestMinimizedState(mMovementBounds, mMenuController);
+                    if (mMenuController.isMenuVisible()) {
+                        // If the user dragged the expanded PiP to the edge, then hiding the menu
+                        // will trigger the PiP to be scaled back to the normal size with the
+                        // minimize offset adjusted
+                        mMenuController.hideMenu();
+                    } else {
+                        mMotionHelper.animateToClosestMinimizedState(mMovementBounds);
+                    }
                     return true;
                 }
                 if (mIsMinimized) {
-                    // If we're dragging and it wasn't a minimize gesture
-                    // then we shouldn't be minimized.
+                    // If we're dragging and it wasn't a minimize gesture then we shouldn't be
+                    // minimized.
                     setMinimizedStateInternal(false);
                 }
 
+                // If the menu is still visible, and we aren't minimized, then just poke the menu
+                // so that it will timeout after the user stops touching it
+                if (mMenuController.isMenuVisible()) {
+                    mMenuController.showMenu();
+                }
+
                 final float velocity = PointF.length(vel.x, vel.y);
                 if (velocity > mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
                     mMotionHelper.flingToSnapTarget(velocity, vel.x, vel.y, mMovementBounds);
@@ -503,9 +485,8 @@
                 // This was a tap, so no longer minimized
                 mMotionHelper.animateToClosestSnapTarget(mMovementBounds);
                 setMinimizedStateInternal(false);
-            } else if (!mIsTappingThrough) {
+            } else if (!mIsMenuVisible) {
                 mMenuController.showMenu();
-                mIsTappingThrough = true;
             } else {
                 mMotionHelper.expandPip();
             }
@@ -542,8 +523,8 @@
     /**
      * Updates the current movement bounds based on whether the menu is currently visible.
      */
-    private void updateMovementBounds() {
-        mMovementBounds = mIsMenuVisible
+    private void updateMovementBounds(boolean isExpanded) {
+        mMovementBounds = isExpanded
                 ? mExpandedMovementBounds
                 : mNormalMovementBounds;
     }
@@ -556,9 +537,8 @@
         pw.println(innerPrefix + "mNormalMovementBounds=" + mNormalMovementBounds);
         pw.println(innerPrefix + "mExpandedBounds=" + mExpandedBounds);
         pw.println(innerPrefix + "mExpandedMovementBounds=" + mExpandedMovementBounds);
-        pw.println(innerPrefix + "mIsTappingThrough=" + mIsTappingThrough);
-        pw.println(innerPrefix + "mIsMinimized=" + mIsMinimized);
         pw.println(innerPrefix + "mIsMenuVisible=" + mIsMenuVisible);
+        pw.println(innerPrefix + "mIsMinimized=" + mIsMinimized);
         pw.println(innerPrefix + "mIsImeShowing=" + mIsImeShowing);
         pw.println(innerPrefix + "mImeHeight=" + mImeHeight);
         pw.println(innerPrefix + "mSavedSnapFraction=" + mSavedSnapFraction);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
index 702ad0a..a317dc3 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
@@ -37,6 +37,7 @@
     private final PointF mLastTouch = new PointF();
     private final PointF mLastDelta = new PointF();
     private final PointF mVelocity = new PointF();
+    private boolean mAllowTouches = true;
     private boolean mIsUserInteracting = false;
     private boolean mIsDragging = false;
     private boolean mStartedDragging = false;
@@ -48,23 +49,41 @@
     }
 
     /**
+     * Resets this state.
+     */
+    public void reset() {
+        mAllowDraggingOffscreen = false;
+        mIsDragging = false;
+        mStartedDragging = false;
+        mIsUserInteracting = false;
+    }
+
+    /**
      * Processess a given touch event and updates the state.
      */
     public void onTouchEvent(MotionEvent ev) {
         switch (ev.getAction()) {
             case MotionEvent.ACTION_DOWN: {
+                if (!mAllowTouches) {
+                    return;
+                }
+
                 // Initialize the velocity tracker
                 initOrResetVelocityTracker();
+
                 mActivePointerId = ev.getPointerId(0);
                 mLastTouch.set(ev.getX(), ev.getY());
                 mDownTouch.set(mLastTouch);
-                mIsDragging = false;
-                mStartedDragging = false;
                 mAllowDraggingOffscreen = true;
                 mIsUserInteracting = true;
                 break;
             }
             case MotionEvent.ACTION_MOVE: {
+                // Skip event if we did not start processing this touch gesture
+                if (!mIsUserInteracting) {
+                    break;
+                }
+
                 // Update the velocity tracker
                 mVelocityTracker.addMovement(ev);
                 int pointerIndex = ev.findPointerIndex(mActivePointerId);
@@ -86,6 +105,11 @@
                 break;
             }
             case MotionEvent.ACTION_POINTER_UP: {
+                // Skip event if we did not start processing this touch gesture
+                if (!mIsUserInteracting) {
+                    break;
+                }
+
                 // Update the velocity tracker
                 mVelocityTracker.addMovement(ev);
 
@@ -100,6 +124,11 @@
                 break;
             }
             case MotionEvent.ACTION_UP: {
+                // Skip event if we did not start processing this touch gesture
+                if (!mIsUserInteracting) {
+                    break;
+                }
+
                 // Update the velocity tracker
                 mVelocityTracker.addMovement(ev);
                 mVelocityTracker.computeCurrentVelocity(1000,
@@ -112,7 +141,6 @@
                 // Fall through to clean up
             }
             case MotionEvent.ACTION_CANCEL: {
-                mIsUserInteracting = false;
                 recycleVelocityTracker();
                 break;
             }
@@ -171,6 +199,19 @@
     }
 
     /**
+     * Sets whether touching is currently allowed.
+     */
+    public void setAllowTouches(boolean allowTouches) {
+        mAllowTouches = allowTouches;
+
+        // If the user happens to touch down before this is sent from the system during a transition
+        // then block any additional handling by resetting the state now
+        if (mIsUserInteracting) {
+            reset();
+        }
+    }
+
+    /**
      * Disallows dragging offscreen for the duration of the current gesture.
      */
     public void setDisallowDraggingOffscreen() {
@@ -202,6 +243,7 @@
     public void dump(PrintWriter pw, String prefix) {
         final String innerPrefix = prefix + "  ";
         pw.println(prefix + TAG);
+        pw.println(innerPrefix + "mAllowTouches=" + mAllowTouches);
         pw.println(innerPrefix + "mDownTouch=" + mDownTouch);
         pw.println(innerPrefix + "mDownDelta=" + mDownDelta);
         pw.println(innerPrefix + "mLastTouch=" + mLastTouch);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index 376a0b6..9a8974d 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -68,34 +68,10 @@
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
     private static final boolean DEBUG_FORCE_ONBOARDING =
             SystemProperties.getBoolean("debug.tv.pip_force_onboarding", false);
+    private static final String SETTINGS_PACKAGE_AND_CLASS_DELIMITER = "/";
 
     private static PipManager sPipManager;
-
-    /**
-     * List of package and class name which are considered as Settings,
-     * so PIP location should be adjusted to the left of the side panel.
-     */
-    private static final List<Pair<String, String>> sSettingsPackageAndClassNamePairList;
-    static {
-        sSettingsPackageAndClassNamePairList = new ArrayList<>();
-        sSettingsPackageAndClassNamePairList.add(new Pair<String, String>(
-                "com.android.tv.settings", null));
-        sSettingsPackageAndClassNamePairList.add(new Pair<String, String>(
-                "com.google.android.leanbacklauncher",
-                "com.google.android.leanbacklauncher.settings.HomeScreenSettingsActivity"));
-        sSettingsPackageAndClassNamePairList.add(new Pair<String, String>(
-                "com.google.android.apps.mediashell",
-                "com.google.android.apps.mediashell.settings.CastSettingsActivity"));
-        sSettingsPackageAndClassNamePairList.add(new Pair<String, String>(
-                "com.google.android.katniss",
-                "com.google.android.katniss.setting.SpeechSettingsActivity"));
-        sSettingsPackageAndClassNamePairList.add(new Pair<String, String>(
-                "com.google.android.katniss",
-                "com.google.android.katniss.setting.SearchSettingsActivity"));
-        sSettingsPackageAndClassNamePairList.add(new Pair<String, String>(
-                "com.google.android.gsf.notouch",
-                "com.google.android.gsf.notouch.UsageDiagnosticsSettingActivity"));
-    }
+    private static List<Pair<String, String>> sSettingsPackageAndClassNamePairList;
 
     /**
      * State when there's no PIP.
@@ -221,7 +197,7 @@
 
         @Override
         public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds,
-                boolean fromImeAdjustement) {
+                Rect animatingBounds, boolean fromImeAdjustement) {
             mHandler.post(() -> {
                 mDefaultPipBounds.set(normalBounds);
             });
@@ -252,6 +228,36 @@
         mOnboardingShown = Prefs.getBoolean(
                 mContext, TV_PICTURE_IN_PICTURE_ONBOARDING_SHOWN, false);
 
+        if (sSettingsPackageAndClassNamePairList == null) {
+            String[] settings = mContext.getResources().getStringArray(
+                    R.array.tv_pip_settings_class_name);
+            sSettingsPackageAndClassNamePairList = new ArrayList<>();
+            if (settings != null) {
+                for (int i = 0; i < settings.length; i++) {
+                    Pair<String, String> entry = null;
+                    String[] packageAndClassName =
+                            settings[i].split(SETTINGS_PACKAGE_AND_CLASS_DELIMITER);
+                    switch (packageAndClassName.length) {
+                        case 1:
+                            entry = Pair.<String, String>create(packageAndClassName[0], null);
+                            break;
+                        case 2:
+                            if (packageAndClassName[1] != null
+                                    && packageAndClassName[1].startsWith(".")) {
+                                entry = Pair.<String, String>create(
+                                        packageAndClassName[0],
+                                        packageAndClassName[0] + packageAndClassName[1]);
+                            }
+                    }
+                    if (entry != null) {
+                        sSettingsPackageAndClassNamePairList.add(entry);
+                    } else {
+                        Log.w(TAG, "Ignoring malformed settings name " + settings[i]);
+                    }
+                }
+            }
+        }
+
         loadConfigurationsAndApply();
         mPipRecentsOverlayManager = new PipRecentsOverlayManager(context);
         mMediaSessionManager =
@@ -331,12 +337,11 @@
      * Moves the PIPed activity to the fullscreen and closes PIP system UI.
      */
     void movePipToFullscreen() {
-        mState = STATE_NO_PIP;
         mPipTaskId = TASK_ID_NO_PIP;
         for (int i = mListeners.size() - 1; i >= 0; --i) {
             mListeners.get(i).onMoveToFullscreen();
         }
-        resizePinnedStack(mState);
+        resizePinnedStack(STATE_NO_PIP);
         updatePipVisibility(false);
     }
 
@@ -382,6 +387,7 @@
         if (DEBUG) Log.d(TAG, "resizePinnedStack() state=" + state);
         boolean wasRecentsShown =
                 (mState == STATE_PIP_RECENTS || mState == STATE_PIP_RECENTS_FOCUSED);
+        boolean wasStateNoPip = (mState == STATE_NO_PIP);
         mState = state;
         for (int i = mListeners.size() - 1; i >= 0; --i) {
             mListeners.get(i).onPipResizeAboutToStart();
@@ -395,6 +401,11 @@
         switch (mState) {
             case STATE_NO_PIP:
                 mCurrentPipBounds = null;
+                // If the state was already STATE_NO_PIP, then do not resize the stack below as it
+                // will not exist
+                if (wasStateNoPip) {
+                    return;
+                }
                 break;
             case STATE_PIP_MENU:
                 mCurrentPipBounds = mMenuModePipBounds;
@@ -412,18 +423,16 @@
                 mCurrentPipBounds = mPipBounds;
                 break;
         }
-        if (mCurrentPipBounds != null) {
-            try {
-                int animationDurationMs = -1;
-                if (wasRecentsShown
-                        && (mState == STATE_PIP_RECENTS || mState == STATE_PIP_RECENTS_FOCUSED)) {
-                    animationDurationMs = mRecentsFocusChangedAnimationDurationMs;
-                }
-                mActivityManager.resizeStack(PINNED_STACK_ID, mCurrentPipBounds,
-                        true, true, true, animationDurationMs);
-            } catch (RemoteException e) {
-                Log.e(TAG, "resizeStack failed", e);
+        try {
+            int animationDurationMs = -1;
+            if (wasRecentsShown
+                    && (mState == STATE_PIP_RECENTS || mState == STATE_PIP_RECENTS_FOCUSED)) {
+                animationDurationMs = mRecentsFocusChangedAnimationDurationMs;
             }
+            mActivityManager.resizeStack(PINNED_STACK_ID, mCurrentPipBounds,
+                    true, true, true, animationDurationMs);
+        } catch (RemoteException e) {
+            Log.e(TAG, "resizeStack failed", e);
         }
     }
 
@@ -695,7 +704,7 @@
         }
 
         @Override
-        public void onPinnedActivityRestartAttempt(String launchedFromPackage) {
+        public void onPinnedActivityRestartAttempt() {
             if (DEBUG) Log.d(TAG, "onPinnedActivityRestartAttempt()");
             if (!checkCurrentUserId(DEBUG)) {
                 return;
diff --git a/packages/SystemUI/src/com/android/systemui/plugins/PluginDependencyProvider.java b/packages/SystemUI/src/com/android/systemui/plugins/PluginDependencyProvider.java
new file mode 100644
index 0000000..59f6d56
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/plugins/PluginDependencyProvider.java
@@ -0,0 +1,50 @@
+/*
+ * 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.plugins;
+
+import android.util.ArrayMap;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.plugins.PluginDependency.DependencyProvider;
+
+public class PluginDependencyProvider extends DependencyProvider {
+
+    private final ArrayMap<Class<?>, Object> mDependencies = new ArrayMap<>();
+    private final PluginManager mManager;
+
+    public PluginDependencyProvider(PluginManager manager) {
+        mManager = manager;
+        PluginDependency.sProvider = this;
+    }
+
+    public <T> void allowPluginDependency(Class<T> cls) {
+        allowPluginDependency(cls, Dependency.get(cls));
+    }
+
+    public <T> void allowPluginDependency(Class<T> cls, T obj) {
+        mDependencies.put(cls, obj);
+    }
+
+    @Override
+    <T> T get(Plugin p, Class<T> cls) {
+        if (!mManager.dependsOn(p, cls)) {
+            throw new IllegalArgumentException(p.getClass() + " does not depend on " + cls);
+        }
+        if (!mDependencies.containsKey(cls)) {
+            throw new IllegalArgumentException("Unknown dependency " + cls);
+        }
+        return (T) mDependencies.get(cls);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/plugins/PluginInstanceManager.java b/packages/SystemUI/src/com/android/systemui/plugins/PluginInstanceManager.java
index e895fa2..79f78c9 100644
--- a/packages/SystemUI/src/com/android/systemui/plugins/PluginInstanceManager.java
+++ b/packages/SystemUI/src/com/android/systemui/plugins/PluginInstanceManager.java
@@ -161,6 +161,16 @@
         mContext.sendBroadcast(intent);
     }
 
+    public <T> boolean dependsOn(Plugin p, Class<T> cls) {
+        ArrayList<PluginInfo> plugins = new ArrayList<>(mPluginHandler.mPlugins);
+        for (PluginInfo info : plugins) {
+            if (info.mPlugin.getClass().getName().equals(p.getClass().getName())) {
+                return info.mVersion != null && info.mVersion.hasClass(cls);
+            }
+        }
+        return false;
+    }
+
     private class MainHandler extends Handler {
         private static final int PLUGIN_CONNECTED = 1;
         private static final int PLUGIN_DISCONNECTED = 2;
@@ -304,9 +314,9 @@
                 // legacy version check.
                 T plugin = (T) pluginClass.newInstance();
                 try {
-                    checkVersion(pluginClass, plugin, mVersion);
+                    VersionInfo version = checkVersion(pluginClass, plugin, mVersion);
                     if (DEBUG) Log.d(TAG, "createPlugin");
-                    return new PluginInfo(pkg, cls, plugin, pluginContext);
+                    return new PluginInfo(pkg, cls, plugin, pluginContext, version);
                 } catch (InvalidVersionException e) {
                     final int icon = mContext.getResources().getIdentifier("tuner", "drawable",
                             mContext.getPackageName());
@@ -348,13 +358,13 @@
                             + ", expected " + mVersion);
                     return null;
                 }
-            } catch (Exception e) {
+            } catch (Throwable e) {
                 Log.w(TAG, "Couldn't load plugin: " + pkg, e);
                 return null;
             }
         }
 
-        private void checkVersion(Class<?> pluginClass, T plugin, VersionInfo version)
+        private VersionInfo checkVersion(Class<?> pluginClass, T plugin, VersionInfo version)
                 throws InvalidVersionException {
             VersionInfo pv = new VersionInfo().addClass(pluginClass);
             if (pv.hasVersionInfo()) {
@@ -364,7 +374,9 @@
                 if (fallbackVersion != version.getDefaultVersion()) {
                     throw new InvalidVersionException("Invalid legacy version", false);
                 }
+                return null;
             }
+            return pv;
         }
     }
 
@@ -396,15 +408,18 @@
 
     static class PluginInfo<T> {
         private final Context mPluginContext;
+        private final VersionInfo mVersion;
         private String mClass;
         T mPlugin;
         String mPackage;
 
-        public PluginInfo(String pkg, String cls, T plugin, Context pluginContext) {
+        public PluginInfo(String pkg, String cls, T plugin, Context pluginContext,
+                VersionInfo info) {
             mPlugin = plugin;
             mClass = cls;
             mPackage = pkg;
             mPluginContext = pluginContext;
+            mVersion = info;
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/plugins/PluginManager.java b/packages/SystemUI/src/com/android/systemui/plugins/PluginManager.java
index 8b4bd7b..9ad862d 100644
--- a/packages/SystemUI/src/com/android/systemui/plugins/PluginManager.java
+++ b/packages/SystemUI/src/com/android/systemui/plugins/PluginManager.java
@@ -29,6 +29,7 @@
 import android.content.res.Resources;
 import android.net.Uri;
 import android.os.Build;
+import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.SystemProperties;
@@ -39,6 +40,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.systemui.Dependency;
 import com.android.systemui.plugins.PluginInstanceManager.PluginContextWrapper;
 import com.android.systemui.plugins.PluginInstanceManager.PluginInfo;
 import com.android.systemui.plugins.annotations.ProvidesInterface;
@@ -93,6 +95,14 @@
         PluginExceptionHandler uncaughtExceptionHandler = new PluginExceptionHandler(
                 defaultHandler);
         Thread.setDefaultUncaughtExceptionHandler(uncaughtExceptionHandler);
+        if (isDebuggable) {
+            new Handler(mBackgroundThread.getLooper()).post(() -> {
+                // Plugin dependencies that don't have another good home can go here, but
+                // dependencies that have better places to init can happen elsewhere.
+                Dependency.get(PluginDependencyProvider.class)
+                        .allowPluginDependency(ActivityStarter.class);
+            });
+        }
     }
 
     public <T extends Plugin> T getOneShotPlugin(Class<T> cls) {
@@ -133,14 +143,7 @@
 
     public <T extends Plugin> void addPluginListener(PluginListener<T> listener, Class<?> cls,
             boolean allowMultiple) {
-        ProvidesInterface info = cls.getDeclaredAnnotation(ProvidesInterface.class);
-        if (info == null) {
-            throw new RuntimeException(cls + " doesn't provide an interface");
-        }
-        if (TextUtils.isEmpty(info.action())) {
-            throw new RuntimeException(cls + " doesn't provide an action");
-        }
-        addPluginListener(info.action(), listener, cls, allowMultiple);
+        addPluginListener(getAction(cls), listener, cls, allowMultiple);
     }
 
     public <T extends Plugin> void addPluginListener(String action, PluginListener<T> listener,
@@ -275,36 +278,29 @@
         return mParentClassLoader;
     }
 
-    public Context getAllPluginContext(Context context) {
-        return new PluginContextWrapper(context,
-                new AllPluginClassLoader(context.getClassLoader()));
-    }
-
     public Context getContext(ApplicationInfo info, String pkg) throws NameNotFoundException {
         ClassLoader classLoader = getClassLoader(info.sourceDir, pkg);
         return new PluginContextWrapper(mContext.createApplicationContext(info, 0), classLoader);
     }
 
-    private class AllPluginClassLoader extends ClassLoader {
-        public AllPluginClassLoader(ClassLoader classLoader) {
-            super(classLoader);
+    public static <P> String getAction(Class<P> cls) {
+        ProvidesInterface info = cls.getDeclaredAnnotation(ProvidesInterface.class);
+        if (info == null) {
+            throw new RuntimeException(cls + " doesn't provide an interface");
         }
+        if (TextUtils.isEmpty(info.action())) {
+            throw new RuntimeException(cls + " doesn't provide an action");
+        }
+        return info.action();
+    }
 
-        @Override
-        public Class<?> loadClass(String s) throws ClassNotFoundException {
-            try {
-                return super.loadClass(s);
-            } catch (ClassNotFoundException e) {
-                for (ClassLoader classLoader : mClassLoaders.values()) {
-                    try {
-                        return classLoader.loadClass(s);
-                    } catch (ClassNotFoundException e1) {
-                        // Will re-throw e if all fail.
-                    }
-                }
-                throw e;
+    public <T> boolean dependsOn(Plugin p, Class<T> cls) {
+        for (int i = 0; i < mPluginMap.size(); i++) {
+            if (mPluginMap.valueAt(i).dependsOn(p, cls)) {
+                return true;
             }
         }
+        return false;
     }
 
     @VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/plugins/VersionInfo.java b/packages/SystemUI/src/com/android/systemui/plugins/VersionInfo.java
index 84f7761..facfd98 100644
--- a/packages/SystemUI/src/com/android/systemui/plugins/VersionInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/plugins/VersionInfo.java
@@ -45,6 +45,7 @@
     }
 
     private void addClass(Class<?> cls, boolean required) {
+        if (mVersions.containsKey(cls)) return;
         ProvidesInterface provider = cls.getDeclaredAnnotation(ProvidesInterface.class);
         if (provider != null) {
             mVersions.put(cls, new Version(provider.version(), true));
@@ -103,6 +104,10 @@
         return null;
     }
 
+    public <T> boolean hasClass(Class<T> cls) {
+        return mVersions.containsKey(cls);
+    }
+
     public static class InvalidVersionException extends RuntimeException {
         private final boolean mTooNew;
 
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index 09ce2ad..daf0622 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -39,6 +39,7 @@
 import android.util.Slog;
 
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.settingslib.Utils;
 import com.android.systemui.R;
 import com.android.systemui.SystemUI;
 import com.android.systemui.statusbar.phone.StatusBar;
@@ -175,8 +176,7 @@
                         .setOnlyAlertOnce(true)
                         .setDeleteIntent(pendingBroadcast(ACTION_DISMISSED_WARNING))
                         .setVisibility(Notification.VISIBILITY_PUBLIC)
-                        .setColor(mContext.getColor(
-                                com.android.internal.R.color.battery_saver_mode_color));
+                        .setColor(Utils.getColorAttr(mContext, android.R.attr.colorError));
         if (hasBatterySettings()) {
             nb.setContentIntent(pendingBroadcast(ACTION_SHOW_BATTERY_SETTINGS));
         }
@@ -245,8 +245,7 @@
                         .setVisibility(Notification.VISIBILITY_PUBLIC)
                         .setContentIntent(pendingBroadcast(ACTION_CLICKED_TEMP_WARNING))
                         .setDeleteIntent(pendingBroadcast(ACTION_DISMISSED_TEMP_WARNING))
-                        .setColor(mContext.getColor(
-                                com.android.internal.R.color.battery_saver_mode_color));
+                        .setColor(Utils.getColorAttr(mContext, android.R.attr.colorError));
         SystemUI.overrideNotificationAppName(mContext, nb);
         final Notification n = nb.build();
         mNoMan.notifyAsUser(TAG_TEMPERATURE, SystemMessage.NOTE_HIGH_TEMP, n, UserHandle.ALL);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java b/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java
new file mode 100644
index 0000000..7fe28c3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java
@@ -0,0 +1,53 @@
+/*
+ * 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.qs;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.widget.FrameLayout;
+import android.widget.FrameLayout.LayoutParams;
+import android.widget.ImageView;
+
+import com.android.settingslib.Utils;
+import com.android.systemui.R;
+import com.android.systemui.plugins.qs.QSTile.State;
+import com.android.systemui.qs.tileimpl.QSTileImpl.ResourceIcon;
+
+// Exists to provide easy way to add sim icon to cell tile
+// TODO Find a better way to handle this and remove it.
+public class CellTileView extends SignalTileView {
+
+    private final ImageView mOverlay;
+
+    public CellTileView(Context context) {
+        super(context);
+        mOverlay = new ImageView(mContext);
+        mOverlay.setImageTintList(ColorStateList.valueOf(Utils.getColorAttr(context,
+                android.R.attr.colorPrimary)));
+        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
+                LayoutParams.MATCH_PARENT);
+        int padding = context.getResources().getDimensionPixelOffset(R.dimen.cell_overlay_padding);
+        params.leftMargin = params.rightMargin = padding;
+        mIconFrame.addView(mOverlay, params);
+    }
+
+    @Override
+    public void setIcon(State state) {
+        State s = state.copy();
+        updateIcon(mOverlay, state);
+        s.icon = ResourceIcon.get(R.drawable.ic_sim);
+        super.setIcon(s);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index 3559257..9da52d0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -263,7 +263,6 @@
         public TilePage(Context context, AttributeSet attrs) {
             super(context, attrs);
             updateResources();
-            setContentDescription(getContext().getString(R.string.accessibility_desc_quick_settings));
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index e0d1cba..a30b03b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -18,16 +18,15 @@
 import android.view.View;
 import android.view.View.OnAttachStateChangeListener;
 import android.view.View.OnLayoutChangeListener;
-import android.widget.TextView;
 
 import com.android.systemui.Dependency;
-import com.android.systemui.plugins.qs.QS;
+import com.android.systemui.plugins.qs.*;
+import com.android.systemui.plugins.qs.QSTileView;
 import com.android.systemui.qs.PagedTileLayout.PageListener;
 import com.android.systemui.qs.QSPanel.QSTileLayout;
-import com.android.systemui.qs.QSTile.Host.Callback;
+import com.android.systemui.qs.QSHost.Callback;
 import com.android.systemui.qs.TouchAnimator.Builder;
 import com.android.systemui.qs.TouchAnimator.Listener;
-import com.android.systemui.statusbar.phone.QSTileHost;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.tuner.TunerService.Tunable;
 
@@ -149,7 +148,7 @@
         TouchAnimator.Builder translationYBuilder = new Builder();
 
         if (mQsPanel.getHost() == null) return;
-        Collection<QSTile<?>> tiles = mQsPanel.getHost().getTiles();
+        Collection<QSTile> tiles = mQsPanel.getHost().getTiles();
         int count = 0;
         int[] loc1 = new int[2];
         int[] loc2 = new int[2];
@@ -162,10 +161,12 @@
 
         QSTileLayout tileLayout = mQsPanel.getTileLayout();
         mAllViews.add((View) tileLayout);
-        firstPageBuilder.addFloat(tileLayout, "translationY", mQsPanel.getHeight(), 0);
+        int heightDiff = mQsPanel.getBottom() - mQs.getHeader().getBottom()
+                + mQs.getHeader().getPaddingBottom();
+        firstPageBuilder.addFloat(tileLayout, "translationY", heightDiff, 0);
 
-        for (QSTile<?> tile : tiles) {
-            QSTileBaseView tileView = mQsPanel.getTileView(tile);
+        for (QSTile tile : tiles) {
+            QSTileView tileView = mQsPanel.getTileView(tile);
             if (tileView == null) {
                 Log.e(TAG, "tileView is null " + tile.getTileSpec());
                 continue;
@@ -174,7 +175,8 @@
             View view = mQs.getView();
             if (count < mNumQuickTiles && mAllowFancy) {
                 // Quick tiles.
-                QSTileBaseView quickTileView = mQuickQsPanel.getTileView(tile);
+                QSTileView quickTileView = mQuickQsPanel.getTileView(tile);
+                if (quickTileView == null) continue;
 
                 lastX = loc1[0];
                 getRelativePosition(loc1, quickTileView.getIcon().getIconView(), view);
@@ -208,7 +210,7 @@
                 final int xDiff = loc2[0] - loc1[0];
                 final int yDiff = loc2[1] - loc1[1];
 
-                firstPageBuilder.addFloat(tileView, "translationY", mQsPanel.getHeight(), 0);
+                firstPageBuilder.addFloat(tileView, "translationY", heightDiff, 0);
                 translationXBuilder.addFloat(tileView, "translationX", -xDiff, 0);
                 translationYBuilder.addFloat(tileView, "translationY", -yDiff, 0);
                 translationYBuilder.addFloat(tileIcon, "translationY", -yDiff, 0);
@@ -216,7 +218,7 @@
                 mAllViews.add(tileIcon);
             } else {
                 firstPageBuilder.addFloat(tileView, "alpha", 0, 1);
-                firstPageBuilder.addFloat(tileView, "translationY", -mQsPanel.getHeight(), 0);
+                firstPageBuilder.addFloat(tileView, "translationY", -heightDiff, 0);
             }
             mAllViews.add(tileView);
             count++;
@@ -225,12 +227,15 @@
             // Make brightness appear static position and alpha in through second half.
             View brightness = mQsPanel.getBrightnessView();
             if (brightness != null) {
-                firstPageBuilder.addFloat(brightness, "translationY", mQsPanel.getHeight(), 0);
+                firstPageBuilder.addFloat(brightness, "translationY", heightDiff, 0);
                 mBrightnessAnimator = new TouchAnimator.Builder()
                         .addFloat(brightness, "alpha", 0, 1)
                         .addFloat(mQsPanel.getPageIndicator(), "alpha", 0, 1)
+                        .addFloat(mQsPanel.getDivider(), "alpha", 0, 1)
                         .setStartDelay(.5f)
                         .build();
+                mAllViews.add(mQsPanel.getPageIndicator());
+                mAllViews.add(mQsPanel.getDivider());
                 mAllViews.add(brightness);
             } else {
                 mBrightnessAnimator = null;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index 91b4d0d..06264ba 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -38,6 +38,7 @@
     protected View mHeader;
     protected float mQsExpansion;
     private QSCustomizer mQSCustomizer;
+    private QSFooter mQSFooter;
 
     public QSContainerImpl(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -49,7 +50,8 @@
         mQSPanel = findViewById(R.id.quick_settings_panel);
         mQSDetail = findViewById(R.id.qs_detail);
         mHeader = findViewById(R.id.header);
-        mQSCustomizer = (QSCustomizer) findViewById(R.id.qs_customize);
+        mQSCustomizer = findViewById(R.id.qs_customize);
+        mQSFooter = findViewById(R.id.qs_footer);
     }
 
     @Override
@@ -60,7 +62,8 @@
         mQSPanel.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(
                 MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.UNSPECIFIED));
         int width = mQSPanel.getMeasuredWidth();
-        int height = ((LayoutParams) mQSPanel.getLayoutParams()).topMargin
+        LayoutParams layoutParams = (LayoutParams) mQSPanel.getLayoutParams();
+        int height = layoutParams.topMargin + layoutParams.bottomMargin
                 + mQSPanel.getMeasuredHeight();
         super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
                 MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
@@ -93,6 +96,8 @@
         int height = calculateContainerHeight();
         setBottom(getTop() + height);
         mQSDetail.setBottom(getTop() + height);
+        // Pin QS Footer to the bottom of the panel.
+        mQSFooter.setTranslationY(height - mQSFooter.getHeight());
     }
 
     protected int calculateContainerHeight() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
index a20b7ba..1709718 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
@@ -37,12 +37,9 @@
 import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
 import com.android.systemui.SysUiServiceProvider;
-import com.android.systemui.ActivityStarter;
-import com.android.systemui.plugins.qs.QS.BaseStatusBarHeader;
-import com.android.systemui.plugins.qs.QS.Callback;
-import com.android.systemui.plugins.qs.QS.DetailAdapter;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.qs.DetailAdapter;
 import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.phone.QSTileHost;
 
 public class QSDetail extends LinearLayout {
 
@@ -68,7 +65,7 @@
     private boolean mScanState;
     private boolean mClosingDetail;
     private boolean mFullyExpanded;
-    private BaseStatusBarHeader mHeader;
+    private QuickStatusBarHeader mHeader;
     private boolean mTriggeredExpand;
     private int mOpenX;
     private int mOpenY;
@@ -117,7 +114,7 @@
         mDetailDoneButton.setOnClickListener(doneListener);
     }
 
-    public void setQsPanel(QSPanel panel, BaseStatusBarHeader header) {
+    public void setQsPanel(QSPanel panel, QuickStatusBarHeader header) {
         mQsPanel = panel;
         mHeader = header;
         mHeader.setCallback(mQsPanelCallback);
@@ -154,7 +151,11 @@
         return mClosingDetail;
     }
 
-
+    public interface Callback {
+        void onShowingDetail(DetailAdapter detail, int x, int y);
+        void onToggleStateChanged(boolean state);
+        void onScanStateChanged(boolean state);
+    }
 
     public void handleShowingDetail(final DetailAdapter adapter, int x, int y,
             boolean toggleQs) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
index dad8bea..65238b1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
@@ -203,16 +203,28 @@
                     }
                 }
             });
-            final ImageView disconnect = (ImageView) view.findViewById(android.R.id.icon2);
-            disconnect.setVisibility(item.canDisconnect ? VISIBLE : GONE);
-            disconnect.setOnClickListener(new OnClickListener() {
-                @Override
-                public void onClick(View v) {
-                    if (mCallback != null) {
-                        mCallback.onDetailItemDisconnect(item);
+
+            final ImageView icon2 = (ImageView) view.findViewById(android.R.id.icon2);
+            if (item.canDisconnect) {
+                icon2.setImageResource(R.drawable.ic_qs_cancel);
+                icon2.setVisibility(VISIBLE);
+                icon2.setClickable(true);
+                icon2.setOnClickListener(new OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        if (mCallback != null) {
+                            mCallback.onDetailItemDisconnect(item);
+                        }
                     }
-                }
-            });
+                });
+            } else if (item.icon2 != -1) {
+                icon2.setVisibility(VISIBLE);
+                icon2.setImageResource(item.icon2);
+                icon2.setClickable(false);
+            } else {
+                icon2.setVisibility(GONE);
+            }
+
             return view;
         }
     };
@@ -245,6 +257,7 @@
         public CharSequence line2;
         public Object tag;
         public boolean canDisconnect;
+        public int icon2 = -1;
     }
 
     public interface Callback {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
index 1835afd..2202b58 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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.
@@ -11,372 +11,381 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
- * limitations under the License.
+ * limitations under the License
  */
+
 package com.android.systemui.qs;
 
-import android.app.AlertDialog;
+import android.app.AlarmManager;
+import android.app.PendingIntent;
 import android.content.Context;
-import android.content.DialogInterface;
 import android.content.Intent;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.provider.Settings;
-import android.text.SpannableStringBuilder;
-import android.text.method.LinkMovementMethod;
-import android.text.style.ClickableSpan;
-import android.util.Log;
-import android.view.LayoutInflater;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.RippleDrawable;
+import android.os.UserManager;
+import android.provider.AlarmClock;
+import android.support.annotation.Nullable;
+import android.support.annotation.VisibleForTesting;
+import android.util.AttributeSet;
 import android.view.View;
-import android.view.ViewGroup;
 import android.view.View.OnClickListener;
 import android.widget.ImageView;
+import android.widget.LinearLayout;
 import android.widget.TextView;
+import android.widget.Toast;
 
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.keyguard.KeyguardStatusView;
 import com.android.systemui.Dependency;
 import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
-import com.android.systemui.ActivityStarter;
-import com.android.systemui.statusbar.phone.QSTileHost;
-import com.android.systemui.statusbar.phone.SystemUIDialog;
-import com.android.systemui.statusbar.policy.SecurityController;
+import com.android.systemui.R.dimen;
+import com.android.systemui.R.id;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.qs.TouchAnimator.Builder;
+import com.android.systemui.statusbar.phone.ExpandableIndicator;
+import com.android.systemui.statusbar.phone.MultiUserSwitch;
+import com.android.systemui.statusbar.phone.SettingsButton;
+import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.NetworkController.EmergencyListener;
+import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
+import com.android.systemui.statusbar.policy.NextAlarmController;
+import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback;
+import com.android.systemui.statusbar.policy.UserInfoController;
+import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
+import com.android.systemui.tuner.TunerService;
 
-import static android.provider.Settings.ACTION_VPN_SETTINGS;
+public class QSFooter extends LinearLayout implements
+        NextAlarmChangeCallback, OnClickListener, OnUserInfoChangedListener, EmergencyListener,
+        SignalCallback {
+    private static final float EXPAND_INDICATOR_THRESHOLD = .93f;
 
-public class QSFooter implements OnClickListener, DialogInterface.OnClickListener {
-    protected static final String TAG = "QSFooter";
-    protected static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+    private ActivityStarter mActivityStarter;
+    private NextAlarmController mNextAlarmController;
+    private UserInfoController mUserInfoController;
+    private SettingsButton mSettingsButton;
+    protected View mSettingsContainer;
 
-    private final View mRootView;
-    private final TextView mFooterText;
-    private final ImageView mFooterIcon;
-    private final ImageView mFooterIcon2;
-    private final Context mContext;
-    private final Callback mCallback = new Callback();
-    private final SecurityController mSecurityController;
-    private final ActivityStarter mActivityStarter;
-    private final Handler mMainHandler;
+    private TextView mAlarmStatus;
+    private View mAlarmStatusCollapsed;
+    private View mDate;
 
-    private AlertDialog mDialog;
-    private QSTileHost mHost;
-    protected H mHandler;
+    private QSPanel mQsPanel;
 
-    private boolean mIsVisible;
-    private boolean mIsIconVisible;
-    private boolean mIsIcon2Visible;
-    private CharSequence mFooterTextContent = null;
-    private int mFooterTextId;
-    private int mFooterIconId;
-    private int mFooterIcon2Id;
+    private boolean mExpanded;
+    private boolean mAlarmShowing;
 
-    public QSFooter(QSPanel qsPanel, Context context) {
-        mRootView = LayoutInflater.from(context)
-                .inflate(R.layout.quick_settings_footer, qsPanel, false);
-        mRootView.setOnClickListener(this);
-        mFooterText = (TextView) mRootView.findViewById(R.id.footer_text);
-        mFooterIcon = (ImageView) mRootView.findViewById(R.id.footer_icon);
-        mFooterIcon2 = (ImageView) mRootView.findViewById(R.id.footer_icon2);
-        mFooterIconId = R.drawable.ic_qs_vpn;
-        mFooterIcon2Id = R.drawable.ic_qs_network_logging;
-        mContext = context;
-        mMainHandler = new Handler(Looper.getMainLooper());
+    protected ExpandableIndicator mExpandIndicator;
+
+    private boolean mListening;
+    private AlarmManager.AlarmClockInfo mNextAlarm;
+
+    private boolean mShowEmergencyCallsOnly;
+    protected MultiUserSwitch mMultiUserSwitch;
+    private ImageView mMultiUserAvatar;
+    private boolean mAlwaysShowMultiUserSwitch;
+
+    protected TouchAnimator mSettingsAlpha;
+    private float mExpansionAmount;
+
+    protected View mEdit;
+    private boolean mShowEditIcon;
+    private TouchAnimator mAnimator;
+    private View mDateTimeGroup;
+
+    public QSFooter(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        Resources res = getResources();
+
+        mShowEditIcon = res.getBoolean(R.bool.config_showQuickSettingsEditingIcon);
+
+        mEdit = findViewById(android.R.id.edit);
+        mEdit.setVisibility(mShowEditIcon ? VISIBLE : GONE);
+
+        if (mShowEditIcon) {
+            findViewById(android.R.id.edit).setOnClickListener(view ->
+                    Dependency.get(ActivityStarter.class).postQSRunnableDismissingKeyguard(() ->
+                            mQsPanel.showEdit(view)));
+        }
+
+        mDateTimeGroup = findViewById(id.date_time_alarm_group);
+        mDate = findViewById(R.id.date);
+
+        mExpandIndicator = findViewById(R.id.expand_indicator);
+        mExpandIndicator.setVisibility(
+                res.getBoolean(R.bool.config_showQuickSettingsExpandIndicator)
+                        ? VISIBLE : GONE);
+
+        mSettingsButton = findViewById(R.id.settings_button);
+        mSettingsContainer = findViewById(R.id.settings_button_container);
+        mSettingsButton.setOnClickListener(this);
+
+        mAlarmStatusCollapsed = findViewById(R.id.alarm_status_collapsed);
+        mAlarmStatus = findViewById(R.id.alarm_status);
+        mDateTimeGroup.setOnClickListener(this);
+
+        mMultiUserSwitch = findViewById(R.id.multi_user_switch);
+        mMultiUserAvatar = mMultiUserSwitch.findViewById(R.id.multi_user_avatar);
+        mAlwaysShowMultiUserSwitch = res.getBoolean(R.bool.config_alwaysShowMultiUserSwitcher);
+
+        // RenderThread is doing more harm than good when touching the header (to expand quick
+        // settings), so disable it for this view
+        ((RippleDrawable) mSettingsButton.getBackground()).setForceSoftware(true);
+        ((RippleDrawable) mExpandIndicator.getBackground()).setForceSoftware(true);
+
+        updateResources();
+
+        mNextAlarmController = Dependency.get(NextAlarmController.class);
+        mUserInfoController = Dependency.get(UserInfoController.class);
         mActivityStarter = Dependency.get(ActivityStarter.class);
-        mSecurityController = Dependency.get(SecurityController.class);
-        mHandler = new H(Dependency.get(Dependency.BG_LOOPER));
+        addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight,
+                oldBottom) -> updateAnimator(right - left));
     }
 
-    public void setHostEnvironment(QSTileHost host) {
-        mHost = host;
+    private void updateAnimator(int width) {
+        int numTiles = QuickQSPanel.getNumQuickTiles(mContext);
+        int size = mContext.getResources().getDimensionPixelSize(R.dimen.qs_quick_tile_size)
+                - mContext.getResources().getDimensionPixelSize(dimen.qs_quick_tile_padding);
+        int remaining = (width - numTiles * size) / (numTiles - 1);
+        int defSpace = mContext.getResources().getDimensionPixelOffset(R.dimen.default_gear_space);
+
+        final Builder builder = new Builder()
+                .addFloat(mSettingsContainer, "translationX", -(remaining - defSpace), 0)
+                .addFloat(mSettingsButton, "rotation", -120, 0)
+                .addFloat(mAlarmStatus, "alpha", 0, 1)
+                .addFloat(mAlarmStatus, "translationX", 0, -mDate.getWidth())
+                .addFloat(mAlarmStatusCollapsed, "translationX", 0, -mDate.getWidth());
+        if (mAlarmShowing) {
+            builder.addFloat(mDate, "alpha", 1, 0);
+        }
+        mAnimator = builder.build();
+        setExpansion(mExpansionAmount);
     }
 
-    public void setListening(boolean listening) {
-        if (listening) {
-            mSecurityController.addCallback(mCallback);
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        updateResources();
+    }
+
+    @Override
+    public void onRtlPropertiesChanged(int layoutDirection) {
+        super.onRtlPropertiesChanged(layoutDirection);
+        updateResources();
+    }
+
+    private void updateResources() {
+        FontSizeUtils.updateFontSize(mAlarmStatus, R.dimen.qs_date_collapsed_size);
+
+        updateSettingsAnimator();
+    }
+
+    private void updateSettingsAnimator() {
+        mSettingsAlpha = createSettingsAlphaAnimator();
+
+        final boolean isRtl = isLayoutRtl();
+        if (isRtl && mDate.getWidth() == 0) {
+            mDate.addOnLayoutChangeListener(new OnLayoutChangeListener() {
+                @Override
+                public void onLayoutChange(View v, int left, int top, int right, int bottom,
+                        int oldLeft, int oldTop, int oldRight, int oldBottom) {
+                    mDate.setPivotX(getWidth());
+                    mDate.removeOnLayoutChangeListener(this);
+                }
+            });
         } else {
-            mSecurityController.removeCallback(mCallback);
+            mDate.setPivotX(isRtl ? mDate.getWidth() : 0);
         }
     }
 
-    public void onConfigurationChanged() {
-        FontSizeUtils.updateFontSize(mFooterText, R.dimen.qs_tile_text_size);
+    @Nullable
+    private TouchAnimator createSettingsAlphaAnimator() {
+        // If the settings icon is not shown and the user switcher is always shown, then there
+        // is nothing to animate.
+        if (!mShowEditIcon && mAlwaysShowMultiUserSwitch) {
+            return null;
+        }
+
+        TouchAnimator.Builder animatorBuilder = new TouchAnimator.Builder();
+
+        if (mShowEditIcon) {
+            animatorBuilder.addFloat(mEdit, "alpha", 0, 1);
+        }
+
+        if (!mAlwaysShowMultiUserSwitch) {
+            animatorBuilder.addFloat(mMultiUserSwitch, "alpha", 0, 1);
+        }
+
+        return animatorBuilder.build();
     }
 
-    public View getView() {
-        return mRootView;
+    public void setExpanded(boolean expanded) {
+        if (mExpanded == expanded) return;
+        mExpanded = expanded;
+        updateEverything();
     }
 
-    public boolean hasFooter() {
-        return mRootView.getVisibility() != View.GONE;
+    @Override
+    public void onNextAlarmChanged(AlarmManager.AlarmClockInfo nextAlarm) {
+        mNextAlarm = nextAlarm;
+        if (nextAlarm != null) {
+            String alarmString = KeyguardStatusView.formatNextAlarm(getContext(), nextAlarm);
+            mAlarmStatus.setText(alarmString);
+            mAlarmStatus.setContentDescription(mContext.getString(
+                    R.string.accessibility_quick_settings_alarm, alarmString));
+            mAlarmStatusCollapsed.setContentDescription(mContext.getString(
+                    R.string.accessibility_quick_settings_alarm, alarmString));
+        }
+        if (mAlarmShowing != (nextAlarm != null)) {
+            mAlarmShowing = nextAlarm != null;
+            updateAnimator(getWidth());
+            updateEverything();
+        }
+    }
+
+    public void setExpansion(float headerExpansionFraction) {
+        mExpansionAmount = headerExpansionFraction;
+        if (mAnimator != null) mAnimator.setPosition(headerExpansionFraction);
+
+        if (mSettingsAlpha != null) {
+            mSettingsAlpha.setPosition(headerExpansionFraction);
+        }
+
+        updateAlarmVisibilities();
+
+        mExpandIndicator.setExpanded(headerExpansionFraction > EXPAND_INDICATOR_THRESHOLD);
+    }
+
+    @Override
+    @VisibleForTesting
+    public void onDetachedFromWindow() {
+        setListening(false);
+        super.onDetachedFromWindow();
+    }
+
+    private void updateAlarmVisibilities() {
+        mAlarmStatus.setVisibility(mAlarmShowing ? View.VISIBLE : View.INVISIBLE);
+        mAlarmStatusCollapsed.setVisibility(mAlarmShowing ? View.VISIBLE : View.INVISIBLE);
+    }
+
+    public void setListening(boolean listening) {
+        if (listening == mListening) {
+            return;
+        }
+        mListening = listening;
+        updateListeners();
+    }
+
+    public View getExpandView() {
+        return findViewById(R.id.expand_indicator);
+    }
+
+    public void updateEverything() {
+        post(() -> {
+            updateVisibilities();
+            setClickable(false);
+        });
+    }
+
+    private void updateVisibilities() {
+        updateAlarmVisibilities();
+        mSettingsContainer.findViewById(R.id.tuner_icon).setVisibility(
+                TunerService.isTunerEnabled(mContext) ? View.VISIBLE : View.INVISIBLE);
+        final boolean isDemo = UserManager.isDeviceInDemoMode(mContext);
+
+        mMultiUserSwitch.setVisibility((mExpanded || mAlwaysShowMultiUserSwitch)
+                && mMultiUserSwitch.hasMultipleUsers() && !isDemo
+                ? View.VISIBLE : View.INVISIBLE);
+
+        if (mShowEditIcon) {
+            mEdit.setVisibility(isDemo || !mExpanded ? View.INVISIBLE : View.VISIBLE);
+        }
+    }
+
+    private void updateListeners() {
+        if (mListening) {
+            mNextAlarmController.addCallback(this);
+            mUserInfoController.addCallback(this);
+            if (Dependency.get(NetworkController.class).hasVoiceCallingFeature()) {
+                Dependency.get(NetworkController.class).addEmergencyListener(this);
+                Dependency.get(NetworkController.class).addCallback(this);
+            }
+        } else {
+            mNextAlarmController.removeCallback(this);
+            mUserInfoController.removeCallback(this);
+            Dependency.get(NetworkController.class).removeEmergencyListener(this);
+            Dependency.get(NetworkController.class).removeCallback(this);
+        }
+    }
+
+    public void setQSPanel(final QSPanel qsPanel) {
+        mQsPanel = qsPanel;
+        if (mQsPanel != null) {
+            mMultiUserSwitch.setQsPanel(qsPanel);
+        }
     }
 
     @Override
     public void onClick(View v) {
-        mHandler.sendEmptyMessage(H.CLICK);
-    }
+        if (v == mSettingsButton) {
+            MetricsLogger.action(mContext,
+                    mExpanded ? MetricsProto.MetricsEvent.ACTION_QS_EXPANDED_SETTINGS_LAUNCH
+                            : MetricsProto.MetricsEvent.ACTION_QS_COLLAPSED_SETTINGS_LAUNCH);
+            if (mSettingsButton.isTunerClick()) {
+                Dependency.get(ActivityStarter.class).postQSRunnableDismissingKeyguard(() -> {
+                    if (TunerService.isTunerEnabled(mContext)) {
+                        TunerService.showResetRequest(mContext, () -> {
+                            // Relaunch settings so that the tuner disappears.
+                            startSettingsActivity();
+                        });
+                    } else {
+                        Toast.makeText(getContext(), R.string.tuner_toast,
+                                Toast.LENGTH_LONG).show();
+                        TunerService.setTunerEnabled(mContext, true);
+                    }
+                    startSettingsActivity();
 
-    private void handleClick() {
-        showDeviceMonitoringDialog();
-    }
-
-    public void showDeviceMonitoringDialog() {
-        mHost.collapsePanels();
-        // TODO: Delay dialog creation until after panels are collapsed.
-        createDialog();
-    }
-
-    public void refreshState() {
-        mHandler.sendEmptyMessage(H.REFRESH_STATE);
-    }
-
-    private void handleRefreshState() {
-        boolean isVpnEnabled = mSecurityController.isVpnEnabled();
-        boolean isNetworkLoggingEnabled = mSecurityController.isNetworkLoggingEnabled();
-        mIsIconVisible = isVpnEnabled || isNetworkLoggingEnabled;
-        mIsIcon2Visible = isVpnEnabled && isNetworkLoggingEnabled;
-        if (mSecurityController.isDeviceManaged()) {
-            final CharSequence organizationName =
-                    mSecurityController.getDeviceOwnerOrganizationName();
-            if (organizationName != null) {
-                mFooterTextContent = mContext.getResources().getString(
-                        R.string.do_disclosure_with_name, organizationName);
+                });
             } else {
-                mFooterTextContent =
-                        mContext.getResources().getString(R.string.do_disclosure_generic);
+                startSettingsActivity();
             }
-            mIsVisible = true;
-            int footerIconId = isVpnEnabled
-                    ? R.drawable.ic_qs_vpn
-                    : R.drawable.ic_qs_network_logging;
-            if (mFooterIconId != footerIconId) {
-                mFooterIconId = footerIconId;
-                mMainHandler.post(mUpdateIcon);
+        } else if (v == mDateTimeGroup) {
+            if (mNextAlarm != null) {
+                PendingIntent showIntent = mNextAlarm.getShowIntent();
+                mActivityStarter.startPendingIntentDismissingKeyguard(showIntent);
+            } else {
+                mActivityStarter.postStartActivityDismissingKeyguard(new Intent(
+                        AlarmClock.ACTION_SHOW_ALARMS), 0);
             }
-        } else {
-            boolean isBranded = mSecurityController.isVpnBranded();
-            mFooterTextContent = mContext.getResources().getText(
-                    isBranded ? R.string.branded_vpn_footer : R.string.vpn_footer);
-            // Update the VPN footer icon, if needed.
-            int footerIconId = isVpnEnabled
-                    ? (isBranded ? R.drawable.ic_qs_branded_vpn : R.drawable.ic_qs_vpn)
-                    : R.drawable.ic_qs_network_logging;
-            if (mFooterIconId != footerIconId) {
-                mFooterIconId = footerIconId;
-                mMainHandler.post(mUpdateIcon);
-            }
-            mIsVisible = mIsIconVisible;
         }
-        mMainHandler.post(mUpdateDisplayState);
+    }
+
+    private void startSettingsActivity() {
+        mActivityStarter.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS),
+                true /* dismissShade */);
     }
 
     @Override
-    public void onClick(DialogInterface dialog, int which) {
-        if (which == DialogInterface.BUTTON_NEGATIVE) {
-            final Intent settingsIntent = new Intent(ACTION_VPN_SETTINGS);
-            mActivityStarter.postStartActivityDismissingKeyguard(settingsIntent, 0);
-        }
-    }
-
-    private void createDialog() {
-        final String deviceOwnerPackage = mSecurityController.getDeviceOwnerName();
-        final String profileOwnerPackage = mSecurityController.getProfileOwnerName();
-        final boolean isNetworkLoggingEnabled = mSecurityController.isNetworkLoggingEnabled();
-        final String primaryVpn = mSecurityController.getPrimaryVpnName();
-        final String profileVpn = mSecurityController.getProfileVpnName();
-        final CharSequence deviceOwnerOrganization =
-                mSecurityController.getDeviceOwnerOrganizationName();
-        boolean hasProfileOwner = mSecurityController.hasProfileOwner();
-        boolean isBranded = deviceOwnerPackage == null && mSecurityController.isVpnBranded();
-
-        mDialog = new SystemUIDialog(mContext);
-        if (!isBranded) {
-            mDialog.setTitle(getTitle(deviceOwnerPackage));
-        }
-        CharSequence msg = getMessage(deviceOwnerPackage, profileOwnerPackage, primaryVpn,
-                profileVpn, deviceOwnerOrganization, hasProfileOwner, isBranded);
-        if (deviceOwnerPackage == null) {
-            mDialog.setMessage(msg);
-            if (mSecurityController.isVpnEnabled() && !mSecurityController.isVpnRestricted()) {
-                mDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getSettingsButton(), this);
-            }
-        } else {
-            View dialogView = LayoutInflater.from(mContext)
-                   .inflate(R.layout.quick_settings_footer_dialog, null, false);
-            mDialog.setView(dialogView);
-            TextView deviceOwnerWarning =
-                    (TextView) dialogView.findViewById(R.id.device_owner_warning);
-            deviceOwnerWarning.setText(msg);
-            // Make the link "learn more" clickable.
-            deviceOwnerWarning.setMovementMethod(new LinkMovementMethod());
-            if (primaryVpn == null) {
-                dialogView.findViewById(R.id.vpn_icon).setVisibility(View.GONE);
-                dialogView.findViewById(R.id.vpn_subtitle).setVisibility(View.GONE);
-                dialogView.findViewById(R.id.vpn_warning).setVisibility(View.GONE);
-            } else {
-                final SpannableStringBuilder message = new SpannableStringBuilder();
-                message.append(mContext.getString(R.string.monitoring_description_do_body_vpn,
-                        primaryVpn));
-                if (!mSecurityController.isVpnRestricted()) {
-                    message.append(mContext.getString(
-                            R.string.monitoring_description_vpn_settings_separator));
-                    message.append(mContext.getString(R.string.monitoring_description_vpn_settings),
-                            new VpnSpan(), 0);
-                }
-
-                TextView vpnWarning = (TextView) dialogView.findViewById(R.id.vpn_warning);
-                vpnWarning.setText(message);
-                // Make the link "Open VPN Settings" clickable.
-                vpnWarning.setMovementMethod(new LinkMovementMethod());
-            }
-            if (!isNetworkLoggingEnabled) {
-                dialogView.findViewById(R.id.network_logging_icon).setVisibility(View.GONE);
-                dialogView.findViewById(R.id.network_logging_subtitle).setVisibility(View.GONE);
-                dialogView.findViewById(R.id.network_logging_warning).setVisibility(View.GONE);
-            }
-        }
-
-        mDialog.setButton(DialogInterface.BUTTON_POSITIVE, getPositiveButton(isBranded), this);
-        mDialog.show();
-        mDialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
-    }
-
-    private String getSettingsButton() {
-        return mContext.getString(R.string.status_bar_settings_settings_button);
-    }
-
-    private String getPositiveButton(boolean isBranded) {
-        return mContext.getString(isBranded ? android.R.string.ok : R.string.quick_settings_done);
-    }
-
-    protected CharSequence getMessage(String deviceOwnerPackage, String profileOwnerPackage,
-            String primaryVpn, String profileVpn, CharSequence deviceOwnerOrganization,
-            boolean hasProfileOwner, boolean isBranded) {
-        if (deviceOwnerPackage != null) {
-            final SpannableStringBuilder message = new SpannableStringBuilder();
-            if (deviceOwnerOrganization != null) {
-                message.append(mContext.getString(
-                        R.string.monitoring_description_do_header_with_name,
-                        deviceOwnerOrganization, deviceOwnerPackage));
-            } else {
-                message.append(mContext.getString(R.string.monitoring_description_do_header_generic,
-                        deviceOwnerPackage));
-            }
-            message.append("\n\n");
-            message.append(mContext.getString(R.string.monitoring_description_do_body));
-            message.append(mContext.getString(
-                    R.string.monitoring_description_do_learn_more_separator));
-            message.append(mContext.getString(R.string.monitoring_description_do_learn_more),
-                    new EnterprisePrivacySpan(), 0);
-            return message;
-        } else if (primaryVpn != null) {
-            if (profileVpn != null) {
-                return mContext.getString(R.string.monitoring_description_app_personal_work,
-                        profileOwnerPackage, profileVpn, primaryVpn);
-            } else {
-                if (isBranded) {
-                    return mContext.getString(R.string.branded_monitoring_description_app_personal,
-                            primaryVpn);
-                } else {
-                    return mContext.getString(R.string.monitoring_description_app_personal,
-                            primaryVpn);
-                }
-            }
-        } else if (profileVpn != null) {
-            return mContext.getString(R.string.monitoring_description_app_work,
-                    profileOwnerPackage, profileVpn);
-        } else if (profileOwnerPackage != null && hasProfileOwner) {
-            return mContext.getString(R.string.do_disclosure_with_name,
-                    profileOwnerPackage);
-        } else {
-            // No device owner, no personal VPN, no work VPN, no user owner. Why are we here?
-            return null;
-        }
-    }
-
-    private int getTitle(String deviceOwner) {
-        if (deviceOwner != null) {
-            return R.string.monitoring_title_device_owned;
-        } else {
-            return R.string.monitoring_title;
-        }
-    }
-
-    private final Runnable mUpdateIcon = new Runnable() {
-        @Override
-        public void run() {
-            mFooterIcon.setImageResource(mFooterIconId);
-            mFooterIcon2.setImageResource(mFooterIcon2Id);
-        }
-    };
-
-    private final Runnable mUpdateDisplayState = new Runnable() {
-        @Override
-        public void run() {
-            if (mFooterTextContent != null) {
-                mFooterText.setText(mFooterTextContent);
-            }
-            mRootView.setVisibility(mIsVisible ? View.VISIBLE : View.GONE);
-            mFooterIcon.setVisibility(mIsIconVisible ? View.VISIBLE : View.INVISIBLE);
-            mFooterIcon2.setVisibility(mIsIcon2Visible ? View.VISIBLE : View.INVISIBLE);
-        }
-    };
-
-    private class Callback implements SecurityController.SecurityControllerCallback {
-        @Override
-        public void onStateChanged() {
-            refreshState();
-        }
-    }
-
-    private class H extends Handler {
-        private static final int CLICK = 0;
-        private static final int REFRESH_STATE = 1;
-
-        private H(Looper looper) {
-            super(looper);
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            String name = null;
-            try {
-                if (msg.what == REFRESH_STATE) {
-                    name = "handleRefreshState";
-                    handleRefreshState();
-                } else if (msg.what == CLICK) {
-                    name = "handleClick";
-                    handleClick();
-                }
-            } catch (Throwable t) {
-                final String error = "Error in " + name;
-                Log.w(TAG, error, t);
-                mHost.warn(error, t);
+    public void setEmergencyCallsOnly(boolean show) {
+        boolean changed = show != mShowEmergencyCallsOnly;
+        if (changed) {
+            mShowEmergencyCallsOnly = show;
+            if (mExpanded) {
+                updateEverything();
             }
         }
     }
 
-    protected class EnterprisePrivacySpan extends ClickableSpan {
-        @Override
-        public void onClick(View widget) {
-            final Intent intent = new Intent(Settings.ACTION_ENTERPRISE_PRIVACY_SETTINGS);
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
-            mDialog.dismiss();
-            mContext.startActivity(intent);
-        }
-
-        @Override
-        public boolean equals(Object object) {
-            return object instanceof EnterprisePrivacySpan;
-        }
-    }
-
-    protected class VpnSpan extends ClickableSpan {
-        @Override
-        public void onClick(View widget) {
-            final Intent intent = new Intent(Settings.ACTION_VPN_SETTINGS);
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
-            mDialog.dismiss();
-            mContext.startActivity(intent);
-        }
+    @Override
+    public void onUserInfoChanged(String name, Drawable picture, String userAccount) {
+        mMultiUserAvatar.setImageDrawable(picture);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 95e0301..63563b2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -24,6 +24,7 @@
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 import android.widget.FrameLayout.LayoutParams;
@@ -33,8 +34,6 @@
 import com.android.systemui.plugins.qs.QS;
 import com.android.systemui.qs.customize.QSCustomizer;
 import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
-import com.android.systemui.statusbar.phone.QSTileHost;
-import com.android.systemui.statusbar.phone.QuickStatusBarHeader;
 import com.android.systemui.statusbar.stack.StackStateAnimator;
 
 public class QSFragment extends Fragment implements QS {
@@ -58,6 +57,7 @@
     private boolean mListening;
     private QSContainerImpl mContainer;
     private int mLayoutDirection;
+    private QSFooter mFooter;
 
     @Override
     public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@@ -68,9 +68,10 @@
     @Override
     public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
-        mQSPanel = (QSPanel) view.findViewById(R.id.quick_settings_panel);
-        mQSDetail = (QSDetail) view.findViewById(R.id.qs_detail);
-        mHeader = (QuickStatusBarHeader) view.findViewById(R.id.header);
+        mQSPanel = view.findViewById(R.id.quick_settings_panel);
+        mQSDetail = view.findViewById(R.id.qs_detail);
+        mHeader = view.findViewById(R.id.header);
+        mFooter = view.findViewById(R.id.qs_footer);
         mContainer = (QSContainerImpl) view;
 
         mQSDetail.setQsPanel(mQSPanel, mHeader);
@@ -79,13 +80,18 @@
         // the row to the full QS panel.
         if (getResources().getBoolean(R.bool.config_showQuickSettingsRow)) {
             mQSAnimator = new QSAnimator(this,
-                    (QuickQSPanel) mHeader.findViewById(R.id.quick_qs_panel), mQSPanel);
+                    mHeader.findViewById(R.id.quick_qs_panel), mQSPanel);
         }
 
-        mQSCustomizer = (QSCustomizer) view.findViewById(R.id.qs_customize);
+        mQSCustomizer = view.findViewById(R.id.qs_customize);
         mQSCustomizer.setQs(this);
     }
 
+    @Override
+    public View getHeader() {
+        return mHeader;
+    }
+
     public void setPanelView(HeightListener panelView) {
         mPanelView = panelView;
     }
@@ -116,6 +122,7 @@
     public void setHost(QSTileHost qsh) {
         mQSPanel.setHost(qsh, mQSCustomizer);
         mHeader.setQSPanel(mQSPanel);
+        mFooter.setQSPanel(mQSPanel);
         mQSDetail.setHost(qsh);
 
         if (mQSAnimator != null) {
@@ -133,13 +140,14 @@
                 : View.INVISIBLE);
         mHeader.setExpanded((mKeyguardShowing && !mHeaderAnimating)
                 || (mQsExpanded && !mStackScrollerOverscrolling));
+        mFooter.setVisibility((mQsExpanded || !mKeyguardShowing || mHeaderAnimating)
+                ? View.VISIBLE
+                : View.INVISIBLE);
+        mFooter.setExpanded((mKeyguardShowing && !mHeaderAnimating)
+                || (mQsExpanded && !mStackScrollerOverscrolling));
         mQSPanel.setVisibility(expandVisually ? View.VISIBLE : View.INVISIBLE);
     }
 
-    public BaseStatusBarHeader getHeader() {
-        return mHeader;
-    }
-
     public QSPanel getQsPanel() {
         return mQSPanel;
     }
@@ -154,7 +162,7 @@
 
     public void setHeaderClickable(boolean clickable) {
         if (DEBUG) Log.d(TAG, "setHeaderClickable " + clickable);
-        mHeader.setClickable(clickable);
+        mFooter.getExpandView().setClickable(clickable);
     }
 
     public void setExpanded(boolean expanded) {
@@ -185,11 +193,13 @@
         if (DEBUG) Log.d(TAG, "setListening " + listening);
         mListening = listening;
         mHeader.setListening(listening);
+        mFooter.setListening(listening);
         mQSPanel.setListening(mListening && mQsExpanded);
     }
 
     public void setHeaderListening(boolean listening) {
         mHeader.setListening(listening);
+        mFooter.setListening(listening);
     }
 
     public void setQsExpansion(float expansion, float headerTranslation) {
@@ -201,7 +211,9 @@
                     : headerTranslation);
         }
         mHeader.setExpansion(mKeyguardShowing ? 1 : expansion);
-        mQSPanel.setTranslationY(translationScaleY * mQSPanel.getHeight());
+        mFooter.setExpansion(mKeyguardShowing ? 1 : expansion);
+        int heightDiff = mQSPanel.getBottom() - mHeader.getBottom() + mHeader.getPaddingBottom();
+        mQSPanel.setTranslationY(translationScaleY * heightDiff);
         mQSDetail.setFullyExpanded(expansion == 1);
 
         if (mQSAnimator != null) {
@@ -209,7 +221,7 @@
         }
 
         // Set bounds on the QS panel so it doesn't run over the header.
-        mQsBounds.top = (int) (mQSPanel.getHeight() * (1 - expansion));
+        mQsBounds.top = (int) (mHeader.getBottom() * (1 - expansion));
         mQsBounds.right = mQSPanel.getWidth();
         mQsBounds.bottom = mQSPanel.getHeight();
         mQSPanel.setClipBounds(mQsBounds);
@@ -245,6 +257,11 @@
     }
 
     @Override
+    public void setExpandClickListener(OnClickListener onClickListener) {
+        mFooter.getExpandView().setOnClickListener(onClickListener);
+    }
+
+    @Override
     public void closeDetail() {
         mQSPanel.closeDetail();
     }
@@ -254,6 +271,7 @@
         mContainer.updateBottom();
         mQSPanel.setVisibility(!mQSCustomizer.isCustomizing() ? View.VISIBLE : View.INVISIBLE);
         mHeader.setVisibility(!mQSCustomizer.isCustomizing() ? View.VISIBLE : View.INVISIBLE);
+        mFooter.setVisibility(!mQSCustomizer.isCustomizing() ? View.VISIBLE : View.INVISIBLE);
         // Let the panel know the position changed and it needs to update where notifications
         // and whatnot are.
         mPanelView.onQsHeightChanged();
@@ -268,7 +286,8 @@
             return getView().getHeight();
         }
         if (mQSDetail.isClosingDetail()) {
-            int panelHeight = ((LayoutParams) mQSPanel.getLayoutParams()).topMargin
+            LayoutParams layoutParams = (LayoutParams) mQSPanel.getLayoutParams();
+            int panelHeight = layoutParams.topMargin + layoutParams.bottomMargin +
                     + mQSPanel.getMeasuredHeight();
             return panelHeight + getView().getPaddingBottom();
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
new file mode 100644
index 0000000..29d547c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
@@ -0,0 +1,38 @@
+/*
+ * 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.qs;
+
+import android.content.Context;
+
+import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.qs.external.TileServices;
+
+import java.util.Collection;
+
+public interface QSHost {
+    void warn(String message, Throwable t);
+    void collapsePanels();
+    void openPanels();
+    Context getContext();
+    Collection<QSTile> getTiles();
+    void addCallback(Callback callback);
+    void removeCallback(Callback callback);
+    TileServices getTileServices();
+    void removeTile(String tileSpec);
+
+    interface Callback {
+        void onTilesChanged();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index e8d5ece..8298cbb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -16,12 +16,15 @@
 
 package com.android.systemui.qs;
 
+import static com.android.systemui.qs.tileimpl.QSTileImpl.getColorForState;
+
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.os.Handler;
 import android.os.Message;
+import android.service.quicksettings.Tile;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -31,14 +34,14 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.plugins.qs.QS;
-import com.android.systemui.plugins.qs.QS.DetailAdapter;
-import com.android.systemui.qs.QSTile.Host.Callback;
+import com.android.systemui.plugins.qs.DetailAdapter;
+import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.plugins.qs.QSTileView;
+import com.android.systemui.qs.QSHost.Callback;
 import com.android.systemui.qs.customize.QSCustomizer;
 import com.android.systemui.qs.external.CustomTile;
 import com.android.systemui.settings.BrightnessController;
 import com.android.systemui.settings.ToggleSliderView;
-import com.android.systemui.statusbar.phone.QSTileHost;
 import com.android.systemui.statusbar.policy.BrightnessMirrorController;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.tuner.TunerService.Tunable;
@@ -62,11 +65,11 @@
     protected boolean mExpanded;
     protected boolean mListening;
 
-    private QS.Callback mCallback;
+    private QSDetail.Callback mCallback;
     private BrightnessController mBrightnessController;
     protected QSTileHost mHost;
 
-    protected QSFooter mFooter;
+    protected QSSecurityFooter mFooter;
     private boolean mGridContentVisible = true;
 
     protected QSTileLayout mTileLayout;
@@ -75,6 +78,7 @@
     private Record mDetailRecord;
 
     private BrightnessMirrorController mBrightnessMirrorController;
+    private View mDivider;
 
     public QSPanel(Context context) {
         this(context, null);
@@ -92,7 +96,7 @@
 
         setupTileLayout();
 
-        mFooter = new QSFooter(this, context);
+        mFooter = new QSSecurityFooter(this, context);
         addView(mFooter.getView());
 
         mPageIndicator = LayoutInflater.from(context).inflate(
@@ -102,11 +106,23 @@
             ((PagedTileLayout) mTileLayout).setPageIndicator((PageIndicator) mPageIndicator);
         }
 
+        addDivider();
+
         updateResources();
 
         mBrightnessController = new BrightnessController(getContext(),
-                (ImageView) findViewById(R.id.brightness_icon),
-                (ToggleSliderView) findViewById(R.id.brightness_slider));
+                findViewById(R.id.brightness_icon),
+                findViewById(R.id.brightness_slider));
+    }
+
+    protected void addDivider() {
+        mDivider = LayoutInflater.from(mContext).inflate(R.layout.qs_divider, this, false);
+        mDivider.setBackgroundColor(getColorForState(mContext, Tile.STATE_INACTIVE));
+        addView(mDivider);
+    }
+
+    public View getDivider() {
+        return mDivider;
     }
 
     public View getPageIndicator() {
@@ -159,11 +175,11 @@
     }
 
     public void openDetails(String subPanel) {
-        QSTile<?> tile = getTile(subPanel);
+        QSTile tile = getTile(subPanel);
         showDetailAdapter(true, tile.getDetailAdapter(), new int[] {getWidth() / 2, 0});
     }
 
-    private QSTile<?> getTile(String subPanel) {
+    private QSTile getTile(String subPanel) {
         for (int i = 0; i < mRecords.size(); i++) {
             if (subPanel.equals(mRecords.get(i).tile.getTileSpec())) {
                 return mRecords.get(i).tile;
@@ -174,8 +190,8 @@
 
     public void setBrightnessMirror(BrightnessMirrorController c) {
         mBrightnessMirrorController = c;
-        ToggleSliderView brightnessSlider = (ToggleSliderView) findViewById(R.id.brightness_slider);
-        ToggleSliderView mirror = (ToggleSliderView) c.getMirror().findViewById(
+        ToggleSliderView brightnessSlider = findViewById(R.id.brightness_slider);
+        ToggleSliderView mirror = c.getMirror().findViewById(
                 R.id.brightness_slider);
         brightnessSlider.setMirror(mirror);
         brightnessSlider.setMirrorController(c);
@@ -185,7 +201,7 @@
         return mBrightnessView;
     }
 
-    public void setCallback(QS.Callback callback) {
+    public void setCallback(QSDetail.Callback callback) {
         mCallback = callback;
     }
 
@@ -301,17 +317,17 @@
         mHandler.obtainMessage(H.SHOW_DETAIL, show ? 1 : 0, 0, r).sendToTarget();
     }
 
-    public void setTiles(Collection<QSTile<?>> tiles) {
+    public void setTiles(Collection<QSTile> tiles) {
         setTiles(tiles, false);
     }
 
-    public void setTiles(Collection<QSTile<?>> tiles, boolean collapsedView) {
+    public void setTiles(Collection<QSTile> tiles, boolean collapsedView) {
         for (TileRecord record : mRecords) {
             mTileLayout.removeTile(record);
             record.tile.removeCallback(record.callback);
         }
         mRecords.clear();
-        for (QSTile<?> tile : tiles) {
+        for (QSTile tile : tiles) {
             addTile(tile, collapsedView);
         }
     }
@@ -320,15 +336,15 @@
         r.tileView.onStateChanged(state);
     }
 
-    protected QSTileBaseView createTileView(QSTile<?> tile, boolean collapsedView) {
-        return new QSTileView(mContext, tile.createTileView(mContext), collapsedView);
+    protected QSTileView createTileView(QSTile tile, boolean collapsedView) {
+        return mHost.createTileView(tile, collapsedView);
     }
 
     protected boolean shouldShowDetail() {
         return mExpanded;
     }
 
-    protected TileRecord addTile(final QSTile<?> tile, boolean collapsedView) {
+    protected TileRecord addTile(final QSTile tile, boolean collapsedView) {
         final TileRecord r = new TileRecord();
         r.tile = tile;
         r.tileView = createTileView(tile, collapsedView);
@@ -372,10 +388,7 @@
         };
         r.tile.addCallback(callback);
         r.callback = callback;
-        r.tileView.init(v -> r.tile.click(), v -> r.tile.secondaryClick(), v -> {
-            r.tile.longClick();
-            return true;
-        });
+        r.tileView.init(r.tile);
         r.tile.refreshState();
         mRecords.add(r);
 
@@ -441,15 +454,7 @@
         }
         r.tile.setDetailListening(show);
         int x = r.tileView.getLeft() + r.tileView.getWidth() / 2;
-        int y;
-        if (r.tileView instanceof QSTileView) {
-            View labelContainer = (View) ((QSTileView) r.tileView).getLabel().getParent();
-            y = r.tileView.getTop() + mTileLayout.getOffsetTop(r) + getTop()
-                    + labelContainer.getTop() + labelContainer.getHeight() / 2;
-        } else {
-            y = r.tileView.getTop() + mTileLayout.getOffsetTop(r) + r.tileView.getHeight() / 2
-                    + getTop();
-        }
+        int y = r.tileView.getDetailY() + mTileLayout.getOffsetTop(r) + getTop();
         handleShowDetailImpl(r, show, x, y);
     }
 
@@ -515,7 +520,7 @@
         return mTileLayout;
     }
 
-    QSTileBaseView getTileView(QSTile<?> tile) {
+    QSTileView getTileView(QSTile tile) {
         for (TileRecord r : mRecords) {
             if (r.tile == tile) {
                 return r.tileView;
@@ -524,7 +529,7 @@
         return null;
     }
 
-    public QSFooter getFooter() {
+    public QSSecurityFooter getFooter() {
         return mFooter;
     }
 
@@ -553,8 +558,8 @@
     }
 
     public static final class TileRecord extends Record {
-        public QSTile<?> tile;
-        public QSTileBaseView tileView;
+        public QSTile tile;
+        public com.android.systemui.plugins.qs.QSTileView tileView;
         public boolean scanState;
         public QSTile.Callback callback;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
new file mode 100644
index 0000000..4b2c20f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
@@ -0,0 +1,381 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.qs;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.provider.Settings;
+import android.text.SpannableStringBuilder;
+import android.text.method.LinkMovementMethod;
+import android.text.style.ClickableSpan;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.View.OnClickListener;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.FontSizeUtils;
+import com.android.systemui.R;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.statusbar.phone.SystemUIDialog;
+import com.android.systemui.statusbar.policy.SecurityController;
+
+import static android.provider.Settings.ACTION_VPN_SETTINGS;
+
+public class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListener {
+    protected static final String TAG = "QSSecurityFooter";
+    protected static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+    private final View mRootView;
+    private final TextView mFooterText;
+    private final ImageView mFooterIcon;
+    private final ImageView mFooterIcon2;
+    private final Context mContext;
+    private final Callback mCallback = new Callback();
+    private final SecurityController mSecurityController;
+    private final ActivityStarter mActivityStarter;
+    private final Handler mMainHandler;
+
+    private AlertDialog mDialog;
+    private QSTileHost mHost;
+    protected H mHandler;
+
+    private boolean mIsVisible;
+    private boolean mIsIconVisible;
+    private boolean mIsIcon2Visible;
+    private CharSequence mFooterTextContent = null;
+    private int mFooterTextId;
+    private int mFooterIconId;
+    private int mFooterIcon2Id;
+
+    public QSSecurityFooter(QSPanel qsPanel, Context context) {
+        mRootView = LayoutInflater.from(context)
+                .inflate(R.layout.quick_settings_footer, qsPanel, false);
+        mRootView.setOnClickListener(this);
+        mFooterText = (TextView) mRootView.findViewById(R.id.footer_text);
+        mFooterIcon = (ImageView) mRootView.findViewById(R.id.footer_icon);
+        mFooterIcon2 = (ImageView) mRootView.findViewById(R.id.footer_icon2);
+        mFooterIconId = R.drawable.ic_qs_vpn;
+        mFooterIcon2Id = R.drawable.ic_qs_network_logging;
+        mContext = context;
+        mMainHandler = new Handler(Looper.getMainLooper());
+        mActivityStarter = Dependency.get(ActivityStarter.class);
+        mSecurityController = Dependency.get(SecurityController.class);
+        mHandler = new H(Dependency.get(Dependency.BG_LOOPER));
+    }
+
+    public void setHostEnvironment(QSTileHost host) {
+        mHost = host;
+    }
+
+    public void setListening(boolean listening) {
+        if (listening) {
+            mSecurityController.addCallback(mCallback);
+        } else {
+            mSecurityController.removeCallback(mCallback);
+        }
+    }
+
+    public void onConfigurationChanged() {
+        FontSizeUtils.updateFontSize(mFooterText, R.dimen.qs_tile_text_size);
+    }
+
+    public View getView() {
+        return mRootView;
+    }
+
+    public boolean hasFooter() {
+        return mRootView.getVisibility() != View.GONE;
+    }
+
+    @Override
+    public void onClick(View v) {
+        mHandler.sendEmptyMessage(H.CLICK);
+    }
+
+    private void handleClick() {
+        showDeviceMonitoringDialog();
+    }
+
+    public void showDeviceMonitoringDialog() {
+        mHost.collapsePanels();
+        // TODO: Delay dialog creation until after panels are collapsed.
+        createDialog();
+    }
+
+    public void refreshState() {
+        mHandler.sendEmptyMessage(H.REFRESH_STATE);
+    }
+
+    private void handleRefreshState() {
+        boolean isVpnEnabled = mSecurityController.isVpnEnabled();
+        boolean isNetworkLoggingEnabled = mSecurityController.isNetworkLoggingEnabled();
+        mIsIconVisible = isVpnEnabled || isNetworkLoggingEnabled;
+        mIsIcon2Visible = isVpnEnabled && isNetworkLoggingEnabled;
+        if (mSecurityController.isDeviceManaged()) {
+            final CharSequence organizationName =
+                    mSecurityController.getDeviceOwnerOrganizationName();
+            if (organizationName != null) {
+                mFooterTextContent = mContext.getResources().getString(
+                        R.string.do_disclosure_with_name, organizationName);
+            } else {
+                mFooterTextContent =
+                        mContext.getResources().getString(R.string.do_disclosure_generic);
+            }
+            mIsVisible = true;
+            int footerIconId = isVpnEnabled
+                    ? R.drawable.ic_qs_vpn
+                    : R.drawable.ic_qs_network_logging;
+            if (mFooterIconId != footerIconId) {
+                mFooterIconId = footerIconId;
+                mMainHandler.post(mUpdateIcon);
+            }
+        } else {
+            boolean isBranded = mSecurityController.isVpnBranded();
+            mFooterTextContent = mContext.getResources().getText(
+                    isBranded ? R.string.branded_vpn_footer : R.string.vpn_footer);
+            // Update the VPN footer icon, if needed.
+            int footerIconId = isVpnEnabled
+                    ? (isBranded ? R.drawable.ic_qs_branded_vpn : R.drawable.ic_qs_vpn)
+                    : R.drawable.ic_qs_network_logging;
+            if (mFooterIconId != footerIconId) {
+                mFooterIconId = footerIconId;
+                mMainHandler.post(mUpdateIcon);
+            }
+            mIsVisible = mIsIconVisible;
+        }
+        mMainHandler.post(mUpdateDisplayState);
+    }
+
+    @Override
+    public void onClick(DialogInterface dialog, int which) {
+        if (which == DialogInterface.BUTTON_NEGATIVE) {
+            final Intent settingsIntent = new Intent(ACTION_VPN_SETTINGS);
+            mActivityStarter.postStartActivityDismissingKeyguard(settingsIntent, 0);
+        }
+    }
+
+    private void createDialog() {
+        final String deviceOwnerPackage = mSecurityController.getDeviceOwnerName();
+        final String profileOwnerPackage = mSecurityController.getProfileOwnerName();
+        final boolean isNetworkLoggingEnabled = mSecurityController.isNetworkLoggingEnabled();
+        final String primaryVpn = mSecurityController.getPrimaryVpnName();
+        final String profileVpn = mSecurityController.getProfileVpnName();
+        final CharSequence deviceOwnerOrganization =
+                mSecurityController.getDeviceOwnerOrganizationName();
+        boolean hasProfileOwner = mSecurityController.hasProfileOwner();
+        boolean isBranded = deviceOwnerPackage == null && mSecurityController.isVpnBranded();
+
+        mDialog = new SystemUIDialog(mContext);
+        if (!isBranded) {
+            mDialog.setTitle(getTitle(deviceOwnerPackage));
+        }
+        CharSequence msg = getMessage(deviceOwnerPackage, profileOwnerPackage, primaryVpn,
+                profileVpn, deviceOwnerOrganization, hasProfileOwner, isBranded);
+        if (deviceOwnerPackage == null) {
+            mDialog.setMessage(msg);
+            if (mSecurityController.isVpnEnabled() && !mSecurityController.isVpnRestricted()) {
+                mDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getSettingsButton(), this);
+            }
+        } else {
+            View dialogView = LayoutInflater.from(mContext)
+                   .inflate(R.layout.quick_settings_footer_dialog, null, false);
+            mDialog.setView(dialogView);
+            TextView deviceOwnerWarning =
+                    (TextView) dialogView.findViewById(R.id.device_owner_warning);
+            deviceOwnerWarning.setText(msg);
+            // Make the link "learn more" clickable.
+            deviceOwnerWarning.setMovementMethod(new LinkMovementMethod());
+            if (primaryVpn == null) {
+                dialogView.findViewById(R.id.vpn_icon).setVisibility(View.GONE);
+                dialogView.findViewById(R.id.vpn_subtitle).setVisibility(View.GONE);
+                dialogView.findViewById(R.id.vpn_warning).setVisibility(View.GONE);
+            } else {
+                final SpannableStringBuilder message = new SpannableStringBuilder();
+                message.append(mContext.getString(R.string.monitoring_description_do_body_vpn,
+                        primaryVpn));
+                if (!mSecurityController.isVpnRestricted()) {
+                    message.append(mContext.getString(
+                            R.string.monitoring_description_vpn_settings_separator));
+                    message.append(mContext.getString(R.string.monitoring_description_vpn_settings),
+                            new VpnSpan(), 0);
+                }
+
+                TextView vpnWarning = (TextView) dialogView.findViewById(R.id.vpn_warning);
+                vpnWarning.setText(message);
+                // Make the link "Open VPN Settings" clickable.
+                vpnWarning.setMovementMethod(new LinkMovementMethod());
+            }
+            if (!isNetworkLoggingEnabled) {
+                dialogView.findViewById(R.id.network_logging_icon).setVisibility(View.GONE);
+                dialogView.findViewById(R.id.network_logging_subtitle).setVisibility(View.GONE);
+                dialogView.findViewById(R.id.network_logging_warning).setVisibility(View.GONE);
+            }
+        }
+
+        mDialog.setButton(DialogInterface.BUTTON_POSITIVE, getPositiveButton(isBranded), this);
+        mDialog.show();
+        mDialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+    }
+
+    private String getSettingsButton() {
+        return mContext.getString(R.string.status_bar_settings_settings_button);
+    }
+
+    private String getPositiveButton(boolean isBranded) {
+        return mContext.getString(isBranded ? android.R.string.ok : R.string.quick_settings_done);
+    }
+
+    protected CharSequence getMessage(String deviceOwnerPackage, String profileOwnerPackage,
+            String primaryVpn, String profileVpn, CharSequence deviceOwnerOrganization,
+            boolean hasProfileOwner, boolean isBranded) {
+        if (deviceOwnerPackage != null) {
+            final SpannableStringBuilder message = new SpannableStringBuilder();
+            if (deviceOwnerOrganization != null) {
+                message.append(mContext.getString(
+                        R.string.monitoring_description_do_header_with_name,
+                        deviceOwnerOrganization, deviceOwnerPackage));
+            } else {
+                message.append(mContext.getString(R.string.monitoring_description_do_header_generic,
+                        deviceOwnerPackage));
+            }
+            message.append("\n\n");
+            message.append(mContext.getString(R.string.monitoring_description_do_body));
+            message.append(mContext.getString(
+                    R.string.monitoring_description_do_learn_more_separator));
+            message.append(mContext.getString(R.string.monitoring_description_do_learn_more),
+                    new EnterprisePrivacySpan(), 0);
+            return message;
+        } else if (primaryVpn != null) {
+            if (profileVpn != null) {
+                return mContext.getString(R.string.monitoring_description_app_personal_work,
+                        profileOwnerPackage, profileVpn, primaryVpn);
+            } else {
+                if (isBranded) {
+                    return mContext.getString(R.string.branded_monitoring_description_app_personal,
+                            primaryVpn);
+                } else {
+                    return mContext.getString(R.string.monitoring_description_app_personal,
+                            primaryVpn);
+                }
+            }
+        } else if (profileVpn != null) {
+            return mContext.getString(R.string.monitoring_description_app_work,
+                    profileOwnerPackage, profileVpn);
+        } else if (profileOwnerPackage != null && hasProfileOwner) {
+            return mContext.getString(R.string.do_disclosure_with_name,
+                    profileOwnerPackage);
+        } else {
+            // No device owner, no personal VPN, no work VPN, no user owner. Why are we here?
+            return null;
+        }
+    }
+
+    private int getTitle(String deviceOwner) {
+        if (deviceOwner != null) {
+            return R.string.monitoring_title_device_owned;
+        } else {
+            return R.string.monitoring_title;
+        }
+    }
+
+    private final Runnable mUpdateIcon = new Runnable() {
+        @Override
+        public void run() {
+            mFooterIcon.setImageResource(mFooterIconId);
+            mFooterIcon2.setImageResource(mFooterIcon2Id);
+        }
+    };
+
+    private final Runnable mUpdateDisplayState = new Runnable() {
+        @Override
+        public void run() {
+            if (mFooterTextContent != null) {
+                mFooterText.setText(mFooterTextContent);
+            }
+            mRootView.setVisibility(mIsVisible ? View.VISIBLE : View.GONE);
+            mFooterIcon.setVisibility(mIsIconVisible ? View.VISIBLE : View.INVISIBLE);
+            mFooterIcon2.setVisibility(mIsIcon2Visible ? View.VISIBLE : View.INVISIBLE);
+        }
+    };
+
+    private class Callback implements SecurityController.SecurityControllerCallback {
+        @Override
+        public void onStateChanged() {
+            refreshState();
+        }
+    }
+
+    private class H extends Handler {
+        private static final int CLICK = 0;
+        private static final int REFRESH_STATE = 1;
+
+        private H(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            String name = null;
+            try {
+                if (msg.what == REFRESH_STATE) {
+                    name = "handleRefreshState";
+                    handleRefreshState();
+                } else if (msg.what == CLICK) {
+                    name = "handleClick";
+                    handleClick();
+                }
+            } catch (Throwable t) {
+                final String error = "Error in " + name;
+                Log.w(TAG, error, t);
+                mHost.warn(error, t);
+            }
+        }
+    }
+
+    protected class EnterprisePrivacySpan extends ClickableSpan {
+        @Override
+        public void onClick(View widget) {
+            final Intent intent = new Intent(Settings.ACTION_ENTERPRISE_PRIVACY_SETTINGS);
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+            mDialog.dismiss();
+            mContext.startActivity(intent);
+        }
+
+        @Override
+        public boolean equals(Object object) {
+            return object instanceof EnterprisePrivacySpan;
+        }
+    }
+
+    protected class VpnSpan extends ClickableSpan {
+        @Override
+        public void onClick(View widget) {
+            final Intent intent = new Intent(Settings.ACTION_VPN_SETTINGS);
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+            mDialog.dismiss();
+            mContext.startActivity(intent);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
similarity index 73%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
rename to packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index a1022c4..0ca115e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -1,20 +1,18 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
  */
 
-package com.android.systemui.statusbar.phone;
+package com.android.systemui.qs;
 
 import android.app.ActivityManager;
 import android.content.ComponentName;
@@ -32,28 +30,18 @@
 
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.qs.QSTile;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.plugins.qs.QSFactory;
+import com.android.systemui.plugins.qs.QSTileView;
+import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.qs.external.CustomTile;
 import com.android.systemui.qs.external.TileLifecycleManager;
 import com.android.systemui.qs.external.TileServices;
-import com.android.systemui.qs.tiles.AirplaneModeTile;
-import com.android.systemui.qs.tiles.BatteryTile;
-import com.android.systemui.qs.tiles.BluetoothTile;
-import com.android.systemui.qs.tiles.CastTile;
-import com.android.systemui.qs.tiles.CellularTile;
-import com.android.systemui.qs.tiles.ColorInversionTile;
-import com.android.systemui.qs.tiles.DataSaverTile;
-import com.android.systemui.qs.tiles.DndTile;
-import com.android.systemui.qs.tiles.FlashlightTile;
-import com.android.systemui.qs.tiles.HotspotTile;
-import com.android.systemui.qs.tiles.IntentTile;
-import com.android.systemui.qs.tiles.LocationTile;
-import com.android.systemui.qs.tiles.NfcTile;
-import com.android.systemui.qs.tiles.NightDisplayTile;
-import com.android.systemui.qs.tiles.RotationLockTile;
-import com.android.systemui.qs.tiles.UserTile;
-import com.android.systemui.qs.tiles.WifiTile;
-import com.android.systemui.qs.tiles.WorkModeTile;
+import com.android.systemui.qs.tileimpl.QSFactoryImpl;
+import com.android.systemui.statusbar.phone.AutoTileManager;
+import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.tuner.TunerService.Tunable;
 
@@ -64,7 +52,7 @@
 import java.util.List;
 
 /** Platform implementation of the quick settings tile host **/
-public class QSTileHost implements QSTile.Host, Tunable {
+public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory> {
     private static final String TAG = "QSTileHost";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
@@ -72,13 +60,14 @@
 
     private final Context mContext;
     private final StatusBar mStatusBar;
-    private final LinkedHashMap<String, QSTile<?>> mTiles = new LinkedHashMap<>();
+    private final LinkedHashMap<String, QSTile> mTiles = new LinkedHashMap<>();
     protected final ArrayList<String> mTileSpecs = new ArrayList<>();
     private final TileServices mServices;
 
     private final List<Callback> mCallbacks = new ArrayList<>();
     private final AutoTileManager mAutoTiles;
     private final StatusBarIconController mIconController;
+    private final ArrayList<QSFactory> mQsFactories = new ArrayList<>();
     private int mCurrentUser;
 
     public QSTileHost(Context context, StatusBar statusBar,
@@ -89,6 +78,9 @@
 
         mServices = new TileServices(this, Dependency.get(Dependency.BG_LOOPER));
 
+        mQsFactories.add(new QSFactoryImpl(this));
+        Dependency.get(PluginManager.class).addPluginListener(this, QSFactory.class, true);
+
         Dependency.get(TunerService.class).addTunable(this, TILES_SETTING);
         // AutoTileManager can modify mTiles so make sure mTiles has already been initialized.
         mAutoTiles = new AutoTileManager(context, this);
@@ -103,6 +95,26 @@
         mAutoTiles.destroy();
         Dependency.get(TunerService.class).removeTunable(this);
         mServices.destroy();
+        Dependency.get(PluginManager.class).removePluginListener(this);
+    }
+
+    @Override
+    public void onPluginConnected(QSFactory plugin, Context pluginContext) {
+        // Give plugins priority over creation so they can override if they wish.
+        mQsFactories.add(0, plugin);
+        String value = Dependency.get(TunerService.class).getValue(TILES_SETTING);
+        // Force remove and recreate of all tiles.
+        onTuningChanged(TILES_SETTING, "");
+        onTuningChanged(TILES_SETTING, value);
+    }
+
+    @Override
+    public void onPluginDisconnected(QSFactory plugin) {
+        mQsFactories.remove(plugin);
+        // Force remove and recreate of all tiles.
+        String value = Dependency.get(TunerService.class).getValue(TILES_SETTING);
+        onTuningChanged(TILES_SETTING, "");
+        onTuningChanged(TILES_SETTING, value);
     }
 
     @Override
@@ -116,7 +128,7 @@
     }
 
     @Override
-    public Collection<QSTile<?>> getTiles() {
+    public Collection<QSTile> getTiles() {
         return mTiles.values();
     }
 
@@ -162,9 +174,9 @@
                     if (DEBUG) Log.d(TAG, "Destroying tile: " + tile.getKey());
                     tile.getValue().destroy();
                 });
-        final LinkedHashMap<String, QSTile<?>> newTiles = new LinkedHashMap<>();
+        final LinkedHashMap<String, QSTile> newTiles = new LinkedHashMap<>();
         for (String tileSpec : tileSpecs) {
-            QSTile<?> tile = mTiles.get(tileSpec);
+            QSTile tile = mTiles.get(tileSpec);
             if (tile != null && (!(tile instanceof CustomTile)
                     || ((CustomTile) tile).getUser() == currentUser)) {
                 if (tile.isAvailable()) {
@@ -259,31 +271,24 @@
                 TextUtils.join(",", newTiles), ActivityManager.getCurrentUser());
     }
 
-    public QSTile<?> createTile(String tileSpec) {
-        if (tileSpec.equals("wifi")) return new WifiTile(this);
-        else if (tileSpec.equals("bt")) return new BluetoothTile(this);
-        else if (tileSpec.equals("cell")) return new CellularTile(this);
-        else if (tileSpec.equals("dnd")) return new DndTile(this);
-        else if (tileSpec.equals("inversion")) return new ColorInversionTile(this);
-        else if (tileSpec.equals("airplane")) return new AirplaneModeTile(this);
-        else if (tileSpec.equals("work")) return new WorkModeTile(this);
-        else if (tileSpec.equals("rotation")) return new RotationLockTile(this);
-        else if (tileSpec.equals("flashlight")) return new FlashlightTile(this);
-        else if (tileSpec.equals("location")) return new LocationTile(this);
-        else if (tileSpec.equals("cast")) return new CastTile(this);
-        else if (tileSpec.equals("hotspot")) return new HotspotTile(this);
-        else if (tileSpec.equals("user")) return new UserTile(this);
-        else if (tileSpec.equals("battery")) return new BatteryTile(this);
-        else if (tileSpec.equals("saver")) return new DataSaverTile(this);
-        else if (tileSpec.equals("night")) return new NightDisplayTile(this);
-        else if (tileSpec.equals("nfc")) return new NfcTile(this);
-        // Intent tiles.
-        else if (tileSpec.startsWith(IntentTile.PREFIX)) return IntentTile.create(this,tileSpec);
-        else if (tileSpec.startsWith(CustomTile.PREFIX)) return CustomTile.create(this,tileSpec);
-        else {
-            Log.w(TAG, "Bad tile spec: " + tileSpec);
-            return null;
+    public QSTile createTile(String tileSpec) {
+        for (int i = 0; i < mQsFactories.size(); i++) {
+            QSTile t = mQsFactories.get(i).createTile(tileSpec);
+            if (t != null) {
+                return t;
+            }
         }
+        return null;
+    }
+
+    public QSTileView createTileView(QSTile tile, boolean collapsedView) {
+        for (int i = 0; i < mQsFactories.size(); i++) {
+            QSTileView view = mQsFactories.get(i).createTileView(tile, collapsedView);
+            if (view != null) {
+                return view;
+            }
+        }
+        throw new RuntimeException("Default factory didn't create view for " + tile.getTileSpec());
     }
 
     protected List<String> loadTileSpecs(Context context, String tileList) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index d789b44..8539cb9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -17,7 +17,6 @@
 package com.android.systemui.qs;
 
 import android.content.Context;
-import android.content.res.Configuration;
 import android.util.AttributeSet;
 import android.view.Gravity;
 import android.view.View;
@@ -26,10 +25,11 @@
 
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.qs.QSTile.SignalState;
-import com.android.systemui.qs.QSTile.State;
+import com.android.systemui.plugins.qs.*;
+import com.android.systemui.plugins.qs.QSTile.SignalState;
+import com.android.systemui.plugins.qs.QSTile.State;
+import com.android.systemui.plugins.qs.QSTileView;
 import com.android.systemui.qs.customize.QSCustomizer;
-import com.android.systemui.statusbar.phone.QSTileHost;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.tuner.TunerService.Tunable;
 
@@ -45,10 +45,12 @@
 
     private int mMaxTiles;
     protected QSPanel mFullPanel;
-    private View mHeader;
 
     public QuickQSPanel(Context context, AttributeSet attrs) {
         super(context, attrs);
+        if (mFooter != null) {
+            removeView((View) mFooter.getView());
+        }
         if (mTileLayout != null) {
             for (int i = 0; i < mRecords.size(); i++) {
                 mTileLayout.removeTile(mRecords.get(i));
@@ -61,6 +63,10 @@
     }
 
     @Override
+    protected void addDivider() {
+    }
+
+    @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
         Dependency.get(TunerService.class).addTunable(mNumTiles, NUM_QUICK_TILES);
@@ -74,7 +80,6 @@
 
     public void setQSPanelAndHeader(QSPanel fullPanel, View header) {
         mFullPanel = fullPanel;
-        mHeader = header;
     }
 
     @Override
@@ -85,22 +90,17 @@
     @Override
     protected void drawTile(TileRecord r, State state) {
         if (state instanceof SignalState) {
-            State copy = r.tile.newTileState();
+            SignalState copy = new SignalState();
             state.copyTo(copy);
             // No activity shown in the quick panel.
-            ((SignalState) copy).activityIn = false;
-            ((SignalState) copy).activityOut = false;
+            copy.activityIn = false;
+            copy.activityOut = false;
             state = copy;
         }
         super.drawTile(r, state);
     }
 
     @Override
-    protected QSTileBaseView createTileView(QSTile<?> tile, boolean collapsedView) {
-        return new QSTileBaseView(mContext, tile.createTileView(mContext), collapsedView);
-    }
-
-    @Override
     public void setHost(QSTileHost host, QSCustomizer customizer) {
         super.setHost(host, customizer);
         setTiles(mHost.getTiles());
@@ -123,9 +123,9 @@
     }
 
     @Override
-    public void setTiles(Collection<QSTile<?>> tiles) {
-        ArrayList<QSTile<?>> quickTiles = new ArrayList<>();
-        for (QSTile<?> tile : tiles) {
+    public void setTiles(Collection<QSTile> tiles) {
+        ArrayList<QSTile> quickTiles = new ArrayList<>();
+        for (QSTile tile : tiles) {
             quickTiles.add(tile);
             if (quickTiles.size() == mMaxTiles) {
                 break;
@@ -141,7 +141,7 @@
         }
     };
 
-    public int getNumQuickTiles(Context context) {
+    public static int getNumQuickTiles(Context context) {
         return Dependency.get(TunerService.class).getValue(NUM_QUICK_TILES, 6);
     }
 
@@ -206,7 +206,7 @@
             tile.tile.setListening(this, false);
         }
 
-        private int getChildIndex(QSTileBaseView tileView) {
+        private int getChildIndex(QSTileView tileView) {
             final int N = getChildCount();
             for (int i = 0; i < N; i++) {
                 if (getChildAt(i) == tileView) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
new file mode 100644
index 0000000..d0d6f61
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -0,0 +1,146 @@
+/*
+ * 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.qs;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.support.annotation.VisibleForTesting;
+import android.util.AttributeSet;
+import android.widget.RelativeLayout;
+
+import com.android.settingslib.Utils;
+import com.android.systemui.BatteryMeterView;
+import com.android.systemui.Dependency;
+import com.android.systemui.R;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.qs.QSDetail.Callback;
+import com.android.systemui.statusbar.SignalClusterView;
+
+
+public class QuickStatusBarHeader extends RelativeLayout {
+
+    private ActivityStarter mActivityStarter;
+
+    private QSPanel mQsPanel;
+
+    private boolean mExpanded;
+    private boolean mListening;
+
+    protected QuickQSPanel mHeaderQsPanel;
+    protected QSTileHost mHost;
+
+    public QuickStatusBarHeader(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        Resources res = getResources();
+
+        mHeaderQsPanel = findViewById(R.id.quick_qs_panel);
+        mHeaderQsPanel.setVisibility(res.getBoolean(R.bool.config_showQuickSettingsRow)
+                ? VISIBLE : GONE);
+
+        // RenderThread is doing more harm than good when touching the header (to expand quick
+        // settings), so disable it for this view
+
+        updateResources();
+
+        // Set the light/dark theming on the header status UI to match the current theme.
+        SignalClusterView cluster = findViewById(R.id.signal_cluster);
+        int colorForeground = Utils.getColorAttr(getContext(), android.R.attr.colorForeground);
+        float intensity = colorForeground == Color.WHITE ? 0 : 1;
+        cluster.onDarkChanged(new Rect(0, 0, 0, 0), intensity, colorForeground);
+
+        BatteryMeterView battery = findViewById(R.id.battery);
+        battery.setForceShowPercent(true);
+        int colorSecondary = Utils.getColorAttr(getContext(), android.R.attr.textColorSecondary);
+        battery.setRawColors(colorForeground, colorSecondary);
+
+        mActivityStarter = Dependency.get(ActivityStarter.class);
+    }
+
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        updateResources();
+    }
+
+    @Override
+    public void onRtlPropertiesChanged(int layoutDirection) {
+        super.onRtlPropertiesChanged(layoutDirection);
+        updateResources();
+    }
+
+    private void updateResources() {
+    }
+
+    public int getCollapsedHeight() {
+        return getHeight();
+    }
+
+    public int getExpandedHeight() {
+        return getHeight();
+    }
+
+    public void setExpanded(boolean expanded) {
+        if (mExpanded == expanded) return;
+        mExpanded = expanded;
+        mHeaderQsPanel.setExpanded(expanded);
+        updateEverything();
+    }
+
+    public void setExpansion(float headerExpansionFraction) {
+    }
+
+    @Override
+    @VisibleForTesting
+    public void onDetachedFromWindow() {
+        setListening(false);
+        super.onDetachedFromWindow();
+    }
+
+    public void setListening(boolean listening) {
+        if (listening == mListening) {
+            return;
+        }
+        mHeaderQsPanel.setListening(listening);
+        mListening = listening;
+    }
+
+    public void updateEverything() {
+        post(() -> setClickable(false));
+    }
+
+    public void setQSPanel(final QSPanel qsPanel) {
+        mQsPanel = qsPanel;
+        setupHost(qsPanel.getHost());
+    }
+
+    public void setupHost(final QSTileHost host) {
+        mHost = host;
+        //host.setHeaderView(mExpandIndicator);
+        mHeaderQsPanel.setQSPanelAndHeader(mQsPanel, this);
+        mHeaderQsPanel.setHost(host, null /* No customization in header */);
+    }
+
+    public void setCallback(Callback qsPanelCallback) {
+        mHeaderQsPanel.setCallback(qsPanelCallback);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java b/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
index 8555e31..01f8169 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
@@ -24,15 +24,17 @@
 import android.widget.ImageView;
 
 import com.android.systemui.R;
-import com.android.systemui.qs.QSTile.SignalState;
+import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.plugins.qs.QSTile.SignalState;
+import com.android.systemui.qs.tileimpl.QSIconViewImpl;
 
 /** View that represents a custom quick settings tile for displaying signal info (wifi/cell). **/
-public final class SignalTileView extends QSIconView {
+public class SignalTileView extends QSIconViewImpl {
     private static final long DEFAULT_DURATION = new ValueAnimator().getDuration();
     private static final long SHORT_DURATION = DEFAULT_DURATION / 3;
 
-    private FrameLayout mIconFrame;
-    private ImageView mSignal;
+    protected FrameLayout mIconFrame;
+    protected ImageView mSignal;
     private ImageView mIn;
     private ImageView mOut;
 
@@ -107,9 +109,6 @@
         final SignalState s = (SignalState) state;
         setIcon(mSignal, s);
         Drawable drawable = mSignal.getDrawable();
-        if (state.autoMirrorDrawable && drawable != null) {
-            drawable.setAutoMirrored(true);
-        }
         final boolean shown = isShown();
         setVisibility(mIn, shown, s.activityIn);
         setVisibility(mOut, shown, s.activityOut);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.java b/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.java
index 26fc6df..0629d66 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.java
@@ -19,8 +19,8 @@
 import android.view.View;
 import android.widget.TextView;
 import com.android.systemui.R;
-import com.android.systemui.qs.QSIconView;
-import com.android.systemui.qs.QSTileView;
+import com.android.systemui.plugins.qs.QSIconView;
+import com.android.systemui.qs.tileimpl.QSTileView;
 import libcore.util.Objects;
 
 public class CustomizeTileView extends QSTileView {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 730b55d..c0fb4d5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -20,6 +20,8 @@
 import android.animation.AnimatorListenerAdapter;
 import android.content.Context;
 import android.content.res.Configuration;
+import android.os.Handler;
+import android.os.Looper;
 import android.support.v7.widget.DefaultItemAnimator;
 import android.support.v7.widget.GridLayoutManager;
 import android.support.v7.widget.RecyclerView;
@@ -40,9 +42,9 @@
 import com.android.systemui.R;
 import com.android.systemui.plugins.qs.QS;
 import com.android.systemui.qs.QSDetailClipper;
-import com.android.systemui.qs.QSTile;
+import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
-import com.android.systemui.statusbar.phone.QSTileHost;
+import com.android.systemui.qs.QSTileHost;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
 import com.android.systemui.statusbar.policy.KeyguardMonitor.Callback;
 
@@ -69,6 +71,9 @@
     private boolean mCustomizing;
     private NotificationsQuickSettingsContainer mNotifQsContainer;
     private QS mQs;
+    private boolean mFinishedFetchingTiles = false;
+    private int mX;
+    private int mY;
 
     public QSCustomizer(Context context, AttributeSet attrs) {
         super(new ContextThemeWrapper(context, R.style.edit_theme), attrs);
@@ -131,12 +136,14 @@
 
     public void show(int x, int y) {
         if (!isShown) {
+            mX = x;
+            mY = y;
             MetricsLogger.visible(getContext(), MetricsProto.MetricsEvent.QS_EDIT);
             isShown = true;
             setTileSpecs();
             setVisibility(View.VISIBLE);
             mClipper.animateCircularClip(x, y, true, mExpandAnimationListener);
-            new TileQueryHelper(mContext, mHost).setListener(mTileAdapter);
+            queryTiles();
             mNotifQsContainer.setCustomizerAnimating(true);
             mNotifQsContainer.setCustomizerShowing(true);
             announceForAccessibility(mContext.getString(
@@ -145,6 +152,15 @@
         }
     }
 
+    private void queryTiles() {
+        mFinishedFetchingTiles = false;
+        Runnable tileQueryFetchCompletion = () -> {
+            Handler mainHandler = new Handler(Looper.getMainLooper());
+            mainHandler.post(() -> mFinishedFetchingTiles = true);
+        };
+        new TileQueryHelper(mContext, mHost, mTileAdapter, tileQueryFetchCompletion);
+    }
+
     public void hide(int x, int y) {
         if (isShown) {
             MetricsLogger.hidden(getContext(), MetricsProto.MetricsEvent.QS_EDIT);
@@ -152,7 +168,7 @@
             mToolbar.dismissPopupMenus();
             setCustomizing(false);
             save();
-            mClipper.animateCircularClip(x, y, false, mCollapseAnimationListener);
+            mClipper.animateCircularClip(mX, mY, false, mCollapseAnimationListener);
             mNotifQsContainer.setCustomizerAnimating(true);
             mNotifQsContainer.setCustomizerShowing(false);
             announceForAccessibility(mContext.getString(
@@ -204,7 +220,9 @@
     }
 
     private void save() {
-        mTileAdapter.saveSpecs(mHost);
+        if (mFinishedFetchingTiles) {
+            mTileAdapter.saveSpecs(mHost);
+        }
     }
 
     private final Callback mKeyguardCallback = () -> {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index 4e30797..c33d7da 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -42,12 +42,12 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.systemui.R;
-import com.android.systemui.qs.QSIconView;
+import com.android.systemui.qs.tileimpl.QSIconViewImpl;
 import com.android.systemui.qs.customize.TileAdapter.Holder;
 import com.android.systemui.qs.customize.TileQueryHelper.TileInfo;
 import com.android.systemui.qs.customize.TileQueryHelper.TileStateListener;
 import com.android.systemui.qs.external.CustomTile;
-import com.android.systemui.statusbar.phone.QSTileHost;
+import com.android.systemui.qs.QSTileHost;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
 
 import java.util.ArrayList;
@@ -190,7 +190,7 @@
         }
         FrameLayout frame = (FrameLayout) inflater.inflate(R.layout.qs_customize_tile_frame, parent,
                 false);
-        frame.addView(new CustomizeTileView(context, new QSIconView(context)));
+        frame.addView(new CustomizeTileView(context, new QSIconViewImpl(context)));
         return new Holder(frame);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
index 72e6fcc0..547bef7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
@@ -24,7 +24,6 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.graphics.drawable.Drawable;
-import android.os.AsyncTask;
 import android.os.Handler;
 import android.os.Looper;
 import android.service.quicksettings.TileService;
@@ -32,11 +31,11 @@
 
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.qs.QSTile;
-import com.android.systemui.qs.QSTile.DrawableIcon;
-import com.android.systemui.qs.QSTile.State;
+import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.plugins.qs.QSTile.State;
+import com.android.systemui.qs.tileimpl.QSTileImpl.DrawableIcon;
 import com.android.systemui.qs.external.CustomTile;
-import com.android.systemui.statusbar.phone.QSTileHost;
+import com.android.systemui.qs.QSTileHost;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -49,22 +48,36 @@
     private final ArrayList<TileInfo> mTiles = new ArrayList<>();
     private final ArrayList<String> mSpecs = new ArrayList<>();
     private final Context mContext;
-    private TileStateListener mListener;
+    private final TileStateListener mListener;
+    private final QSTileHost mHost;
+    private final Runnable mCompletion;
 
-    public TileQueryHelper(Context context, QSTileHost host) {
+    public TileQueryHelper(Context context, QSTileHost host,
+            TileStateListener listener, Runnable completion) {
         mContext = context;
-        addSystemTiles(host);
+        mListener = listener;
+        mHost = host;
+        mCompletion = completion;
+        addSystemTiles();
         // TODO: Live?
     }
 
-    private void addSystemTiles(final QSTileHost host) {
-        String possible = mContext.getString(R.string.quick_settings_tiles_stock);
-        String[] possibleTiles = possible.split(",");
+    private void addSystemTiles() {
+        // Enqueue jobs to fetch every system tile and then ever package tile.
         final Handler qsHandler = new Handler((Looper) Dependency.get(Dependency.BG_LOOPER));
         final Handler mainHandler = new Handler(Looper.getMainLooper());
+        addStockTiles(mainHandler, qsHandler);
+        addPackageTiles(mainHandler, qsHandler);
+        // Then enqueue the completion. It should always be last
+        qsHandler.post(mCompletion);
+    }
+
+    private void addStockTiles(Handler mainHandler, Handler bgHandler) {
+        String possible = mContext.getString(R.string.quick_settings_tiles_stock);
+        String[] possibleTiles = possible.split(",");
         for (int i = 0; i < possibleTiles.length; i++) {
             final String spec = possibleTiles[i];
-            final QSTile<?> tile = host.createTile(spec);
+            final QSTile tile = mHost.createTile(spec);
             if (tile == null) {
                 continue;
             } else if (!tile.isAvailable()) {
@@ -75,11 +88,10 @@
             tile.clearState();
             tile.refreshState();
             tile.setListening(this, false);
-            qsHandler.post(new Runnable() {
+            bgHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    final QSTile.State state = tile.newTileState();
-                    tile.getState().copyTo(state);
+                    final QSTile.State state = tile.getState().copy();
                     // Ignore the current state and get the generic label instead.
                     state.label = tile.getTileLabel();
                     tile.destroy();
@@ -93,64 +105,16 @@
                 }
             });
         }
-        qsHandler.post(new Runnable() {
-            @Override
-            public void run() {
-                mainHandler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        new QueryTilesTask().execute(host.getTiles());
-                    }
-                });
-            }
-        });
     }
 
-    public void setListener(TileStateListener listener) {
-        mListener = listener;
-    }
-
-    private void addTile(String spec, CharSequence appLabel, State state, boolean isSystem) {
-        if (mSpecs.contains(spec)) {
-            return;
-        }
-        TileInfo info = new TileInfo();
-        info.state = state;
-        info.state.minimalAccessibilityClassName = info.state.expandedAccessibilityClassName =
-                Button.class.getName();
-        info.spec = spec;
-        info.appLabel = appLabel;
-        info.isSystem = isSystem;
-        mTiles.add(info);
-        mSpecs.add(spec);
-    }
-
-    private void addTile(String spec, Drawable drawable, CharSequence label, CharSequence appLabel,
-            Context context) {
-        QSTile.State state = new QSTile.State();
-        state.label = label;
-        state.contentDescription = label;
-        state.icon = new DrawableIcon(drawable);
-        state.autoMirrorDrawable = false;
-        addTile(spec, appLabel, state, false);
-    }
-
-    public static class TileInfo {
-        public String spec;
-        public CharSequence appLabel;
-        public QSTile.State state;
-        public boolean isSystem;
-    }
-
-    private class QueryTilesTask extends
-            AsyncTask<Collection<QSTile<?>>, Void, Collection<TileInfo>> {
-        @Override
-        protected Collection<TileInfo> doInBackground(Collection<QSTile<?>>... params) {
-            List<TileInfo> tiles = new ArrayList<>();
+    private void addPackageTiles(Handler mainHandler, Handler bgHandler) {
+        bgHandler.post(() -> {
+            Collection<QSTile> params = mHost.getTiles();
             PackageManager pm = mContext.getPackageManager();
             List<ResolveInfo> services = pm.queryIntentServicesAsUser(
                     new Intent(TileService.ACTION_QS_TILE), 0, ActivityManager.getCurrentUser());
             String stockTiles = mContext.getString(R.string.quick_settings_tiles_stock);
+
             for (ResolveInfo info : services) {
                 String packageName = info.serviceInfo.packageName;
                 ComponentName componentName = new ComponentName(packageName, info.serviceInfo.name);
@@ -162,7 +126,7 @@
 
                 final CharSequence appLabel = info.serviceInfo.applicationInfo.loadLabel(pm);
                 String spec = CustomTile.toSpec(componentName);
-                State state = getState(params[0], spec);
+                State state = getState(params, spec);
                 if (state != null) {
                     addTile(spec, appLabel, state, false);
                     continue;
@@ -182,25 +146,48 @@
                 CharSequence label = info.serviceInfo.loadLabel(pm);
                 addTile(spec, icon, label != null ? label.toString() : "null", appLabel, mContext);
             }
-            return tiles;
-        }
+            mainHandler.post(() -> mListener.onTilesChanged(mTiles));
+        });
+    }
 
-        private State getState(Collection<QSTile<?>> tiles, String spec) {
-            for (QSTile<?> tile : tiles) {
-                if (spec.equals(tile.getTileSpec())) {
-                    final QSTile.State state = tile.newTileState();
-                    tile.getState().copyTo(state);
-                    return state;
-                }
+    private State getState(Collection<QSTile> tiles, String spec) {
+        for (QSTile tile : tiles) {
+            if (spec.equals(tile.getTileSpec())) {
+                return tile.getState().copy();
             }
-            return null;
         }
+        return null;
+    }
 
-        @Override
-        protected void onPostExecute(Collection<TileInfo> result) {
-            mTiles.addAll(result);
-            mListener.onTilesChanged(mTiles);
+    private void addTile(String spec, CharSequence appLabel, State state, boolean isSystem) {
+        if (mSpecs.contains(spec)) {
+            return;
         }
+        TileInfo info = new TileInfo();
+        info.state = state;
+        info.state.expandedAccessibilityClassName =
+                Button.class.getName();
+        info.spec = spec;
+        info.appLabel = appLabel;
+        info.isSystem = isSystem;
+        mTiles.add(info);
+        mSpecs.add(spec);
+    }
+
+    private void addTile(String spec, Drawable drawable, CharSequence label, CharSequence appLabel,
+            Context context) {
+        QSTile.State state = new QSTile.State();
+        state.label = label;
+        state.contentDescription = label;
+        state.icon = new DrawableIcon(drawable);
+        addTile(spec, appLabel, state, false);
+    }
+
+    public static class TileInfo {
+        public String spec;
+        public CharSequence appLabel;
+        public QSTile.State state;
+        public boolean isSystem;
     }
 
     public interface TileStateListener {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index dea56aa1..6f35017 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -30,26 +30,24 @@
 import android.service.quicksettings.IQSTileService;
 import android.service.quicksettings.Tile;
 import android.service.quicksettings.TileService;
-import android.text.SpannableStringBuilder;
-import android.text.style.ForegroundColorSpan;
 import android.util.Log;
 import android.view.IWindowManager;
-import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.R;
 import com.android.systemui.Dependency;
-import com.android.systemui.ActivityStarter;
-import com.android.systemui.qs.QSTile;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.plugins.qs.QSTile.State;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.qs.external.TileLifecycleManager.TileChangeListener;
-import com.android.systemui.statusbar.phone.QSTileHost;
+import com.android.systemui.qs.QSTileHost;
 import libcore.util.Objects;
 
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
 
-public class CustomTile extends QSTile<QSTile.State> implements TileChangeListener {
+public class CustomTile extends QSTileImpl<State> implements TileChangeListener {
     public static final String PREFIX = "custom(";
 
     private static final boolean DEBUG = false;
@@ -87,7 +85,7 @@
     private void setTileIcon() {
         try {
             PackageManager pm = mContext.getPackageManager();
-            int flags = PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE;
+            int flags = PackageManager.MATCH_DIRECT_BOOT_UNAWARE | PackageManager.MATCH_DIRECT_BOOT_AWARE;
             if (isSystemApp(pm)) {
                 flags |= PackageManager.MATCH_DISABLED_COMPONENTS;
             }
@@ -227,7 +225,6 @@
     @Override
     public State newTileState() {
         State state = new State();
-        state.autoMirrorDrawable = false;
         return state;
     }
 
@@ -292,7 +289,7 @@
             drawable = mTile.getIcon().loadDrawable(mContext);
         } catch (Exception e) {
             Log.w(TAG, "Invalid icon, forcing into unavailable state");
-            tileState = Tile.STATE_UNAVAILABLE;
+            state.state = Tile.STATE_UNAVAILABLE;
             drawable = mDefaultIcon.loadDrawable(mContext);
         }
         state.icon = new DrawableIcon(drawable);
@@ -330,7 +327,7 @@
         return ComponentName.unflattenFromString(action);
     }
 
-    public static QSTile<?> create(QSTileHost host, String spec) {
+    public static QSTile create(QSTileHost host, String spec) {
         if (spec == null || !spec.startsWith(PREFIX) || !spec.endsWith(")")) {
             throw new IllegalArgumentException("Bad custom tile spec: " + spec);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
index ec4ca7a6..d9c3cc3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
@@ -37,7 +37,7 @@
 
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.systemui.Dependency;
-import com.android.systemui.statusbar.phone.QSTileHost;
+import com.android.systemui.qs.QSTileHost;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
new file mode 100644
index 0000000..17a0d33
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use mHost file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.qs.tileimpl;
+
+import android.content.Context;
+import android.util.Log;
+
+import com.android.systemui.plugins.qs.*;
+import com.android.systemui.plugins.qs.QSTileView;
+import com.android.systemui.qs.external.CustomTile;
+import com.android.systemui.qs.tiles.AirplaneModeTile;
+import com.android.systemui.qs.tiles.BatterySaverTile;
+import com.android.systemui.qs.tiles.BluetoothTile;
+import com.android.systemui.qs.tiles.CastTile;
+import com.android.systemui.qs.tiles.CellularTile;
+import com.android.systemui.qs.tiles.ColorInversionTile;
+import com.android.systemui.qs.tiles.DataSaverTile;
+import com.android.systemui.qs.tiles.DndTile;
+import com.android.systemui.qs.tiles.FlashlightTile;
+import com.android.systemui.qs.tiles.HotspotTile;
+import com.android.systemui.qs.tiles.IntentTile;
+import com.android.systemui.qs.tiles.LocationTile;
+import com.android.systemui.qs.tiles.NfcTile;
+import com.android.systemui.qs.tiles.NightDisplayTile;
+import com.android.systemui.qs.tiles.RotationLockTile;
+import com.android.systemui.qs.tiles.UserTile;
+import com.android.systemui.qs.tiles.WifiTile;
+import com.android.systemui.qs.tiles.WorkModeTile;
+import com.android.systemui.qs.QSTileHost;
+
+public class QSFactoryImpl implements QSFactory {
+
+    private static final String TAG = "QSFactory";
+    private final QSTileHost mHost;
+
+    public QSFactoryImpl(QSTileHost host) {
+        mHost = host;
+    }
+
+    public QSTile createTile(String tileSpec) {
+        if (tileSpec.equals("wifi")) return new WifiTile(mHost);
+        else if (tileSpec.equals("bt")) return new BluetoothTile(mHost);
+        else if (tileSpec.equals("cell")) return new CellularTile(mHost);
+        else if (tileSpec.equals("dnd")) return new DndTile(mHost);
+        else if (tileSpec.equals("inversion")) return new ColorInversionTile(mHost);
+        else if (tileSpec.equals("airplane")) return new AirplaneModeTile(mHost);
+        else if (tileSpec.equals("work")) return new WorkModeTile(mHost);
+        else if (tileSpec.equals("rotation")) return new RotationLockTile(mHost);
+        else if (tileSpec.equals("flashlight")) return new FlashlightTile(mHost);
+        else if (tileSpec.equals("location")) return new LocationTile(mHost);
+        else if (tileSpec.equals("cast")) return new CastTile(mHost);
+        else if (tileSpec.equals("hotspot")) return new HotspotTile(mHost);
+        else if (tileSpec.equals("user")) return new UserTile(mHost);
+        else if (tileSpec.equals("battery")) return new BatterySaverTile(mHost);
+        else if (tileSpec.equals("saver")) return new DataSaverTile(mHost);
+        else if (tileSpec.equals("night")) return new NightDisplayTile(mHost);
+        else if (tileSpec.equals("nfc")) return new NfcTile(mHost);
+        // Intent tiles.
+        else if (tileSpec.startsWith(IntentTile.PREFIX)) return IntentTile.create(mHost, tileSpec);
+        else if (tileSpec.startsWith(CustomTile.PREFIX)) return CustomTile.create(mHost, tileSpec);
+        else {
+            Log.w(TAG, "Bad tile spec: " + tileSpec);
+            return null;
+        }
+    }
+
+    @Override
+    public QSTileView createTileView(QSTile tile, boolean collapsedView) {
+        Context context = mHost.getContext();
+        QSIconView icon = tile.createTileView(context);
+        if (collapsedView) {
+            return new QSTileBaseView(context, icon, collapsedView);
+        } else {
+            return new com.android.systemui.qs.tileimpl.QSTileView(context, icon);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
similarity index 81%
rename from packages/SystemUI/src/com/android/systemui/qs/QSIconView.java
rename to packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
index f28a0e7..a751ef4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
@@ -1,22 +1,20 @@
 /*
- * Copyright (C) 2015 The Android Open Source Project
+ * 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
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
  */
 
-package com.android.systemui.qs;
+package com.android.systemui.qs.tileimpl;
 
-import static com.android.systemui.qs.QSTile.getColorForState;
+import static com.android.systemui.qs.tileimpl.QSTileImpl.getColorForState;
 
 import android.animation.ValueAnimator;
 import android.content.Context;
@@ -26,15 +24,17 @@
 import android.graphics.drawable.Animatable;
 import android.graphics.drawable.Drawable;
 import android.view.View;
-import android.view.ViewGroup;
 import android.widget.ImageView;
 import android.widget.ImageView.ScaleType;
 
 import com.android.systemui.R;
+import com.android.systemui.plugins.qs.QSIconView;
+import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.plugins.qs.QSTile.State;
 
 import java.util.Objects;
 
-public class QSIconView extends ViewGroup {
+public class QSIconViewImpl extends QSIconView {
 
     protected final View mIcon;
     protected final int mIconSizePx;
@@ -43,7 +43,7 @@
     private int mState = -1;
     private int mTint;
 
-    public QSIconView(Context context) {
+    public QSIconViewImpl(Context context) {
         super(context);
 
         final Resources res = context.getResources();
@@ -82,13 +82,13 @@
         setIcon((ImageView) mIcon, state);
     }
 
-    protected void setIcon(ImageView iv, QSTile.State state) {
+    protected void updateIcon(ImageView iv, State state) {
         if (!Objects.equals(state.icon, iv.getTag(R.id.qs_icon_tag))) {
             Drawable d = state.icon != null
                     ? iv.isShown() && mAnimationEnabled ? state.icon.getDrawable(mContext)
                     : state.icon.getInvisibleDrawable(mContext) : null;
             int padding = state.icon != null ? state.icon.getPadding() : 0;
-            if (d != null && state.autoMirrorDrawable) {
+            if (d != null) {
                 d.setAutoMirrored(true);
             }
             iv.setImageDrawable(d);
@@ -102,13 +102,17 @@
                 }
             }
         }
+    }
+
+    protected void setIcon(ImageView iv, QSTile.State state) {
+        updateIcon(iv, state);
         if (state.disabledByPolicy) {
             iv.setColorFilter(getContext().getColor(R.color.qs_tile_disabled_color));
         } else {
             iv.clearColorFilter();
         }
         if (state.state != mState) {
-            int color = getColorForState(getContext(), state.state);
+            int color = getColor(state.state);
             mState = state.state;
             if (iv.isShown()) {
                 animateGrayScale(mTint, color, iv);
@@ -120,6 +124,10 @@
         }
     }
 
+    protected int getColor(int state) {
+        return getColorForState(getContext(), state);
+    }
+
     public static void animateGrayScale(int fromColor, int toColor, ImageView iv) {
         final float fromAlpha = Color.alpha(fromColor);
         final float toAlpha = Color.alpha(toColor);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
similarity index 86%
rename from packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java
rename to packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
index c750fdc..043490c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
@@ -1,19 +1,17 @@
 /*
- * Copyright (C) 2015 The Android Open Source Project
+ * 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
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
  */
-package com.android.systemui.qs;
+package com.android.systemui.qs.tileimpl;
 
 import android.content.Context;
 import android.content.res.TypedArray;
@@ -29,12 +27,12 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.FrameLayout;
-import android.widget.LinearLayout;
 import android.widget.Switch;
 
 import com.android.systemui.R;
+import com.android.systemui.plugins.qs.*;
 
-public class QSTileBaseView extends LinearLayout {
+public class QSTileBaseView extends com.android.systemui.plugins.qs.QSTileView {
 
     private static final String TAG = "QSTileBaseView";
     private final H mHandler = new H();
@@ -102,6 +100,14 @@
         mRipple.setHotspotBounds(cx - rad, cy - rad, cx + rad, cy + rad);
     }
 
+    @Override
+    public void init(QSTile tile) {
+        init(v -> tile.click(), v -> tile.secondaryClick(), view -> {
+            tile.longClick();
+            return true;
+        });
+    }
+
     public void init(OnClickListener click, OnClickListener secondaryClick,
             OnLongClickListener longClick) {
         setClickable(true);
@@ -143,21 +149,18 @@
 
     protected void handleStateChanged(QSTile.State state) {
         mIcon.setIcon(state);
-        if (mCollapsedView && !TextUtils.isEmpty(state.minimalContentDescription)) {
-            setContentDescription(state.minimalContentDescription);
-        } else {
-            setContentDescription(state.contentDescription);
-        }
-        if (mCollapsedView) {
-            mAccessibilityClass = state.minimalAccessibilityClassName;
-        } else {
-            mAccessibilityClass = state.expandedAccessibilityClassName;
-        }
+        setContentDescription(state.contentDescription);
+        mAccessibilityClass = state.expandedAccessibilityClassName;
         if (state instanceof QSTile.BooleanState) {
             mTileState = ((QSTile.BooleanState) state).value;
         }
     }
 
+    @Override
+    public int getDetailY() {
+        return getTop() + getHeight() / 2;
+    }
+
     public QSIconView getIcon() {
         return mIcon;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
similarity index 63%
rename from packages/SystemUI/src/com/android/systemui/qs/QSTile.java
rename to packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
index 0829ae5..5ac7891 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
@@ -1,20 +1,20 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
  */
 
-package com.android.systemui.qs;
+package com.android.systemui.qs.tileimpl;
+
+import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 
 import android.app.ActivityManager;
 import android.content.Context;
@@ -31,21 +31,16 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.Utils;
 import com.android.systemui.Dependency;
-import com.android.systemui.ActivityStarter;
-import com.android.systemui.plugins.qs.QS.DetailAdapter;
-import com.android.systemui.qs.QSTile.State;
-import com.android.systemui.qs.external.TileServices;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.qs.DetailAdapter;
+import com.android.systemui.plugins.qs.QSIconView;
+import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.plugins.qs.QSTile.State;
+import com.android.systemui.qs.QSHost;
 
 import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Objects;
-
-import com.android.settingslib.Utils;
-
-import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
-
-import com.android.systemui.R;
 
 /**
  * Base quick-settings tile, extend this to create a new tile.
@@ -54,13 +49,13 @@
  * handleUpdateState.  Callbacks affecting state should use refreshState to trigger another
  * state update pass on tile looper.
  */
-public abstract class QSTile<TState extends State> {
+public abstract class QSTileImpl<TState extends State> implements QSTile {
     protected final String TAG = "Tile." + getClass().getSimpleName();
     protected static final boolean DEBUG = Log.isLoggable("Tile", Log.DEBUG);
 
-    protected final Host mHost;
+    protected final QSHost mHost;
     protected final Context mContext;
-    protected final H mHandler;
+    protected final H mHandler = new H(Dependency.get(Dependency.BG_LOOPER));
     protected final Handler mUiHandler = new Handler(Looper.getMainLooper());
     private final ArraySet<Object> mListeners = new ArraySet<>();
 
@@ -70,6 +65,7 @@
     private boolean mAnnounceNextStateChange;
 
     private String mTileSpec;
+    private EnforcedAdmin mEnforcedAdmin;
 
     public abstract TState newTileState();
 
@@ -85,10 +81,9 @@
      */
     abstract public int getMetricsCategory();
 
-    protected QSTile(Host host) {
+    protected QSTileImpl(QSHost host) {
         mHost = host;
         mContext = host.getContext();
-        mHandler = new H(Dependency.get(Dependency.BG_LOOPER));
     }
 
     /**
@@ -117,12 +112,12 @@
         mTileSpec = tileSpec;
     }
 
-    public Host getHost() {
+    public QSHost getHost() {
         return mHost;
     }
 
     public QSIconView createTileView(Context context) {
-        return new QSIconView(context);
+        return new QSIconViewImpl(context);
     }
 
     public DetailAdapter getDetailAdapter() {
@@ -172,7 +167,7 @@
         mHandler.obtainMessage(H.SHOW_DETAIL, show ? 1 : 0, 0).sendToTarget();
     }
 
-    public final void refreshState() {
+    public void refreshState() {
         refreshState(null);
     }
 
@@ -180,7 +175,7 @@
         mHandler.obtainMessage(H.REFRESH_STATE, arg).sendToTarget();
     }
 
-    public final void clearState() {
+    public void clearState() {
         mHandler.sendEmptyMessage(H.CLEAR_STATE);
     }
 
@@ -308,10 +303,10 @@
         if (admin != null && !RestrictedLockUtils.hasBaseUserRestriction(mContext,
                 userRestriction, ActivityManager.getCurrentUser())) {
             state.disabledByPolicy = true;
-            state.enforcedAdmin = admin;
+            mEnforcedAdmin = admin;
         } else {
             state.disabledByPolicy = false;
-            state.enforcedAdmin = null;
+            mEnforcedAdmin = null;
         }
     }
 
@@ -370,7 +365,7 @@
                     name = "handleClick";
                     if (mState.disabledByPolicy) {
                         Intent intent = RestrictedLockUtils.getShowAdminSupportDetailsIntent(
-                                mContext, mState.enforcedAdmin);
+                                mContext, mEnforcedAdmin);
                         Dependency.get(ActivityStarter.class).postStartActivityDismissingKeyguard(
                                 intent, 0);
                     } else {
@@ -418,47 +413,6 @@
         }
     }
 
-    public interface Callback {
-        void onStateChanged(State state);
-        void onShowDetail(boolean show);
-        void onToggleStateChanged(boolean state);
-        void onScanStateChanged(boolean state);
-        void onAnnouncementRequested(CharSequence announcement);
-    }
-
-    public interface Host {
-        void warn(String message, Throwable t);
-        void collapsePanels();
-        void openPanels();
-        Context getContext();
-        Collection<QSTile<?>> getTiles();
-        void addCallback(Callback callback);
-        void removeCallback(Callback callback);
-        TileServices getTileServices();
-        void removeTile(String tileSpec);
-
-        interface Callback {
-            void onTilesChanged();
-        }
-    }
-
-    public static abstract class Icon {
-        abstract public Drawable getDrawable(Context context);
-
-        public Drawable getInvisibleDrawable(Context context) {
-            return getDrawable(context);
-        }
-
-        @Override
-        public int hashCode() {
-            return Icon.class.hashCode();
-        }
-
-        public int getPadding() {
-            return 0;
-        }
-    }
-
     public static class DrawableIcon extends Icon {
         protected final Drawable mDrawable;
 
@@ -539,145 +493,4 @@
             return context.getDrawable(mAnimatedResId).getConstantState().newDrawable();
         }
     }
-
-    public static class State {
-        public Icon icon;
-        public int state = Tile.STATE_ACTIVE;
-        public CharSequence label;
-        public CharSequence contentDescription;
-        public CharSequence dualLabelContentDescription;
-        public CharSequence minimalContentDescription;
-        public boolean autoMirrorDrawable = true;
-        public boolean disabledByPolicy;
-        public boolean dualTarget = false;
-        public EnforcedAdmin enforcedAdmin;
-        public String minimalAccessibilityClassName;
-        public String expandedAccessibilityClassName;
-
-        public boolean copyTo(State other) {
-            if (other == null) throw new IllegalArgumentException();
-            if (!other.getClass().equals(getClass())) throw new IllegalArgumentException();
-            final boolean changed = !Objects.equals(other.icon, icon)
-                    || !Objects.equals(other.label, label)
-                    || !Objects.equals(other.contentDescription, contentDescription)
-                    || !Objects.equals(other.autoMirrorDrawable, autoMirrorDrawable)
-                    || !Objects.equals(other.dualLabelContentDescription,
-                    dualLabelContentDescription)
-                    || !Objects.equals(other.minimalContentDescription,
-                    minimalContentDescription)
-                    || !Objects.equals(other.minimalAccessibilityClassName,
-                    minimalAccessibilityClassName)
-                    || !Objects.equals(other.expandedAccessibilityClassName,
-                    expandedAccessibilityClassName)
-                    || !Objects.equals(other.disabledByPolicy, disabledByPolicy)
-                    || !Objects.equals(other.state, state)
-                    || !Objects.equals(other.enforcedAdmin, enforcedAdmin)
-                    || !Objects.equals(other.dualTarget, dualTarget);
-            other.icon = icon;
-            other.label = label;
-            other.contentDescription = contentDescription;
-            other.dualLabelContentDescription = dualLabelContentDescription;
-            other.minimalContentDescription = minimalContentDescription;
-            other.minimalAccessibilityClassName = minimalAccessibilityClassName;
-            other.expandedAccessibilityClassName = expandedAccessibilityClassName;
-            other.autoMirrorDrawable = autoMirrorDrawable;
-            other.disabledByPolicy = disabledByPolicy;
-            other.state = state;
-            other.dualTarget = dualTarget;
-            if (enforcedAdmin == null) {
-                other.enforcedAdmin = null;
-            } else if (other.enforcedAdmin == null) {
-                other.enforcedAdmin = new EnforcedAdmin(enforcedAdmin);
-            } else {
-                enforcedAdmin.copyTo(other.enforcedAdmin);
-            }
-            return changed;
-        }
-
-        @Override
-        public String toString() {
-            return toStringBuilder().toString();
-        }
-
-        protected StringBuilder toStringBuilder() {
-            final StringBuilder sb = new StringBuilder(getClass().getSimpleName()).append('[');
-            sb.append(",icon=").append(icon);
-            sb.append(",label=").append(label);
-            sb.append(",contentDescription=").append(contentDescription);
-            sb.append(",dualLabelContentDescription=").append(dualLabelContentDescription);
-            sb.append(",minimalContentDescription=").append(minimalContentDescription);
-            sb.append(",minimalAccessibilityClassName=").append(minimalAccessibilityClassName);
-            sb.append(",expandedAccessibilityClassName=").append(expandedAccessibilityClassName);
-            sb.append(",autoMirrorDrawable=").append(autoMirrorDrawable);
-            sb.append(",disabledByPolicy=").append(disabledByPolicy);
-            sb.append(",enforcedAdmin=").append(enforcedAdmin);
-            sb.append(",dualTarget=").append(dualTarget);
-            sb.append(",state=").append(state);
-            return sb.append(']');
-        }
-    }
-
-    public static class BooleanState extends State {
-        public boolean value;
-
-        @Override
-        public boolean copyTo(State other) {
-            final BooleanState o = (BooleanState) other;
-            final boolean changed = super.copyTo(other) || o.value != value;
-            o.value = value;
-            return changed;
-        }
-
-        @Override
-        protected StringBuilder toStringBuilder() {
-            final StringBuilder rt = super.toStringBuilder();
-            rt.insert(rt.length() - 1, ",value=" + value);
-            return rt;
-        }
-    }
-
-    public static class AirplaneBooleanState extends BooleanState {
-        public boolean isAirplaneMode;
-
-        @Override
-        public boolean copyTo(State other) {
-            final AirplaneBooleanState o = (AirplaneBooleanState) other;
-            final boolean changed = super.copyTo(other) || o.isAirplaneMode != isAirplaneMode;
-            o.isAirplaneMode = isAirplaneMode;
-            return changed;
-        }
-    }
-
-    public static final class SignalState extends BooleanState {
-        public boolean connected;
-        public boolean activityIn;
-        public boolean activityOut;
-        public boolean filter;
-        public boolean isOverlayIconWide;
-
-        @Override
-        public boolean copyTo(State other) {
-            final SignalState o = (SignalState) other;
-            final boolean changed = o.connected != connected || o.activityIn != activityIn
-                    || o.activityOut != activityOut
-                    || o.isOverlayIconWide != isOverlayIconWide;
-            o.connected = connected;
-            o.activityIn = activityIn;
-            o.activityOut = activityOut;
-            o.filter = filter;
-            o.isOverlayIconWide = isOverlayIconWide;
-            return super.copyTo(other) || changed;
-        }
-
-        @Override
-        protected StringBuilder toStringBuilder() {
-            final StringBuilder rt = super.toStringBuilder();
-            rt.insert(rt.length() - 1, ",connected=" + connected);
-            rt.insert(rt.length() - 1, ",activityIn=" + activityIn);
-            rt.insert(rt.length() - 1, ",activityOut=" + activityOut);
-            rt.insert(rt.length() - 1, ",filter=" + filter);
-            rt.insert(rt.length() - 1, ",wideOverlayIcon=" + isOverlayIconWide);
-            return rt;
-        }
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
similarity index 73%
rename from packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
rename to packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
index 428fe9b..2c04e82 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
@@ -1,40 +1,35 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
  */
 
-package com.android.systemui.qs;
-
-import static com.android.systemui.qs.QSTile.getColorForState;
+package com.android.systemui.qs.tileimpl;
 
 import android.content.Context;
 import android.content.res.Configuration;
-import android.graphics.drawable.RippleDrawable;
 import android.service.quicksettings.Tile;
 import android.text.SpannableStringBuilder;
 import android.text.style.ForegroundColorSpan;
 import android.view.Gravity;
 import android.view.LayoutInflater;
-import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
 import android.widget.ImageView;
 import android.widget.TextView;
 
 import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
+import com.android.systemui.plugins.qs.QSIconView;
+import com.android.systemui.plugins.qs.QSTile;
 
 import libcore.util.Objects;
 
@@ -76,6 +71,11 @@
         FontSizeUtils.updateFontSize(mLabel, R.dimen.qs_tile_text_size);
     }
 
+    @Override
+    public int getDetailY() {
+        return getTop() + mLabelContainer.getTop() + mLabelContainer.getHeight() / 2;
+    }
+
     protected void createLabel() {
         mLabelContainer = (ViewGroup) LayoutInflater.from(getContext())
                 .inflate(R.layout.qs_tile_label, this, false);
@@ -84,7 +84,6 @@
         mLabel = (TextView) mLabelContainer.findViewById(R.id.tile_label);
         mPadLock = (ImageView) mLabelContainer.findViewById(R.id.restricted_padlock);
 
-        mLabelContainer.setBackground(newTileBackground());
         addView(mLabelContainer);
     }
 
@@ -93,7 +92,7 @@
         super.handleStateChanged(state);
         if (!Objects.equal(mLabel.getText(), state.label) || mState != state.state) {
             if (state.state == Tile.STATE_UNAVAILABLE) {
-                int color = getColorForState(getContext(), state.state);
+                int color = QSTileImpl.getColorForState(getContext(), state.state);
                 state.label = new SpannableStringBuilder().append(state.label,
                         new ForegroundColorSpan(color),
                         SpannableStringBuilder.SPAN_INCLUSIVE_INCLUSIVE);
@@ -102,6 +101,11 @@
             mLabel.setText(state.label);
         }
         mDivider.setVisibility(state.dualTarget ? View.VISIBLE : View.INVISIBLE);
+        if (state.dualTarget != mLabelContainer.isClickable()) {
+            mLabelContainer.setClickable(state.dualTarget);
+            mLabelContainer.setLongClickable(state.dualTarget);
+            mLabelContainer.setBackground(state.dualTarget ? newTileBackground() : null);
+        }
         mLabel.setEnabled(!state.disabledByPolicy);
         mPadLock.setVisibility(state.disabledByPolicy ? View.VISIBLE : View.GONE);
     }
@@ -110,7 +114,9 @@
     public void init(OnClickListener click, OnClickListener secondaryClick,
             OnLongClickListener longClick) {
         super.init(click, secondaryClick, longClick);
-        mLabelContainer.setClickable(true);
         mLabelContainer.setOnClickListener(secondaryClick);
+        mLabelContainer.setOnLongClickListener(longClick);
+        mLabelContainer.setClickable(false);
+        mLabelContainer.setLongClickable(false);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
index e8f90ac..c5f798e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
@@ -30,10 +30,12 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.qs.GlobalSetting;
-import com.android.systemui.qs.QSTile;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
 
 /** Quick settings tile: Airplane mode **/
-public class AirplaneModeTile extends QSTile<QSTile.BooleanState> {
+public class AirplaneModeTile extends QSTileImpl<BooleanState> {
     private final AnimationIcon mEnable =
             new AnimationIcon(R.drawable.ic_signal_airplane_enable_animation,
                     R.drawable.ic_signal_airplane_disable);
@@ -44,7 +46,7 @@
 
     private boolean mListening;
 
-    public AirplaneModeTile(Host host) {
+    public AirplaneModeTile(QSHost host) {
         super(host);
 
         mSetting = new GlobalSetting(mContext, mHandler, Global.AIRPLANE_MODE_ON) {
@@ -95,8 +97,7 @@
         }
         state.state = airplaneMode ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
         state.contentDescription = state.label;
-        state.minimalAccessibilityClassName = state.expandedAccessibilityClassName
-                = Switch.class.getName();
+        state.expandedAccessibilityClassName = Switch.class.getName();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
similarity index 87%
rename from packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
rename to packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
index f7bfc1e..c7979d8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
@@ -29,23 +29,25 @@
 import android.view.View.OnAttachStateChangeListener;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
-import android.widget.Button;
 import android.widget.Checkable;
 import android.widget.ImageView;
+import android.widget.Switch;
 import android.widget.TextView;
+
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settingslib.BatteryInfo;
 import com.android.settingslib.graph.BatteryMeterDrawableBase;
 import com.android.settingslib.graph.UsageView;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.plugins.qs.QS.DetailAdapter;
-import com.android.systemui.qs.QSTile;
+import com.android.systemui.plugins.qs.DetailAdapter;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.statusbar.policy.BatteryController;
 
-import java.text.NumberFormat;
-
-public class BatteryTile extends QSTile<QSTile.State> implements BatteryController.BatteryStateChangeCallback {
+public class BatterySaverTile extends QSTileImpl<BooleanState> implements
+        BatteryController.BatteryStateChangeCallback {
 
     private final BatteryController mBatteryController;
     private final BatteryDetail mBatteryDetail = new BatteryDetail();
@@ -56,19 +58,14 @@
     private boolean mDetailShown;
     private boolean mPluggedIn;
 
-    public BatteryTile(Host host) {
+    public BatterySaverTile(QSHost host) {
         super(host);
         mBatteryController = Dependency.get(BatteryController.class);
     }
 
     @Override
-    public State newTileState() {
-        return new QSTile.State();
-    }
-
-    @Override
-    public DetailAdapter getDetailAdapter() {
-        return mBatteryDetail;
+    public BooleanState newTileState() {
+        return new BooleanState();
     }
 
     @Override
@@ -109,22 +106,14 @@
     }
 
     @Override
-    protected void handleUpdateState(State state, Object arg) {
-        int level = (arg != null) ? (Integer) arg : mLevel;
-        String percentage = NumberFormat.getPercentInstance().format((double) level / 100.0);
-
+    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);
         state.label = mContext.getString(R.string.battery_detail_switch_title);
-        state.contentDescription = mContext.getString(R.string.accessibility_quick_settings_battery,
-                percentage) + "," +
-                (mPowerSave ? mContext.getString(R.string.battery_saver_notification_title)
-                        : mCharging ? mContext.getString(R.string.expanded_header_battery_charging)
-                                : "")
-                + "," + mContext.getString(R.string.accessibility_battery_details);
-        state.minimalAccessibilityClassName = state.expandedAccessibilityClassName
-                = Button.class.getName();
+        state.contentDescription = state.label;
+        state.value = mPowerSave;
+        state.expandedAccessibilityClassName = Switch.class.getName();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 4b56ecd..d552a2e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -26,7 +26,6 @@
 import android.text.TextUtils;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.Button;
 import android.widget.Switch;
 
 import com.android.internal.logging.MetricsLogger;
@@ -34,25 +33,27 @@
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.ActivityStarter;
-import com.android.systemui.plugins.qs.QS.DetailAdapter;
+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.QSTile;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.statusbar.policy.BluetoothController;
 
 import java.util.ArrayList;
 import java.util.Collection;
 
 /** Quick settings tile: Bluetooth **/
-public class BluetoothTile extends QSTile<QSTile.BooleanState>  {
+public class BluetoothTile extends QSTileImpl<BooleanState> {
     private static final Intent BLUETOOTH_SETTINGS = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);
 
     private final BluetoothController mController;
     private final BluetoothDetailAdapter mDetailAdapter;
     private final ActivityStarter mActivityStarter;
 
-    public BluetoothTile(Host host) {
+    public BluetoothTile(QSHost host) {
         super(host);
         mController = Dependency.get(BluetoothController.class);
         mActivityStarter = Dependency.get(ActivityStarter.class);
@@ -117,9 +118,6 @@
         final boolean connecting = mController.isBluetoothConnecting();
         state.dualTarget = true;
         state.value = enabled;
-        state.autoMirrorDrawable = false;
-        state.minimalContentDescription =
-                mContext.getString(R.string.accessibility_quick_settings_bluetooth);
         if (enabled) {
             state.label = null;
             if (connected) {
@@ -127,22 +125,16 @@
                 state.label = mController.getLastDeviceName();
                 state.contentDescription = mContext.getString(
                         R.string.accessibility_bluetooth_name, state.label);
-                state.minimalContentDescription = state.minimalContentDescription + ","
-                        + state.contentDescription;
             } else if (connecting) {
                 state.icon = ResourceIcon.get(R.drawable.ic_qs_bluetooth_connecting);
                 state.contentDescription = mContext.getString(
                         R.string.accessibility_quick_settings_bluetooth_connecting);
                 state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
-                state.minimalContentDescription = state.minimalContentDescription + ","
-                        + state.contentDescription;
             } else {
                 state.icon = ResourceIcon.get(R.drawable.ic_qs_bluetooth_on);
                 state.contentDescription = mContext.getString(
                         R.string.accessibility_quick_settings_bluetooth_on) + ","
                         + mContext.getString(R.string.accessibility_not_connected);
-                state.minimalContentDescription = state.minimalContentDescription + ","
-                        + mContext.getString(R.string.accessibility_not_connected);
             }
             if (TextUtils.isEmpty(state.label)) {
                 state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
@@ -164,8 +156,7 @@
         state.dualLabelContentDescription = bluetoothName;
         state.contentDescription = state.contentDescription + "," + mContext.getString(
                 R.string.accessibility_quick_settings_open_settings, getTileLabel());
-        state.expandedAccessibilityClassName = Button.class.getName();
-        state.minimalAccessibilityClassName = Switch.class.getName();
+        state.expandedAccessibilityClassName = Switch.class.getName();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 3c28f76..a1d3d26 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -30,11 +30,13 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.ActivityStarter;
-import com.android.systemui.plugins.qs.QS.DetailAdapter;
+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.QSTile;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.statusbar.policy.CastController;
 import com.android.systemui.statusbar.policy.CastController.CastDevice;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
@@ -43,7 +45,7 @@
 import java.util.Set;
 
 /** Quick settings tile: Cast **/
-public class CastTile extends QSTile<QSTile.BooleanState> {
+public class CastTile extends QSTileImpl<BooleanState> {
     private static final Intent CAST_SETTINGS =
             new Intent(Settings.ACTION_CAST_SETTINGS);
 
@@ -53,7 +55,7 @@
     private final Callback mCallback = new Callback();
     private final ActivityStarter mActivityStarter;
 
-    public CastTile(Host host) {
+    public CastTile(QSHost host) {
         super(host);
         mController = Dependency.get(CastController.class);
         mDetailAdapter = new CastDetailAdapter();
@@ -126,7 +128,6 @@
         state.label = mContext.getString(R.string.quick_settings_cast_title);
         state.contentDescription = state.label;
         state.value = false;
-        state.autoMirrorDrawable = false;
         final Set<CastDevice> devices = mController.getCastDevices();
         boolean connecting = false;
         for (CastDevice device : devices) {
@@ -146,8 +147,7 @@
         state.icon = ResourceIcon.get(state.value ? R.drawable.ic_qs_cast_on
                 : R.drawable.ic_qs_cast_off);
         mDetailAdapter.updateItems(devices);
-        state.minimalAccessibilityClassName = state.expandedAccessibilityClassName =
-                Button.class.getName();
+        state.expandedAccessibilityClassName = Button.class.getName();
         state.contentDescription = state.contentDescription + ","
                 + mContext.getString(R.string.accessibility_quick_settings_open_details);
     }
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 bae163f..ca70336 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -24,24 +24,26 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.Button;
+import android.widget.Switch;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settingslib.net.DataUsageController;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.ActivityStarter;
-import com.android.systemui.plugins.qs.QS.DetailAdapter;
-import com.android.systemui.qs.QSIconView;
-import com.android.systemui.qs.QSTile;
-import com.android.systemui.qs.SignalTileView;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.qs.DetailAdapter;
+import com.android.systemui.plugins.qs.QSIconView;
+import com.android.systemui.plugins.qs.QSTile.SignalState;
+import com.android.systemui.qs.CellTileView;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
 
 /** Quick settings tile: Cellular **/
-public class CellularTile extends QSTile<QSTile.SignalState> {
+public class CellularTile extends QSTileImpl<SignalState> {
     static final Intent CELLULAR_SETTINGS = new Intent().setComponent(new ComponentName(
             "com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity"));
 
@@ -52,7 +54,7 @@
     private final CellSignalCallback mSignalCallback = new CellSignalCallback();
     private final ActivityStarter mActivityStarter;
 
-    public CellularTile(Host host) {
+    public CellularTile(QSHost host) {
         super(host);
         mController = Dependency.get(NetworkController.class);
         mActivityStarter = Dependency.get(ActivityStarter.class);
@@ -81,7 +83,7 @@
 
     @Override
     public QSIconView createTileView(Context context) {
-        return new SignalTileView(context);
+        return new CellTileView(context);
     }
 
     @Override
@@ -126,40 +128,13 @@
         } else {
             state.icon = ResourceIcon.get(iconId);
         }
-        state.dualTarget = true;
-        state.isOverlayIconWide = cb.isDataTypeIconWide;
-        state.autoMirrorDrawable = !cb.noSim;
-        state.filter = iconId != R.drawable.ic_qs_no_sim;
         state.activityIn = cb.enabled && cb.activityIn;
         state.activityOut = cb.enabled && cb.activityOut;
 
-        state.label = cb.enabled
-                ? removeTrailingPeriod(cb.enabledDesc)
-                : r.getString(R.string.quick_settings_rssi_emergency_only);
+        state.label = r.getString(R.string.mobile_data);
 
-        final String signalContentDesc = cb.enabled && (cb.mobileSignalIconId > 0)
-                ? cb.signalContentDescription
-                : r.getString(R.string.accessibility_no_signal);
-
-        if (cb.noSim) {
-            state.contentDescription = state.label;
-        } else {
-            String enabledDesc = cb.enabled ? r.getString(R.string.accessibility_cell_data_on)
-                    : r.getString(R.string.accessibility_cell_data_off);
-
-            state.contentDescription = r.getString(
-                    R.string.accessibility_quick_settings_mobile,
-                    enabledDesc, signalContentDesc,
-                    state.label);
-            state.minimalContentDescription = r.getString(
-                    R.string.accessibility_quick_settings_mobile,
-                    r.getString(R.string.accessibility_cell_data), signalContentDesc,
-                    state.label);
-        }
-        state.contentDescription = state.contentDescription + "," + r.getString(
-                R.string.accessibility_quick_settings_open_settings, getTileLabel());
-        state.minimalAccessibilityClassName = state.expandedAccessibilityClassName
-                = Button.class.getName();
+        state.contentDescription = state.label;
+        state.expandedAccessibilityClassName = Switch.class.getName();
         state.value = mDataController.isMobileDataSupported()
                 && mDataController.isMobileDataEnabled();
         state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
index 0a8afb0..e33b680 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -25,11 +25,13 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
-import com.android.systemui.qs.QSTile;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.qs.SecureSetting;
 
 /** Quick settings tile: Invert colors **/
-public class ColorInversionTile extends QSTile<QSTile.BooleanState> {
+public class ColorInversionTile extends QSTileImpl<BooleanState> {
 
     private final AnimationIcon mEnable
             = new AnimationIcon(R.drawable.ic_invert_colors_enable_animation,
@@ -41,7 +43,7 @@
 
     private boolean mListening;
 
-    public ColorInversionTile(Host host) {
+    public ColorInversionTile(QSHost host) {
         super(host);
 
         mSetting = new SecureSetting(mContext, mHandler,
@@ -99,8 +101,7 @@
         state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
         state.label = mContext.getString(R.string.quick_settings_inversion_label);
         state.icon = enabled ? mEnable : mDisable;
-        state.minimalAccessibilityClassName = state.expandedAccessibilityClassName
-                = Switch.class.getName();
+        state.expandedAccessibilityClassName = Switch.class.getName();
         state.contentDescription = state.label;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
index 412fe3d..7a25140 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
@@ -24,17 +24,19 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
-import com.android.systemui.qs.QSTile;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
 import com.android.systemui.statusbar.policy.DataSaverController;
 import com.android.systemui.statusbar.policy.NetworkController;
 
-public class DataSaverTile extends QSTile<QSTile.BooleanState> implements
+public class DataSaverTile extends QSTileImpl<BooleanState> implements
         DataSaverController.Listener{
 
     private final DataSaverController mDataSaverController;
 
-    public DataSaverTile(Host host) {
+    public DataSaverTile(QSHost host) {
         super(host);
         mDataSaverController = Dependency.get(NetworkController.class).getDataSaverController();
     }
@@ -104,8 +106,7 @@
         state.contentDescription = state.label;
         state.icon = ResourceIcon.get(state.value ? R.drawable.ic_data_saver
                 : R.drawable.ic_data_saver_off);
-        state.minimalAccessibilityClassName = state.expandedAccessibilityClassName
-                = Switch.class.getName();
+        state.expandedAccessibilityClassName = Switch.class.getName();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
index c7b6aea..9cd79f8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
@@ -91,7 +91,7 @@
                     formatBytes(info.usageLevel));
             bottom = res.getString(R.string.quick_settings_cellular_detail_data_limit,
                     formatBytes(info.limitLevel));
-            usageColor = mContext.getColor(R.color.system_warning_color);
+            usageColor = Utils.getDefaultColor(mContext, android.R.attr.colorError);
         }
 
         if (usageColor == 0) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 4072b44..d3586c4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -39,14 +39,17 @@
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
 import com.android.systemui.SysUIToast;
-import com.android.systemui.ActivityStarter;
-import com.android.systemui.plugins.qs.QS.DetailAdapter;
-import com.android.systemui.qs.QSTile;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.qs.DetailAdapter;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.statusbar.policy.ZenModeController;
 import com.android.systemui.volume.ZenModePanel;
 
 /** Quick settings tile: Do not disturb **/
-public class DndTile extends QSTile<QSTile.BooleanState> {
+public class DndTile extends QSTileImpl<BooleanState> {
 
     private static final Intent ZEN_SETTINGS =
             new Intent(Settings.ACTION_ZEN_MODE_SETTINGS);
@@ -74,7 +77,7 @@
     private boolean mShowingDetail;
     private boolean mReceiverRegistered;
 
-    public DndTile(Host host) {
+    public DndTile(QSHost host) {
         super(host);
         mController = Dependency.get(ZenModeController.class);
         mDetailAdapter = new DndDetailAdapter();
@@ -195,8 +198,7 @@
         if (valueChanged) {
             fireToggleStateChanged(state.value);
         }
-        state.minimalAccessibilityClassName = state.expandedAccessibilityClassName
-                = Switch.class.getName();
+        state.expandedAccessibilityClassName = Switch.class.getName();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
index ac82753..7b0fd73 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
@@ -21,19 +21,19 @@
 import android.graphics.drawable.Drawable;
 import android.provider.MediaStore;
 import android.service.quicksettings.Tile;
-import android.text.SpannableStringBuilder;
-import android.text.style.ForegroundColorSpan;
 import android.widget.Switch;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.qs.QSTile;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.statusbar.policy.FlashlightController;
 
 /** Quick settings tile: Control flashlight **/
-public class FlashlightTile extends QSTile<QSTile.BooleanState> implements
+public class FlashlightTile extends QSTileImpl<BooleanState> implements
         FlashlightController.FlashlightListener {
 
     private final AnimationIcon mEnable
@@ -44,7 +44,7 @@
             R.drawable.ic_signal_flashlight_enable);
     private final FlashlightController mFlashlightController;
 
-    public FlashlightTile(Host host) {
+    public FlashlightTile(QSHost host) {
         super(host);
         mFlashlightController = Dependency.get(FlashlightController.class);
     }
@@ -127,8 +127,7 @@
         final AnimationIcon icon = state.value ? mEnable : mDisable;
         state.icon = icon;
         state.contentDescription = mContext.getString(R.string.quick_settings_flashlight_label);
-        state.minimalAccessibilityClassName = state.expandedAccessibilityClassName
-                = Switch.class.getName();
+        state.expandedAccessibilityClassName = Switch.class.getName();
         state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index dab5967..6662937 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -16,18 +16,13 @@
 
 package com.android.systemui.qs.tiles;
 
-import android.content.BroadcastReceiver;
 import android.content.ComponentName;
-import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.UserManager;
 
-import android.provider.Settings;
 import android.provider.Settings.Global;
 import android.service.quicksettings.Tile;
-import android.text.SpannableStringBuilder;
-import android.text.style.ForegroundColorSpan;
 import android.widget.Switch;
 
 import com.android.internal.logging.MetricsLogger;
@@ -35,11 +30,13 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.qs.GlobalSetting;
-import com.android.systemui.qs.QSTile;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.plugins.qs.QSTile.AirplaneBooleanState;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.statusbar.policy.HotspotController;
 
 /** Quick settings tile: Hotspot **/
-public class HotspotTile extends QSTile<QSTile.AirplaneBooleanState> {
+public class HotspotTile extends QSTileImpl<AirplaneBooleanState> {
     static final Intent TETHER_SETTINGS = new Intent().setComponent(new ComponentName(
              "com.android.settings", "com.android.settings.TetherSettings"));
 
@@ -57,7 +54,7 @@
     private final GlobalSetting mAirplaneMode;
     private boolean mListening;
 
-    public HotspotTile(Host host) {
+    public HotspotTile(QSHost host) {
         super(host);
         mController = Dependency.get(HotspotController.class);
         mAirplaneMode = new GlobalSetting(mContext, mHandler, Global.AIRPLANE_MODE_ON) {
@@ -136,8 +133,7 @@
         } else if (wasAirplane) {
             state.icon = mDisableNoAnimation;
         }
-        state.minimalAccessibilityClassName = state.expandedAccessibilityClassName
-                = Switch.class.getName();
+        state.expandedAccessibilityClassName = Switch.class.getName();
         state.contentDescription = state.label;
         state.state = state.isAirplaneMode ? Tile.STATE_UNAVAILABLE
                 : state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
index fcc9596..c953363 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
@@ -32,13 +32,16 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
-import com.android.systemui.ActivityStarter;
-import com.android.systemui.qs.QSTile;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.plugins.qs.QSTile.State;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
 
 import java.util.Arrays;
 import java.util.Objects;
 
-public class IntentTile extends QSTile<QSTile.State> {
+public class IntentTile extends QSTileImpl<State> {
     public static final String PREFIX = "intent(";
 
     private PendingIntent mOnClick;
@@ -50,7 +53,7 @@
 
     private Intent mLastIntent;
 
-    private IntentTile(Host host, String action) {
+    private IntentTile(QSHost host, String action) {
         super(host);
         mContext.registerReceiver(mReceiver, new IntentFilter(action));
     }
@@ -61,7 +64,7 @@
         mContext.unregisterReceiver(mReceiver);
     }
 
-    public static QSTile<?> create(Host host, String spec) {
+    public static QSTile create(QSHost host, String spec) {
         if (spec == null || !spec.startsWith(PREFIX) || !spec.endsWith(")")) {
             throw new IllegalArgumentException("Bad intent tile spec: " + spec);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index 423a1df..b5c02cb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -26,14 +26,16 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.ActivityStarter;
-import com.android.systemui.qs.QSTile;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
 import com.android.systemui.statusbar.policy.LocationController;
 import com.android.systemui.statusbar.policy.LocationController.LocationSettingsChangeCallback;
 
 /** Quick settings tile: Location **/
-public class LocationTile extends QSTile<QSTile.BooleanState> {
+public class LocationTile extends QSTileImpl<BooleanState> {
 
     private final AnimationIcon mEnable =
             new AnimationIcon(R.drawable.ic_signal_location_enable_animation,
@@ -46,7 +48,7 @@
     private final KeyguardMonitor mKeyguard;
     private final Callback mCallback = new Callback();
 
-    public LocationTile(Host host) {
+    public LocationTile(QSHost host) {
         super(host);
         mController = Dependency.get(LocationController.class);
         mKeyguard = Dependency.get(KeyguardMonitor.class);
@@ -115,8 +117,7 @@
                     R.string.accessibility_quick_settings_location_off);
         }
         state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
-        state.minimalAccessibilityClassName = state.expandedAccessibilityClassName
-                = Switch.class.getName();
+        state.expandedAccessibilityClassName = Switch.class.getName();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
index 967c922..3299339 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
@@ -30,16 +30,18 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
-import com.android.systemui.qs.QSTile;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
 
 /** Quick settings tile: Enable/Disable NFC **/
-public class NfcTile extends QSTile<QSTile.BooleanState> {
+public class NfcTile extends QSTileImpl<BooleanState> {
 
     private NfcAdapter mAdapter;
 
     private boolean mListening;
 
-    public NfcTile(Host host) {
+    public NfcTile(QSHost host) {
         super(host);
     }
 
@@ -108,8 +110,7 @@
         state.value = mAdapter == null ? false : mAdapter.isEnabled();
         state.label = mContext.getString(R.string.quick_settings_nfc_label);
         state.icon = new DrawableIcon(state.value ? mEnable : mDisable);
-        state.minimalAccessibilityClassName = state.expandedAccessibilityClassName
-                = Switch.class.getName();
+        state.expandedAccessibilityClassName = Switch.class.getName();
         state.contentDescription = state.label;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
index b8ba28d8..8b47216 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
@@ -26,15 +26,17 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
-import com.android.systemui.qs.QSTile;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
 
-public class NightDisplayTile extends QSTile<QSTile.BooleanState>
+public class NightDisplayTile extends QSTileImpl<BooleanState>
         implements NightDisplayController.Callback {
 
     private NightDisplayController mController;
     private boolean mIsListening;
 
-    public NightDisplayTile(Host host) {
+    public NightDisplayTile(QSHost host) {
         super(host);
         mController = new NightDisplayController(mContext, ActivityManager.getCurrentUser());
     }
@@ -80,8 +82,7 @@
                 mContext.getString(R.string.quick_settings_night_display_label);
         state.icon = ResourceIcon.get(isActivated ? R.drawable.ic_qs_night_display_on
                 : R.drawable.ic_qs_night_display_off);
-        state.minimalAccessibilityClassName = state.expandedAccessibilityClassName =
-                Switch.class.getName();
+        state.expandedAccessibilityClassName = Switch.class.getName();
         state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
index 2c0af17..d5d91db 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
@@ -28,12 +28,14 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.qs.QSTile;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.statusbar.policy.RotationLockController;
 import com.android.systemui.statusbar.policy.RotationLockController.RotationLockControllerCallback;
 
 /** Quick settings tile: Rotation **/
-public class RotationLockTile extends QSTile<QSTile.BooleanState> {
+public class RotationLockTile extends QSTileImpl<BooleanState> {
     private final AnimationIcon mPortraitToAuto
             = new AnimationIcon(R.drawable.ic_portrait_to_auto_rotate_animation,
             R.drawable.ic_portrait_from_auto_rotate);
@@ -50,7 +52,7 @@
 
     private final RotationLockController mController;
 
-    public RotationLockTile(Host host) {
+    public RotationLockTile(QSHost host) {
         super(host);
         mController = Dependency.get(RotationLockController.class);
     }
@@ -106,8 +108,7 @@
             state.icon = portrait ? mPortraitToAuto : mLandscapeToAuto;
         }
         state.contentDescription = getAccessibilityString(rotationLocked);
-        state.minimalAccessibilityClassName = state.expandedAccessibilityClassName
-                = Switch.class.getName();
+        state.expandedAccessibilityClassName = Switch.class.getName();
         state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
index c20c6bb..d6043f4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
@@ -23,18 +23,21 @@
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
-import com.android.systemui.plugins.qs.QS.DetailAdapter;
-import com.android.systemui.qs.QSTile;
+import com.android.systemui.plugins.qs.DetailAdapter;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.plugins.qs.QSTile.State;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.statusbar.policy.UserInfoController;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
 
-public class UserTile extends QSTile<QSTile.State> implements UserInfoController.OnUserInfoChangedListener {
+public class UserTile extends QSTileImpl<State> implements UserInfoController.OnUserInfoChangedListener {
 
     private final UserSwitcherController mUserSwitcherController;
     private final UserInfoController mUserInfoController;
     private Pair<String, Drawable> mLastUpdate;
 
-    public UserTile(Host host) {
+    public UserTile(QSHost host) {
         super(host);
         mUserSwitcherController = Dependency.get(UserSwitcherController.class);
         mUserInfoController = Dependency.get(UserInfoController.class);
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 90a9db6..0270641 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -25,7 +25,6 @@
 import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.Button;
 import android.widget.Switch;
 
 import com.android.internal.logging.MetricsLogger;
@@ -33,12 +32,15 @@
 import com.android.settingslib.wifi.AccessPoint;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.ActivityStarter;
-import com.android.systemui.plugins.qs.QS.DetailAdapter;
+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.QSIconView;
-import com.android.systemui.qs.QSTile;
+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.SignalTileView;
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.NetworkController.AccessPointController;
@@ -48,7 +50,7 @@
 import java.util.List;
 
 /** Quick settings tile: Wifi **/
-public class WifiTile extends QSTile<QSTile.SignalState> {
+public class WifiTile extends QSTileImpl<SignalState> {
     private static final Intent WIFI_SETTINGS = new Intent(Settings.ACTION_WIFI_SETTINGS);
 
     protected final NetworkController mController;
@@ -59,7 +61,7 @@
     protected final WifiSignalCallback mSignalCallback = new WifiSignalCallback();
     private final ActivityStarter mActivityStarter;
 
-    public WifiTile(Host host) {
+    public WifiTile(QSHost host) {
         super(host);
         mController = Dependency.get(NetworkController.class);
         mWifiController = mController.getAccessPointController();
@@ -152,10 +154,8 @@
         }
         state.dualTarget = true;
         state.value = cb.enabled;
-        state.connected = wifiConnected;
         state.activityIn = cb.enabled && cb.activityIn;
         state.activityOut = cb.enabled && cb.activityOut;
-        state.filter = true;
         final StringBuffer minimalContentDescription = new StringBuffer();
         final StringBuffer expandedContentDescription = new StringBuffer();
         final Resources r = mContext.getResources();
@@ -187,17 +187,15 @@
             expandedContentDescription.append(
                     r.getString(R.string.quick_settings_wifi_off_label));
         }
-        state.minimalContentDescription =  minimalContentDescription;
         expandedContentDescription.append(",").append(
                 r.getString(R.string.accessibility_quick_settings_open_settings, getTileLabel()));
         state.contentDescription = expandedContentDescription;
         CharSequence wifiName = state.label;
-        if (state.connected) {
+        if (cb.connected) {
             wifiName = r.getString(R.string.accessibility_wifi_name, state.label);
         }
         state.dualLabelContentDescription = wifiName;
-        state.expandedAccessibilityClassName = Button.class.getName();
-        state.minimalAccessibilityClassName = Switch.class.getName();
+        state.expandedAccessibilityClassName = Switch.class.getName();
         state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
     }
 
@@ -372,9 +370,9 @@
                     item.icon = mWifiController.getIcon(ap);
                     item.line1 = ap.getSsid();
                     item.line2 = ap.isActive() ? ap.getSummary() : null;
-                    item.overlay = ap.getSecurity() != AccessPoint.SECURITY_NONE
-                            ? mContext.getDrawable(R.drawable.qs_ic_wifi_lock)
-                            : null;
+                    item.icon2 = ap.getSecurity() != AccessPoint.SECURITY_NONE
+                            ? R.drawable.qs_ic_wifi_lock
+                            : -1;
                     items[i] = item;
                 }
             }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
index 7e6bb3b..5086091 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
@@ -25,11 +25,13 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.qs.QSTile;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.statusbar.phone.ManagedProfileController;
 
 /** Quick settings tile: Work profile on/off */
-public class WorkModeTile extends QSTile<QSTile.BooleanState> implements
+public class WorkModeTile extends QSTileImpl<BooleanState> implements
         ManagedProfileController.Callback {
     private final AnimationIcon mEnable =
             new AnimationIcon(R.drawable.ic_signal_workmode_enable_animation,
@@ -40,7 +42,7 @@
 
     private final ManagedProfileController mProfileController;
 
-    public WorkModeTile(Host host) {
+    public WorkModeTile(QSHost host) {
         super(host);
         mProfileController = Dependency.get(ManagedProfileController.class);
     }
@@ -108,8 +110,7 @@
             state.contentDescription =  mContext.getString(
                     R.string.accessibility_quick_settings_work_mode_off);
         }
-        state.minimalAccessibilityClassName = state.expandedAccessibilityClassName
-                = Switch.class.getName();
+        state.expandedAccessibilityClassName = Switch.class.getName();
         state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 8de4e58..33ad7fb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -375,6 +375,10 @@
         MutableBoolean isHomeStackVisible = new MutableBoolean(true);
         if (!ssp.isRecentsActivityVisible(isHomeStackVisible)) {
             ActivityManager.RunningTaskInfo runningTask = ssp.getRunningTask();
+            if (runningTask == null) {
+                return;
+            }
+
             RecentsTaskLoader loader = Recents.getTaskLoader();
             sInstanceLoadPlan = loader.createLoadPlan(mContext);
             sInstanceLoadPlan.preloadRawTasks(!isHomeStackVisible.value);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index cda902b..12332fb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -153,7 +153,8 @@
         public void onTaskStackChanged() { }
         public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) { }
         public void onActivityPinned() { }
-        public void onPinnedActivityRestartAttempt(String launchedFromPackage) { }
+        public void onPinnedActivityRestartAttempt() { }
+        public void onPinnedStackAnimationStarted() { }
         public void onPinnedStackAnimationEnded() { }
         public void onActivityForcedResizable(String packageName, int taskId) { }
         public void onActivityDismissingDockedStack() { }
@@ -198,14 +199,20 @@
         }
 
         @Override
-        public void onPinnedActivityRestartAttempt(String launchedFromPackage)
+        public void onPinnedActivityRestartAttempt()
                 throws RemoteException{
             mHandler.removeMessages(H.ON_PINNED_ACTIVITY_RESTART_ATTEMPT);
-            mHandler.obtainMessage(H.ON_PINNED_ACTIVITY_RESTART_ATTEMPT, launchedFromPackage)
+            mHandler.obtainMessage(H.ON_PINNED_ACTIVITY_RESTART_ATTEMPT)
                     .sendToTarget();
         }
 
         @Override
+        public void onPinnedStackAnimationStarted() throws RemoteException {
+            mHandler.removeMessages(H.ON_PINNED_STACK_ANIMATION_STARTED);
+            mHandler.sendEmptyMessage(H.ON_PINNED_STACK_ANIMATION_STARTED);
+        }
+
+        @Override
         public void onPinnedStackAnimationEnded() throws RemoteException {
             mHandler.removeMessages(H.ON_PINNED_STACK_ANIMATION_ENDED);
             mHandler.sendEmptyMessage(H.ON_PINNED_STACK_ANIMATION_ENDED);
@@ -512,7 +519,7 @@
 
         try {
             return mIam.moveTaskToDockedStack(taskId, createMode, true /* onTop */,
-                    false /* animate */, initialBounds, true /* moveHomeStackFront */ );
+                    false /* animate */, initialBounds);
         } catch (RemoteException e) {
             e.printStackTrace();
         }
@@ -1219,6 +1226,7 @@
         private static final int ON_ACTIVITY_FORCED_RESIZABLE = 6;
         private static final int ON_ACTIVITY_DISMISSING_DOCKED_STACK = 7;
         private static final int ON_TASK_PROFILE_LOCKED = 8;
+        private static final int ON_PINNED_STACK_ANIMATION_STARTED = 9;
 
         @Override
         public void handleMessage(Message msg) {
@@ -1244,7 +1252,13 @@
                 }
                 case ON_PINNED_ACTIVITY_RESTART_ATTEMPT: {
                     for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
-                        mTaskStackListeners.get(i).onPinnedActivityRestartAttempt((String) msg.obj);
+                        mTaskStackListeners.get(i).onPinnedActivityRestartAttempt();
+                    }
+                    break;
+                }
+                case ON_PINNED_STACK_ANIMATION_STARTED: {
+                    for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+                        mTaskStackListeners.get(i).onPinnedStackAnimationStarted();
                     }
                     break;
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
index 02b0113..e0dac09 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
@@ -197,6 +197,7 @@
                     bm.getHeight() - thumbnailData.insets.top - thumbnailData.insets.bottom);
             mThumbnailData = thumbnailData;
             updateThumbnailMatrix();
+            updateThumbnailPaintFilter();
         } else {
             mBitmapShader = null;
             mDrawPaint.setShader(null);
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 9a4b45a..2d47c7b 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -21,6 +21,7 @@
 import android.animation.AnimatorSet;
 import android.animation.ValueAnimator;
 import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.app.admin.DevicePolicyManager;
 import android.app.Notification;
 import android.app.Notification.BigPictureStyle;
 import android.app.NotificationManager;
@@ -46,6 +47,7 @@
 import android.os.Bundle;
 import android.os.Environment;
 import android.os.Process;
+import android.os.UserHandle;
 import android.provider.MediaStore;
 import android.util.DisplayMetrics;
 import android.view.Display;
@@ -866,6 +868,16 @@
             .setAutoCancel(true)
             .setColor(context.getColor(
                         com.android.internal.R.color.system_notification_accent_color));
+        final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
+                Context.DEVICE_POLICY_SERVICE);
+        final Intent intent = dpm.createAdminSupportIntent(
+                DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE);
+        if (intent != null) {
+            final PendingIntent pendingIntent = PendingIntent.getActivityAsUser(
+                    context, 0, intent, 0, null, UserHandle.CURRENT);
+            b.setContentIntent(pendingIntent);
+        }
+
         SystemUI.overrideNotificationAppName(context, b);
 
         Notification n = new Notification.BigTextStyle(b)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index 0bd6491..d4997ea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -38,6 +38,7 @@
 import com.android.systemui.classifier.FalsingManager;
 import com.android.systemui.statusbar.notification.FakeShadowView;
 import com.android.systemui.statusbar.notification.NotificationUtils;
+import com.android.systemui.statusbar.phone.DoubleTapHelper;
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.stack.StackStateAnimator;
 
@@ -47,7 +48,6 @@
  */
 public abstract class ActivatableNotificationView extends ExpandableOutlineView {
 
-    private static final long DOUBLETAP_TIMEOUT_MS = 1200;
     private static final int BACKGROUND_ANIMATION_LENGTH_MS = 220;
     private static final int ACTIVATE_ANIMATION_LENGTH = 220;
     private static final int DARK_ANIMATION_LENGTH = 170;
@@ -101,6 +101,7 @@
     private final int mLowPriorityRippleColor;
     protected final int mNormalRippleColor;
     private final AccessibilityManager mAccessibilityManager;
+    private final DoubleTapHelper mDoubleTapHelper;
 
     private boolean mDimmed;
     private boolean mDark;
@@ -114,14 +115,6 @@
      */
     private boolean mActivated;
 
-    private float mDownX;
-    private float mDownY;
-    private final float mTouchSlop;
-
-    private float mActivationX;
-    private float mActivationY;
-    private final float mDoubleTapSlop;
-
     private OnActivatedListener mOnActivatedListener;
 
     private final Interpolator mSlowOutFastInInterpolator;
@@ -143,7 +136,6 @@
     private final int mLowPriorityColor;
     private boolean mIsBelowSpeedBump;
     private FalsingManager mFalsingManager;
-    private boolean mTrackTouch;
 
     private float mNormalBackgroundVisibilityAmount;
     private ValueAnimator mFadeInFromDarkAnimator;
@@ -183,8 +175,6 @@
 
     public ActivatableNotificationView(Context context, AttributeSet attrs) {
         super(context, attrs);
-        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
-        mDoubleTapSlop = context.getResources().getDimension(R.dimen.double_tap_slop);
         mSlowOutFastInInterpolator = new PathInterpolator(0.8f, 0.0f, 0.6f, 1.0f);
         mSlowOutLinearInInterpolator = new PathInterpolator(0.8f, 0.0f, 1.0f, 1.0f);
         setClipChildren(false);
@@ -200,6 +190,14 @@
                 R.color.notification_ripple_untinted_color);
         mFalsingManager = FalsingManager.getInstance(context);
         mAccessibilityManager = AccessibilityManager.getInstance(mContext);
+
+        mDoubleTapHelper = new DoubleTapHelper(this, (active) -> {
+            if (active) {
+                makeActive();
+            } else {
+                makeInactive(true /* animate */);
+            }
+        }, this::performClick, this::handleSlideBack, mFalsingManager::onNotificationDoubleTap);
     }
 
     @Override
@@ -284,60 +282,7 @@
     }
 
     private boolean handleTouchEventDimmed(MotionEvent event) {
-        int action = event.getActionMasked();
-        switch (action) {
-            case MotionEvent.ACTION_DOWN:
-                mDownX = event.getX();
-                mDownY = event.getY();
-                mTrackTouch = true;
-                if (mDownY > getActualHeight()) {
-                    mTrackTouch = false;
-                }
-                break;
-            case MotionEvent.ACTION_MOVE:
-                if (!isWithinTouchSlop(event)) {
-                    makeInactive(true /* animate */);
-                    mTrackTouch = false;
-                }
-                break;
-            case MotionEvent.ACTION_UP:
-                if (isWithinTouchSlop(event)) {
-                    if (handleSlideBack()) {
-                        return true;
-                    }
-                    if (!mActivated) {
-                        makeActive();
-                        postDelayed(mTapTimeoutRunnable, DOUBLETAP_TIMEOUT_MS);
-                        mActivationX = event.getX();
-                        mActivationY = event.getY();
-                    } else {
-                        boolean withinDoubleTapSlop = isWithinDoubleTapSlop(event);
-                        mFalsingManager.onNotificationDoubleTap(
-                                withinDoubleTapSlop,
-                                event.getX() - mActivationX,
-                                event.getY() - mActivationY);
-                        if (withinDoubleTapSlop) {
-                            if (!performClick()) {
-                                return false;
-                            }
-                        } else {
-                            makeInactive(true /* animate */);
-                            mTrackTouch = false;
-                        }
-                    }
-                } else {
-                    makeInactive(true /* animate */);
-                    mTrackTouch = false;
-                }
-                break;
-            case MotionEvent.ACTION_CANCEL:
-                makeInactive(true /* animate */);
-                mTrackTouch = false;
-                break;
-            default:
-                break;
-        }
-        return mTrackTouch;
+        return mDoubleTapHelper.onTouchEvent(event, getActualHeight());
     }
 
     private void makeActive() {
@@ -425,21 +370,6 @@
         removeCallbacks(mTapTimeoutRunnable);
     }
 
-    private boolean isWithinTouchSlop(MotionEvent event) {
-        return Math.abs(event.getX() - mDownX) < mTouchSlop
-                && Math.abs(event.getY() - mDownY) < mTouchSlop;
-    }
-
-    private boolean isWithinDoubleTapSlop(MotionEvent event) {
-        if (!mActivated) {
-            // If we're not activated there's no double tap slop to satisfy.
-            return true;
-        }
-
-        return Math.abs(event.getX() - mActivationX) < mDoubleTapSlop
-                && Math.abs(event.getY() - mActivationY) < mDoubleTapSlop;
-    }
-
     public void setDimmed(boolean dimmed, boolean fade) {
         if (mDimmed != dimmed) {
             mDimmed = dimmed;
@@ -993,12 +923,6 @@
         mOnActivatedListener = onActivatedListener;
     }
 
-    public void reset() {
-        setTintColor(0);
-        resetBackgroundAlpha();
-        setBelowSpeedBump(false);
-    }
-
     public boolean hasSameBgColor(ActivatableNotificationView otherView) {
         return calculateBgColor() == otherView.calculateBgColor();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 995901b..09b7bec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -177,6 +177,10 @@
         disable(state1, state2, true);
     }
 
+    public void recomputeDisableFlags(boolean animate) {
+        disable(mDisable1, mDisable2, animate);
+    }
+
     public void animateExpandNotificationsPanel() {
         synchronized (mLock) {
             mHandler.removeMessages(MSG_EXPAND_NOTIFICATIONS);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
index 19132da..334991f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
@@ -133,6 +133,7 @@
                         mDragDownCallback.setEmptyDragAmount(0f);
                     } else {
                         mCallback.setUserLockedChild(mStartingChild, false);
+                        mStartingChild = null;
                     }
                     mDraggingDown = false;
                 } else {
@@ -214,6 +215,7 @@
         mFalsingManager.onNotificatonStopDraggingDown();
         if (mStartingChild != null) {
             cancelExpansion(mStartingChild);
+            mStartingChild = null;
         } else {
             cancelExpansion();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index bfe4bb2..00968ee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar;
 
+import static com.android.systemui.statusbar.notification.NotificationInflater.InflationExceptionHandler;
+
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
@@ -42,6 +44,7 @@
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.Chronometer;
 import android.widget.ImageView;
+import android.widget.RemoteViews;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -52,6 +55,8 @@
 import com.android.systemui.classifier.FalsingManager;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowProvider.MenuItem;
 import com.android.systemui.statusbar.notification.HybridNotificationView;
+import com.android.systemui.statusbar.notification.InflationException;
+import com.android.systemui.statusbar.notification.NotificationInflater;
 import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
@@ -70,6 +75,7 @@
 
     private static final int DEFAULT_DIVIDER_ALPHA = 0x29;
     private static final int COLORED_DIVIDER_ALPHA = 0x7B;
+    private final NotificationInflater mNotificationInflater;
     private int mIconTransformContentShift;
     private int mIconTransformContentShiftNoIcon;
     private int mNotificationMinHeightLegacy;
@@ -152,14 +158,15 @@
     private OnClickListener mExpandClickListener = new OnClickListener() {
         @Override
         public void onClick(View v) {
-            if (!mShowingPublic && mGroupManager.isSummaryOfGroup(mStatusBarNotification)) {
+            if (!mShowingPublic && (!mIsLowPriority || isExpanded())
+                    && mGroupManager.isSummaryOfGroup(mStatusBarNotification)) {
                 mGroupExpansionChanging = true;
                 final boolean wasExpanded = mGroupManager.isGroupExpanded(mStatusBarNotification);
                 boolean nowExpanded = mGroupManager.toggleGroupExpansion(mStatusBarNotification);
                 mOnExpandClickListener.onExpandClicked(mEntry, nowExpanded);
                 MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTIFICATION_GROUP_EXPANDER,
                         nowExpanded);
-                logExpansionEvent(true /* userAction */, wasExpanded);
+                onExpansionChanged(true /* userAction */, wasExpanded);
             } else {
                 if (v.isAccessibilityFocused()) {
                     mPrivateLayout.setFocusOnVisibilityChange();
@@ -246,6 +253,7 @@
         }
         if (mIsSummaryWithChildren) {
             setIconAnimationRunningForChild(running, mChildrenContainer.getHeaderView());
+            setIconAnimationRunningForChild(running, mChildrenContainer.getLowPriorityHeaderView());
             List<ExpandableNotificationRow> notificationChildren =
                     mChildrenContainer.getNotificationChildren();
             for (int i = 0; i < notificationChildren.size(); i++) {
@@ -298,17 +306,22 @@
         }
     }
 
-    public void onNotificationUpdated(NotificationData.Entry entry) {
+    public void updateNotification(NotificationData.Entry entry) throws InflationException {
         mEntry = entry;
         mStatusBarNotification = entry.notification;
+        mNotificationInflater.inflateNotificationViews();
+        onNotificationUpdated();
+    }
+
+    private void onNotificationUpdated() {
         for (NotificationContentView l : mLayouts) {
-            l.onNotificationUpdated(entry);
+            l.onNotificationUpdated(mEntry);
         }
         mIsColorized = mStatusBarNotification.getNotification().isColorized();
         mShowingPublicInitialized = false;
         updateNotificationColor();
         if (mIsSummaryWithChildren) {
-            mChildrenContainer.recreateNotificationHeader(mExpandClickListener, mEntry.notification);
+            mChildrenContainer.recreateNotificationHeader(mExpandClickListener);
             mChildrenContainer.onNotificationUpdated();
         }
         if (mIconAnimationRunning) {
@@ -458,6 +471,9 @@
         boolean childInGroup = StatusBar.ENABLE_CHILD_NOTIFICATIONS && isChildInGroup;
         mNotificationParent = childInGroup ? parent : null;
         mPrivateLayout.setIsChildInGroup(childInGroup);
+        if (mNotificationInflater.setIsChildInGroup(childInGroup)) {
+            onNotificationUpdated();
+        }
         resetBackgroundAlpha();
         updateBackgroundForGroupState();
         updateClickAndFocus();
@@ -671,9 +687,13 @@
         return mPrivateLayout.getNotificationHeader();
     }
 
-    private NotificationHeaderView getVisibleNotificationHeader() {
+    /**
+     * @return the currently visible notification header. This can be different from
+     * {@link #getNotificationHeader()} in case it is a low-priority group.
+     */
+    public NotificationHeaderView getVisibleNotificationHeader() {
         if (mIsSummaryWithChildren && !mShowingPublic) {
-            return mChildrenContainer.getHeaderView();
+            return mChildrenContainer.getVisibleHeader();
         }
         return getShowingLayout().getVisibleNotificationHeader();
     }
@@ -711,7 +731,7 @@
         }
     }
 
-    public void reInflateViews() {
+    public void onDensityOrFontScaleChanged() {
         initDimens();
         if (mIsSummaryWithChildren) {
             if (mChildrenContainer != null) {
@@ -742,6 +762,8 @@
         for (NotificationContentView l : mLayouts) {
             l.reInflateViews();
         }
+        mNotificationInflater.onDensityOrFontScaleChanged();
+        onNotificationUpdated();
     }
 
     public void setContentBackground(int customBackgroundColor, boolean animate,
@@ -891,7 +913,7 @@
     }
 
     public View getNotificationIcon() {
-        NotificationHeaderView notificationHeader = getNotificationHeader();
+        NotificationHeaderView notificationHeader = getVisibleNotificationHeader();
         if (notificationHeader != null) {
             return notificationHeader.getIcon();
         }
@@ -905,12 +927,7 @@
         if (areGutsExposed()) {
             return false;
         }
-        if (mIsSummaryWithChildren) {
-            return true;
-        }
-        NotificationContentView showingLayout = getShowingLayout();
-        NotificationHeaderView notificationHeader = showingLayout.getVisibleNotificationHeader();
-        return notificationHeader != null;
+        return getVisibleNotificationHeader() != null;
     }
 
     /**
@@ -1008,17 +1025,32 @@
     public void setIsLowPriority(boolean isLowPriority) {
         mIsLowPriority = isLowPriority;
         mPrivateLayout.setIsLowPriority(isLowPriority);
+        mNotificationInflater.setIsLowPriority(mIsLowPriority);
         if (mChildrenContainer != null) {
             mChildrenContainer.setIsLowPriority(isLowPriority);
         }
     }
 
+    public boolean isLowPriority() {
+        return mIsLowPriority;
+    }
+
     public void setUseIncreasedCollapsedHeight(boolean use) {
         mUseIncreasedCollapsedHeight = use;
+        mNotificationInflater.setUsesIncreasedHeight(use);
     }
 
     public void setUseIncreasedHeadsUpHeight(boolean use) {
         mUseIncreasedHeadsUpHeight = use;
+        mNotificationInflater.setUsesIncreasedHeadsUpHeight(use);
+    }
+
+    public void setRemoteViewClickHandler(RemoteViews.OnClickHandler remoteViewClickHandler) {
+        mNotificationInflater.setRemoteViewClickHandler(remoteViewClickHandler);
+    }
+
+    public void setInflateExceptionHandler(InflationExceptionHandler inflateExceptionHandler) {
+        mNotificationInflater.setInflateExceptionHandler(inflateExceptionHandler);
     }
 
     public interface ExpansionLogger {
@@ -1028,6 +1060,7 @@
     public ExpandableNotificationRow(Context context, AttributeSet attrs) {
         super(context, attrs);
         mFalsingManager = FalsingManager.getInstance(context);
+        mNotificationInflater = new NotificationInflater(this);
         initDimens();
     }
 
@@ -1063,26 +1096,8 @@
     /**
      * Resets this view so it can be re-used for an updated notification.
      */
-    @Override
     public void reset() {
-        super.reset();
-        final boolean wasExpanded = isExpanded();
-        mExpandable = false;
-        mHasUserChangedExpansion = false;
-        mUserLocked = false;
-        mShowingPublic = false;
-        mSensitive = false;
         mShowingPublicInitialized = false;
-        mIsSystemExpanded = false;
-        mOnKeyguard = false;
-        mPublicLayout.reset();
-        mPrivateLayout.reset();
-        resetHeight();
-        resetTranslation();
-        logExpansionEvent(false, wasExpanded);
-    }
-
-    public void resetHeight() {
         onHeightReset();
         requestLayout();
     }
@@ -1124,7 +1139,7 @@
             public void onInflate(ViewStub stub, View inflated) {
                 mChildrenContainer = (NotificationChildrenContainer) inflated;
                 mChildrenContainer.setIsLowPriority(mIsLowPriority);
-                mChildrenContainer.setNotificationParent(ExpandableNotificationRow.this);
+                mChildrenContainer.setContainingNotification(ExpandableNotificationRow.this);
                 mChildrenContainer.onNotificationUpdated();
                 mTranslateableViews.add(mChildrenContainer);
             }
@@ -1253,9 +1268,6 @@
         if (mChildrenContainer != null) {
             mChildrenContainer.setVisibility(!mShowingPublic && mIsSummaryWithChildren ? VISIBLE
                     : INVISIBLE);
-            mChildrenContainer.updateHeaderVisibility(!mShowingPublic && mIsSummaryWithChildren
-                    ? VISIBLE
-                    : INVISIBLE);
         }
         // The limits might have changed if the view suddenly became a group or vice versa
         updateLimits();
@@ -1323,7 +1335,6 @@
      */
     public void setUserExpanded(boolean userExpanded) {
         setUserExpanded(userExpanded, false /* allowChildExpansion */);
-        updateShelfIconColor();
     }
 
     /**
@@ -1334,22 +1345,28 @@
      */
     public void setUserExpanded(boolean userExpanded, boolean allowChildExpansion) {
         mFalsingManager.setNotificationExpanded();
-        if (mIsSummaryWithChildren && !mShowingPublic && allowChildExpansion) {
+        if (mIsSummaryWithChildren && !mShowingPublic && allowChildExpansion
+                && !mChildrenContainer.showingAsLowPriority()) {
             final boolean wasExpanded = mGroupManager.isGroupExpanded(mStatusBarNotification);
             mGroupManager.setGroupExpanded(mStatusBarNotification, userExpanded);
-            logExpansionEvent(true /* userAction */, wasExpanded);
+            onExpansionChanged(true /* userAction */, wasExpanded);
             return;
         }
         if (userExpanded && !mExpandable) return;
         final boolean wasExpanded = isExpanded();
         mHasUserChangedExpansion = true;
         mUserExpanded = userExpanded;
-        logExpansionEvent(true, wasExpanded);
+        onExpansionChanged(true /* userAction */, wasExpanded);
     }
 
     public void resetUserExpansion() {
+        boolean changed = mUserExpanded;
         mHasUserChangedExpansion = false;
         mUserExpanded = false;
+        if (changed && mIsSummaryWithChildren) {
+            mChildrenContainer.onExpansionChanged();
+        }
+        updateShelfIconColor();
     }
 
     public boolean isUserLocked() {
@@ -1383,9 +1400,8 @@
         if (expand != mIsSystemExpanded) {
             final boolean wasExpanded = isExpanded();
             mIsSystemExpanded = expand;
-            updateShelfIconColor();
             notifyHeightChanged(false /* needsAnimation */);
-            logExpansionEvent(false, wasExpanded);
+            onExpansionChanged(false /* userAction */, wasExpanded);
             if (mIsSummaryWithChildren) {
                 mChildrenContainer.updateGroupOverflow();
             }
@@ -1399,7 +1415,7 @@
         if (onKeyguard != mOnKeyguard) {
             final boolean wasExpanded = isExpanded();
             mOnKeyguard = onKeyguard;
-            logExpansionEvent(false, wasExpanded);
+            onExpansionChanged(false /* userAction */, wasExpanded);
             if (wasExpanded != isExpanded()) {
                 if (mIsSummaryWithChildren) {
                     mChildrenContainer.updateGroupOverflow();
@@ -1470,8 +1486,8 @@
         mIsSummaryWithChildren = StatusBar.ENABLE_CHILD_NOTIFICATIONS
                 && mChildrenContainer != null && mChildrenContainer.getNotificationChildCount() > 0;
         if (mIsSummaryWithChildren && mChildrenContainer.getHeaderView() == null) {
-            mChildrenContainer.recreateNotificationHeader(mExpandClickListener,
-                    mEntry.notification);
+            mChildrenContainer.recreateNotificationHeader(mExpandClickListener
+            );
         }
         getShowingLayout().updateBackgroundColor(false /* animate */);
         mPrivateLayout.updateExpandButtons(isExpandable());
@@ -1526,7 +1542,7 @@
      * the top.
      */
     private void updateContentShiftHeight() {
-        NotificationHeaderView notificationHeader = getNotificationHeader();
+        NotificationHeaderView notificationHeader = getVisibleNotificationHeader();
         if (notificationHeader != null) {
             CachingIconView icon = notificationHeader.getIcon();
             mIconTransformContentShift = getRelativeTopPadding(icon) + icon.getHeight();
@@ -1698,6 +1714,9 @@
 
     @Override
     public boolean isContentExpandable() {
+        if (mIsSummaryWithChildren && !mShowingPublic) {
+            return true;
+        }
         NotificationContentView showingLayout = getShowingLayout();
         return showingLayout.isContentExpandable();
     }
@@ -1737,7 +1756,17 @@
 
     @Override
     public void setActualHeight(int height, boolean notifyListeners) {
+        boolean changed = height != getActualHeight();
         super.setActualHeight(height, notifyListeners);
+        if (changed && isRemoved()) {
+            // TODO: remove this once we found the gfx bug for this.
+            // This is a hack since a removed view sometimes would just stay blank. it occured
+            // when sending yourself a message and then clicking on it.
+            ViewGroup parent = (ViewGroup) getParent();
+            if (parent != null) {
+                parent.invalidate();
+            }
+        }
         if (mGuts != null && mGuts.isExposed()) {
             mGuts.setActualHeight(height);
             return;
@@ -1828,9 +1857,9 @@
         return mShowingPublic ? mPublicLayout : mPrivateLayout;
     }
 
-    public void setShowingLegacyBackground(boolean showing) {
+    public void setLegacy(boolean legacy) {
         for (NotificationContentView l : mLayouts) {
-            l.setShowingLegacyBackground(showing);
+            l.setLegacy(legacy);
         }
     }
 
@@ -1910,7 +1939,7 @@
             if (isGroupExpanded()) {
                 return 1.0f;
             } else if (isUserLocked()) {
-                return mChildrenContainer.getGroupExpandFraction();
+                return mChildrenContainer.getIncreasedPaddingAmount();
             }
         } else if (isColorized() && (!mIsLowPriority || isExpanded())) {
             return -1.0f;
@@ -1933,13 +1962,19 @@
         return super.disallowSingleClick(event);
     }
 
-    private void logExpansionEvent(boolean userAction, boolean wasExpanded) {
+    private void onExpansionChanged(boolean userAction, boolean wasExpanded) {
         boolean nowExpanded = isExpanded();
-        if (mIsSummaryWithChildren) {
+        if (mIsSummaryWithChildren && (!mIsLowPriority || wasExpanded)) {
             nowExpanded = mGroupManager.isGroupExpanded(mStatusBarNotification);
         }
-        if (wasExpanded != nowExpanded && mLogger != null) {
-            mLogger.logNotificationExpansion(mLoggingKey, userAction, nowExpanded) ;
+        if (nowExpanded != wasExpanded) {
+            updateShelfIconColor();
+            if (mLogger != null) {
+                mLogger.logNotificationExpansion(mLoggingKey, userAction, nowExpanded);
+            }
+            if (mIsSummaryWithChildren) {
+                mChildrenContainer.onExpansionChanged();
+            }
         }
     }
 
@@ -1949,6 +1984,26 @@
         if (canViewBeDismissed()) {
             info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_DISMISS);
         }
+        boolean expandable = mShowingPublic;
+        boolean isExpanded = false;
+        if (!expandable) {
+            if (mIsSummaryWithChildren) {
+                expandable = true;
+                if (!mIsLowPriority || isExpanded()) {
+                    isExpanded = isGroupExpanded();
+                }
+            } else {
+                expandable = mPrivateLayout.isContentExpandable();
+                isExpanded = isExpanded();
+            }
+        }
+        if (expandable) {
+            if (isExpanded) {
+                info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_COLLAPSE);
+            } else {
+                info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_EXPAND);
+            }
+        }
     }
 
     @Override
@@ -1961,6 +2016,10 @@
                 NotificationStackScrollLayout.performDismiss(this, mGroupManager,
                         true /* fromAccessibility */);
                 return true;
+            case AccessibilityNodeInfo.ACTION_COLLAPSE:
+            case AccessibilityNodeInfo.ACTION_EXPAND:
+                mExpandClickListener.onClick(this);
+                return true;
         }
         return false;
     }
@@ -1980,7 +2039,8 @@
 
     @Override
     public boolean isAboveShelf() {
-        return mIsPinned || mHeadsupDisappearRunning || (mIsHeadsUp && mAboveShelf);
+        return !isOnKeyguard()
+                && (mIsPinned || mHeadsupDisappearRunning || (mIsHeadsUp && mAboveShelf));
     }
 
     public void setShowAmbient(boolean showAmbient) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index bc992d8..fb92a67 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -42,6 +42,7 @@
 import com.android.internal.app.IBatteryStats;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.settingslib.Utils;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
@@ -365,7 +366,7 @@
             if (!updateMonitor.isUnlockingWithFingerprintAllowed()) {
                 return;
             }
-            int errorColor = mContext.getResources().getColor(R.color.system_warning_color, null);
+            int errorColor = Utils.getColorError(mContext);
             if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
                 mStatusBarKeyguardViewManager.showBouncerMessage(helpString, errorColor);
             } else if (updateMonitor.isDeviceInteractive()
@@ -388,7 +389,7 @@
                     || msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
                 return;
             }
-            int errorColor = mContext.getResources().getColor(R.color.system_warning_color, null);
+            int errorColor = Utils.getColorError(mContext);
             if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
                 // When swiping up right after receiving a fingerprint error, the bouncer calls
                 // authenticate leading to the same message being shown again on the bouncer.
@@ -411,8 +412,7 @@
         @Override
         public void onScreenTurnedOn() {
             if (mMessageToShowOnScreenOn != null) {
-                int errorColor = mContext.getResources().getColor(R.color.system_warning_color,
-                        null);
+                int errorColor = Utils.getColorError(mContext);
                 showTransientIndication(mMessageToShowOnScreenOn, errorColor);
                 // We want to keep this message around in case the screen was off
                 mHandler.removeMessages(MSG_HIDE_TRANSIENT);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 57d2e1c..8f160dc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -80,7 +80,7 @@
     private boolean mDark;
     private boolean mAnimate;
     private boolean mIsHeadsUp;
-    private boolean mShowingLegacyBackground;
+    private boolean mLegacy;
     private boolean mIsChildInGroup;
     private int mSmallHeight;
     private int mHeadsUpHeight;
@@ -131,6 +131,7 @@
     private boolean mIconsVisible;
     private int mClipBottomAmount;
     private boolean mIsLowPriority;
+    private boolean mIsContentExpandable;
 
 
     public NotificationContentView(Context context, AttributeSet attrs) {
@@ -140,7 +141,6 @@
                 R.dimen.min_notification_layout_height);
         mNotificationContentMarginEnd = getResources().getDimensionPixelSize(
                 com.android.internal.R.dimen.notification_content_margin_end);
-        reset();
     }
 
     public void setHeights(int smallHeight, int headsUpMaxHeight, int maxHeight,
@@ -329,41 +329,6 @@
         updateVisibility();
     }
 
-    public void reset() {
-        mPreviousExpandedRemoteInputIntent = null;
-        if (mExpandedRemoteInput != null) {
-            mExpandedRemoteInput.onNotificationUpdateOrReset();
-            if (mExpandedRemoteInput.isActive()) {
-                mPreviousExpandedRemoteInputIntent = mExpandedRemoteInput.getPendingIntent();
-                mCachedExpandedRemoteInput = mExpandedRemoteInput;
-                mExpandedRemoteInput.dispatchStartTemporaryDetach();
-                ((ViewGroup)mExpandedRemoteInput.getParent()).removeView(mExpandedRemoteInput);
-            }
-        }
-        if (mExpandedChild != null) {
-            mExpandedChild.animate().cancel();
-            removeView(mExpandedChild);
-            mExpandedRemoteInput = null;
-        }
-        mPreviousHeadsUpRemoteInputIntent = null;
-        if (mHeadsUpRemoteInput != null) {
-            mHeadsUpRemoteInput.onNotificationUpdateOrReset();
-            if (mHeadsUpRemoteInput.isActive()) {
-                mPreviousHeadsUpRemoteInputIntent = mHeadsUpRemoteInput.getPendingIntent();
-                mCachedHeadsUpRemoteInput = mHeadsUpRemoteInput;
-                mHeadsUpRemoteInput.dispatchStartTemporaryDetach();
-                ((ViewGroup)mHeadsUpRemoteInput.getParent()).removeView(mHeadsUpRemoteInput);
-            }
-        }
-        if (mHeadsUpChild != null) {
-            mHeadsUpChild.animate().cancel();
-            removeView(mHeadsUpChild);
-            mHeadsUpRemoteInput = null;
-        }
-        mExpandedChild = null;
-        mHeadsUpChild = null;
-    }
-
     public View getContractedChild() {
         return mContractedChild;
     }
@@ -394,8 +359,30 @@
 
     public void setExpandedChild(View child) {
         if (mExpandedChild != null) {
+            mPreviousExpandedRemoteInputIntent = null;
+            if (mExpandedRemoteInput != null) {
+                mExpandedRemoteInput.onNotificationUpdateOrReset();
+                if (mExpandedRemoteInput.isActive()) {
+                    mPreviousExpandedRemoteInputIntent = mExpandedRemoteInput.getPendingIntent();
+                    mCachedExpandedRemoteInput = mExpandedRemoteInput;
+                    mExpandedRemoteInput.dispatchStartTemporaryDetach();
+                    ((ViewGroup)mExpandedRemoteInput.getParent()).removeView(mExpandedRemoteInput);
+                }
+            }
             mExpandedChild.animate().cancel();
             removeView(mExpandedChild);
+            mExpandedRemoteInput = null;
+        }
+        if (child == null) {
+            mExpandedChild = null;
+            mExpandedWrapper = null;
+            if (mVisibleType == VISIBLE_TYPE_EXPANDED) {
+                mVisibleType = VISIBLE_TYPE_CONTRACTED;
+            }
+            if (mTransformationStartVisibleType == VISIBLE_TYPE_EXPANDED) {
+                mTransformationStartVisibleType = UNDEFINED;
+            }
+            return;
         }
         addView(child);
         mExpandedChild = child;
@@ -405,8 +392,30 @@
 
     public void setHeadsUpChild(View child) {
         if (mHeadsUpChild != null) {
+            mPreviousHeadsUpRemoteInputIntent = null;
+            if (mHeadsUpRemoteInput != null) {
+                mHeadsUpRemoteInput.onNotificationUpdateOrReset();
+                if (mHeadsUpRemoteInput.isActive()) {
+                    mPreviousHeadsUpRemoteInputIntent = mHeadsUpRemoteInput.getPendingIntent();
+                    mCachedHeadsUpRemoteInput = mHeadsUpRemoteInput;
+                    mHeadsUpRemoteInput.dispatchStartTemporaryDetach();
+                    ((ViewGroup)mHeadsUpRemoteInput.getParent()).removeView(mHeadsUpRemoteInput);
+                }
+            }
             mHeadsUpChild.animate().cancel();
             removeView(mHeadsUpChild);
+            mHeadsUpRemoteInput = null;
+        }
+        if (child == null) {
+            mHeadsUpChild = null;
+            mHeadsUpWrapper = null;
+            if (mVisibleType == VISIBLE_TYPE_HEADSUP) {
+                mVisibleType = VISIBLE_TYPE_CONTRACTED;
+            }
+            if (mTransformationStartVisibleType == VISIBLE_TYPE_HEADSUP) {
+                mTransformationStartVisibleType = UNDEFINED;
+            }
+            return;
         }
         addView(child);
         mHeadsUpChild = child;
@@ -623,7 +632,7 @@
     }
 
     public int getMinHeight(boolean likeGroupExpanded) {
-        if (likeGroupExpanded || !mIsChildInGroup || isGroupExpanded() || mIsLowPriority) {
+        if (likeGroupExpanded || !mIsChildInGroup || isGroupExpanded()) {
             return mContractedChild.getHeight();
         } else {
             return mSingleLineView.getHeight();
@@ -897,7 +906,7 @@
                 height = mContentHeight;
             }
             int expandedVisualType = getVisualTypeForHeight(height);
-            int collapsedVisualType = mIsChildInGroup && !isGroupExpanded() && !mIsLowPriority
+            int collapsedVisualType = mIsChildInGroup && !isGroupExpanded()
                     ? VISIBLE_TYPE_SINGLELINE
                     : getVisualTypeForHeight(mContainingNotification.getCollapsedHeight());
             return mTransformationStartVisibleType == collapsedVisualType
@@ -918,7 +927,7 @@
         if (!noExpandedChild && viewHeight == mExpandedChild.getHeight()) {
             return VISIBLE_TYPE_EXPANDED;
         }
-        if (!mUserExpanding && mIsChildInGroup && !isGroupExpanded() && !mIsLowPriority) {
+        if (!mUserExpanding && mIsChildInGroup && !isGroupExpanded()) {
             return VISIBLE_TYPE_SINGLELINE;
         }
 
@@ -941,7 +950,7 @@
     }
 
     public boolean isContentExpandable() {
-        return mExpandedChild != null;
+        return mIsContentExpandable;
     }
 
     public void setDark(boolean dark, boolean fade, long delay) {
@@ -978,25 +987,37 @@
         return false;
     }
 
-    public void setShowingLegacyBackground(boolean showing) {
-        mShowingLegacyBackground = showing;
-        updateShowingLegacyBackground();
+    public void setLegacy(boolean legacy) {
+        mLegacy = legacy;
+        updateLegacy();
     }
 
-    private void updateShowingLegacyBackground() {
+    private void updateLegacy() {
         if (mContractedChild != null) {
-            mContractedWrapper.setShowingLegacyBackground(mShowingLegacyBackground);
+            mContractedWrapper.setLegacy(mLegacy);
         }
         if (mExpandedChild != null) {
-            mExpandedWrapper.setShowingLegacyBackground(mShowingLegacyBackground);
+            mExpandedWrapper.setLegacy(mLegacy);
         }
         if (mHeadsUpChild != null) {
-            mHeadsUpWrapper.setShowingLegacyBackground(mShowingLegacyBackground);
+            mHeadsUpWrapper.setLegacy(mLegacy);
         }
     }
 
     public void setIsChildInGroup(boolean isChildInGroup) {
         mIsChildInGroup = isChildInGroup;
+        if (mContractedChild != null) {
+            mContractedWrapper.setIsChildInGroup(mIsChildInGroup);
+        }
+        if (mExpandedChild != null) {
+            mExpandedWrapper.setIsChildInGroup(mIsChildInGroup);
+        }
+        if (mHeadsUpChild != null) {
+            mHeadsUpWrapper.setIsChildInGroup(mIsChildInGroup);
+        }
+        if (mAmbientChild != null) {
+            mAmbientWrapper.setIsChildInGroup(mIsChildInGroup);
+        }
         updateSingleLineView();
     }
 
@@ -1005,19 +1026,19 @@
         mBeforeN = entry.targetSdk < Build.VERSION_CODES.N;
         updateSingleLineView();
         if (mContractedChild != null) {
-            mContractedWrapper.notifyContentUpdated(entry.notification, mIsLowPriority);
+            mContractedWrapper.notifyContentUpdated(entry.row);
         }
         if (mExpandedChild != null) {
-            mExpandedWrapper.notifyContentUpdated(entry.notification, mIsLowPriority);
+            mExpandedWrapper.notifyContentUpdated(entry.row);
         }
         if (mHeadsUpChild != null) {
-            mHeadsUpWrapper.notifyContentUpdated(entry.notification, mIsLowPriority);
+            mHeadsUpWrapper.notifyContentUpdated(entry.row);
         }
         if (mAmbientChild != null) {
-            mAmbientWrapper.notifyContentUpdated(entry.notification, mIsLowPriority);
+            mAmbientWrapper.notifyContentUpdated(entry.row);
         }
         applyRemoteInput(entry);
-        updateShowingLegacyBackground();
+        updateLegacy();
         mForceSelectNextLayout = true;
         setDark(mDark, false /* animate */, 0 /* delay */);
         mPreviousExpandedRemoteInputIntent = null;
@@ -1176,11 +1197,12 @@
         mExpandable = expandable;
         // if the expanded child has the same height as the collapsed one we hide it.
         if (mExpandedChild != null && mExpandedChild.getHeight() != 0) {
-            if (!mIsHeadsUp || mHeadsUpChild == null || mContainingNotification.isOnKeyguard()) {
-                if (mExpandedChild.getHeight() == mContractedChild.getHeight()) {
+            if ((!mIsHeadsUp && !mHeadsUpAnimatingAway)
+                    || mHeadsUpChild == null || mContainingNotification.isOnKeyguard()) {
+                if (mExpandedChild.getHeight() <= mContractedChild.getHeight()) {
                     expandable = false;
                 }
-            } else if (mExpandedChild.getHeight() == mHeadsUpChild.getHeight()) {
+            } else if (mExpandedChild.getHeight() <= mHeadsUpChild.getHeight()) {
                 expandable = false;
             }
         }
@@ -1193,6 +1215,7 @@
         if (mHeadsUpChild != null) {
             mHeadsUpWrapper.updateExpandability(expandable,  mExpandClickListener);
         }
+        mIsContentExpandable = expandable;
     }
 
     public NotificationHeaderView getNotificationHeader() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index 81db429..8f8d966 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -34,6 +34,7 @@
 
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.util.NotificationColorUtil;
+import com.android.systemui.statusbar.notification.InflationException;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -65,7 +66,6 @@
         public ExpandableNotificationRow row; // the outer expanded view
         private boolean interruption;
         public boolean autoRedacted; // whether the redacted notification was generated by us
-        public boolean legacy; // whether the notification has a legacy, dark background
         public int targetSdk;
         private long lastFullScreenIntentLaunchTime = NOT_LAUNCHED_YET;
         public RemoteViews cachedContentView;
@@ -95,118 +95,20 @@
          * Resets the notification entry to be re-used.
          */
         public void reset() {
-            // NOTE: Icon needs to be preserved for now.
-            // We should fix this at some point.
-            autoRedacted = false;
-            legacy = false;
             lastFullScreenIntentLaunchTime = NOT_LAUNCHED_YET;
             if (row != null) {
                 row.reset();
             }
         }
 
-        public View getContentView() {
-            return row.getPrivateLayout().getContractedChild();
-        }
-
         public View getExpandedContentView() {
             return row.getPrivateLayout().getExpandedChild();
         }
 
-        public View getHeadsUpContentView() {
-            return row.getPrivateLayout().getHeadsUpChild();
-        }
-
         public View getPublicContentView() {
             return row.getPublicLayout().getContractedChild();
         }
 
-        public View getAmbientContentView() {
-            return row.getPrivateLayout().getAmbientChild();
-        }
-
-        public boolean cacheContentViews(Context ctx, Notification updatedNotification,
-                boolean isLowPriority, boolean useIncreasedCollapsedView,
-                boolean useIncreasedHeadsUp) {
-            boolean applyInPlace = false;
-            if (updatedNotification != null) {
-                final Notification.Builder updatedNotificationBuilder
-                        = Notification.Builder.recoverBuilder(ctx, updatedNotification);
-                final RemoteViews newContentView = createContentView(updatedNotificationBuilder,
-                        isLowPriority, useIncreasedCollapsedView);
-                final RemoteViews newBigContentView = createBigContentView(
-                        updatedNotificationBuilder, isLowPriority);
-                final RemoteViews newHeadsUpContentView =
-                        updatedNotificationBuilder.createHeadsUpContentView(useIncreasedHeadsUp);
-                final RemoteViews newPublicNotification
-                        = updatedNotificationBuilder.makePublicContentView();
-                final RemoteViews newAmbientNotification
-                        = updatedNotificationBuilder.makeAmbientNotification();
-
-                boolean sameCustomView = Objects.equals(
-                        notification.getNotification().extras.getBoolean(
-                                Notification.EXTRA_CONTAINS_CUSTOM_VIEW),
-                        updatedNotification.extras.getBoolean(
-                                Notification.EXTRA_CONTAINS_CUSTOM_VIEW));
-                applyInPlace = compareRemoteViews(cachedContentView, newContentView)
-                        && compareRemoteViews(cachedBigContentView, newBigContentView)
-                        && compareRemoteViews(cachedHeadsUpContentView, newHeadsUpContentView)
-                        && compareRemoteViews(cachedPublicContentView, newPublicNotification)
-                        && compareRemoteViews(cachedAmbientContentView, newAmbientNotification)
-                        && sameCustomView;
-                cachedPublicContentView = newPublicNotification;
-                cachedHeadsUpContentView = newHeadsUpContentView;
-                cachedBigContentView = newBigContentView;
-                cachedContentView = newContentView;
-                cachedAmbientContentView = newAmbientNotification;
-            } else {
-                final Notification.Builder builder
-                        = Notification.Builder.recoverBuilder(ctx, notification.getNotification());
-
-                cachedContentView = createContentView(builder, isLowPriority,
-                        useIncreasedCollapsedView);
-                cachedBigContentView = createBigContentView(builder, isLowPriority);
-                cachedHeadsUpContentView = builder.createHeadsUpContentView(useIncreasedHeadsUp);
-                cachedPublicContentView = builder.makePublicContentView();
-                cachedAmbientContentView = builder.makeAmbientNotification();
-
-                applyInPlace = false;
-            }
-            return applyInPlace;
-        }
-
-        private RemoteViews createBigContentView(Notification.Builder builder,
-                boolean isLowPriority) {
-            RemoteViews bigContentView = builder.createBigContentView();
-            if (bigContentView != null) {
-                return bigContentView;
-            }
-            if (isLowPriority) {
-                RemoteViews contentView = builder.createContentView();
-                Notification.Builder.makeHeaderExpanded(contentView);
-                return contentView;
-            }
-            return null;
-        }
-
-        private RemoteViews createContentView(Notification.Builder builder,
-                boolean isLowPriority, boolean useLarge) {
-            if (isLowPriority) {
-                return builder.makeLowPriorityContentView(false /* useRegularSubtext */);
-            }
-            return builder.createContentView(useLarge);
-        }
-
-        // Returns true if the RemoteViews are the same.
-        private boolean compareRemoteViews(final RemoteViews a, final RemoteViews b) {
-            return (a == null && b == null) ||
-                    (a != null && b != null
-                    && b.getPackage() != null
-                    && a.getPackage() != null
-                    && a.getPackage().equals(b.getPackage())
-                    && a.getLayoutId() == b.getLayoutId());
-        }
-
         public void notifyFullScreenIntentLaunched() {
             lastFullScreenIntentLaunchTime = SystemClock.elapsedRealtime();
         }
@@ -219,13 +121,14 @@
          * Create the icons for a notification
          * @param context the context to create the icons with
          * @param sbn the notification
-         * @throws IconException
+         * @throws InflationException
          */
-        public void createIcons(Context context, StatusBarNotification sbn) throws IconException {
+        public void createIcons(Context context, StatusBarNotification sbn)
+                throws InflationException {
             Notification n = sbn.getNotification();
             final Icon smallIcon = n.getSmallIcon();
             if (smallIcon == null) {
-                throw new IconException("No small icon in notification from "
+                throw new InflationException("No small icon in notification from "
                         + sbn.getPackageName());
             }
 
@@ -248,7 +151,7 @@
             if (!icon.set(ic) || !expandedIcon.set(ic)) {
                 icon = null;
                 expandedIcon = null;
-                throw new IconException("Couldn't create icon: " + ic);
+                throw new InflationException("Couldn't create icon: " + ic);
             }
             expandedIcon.setVisibility(View.INVISIBLE);
             expandedIcon.setOnVisibilityChangedListener(
@@ -270,9 +173,9 @@
          * Update the notification icons.
          * @param context the context to create the icons with.
          * @param n the notification to read the icon from.
-         * @throws IconException
+         * @throws InflationException
          */
-        public void updateIcons(Context context, Notification n) throws IconException {
+        public void updateIcons(Context context, Notification n) throws InflationException {
             if (icon != null) {
                 // Update the icon
                 final StatusBarIcon ic = new StatusBarIcon(
@@ -285,7 +188,7 @@
                 icon.setNotification(n);
                 expandedIcon.setNotification(n);
                 if (!icon.set(ic) || !expandedIcon.set(ic)) {
-                    throw new IconException("Couldn't update icon: " + ic);
+                    throw new InflationException("Couldn't update icon: " + ic);
                 }
             }
         }
@@ -612,10 +515,4 @@
         public String getCurrentMediaNotificationKey();
         public NotificationGroupManager getGroupManager();
     }
-
-    public static class IconException extends Exception {
-        IconException(String error) {
-            super(error);
-        }
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
index 9703235..af464c6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
@@ -72,11 +72,6 @@
     private StatusBarNotification mStatusBarNotification;
     private NotificationChannel mNotificationChannel;
 
-    private ImageView mAutoButton;
-    private TextView mImportanceSummary;
-    private TextView mImportanceTitle;
-    private boolean mAuto;
-
     private TextView mNumChannelsView;
     private View mChannelDisabledView;
     private Switch mChannelEnabledSwitch;
@@ -105,8 +100,10 @@
         int appUid = -1;
         String appName = pkg;
         Drawable pkgicon = null;
+        CharSequence channelNameText = "";
+        ApplicationInfo info = null;
         try {
-            final ApplicationInfo info = pm.getApplicationInfo(pkg,
+            info = pm.getApplicationInfo(pkg,
                     PackageManager.MATCH_UNINSTALLED_PACKAGES
                             | PackageManager.MATCH_DISABLED_COMPONENTS
                             | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
@@ -115,6 +112,7 @@
                 appUid = info.uid;
                 appName = String.valueOf(pm.getApplicationLabel(info));
                 pkgicon = pm.getApplicationIcon(info);
+
             }
         } catch (PackageManager.NameNotFoundException e) {
             // app is gone, just show package name and generic icon
@@ -135,11 +133,15 @@
                 R.plurals.notification_num_channels_desc, numChannels), numChannels));
 
         // If this is the placeholder channel, don't use our channel-specific text.
-        CharSequence channelNameText;
         if (channel.getId().equals(NotificationChannel.DEFAULT_CHANNEL_ID)) {
             channelNameText = mContext.getString(R.string.notification_header_default_channel);
         } else {
-            channelNameText = channel.getName();
+            if (info != null && channel.getNameResId() != 0) {
+                channelNameText = pm.getText(pkg, channel.getNameResId(), info);
+            }
+            if (channel.getName() != null) {
+                channelNameText = channel.getName();
+            }
         }
         ((TextView) findViewById(R.id.pkgname)).setText(appName);
         ((TextView) findViewById(R.id.channel_name)).setText(channelNameText);
@@ -152,7 +154,12 @@
                         iNotificationManager.getNotificationChannelGroupForPackage(
                                 channel.getGroup(), pkg, appUid);
                 if (notificationChannelGroup != null) {
-                    groupName = notificationChannelGroup.getName();
+                    if (info != null && notificationChannelGroup.getNameResId() != 0) {
+                        groupName = pm.getText(pkg, notificationChannelGroup.getNameResId(), info);
+                    }
+                    if (notificationChannelGroup.getName() != null) {
+                        groupName = notificationChannelGroup.getName();
+                    }
                 }
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
@@ -171,8 +178,8 @@
 
         boolean nonBlockable = false;
         try {
-            final PackageInfo info = pm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES);
-            nonBlockable = Utils.isSystemPackage(getResources(), pm, info);
+            final PackageInfo pkgInfo = pm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES);
+            nonBlockable = Utils.isSystemPackage(getResources(), pm, pkgInfo);
         } catch (PackageManager.NameNotFoundException e) {
             // unlikely.
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 1cd909ea..8da17fa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -41,7 +41,8 @@
  * A notification shelf view that is placed inside the notification scroller. It manages the
  * overflow icons that don't fit into the regular list anymore.
  */
-public class NotificationShelf extends ActivatableNotificationView {
+public class NotificationShelf extends ActivatableNotificationView implements
+        View.OnLayoutChangeListener {
 
     public static final boolean SHOW_AMBIENT_ICONS = true;
     private static final boolean USE_ANIMATIONS_WHEN_OPENING =
@@ -443,7 +444,8 @@
             }
             int shelfColor = icon.getStaticDrawableColor();
             if (!noIcon && shelfColor != StatusBarIconView.NO_COLOR) {
-                int notificationColor = row.getNotificationHeader().getOriginalNotificationColor();
+                int notificationColor
+                        = row.getVisibleNotificationHeader().getOriginalNotificationColor();
                 shelfColor = NotificationUtils.interpolateColors(notificationColor, shelfColor,
                         iconState.iconAppearAmount);
             }
@@ -493,6 +495,10 @@
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
+        updateRelativeOffset();
+    }
+
+    private void updateRelativeOffset() {
         mCollapsedIcons.getLocationOnScreen(mTmp);
         mRelativeOffset = mTmp[0];
         getLocationOnScreen(mTmp);
@@ -559,6 +565,7 @@
 
     public void setCollapsedIcons(NotificationIconContainer collapsedIcons) {
         mCollapsedIcons = collapsedIcons;
+        mCollapsedIcons.addOnLayoutChangeListener(this);
     }
 
     public void setStatusBarState(int statusBarState) {
@@ -594,6 +601,12 @@
         }
     }
 
+    @Override
+    public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
+            int oldTop, int oldRight, int oldBottom) {
+        updateRelativeOffset();
+    }
+
     private class ShelfState extends ExpandableViewState {
         private float openedAmount;
         private boolean hasItemsInStableShelf;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 89041f9..67be99e5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -83,6 +83,8 @@
     private int mWifiStrengthId = 0;
     private int mLastWifiBadgeId = -1;
     private int mLastWifiStrengthId = -1;
+    private int mWifiActivityId = 0;
+    private int mLastWifiActivityId = -1;
     private boolean mIsAirplaneMode = false;
     private int mAirplaneIconId = 0;
     private int mLastAirplaneIconId = -1;
@@ -97,6 +99,7 @@
     ViewGroup mEthernetGroup, mWifiGroup;
     View mNoSimsCombo;
     ImageView mVpn, mEthernet, mWifi, mAirplane, mNoSims, mEthernetDark, mWifiDark, mNoSimsDark;
+    ImageView mWifiActivity;
     View mWifiAirplaneSpacer;
     View mWifiSignalSpacer;
     LinearLayout mMobileSignalGroup;
@@ -177,6 +180,7 @@
         mWifiGroup      = (ViewGroup) findViewById(R.id.wifi_combo);
         mWifi           = (ImageView) findViewById(R.id.wifi_signal);
         mWifiDark       = (ImageView) findViewById(R.id.wifi_signal_dark);
+        mWifiActivity   = (ImageView) findViewById(R.id.wifi_inout);
         mAirplane       = (ImageView) findViewById(R.id.airplane);
         mNoSims         = (ImageView) findViewById(R.id.no_sims);
         mNoSimsDark     = (ImageView) findViewById(R.id.no_sims_dark);
@@ -267,6 +271,10 @@
         mWifiStrengthId = statusIcon.icon;
         mWifiBadgeId = statusIcon.iconOverlay;
         mWifiDescription = statusIcon.contentDescription;
+        mWifiActivityId = activityIn && activityOut ? R.drawable.stat_sys_wifi_inout
+                : activityIn ? R.drawable.stat_sys_wifi_in
+                : activityOut ? R.drawable.stat_sys_wifi_out
+                : 0;
 
         apply();
     }
@@ -286,6 +294,10 @@
         state.mMobileTypeDescription = typeContentDescription;
         state.mIsMobileTypeIconWide = statusType != 0 && isWide;
         state.mRoaming = roaming;
+        state.mMobileActivityId = activityIn && activityOut ? R.drawable.stat_sys_signal_inout
+                : activityIn ? R.drawable.stat_sys_signal_in
+                : activityOut ? R.drawable.stat_sys_signal_out
+                : 0;
 
         apply();
     }
@@ -409,6 +421,10 @@
             mLastWifiStrengthId = -1;
             mLastWifiBadgeId = -1;
         }
+        if (mWifiActivity !=  null) {
+            mWifiActivity.setImageDrawable(null);
+            mLastWifiActivityId = -1;
+        }
 
         for (PhoneState state : mPhoneStates) {
             if (state.mMobile != null) {
@@ -425,6 +441,10 @@
                 state.mMobileType.setImageDrawable(null);
                 state.mLastMobileTypeId = -1;
             }
+            if (state.mMobileActivity != null) {
+                state.mMobileActivity.setImageDrawable(null);
+                state.mLastMobileActivityId = -1;
+            }
         }
 
         if (mAirplane != null) {
@@ -484,6 +504,12 @@
                 mLastWifiStrengthId = mWifiStrengthId;
                 mLastWifiBadgeId = mWifiBadgeId;
             }
+            if (mWifiActivityId != mLastWifiActivityId) {
+                if (mWifiActivityId != 0) {
+                    setIconForView(mWifiActivity, mWifiActivityId);
+                }
+                mLastWifiActivityId = mWifiActivityId;
+            }
             mWifiGroup.setContentDescription(mWifiDescription);
             mWifiGroup.setVisibility(View.VISIBLE);
         } else {
@@ -495,6 +521,8 @@
                     (mWifiVisible ? "VISIBLE" : "GONE"),
                     mWifiStrengthId));
 
+        mWifiActivity.setVisibility(mWifiActivityId != 0 ? View.VISIBLE : View.GONE);
+
         boolean anyMobileVisible = false;
         int firstMobileTypeId = 0;
         for (PhoneState state : mPhoneStates) {
@@ -603,6 +631,8 @@
         applyDarkIntensity(
                 DarkIconDispatcher.getDarkIntensity(mTintArea, mWifi, mDarkIntensity),
                 mWifi, mWifiDark);
+        setTint(mWifiActivity,
+                DarkIconDispatcher.getTint(mTintArea, mWifiActivity, mIconTint));
         applyDarkIntensity(
                 DarkIconDispatcher.getDarkIntensity(mTintArea, mEthernet, mDarkIntensity),
                 mEthernet, mEthernetDark);
@@ -627,15 +657,17 @@
     private class PhoneState {
         private final int mSubId;
         private boolean mMobileVisible = false;
-        private int mMobileStrengthId = 0, mMobileTypeId = 0;
+        private int mMobileStrengthId = 0, mMobileTypeId = 0, mMobileActivityId = 0;
         private int mLastMobileStrengthId = -1;
         private int mLastMobileTypeId = -1;
+        private int mLastMobileActivityId = -1;
         private boolean mIsMobileTypeIconWide;
         private String mMobileDescription, mMobileTypeDescription;
 
         private ViewGroup mMobileGroup;
         private ImageView mMobile, mMobileDark, mMobileType, mMobileRoaming;
         public boolean mRoaming;
+        private ImageView mMobileActivity;
 
         public PhoneState(int subId, Context context) {
             ViewGroup root = (ViewGroup) LayoutInflater.from(context)
@@ -650,6 +682,7 @@
             mMobileDark     = (ImageView) root.findViewById(R.id.mobile_signal_dark);
             mMobileType     = (ImageView) root.findViewById(R.id.mobile_type);
             mMobileRoaming  = (ImageView) root.findViewById(R.id.mobile_roaming);
+            mMobileActivity = (ImageView) root.findViewById(R.id.mobile_inout);
         }
 
         public boolean apply(boolean isSecondaryIcon) {
@@ -664,6 +697,11 @@
                     mMobileType.setImageResource(mMobileTypeId);
                     mLastMobileTypeId = mMobileTypeId;
                 }
+
+                if (mLastMobileActivityId != mMobileActivityId) {
+                    mMobileActivity.setImageResource(mMobileActivityId);
+                    mLastMobileActivityId = mMobileActivityId;
+                }
                 mMobileGroup.setContentDescription(mMobileTypeDescription
                         + " " + mMobileDescription);
                 mMobileGroup.setVisibility(View.VISIBLE);
@@ -686,6 +724,7 @@
 
             mMobileType.setVisibility(mMobileTypeId != 0 ? View.VISIBLE : View.GONE);
             mMobileRoaming.setVisibility(mRoaming ? View.VISIBLE : View.GONE);
+            mMobileActivity.setVisibility(mMobileActivityId != 0 ? View.VISIBLE : View.GONE);
 
             return mMobileVisible;
         }
@@ -747,6 +786,8 @@
             setTint(mMobileType, DarkIconDispatcher.getTint(tintArea, mMobileType, tint));
             setTint(mMobileRoaming, DarkIconDispatcher.getTint(tintArea, mMobileRoaming,
                     tint));
+            setTint(mMobileActivity,
+                    DarkIconDispatcher.getTint(tintArea, mMobileActivity, tint));
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index aec9a4b..1101701 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -612,8 +612,10 @@
     }
 
     public void setIconAppearAmount(float iconAppearAmount) {
-        mIconAppearAmount = iconAppearAmount;
-        invalidate();
+        if (mIconAppearAmount != iconAppearAmount) {
+            mIconAppearAmount = iconAppearAmount;
+            invalidate();
+        }
     }
 
     public float getIconAppearAmount() {
@@ -625,8 +627,10 @@
     }
 
     public void setDotAppearAmount(float dotAppearAmount) {
-        mDotAppearAmount = dotAppearAmount;
-        invalidate();
+        if (mDotAppearAmount != dotAppearAmount) {
+            mDotAppearAmount = dotAppearAmount;
+            invalidate();
+        }
     }
 
     @Override
diff --git a/core/java/com/android/internal/logging/legacy/Util.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InflationException.java
similarity index 68%
copy from core/java/com/android/internal/logging/legacy/Util.java
copy to packages/SystemUI/src/com/android/systemui/statusbar/notification/InflationException.java
index 99f71ca..b484138 100644
--- a/core/java/com/android/internal/logging/legacy/Util.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InflationException.java
@@ -11,15 +11,16 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
- * limitations under the License.
+ * limitations under the License
  */
-package com.android.internal.logging.legacy;
+
+package com.android.systemui.statusbar.notification;
 
 /**
- * Created by cwren on 11/21/16.
+ * An exception that something went wrong during the inflation
  */
-public class Util {
-    public static boolean debug() {
-        return false;
+public class InflationException extends Exception {
+    public InflationException(String error) {
+        super(error);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigPictureTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigPictureTemplateViewWrapper.java
index 78b967a..7a34b6e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigPictureTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigPictureTemplateViewWrapper.java
@@ -36,9 +36,9 @@
     }
 
     @Override
-    public void notifyContentUpdated(StatusBarNotification notification, boolean isLowPriority) {
-        super.notifyContentUpdated(notification, isLowPriority);
-        updateImageTag(notification);
+    public void notifyContentUpdated(ExpandableNotificationRow row) {
+        super.notifyContentUpdated(row);
+        updateImageTag(row.getStatusBarNotification());
     }
 
     private void updateImageTag(StatusBarNotification notification) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigTextTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigTextTemplateViewWrapper.java
index 39db243..9476eed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigTextTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigTextTemplateViewWrapper.java
@@ -41,11 +41,11 @@
     }
 
     @Override
-    public void notifyContentUpdated(StatusBarNotification notification, boolean isLowPriority) {
+    public void notifyContentUpdated(ExpandableNotificationRow row) {
         // Reinspect the notification. Before the super call, because the super call also updates
         // the transformation types and we need to have our values set by then.
-        resolveViews(notification);
-        super.notifyContentUpdated(notification, isLowPriority);
+        resolveViews(row.getStatusBarNotification());
+        super.notifyContentUpdated(row);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
index e5f32df..3efa29f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
@@ -19,13 +19,8 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
-import android.graphics.Color;
 import android.graphics.ColorMatrixColorFilter;
 import android.graphics.Paint;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
-import android.service.notification.StatusBarNotification;
-import android.support.v4.graphics.ColorUtils;
 import android.view.View;
 
 import com.android.systemui.R;
@@ -40,7 +35,7 @@
 
     private final ViewInvertHelper mInvertHelper;
     private final Paint mGreyPaint = new Paint();
-    private boolean mShowingLegacyBackground;
+    private boolean mIsLegacy;
     private int mLegacyColor;
 
     protected NotificationCustomViewWrapper(View view, ExpandableNotificationRow row) {
@@ -55,7 +50,7 @@
             return;
         }
         super.setDark(dark, fade, delay);
-        if (!mShowingLegacyBackground && mShouldInvertDark) {
+        if (!mIsLegacy && mShouldInvertDark) {
             if (fade) {
                 mInvertHelper.fade(dark, delay);
             } else {
@@ -112,15 +107,14 @@
     @Override
     public int getCustomBackgroundColor() {
         int customBackgroundColor = super.getCustomBackgroundColor();
-        if (customBackgroundColor == 0 && mShowingLegacyBackground) {
+        if (customBackgroundColor == 0 && mIsLegacy) {
             return mLegacyColor;
         }
         return customBackgroundColor;
     }
 
-    @Override
-    public void setShowingLegacyBackground(boolean showing) {
-        super.setShowingLegacyBackground(showing);
-        mShowingLegacyBackground = showing;
+    public void setLegacy(boolean legacy) {
+        super.setLegacy(legacy);
+        mIsLegacy = legacy;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
index 8eab2e9..38e4ec1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
@@ -19,6 +19,7 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
+import android.app.Notification;
 import android.content.Context;
 import android.graphics.Color;
 import android.graphics.ColorFilter;
@@ -26,7 +27,6 @@
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffColorFilter;
 import android.graphics.drawable.Drawable;
-import android.service.notification.StatusBarNotification;
 import android.util.ArraySet;
 import android.view.NotificationHeaderView;
 import android.view.View;
@@ -71,6 +71,7 @@
     private TextView mHeaderText;
     private ImageView mWorkProfileImage;
     private boolean mIsLowPriority;
+    private boolean mTransformLowPriorityTitle;
 
     protected NotificationHeaderViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
         super(view, row);
@@ -100,7 +101,7 @@
 
                     @Override
                     protected boolean hasCustomTransformation() {
-                        return mIsLowPriority;
+                        return mIsLowPriority && mTransformLowPriorityTitle;
                     }
                 }, TRANSFORMING_VIEW_TITLE);
         resolveHeaderViews();
@@ -128,9 +129,10 @@
     }
 
     @Override
-    public void notifyContentUpdated(StatusBarNotification notification, boolean isLowPriority) {
-        super.notifyContentUpdated(notification, isLowPriority);
-        mIsLowPriority = isLowPriority;
+    public void notifyContentUpdated(ExpandableNotificationRow row) {
+        super.notifyContentUpdated(row);
+        mIsLowPriority = row.isLowPriority();
+        mTransformLowPriorityTitle = !row.isChildInGroup() && !row.isSummaryWithChildren();
         ArraySet<View> previousViews = mTransformationHelper.getAllTransformingViews();
 
         // Reinspect the notification.
@@ -139,11 +141,11 @@
         updateTransformedTypes();
         addRemainingTransformTypes();
         updateCropToPaddingForImageViews();
-        mIcon.setTag(ImageTransformState.ICON_TAG, notification.getNotification().getSmallIcon());
+        Notification notification = row.getStatusBarNotification().getNotification();
+        mIcon.setTag(ImageTransformState.ICON_TAG, notification.getSmallIcon());
         // The work profile image is always the same lets just set the icon tag for it not to
         // animate
-        mWorkProfileImage.setTag(ImageTransformState.ICON_TAG,
-                notification.getNotification().getSmallIcon());
+        mWorkProfileImage.setTag(ImageTransformState.ICON_TAG, notification.getSmallIcon());
 
         // We need to reset all views that are no longer transforming in case a view was previously
         // transformed, but now we decided to transform its container instead.
@@ -361,6 +363,12 @@
     }
 
     @Override
+    public void setIsChildInGroup(boolean isChildInGroup) {
+        super.setIsChildInGroup(isChildInGroup);
+        mTransformLowPriorityTitle = !isChildInGroup;
+    }
+
+    @Override
     public void setVisible(boolean visible) {
         super.setVisible(visible);
         mTransformationHelper.setVisible(visible);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java
new file mode 100644
index 0000000..66703ee
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java
@@ -0,0 +1,278 @@
+/*
+ * 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.notification;
+
+import android.app.Notification;
+import android.content.Context;
+import android.service.notification.StatusBarNotification;
+import android.util.Log;
+import android.view.View;
+import android.widget.RemoteViews;
+
+import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.NotificationContentView;
+import com.android.systemui.statusbar.NotificationData;
+import com.android.systemui.statusbar.phone.StatusBar;
+
+import java.util.Objects;
+
+/**
+ * A utility that inflates the right kind of contentView based on the state
+ */
+public class NotificationInflater {
+
+    private static final int FLAG_REINFLATE_ALL = ~0;
+    private static final int FLAG_REINFLATE_CONTENT_VIEW = 1<<0;
+    private static final int FLAG_REINFLATE_EXPANDED_VIEW = 1<<1;
+    private static final int FLAG_REINFLATE_HEADS_UP_VIEW = 1<<2;
+    private static final int FLAG_REINFLATE_PUBLIC_VIEW = 1<<3;
+    private static final int FLAG_REINFLATE_AMBIENT_VIEW = 1<<4;
+
+    private final ExpandableNotificationRow mRow;
+    private boolean mIsLowPriority;
+    private boolean mUsesIncreasedHeight;
+    private boolean mUsesIncreasedHeadsUpHeight;
+    private RemoteViews.OnClickHandler mRemoteViewClickHandler;
+    private boolean mIsChildInGroup;
+    private InflationExceptionHandler mInflateExceptionHandler;
+
+    public NotificationInflater(ExpandableNotificationRow row) {
+        mRow = row;
+    }
+
+    public void setIsLowPriority(boolean isLowPriority) {
+        mIsLowPriority = isLowPriority;
+    }
+
+    /**
+     * Set whether the notification is a child in a group
+     *
+     * @return whether the view was re-inflated
+     */
+    public boolean setIsChildInGroup(boolean childInGroup) {
+        if (childInGroup != mIsChildInGroup) {
+            mIsChildInGroup = childInGroup;
+            if (mIsLowPriority) {
+                try {
+                    int flags = FLAG_REINFLATE_CONTENT_VIEW | FLAG_REINFLATE_EXPANDED_VIEW;
+                    inflateNotificationViews(flags);
+                } catch (InflationException e) {
+                    mInflateExceptionHandler.handleInflationException(
+                            mRow.getStatusBarNotification(), e);
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    public void setUsesIncreasedHeight(boolean usesIncreasedHeight) {
+        mUsesIncreasedHeight = usesIncreasedHeight;
+    }
+
+    public void setUsesIncreasedHeadsUpHeight(boolean usesIncreasedHeight) {
+        mUsesIncreasedHeadsUpHeight = usesIncreasedHeight;
+    }
+
+    public void setRemoteViewClickHandler(RemoteViews.OnClickHandler remoteViewClickHandler) {
+        mRemoteViewClickHandler = remoteViewClickHandler;
+    }
+
+    public void inflateNotificationViews() throws InflationException {
+        inflateNotificationViews(FLAG_REINFLATE_ALL);
+    }
+
+    /**
+     * reinflate all views for the specified flags
+     * @param reInflateFlags flags which views should be reinflated. Use {@link #FLAG_REINFLATE_ALL}
+     *                       to reinflate all of views.
+     * @throws InflationException
+     */
+    private void inflateNotificationViews(int reInflateFlags)
+            throws InflationException {
+        NotificationData.Entry entry = mRow.getEntry();
+        StatusBarNotification sbn = entry.notification;
+        Context context = mRow.getContext();
+        NotificationContentView privateLayout = mRow.getPrivateLayout();
+        try {
+            final Notification.Builder recoveredBuilder
+                    = Notification.Builder.recoverBuilder(context, sbn.getNotification());
+            boolean isLowPriority = mIsLowPriority && !mIsChildInGroup;
+            if ((reInflateFlags & FLAG_REINFLATE_CONTENT_VIEW) != 0) {
+                final RemoteViews newContentView = createContentView(recoveredBuilder,
+                        isLowPriority, mUsesIncreasedHeadsUpHeight);
+                if (!compareRemoteViews(newContentView,
+                        entry.cachedContentView)) {
+                    View contentViewLocal = newContentView.apply(
+                            sbn.getPackageContext(context),
+                            privateLayout,
+                            mRemoteViewClickHandler);
+                    contentViewLocal.setIsRootNamespace(true);
+                    privateLayout.setContractedChild(contentViewLocal);
+                } else {
+                    newContentView.reapply(sbn.getPackageContext(context),
+                            privateLayout.getContractedChild(),
+                            mRemoteViewClickHandler);
+                }
+                entry.cachedContentView = newContentView;
+            }
+
+            if ((reInflateFlags & FLAG_REINFLATE_EXPANDED_VIEW) != 0) {
+                final RemoteViews newBigContentView = createBigContentView(
+                        recoveredBuilder, isLowPriority);
+                if (newBigContentView != null) {
+                    if (!compareRemoteViews(newBigContentView, entry.cachedBigContentView)) {
+                        View bigContentViewLocal = newBigContentView.apply(
+                                sbn.getPackageContext(context),
+                                privateLayout,
+                                mRemoteViewClickHandler);
+                        bigContentViewLocal.setIsRootNamespace(true);
+                        privateLayout.setExpandedChild(bigContentViewLocal);
+                    } else {
+                        newBigContentView.reapply(sbn.getPackageContext(context),
+                                privateLayout.getExpandedChild(),
+                                mRemoteViewClickHandler);
+                    }
+                } else if (entry.cachedBigContentView != null) {
+                    privateLayout.setExpandedChild(null);
+                }
+                entry.cachedBigContentView = newBigContentView;
+                mRow.setExpandable(newBigContentView != null);
+            }
+
+            if ((reInflateFlags & FLAG_REINFLATE_HEADS_UP_VIEW) != 0) {
+                final RemoteViews newHeadsUpContentView =
+                        recoveredBuilder.createHeadsUpContentView(mUsesIncreasedHeight);
+                if (newHeadsUpContentView != null) {
+                    if (!compareRemoteViews(newHeadsUpContentView,
+                            entry.cachedHeadsUpContentView)) {
+                        View headsUpContentViewLocal = newHeadsUpContentView.apply(
+                                sbn.getPackageContext(context),
+                                privateLayout,
+                                mRemoteViewClickHandler);
+                        headsUpContentViewLocal.setIsRootNamespace(true);
+                        privateLayout.setHeadsUpChild(headsUpContentViewLocal);
+                    } else {
+                        newHeadsUpContentView.reapply(sbn.getPackageContext(context),
+                                privateLayout.getHeadsUpChild(),
+                                mRemoteViewClickHandler);
+                    }
+                } else if (entry.cachedHeadsUpContentView != null) {
+                    privateLayout.setHeadsUpChild(null);
+                }
+                entry.cachedHeadsUpContentView = newHeadsUpContentView;
+            }
+
+            if ((reInflateFlags & FLAG_REINFLATE_PUBLIC_VIEW) != 0) {
+                NotificationContentView publicLayout = mRow.getPublicLayout();
+                final RemoteViews newPublicNotification
+                        = recoveredBuilder.makePublicContentView();
+                if (!compareRemoteViews(newPublicNotification, entry.cachedPublicContentView)) {
+                    View publicContentView = newPublicNotification.apply(
+                            sbn.getPackageContext(context),
+                            publicLayout,
+                            mRemoteViewClickHandler);
+                    publicContentView.setIsRootNamespace(true);
+                    publicLayout.setContractedChild(publicContentView);
+                } else {
+                    newPublicNotification.reapply(sbn.getPackageContext(context),
+                            publicLayout.getContractedChild(),
+                            mRemoteViewClickHandler);
+                }
+                entry.cachedPublicContentView = newPublicNotification;
+            }
+
+            if ((reInflateFlags & FLAG_REINFLATE_AMBIENT_VIEW) != 0) {
+                final RemoteViews newAmbientNotification
+                        = recoveredBuilder.makeAmbientNotification();
+                if (!compareRemoteViews(newAmbientNotification, entry.cachedAmbientContentView)) {
+                    View ambientContentView = newAmbientNotification.apply(
+                            sbn.getPackageContext(context),
+                            privateLayout,
+                            mRemoteViewClickHandler);
+                    ambientContentView.setIsRootNamespace(true);
+                    privateLayout.setAmbientChild(ambientContentView);
+                } else {
+                    newAmbientNotification.reapply(sbn.getPackageContext(context),
+                            privateLayout.getAmbientChild(),
+                            mRemoteViewClickHandler);
+                }
+                entry.cachedAmbientContentView = newAmbientNotification;
+            }
+
+        } catch (RuntimeException e) {
+            final String ident = sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId());
+            Log.e(StatusBar.TAG, "couldn't inflate view for notification " + ident, e);
+            throw new InflationException("Couldn't inflate contentViews");
+        }
+    }
+
+    private RemoteViews createBigContentView(Notification.Builder builder,
+            boolean isLowPriority) {
+        RemoteViews bigContentView = builder.createBigContentView();
+        if (bigContentView != null) {
+            return bigContentView;
+        }
+        if (isLowPriority) {
+            RemoteViews contentView = builder.createContentView();
+            Notification.Builder.makeHeaderExpanded(contentView);
+            return contentView;
+        }
+        return null;
+    }
+
+    private RemoteViews createContentView(Notification.Builder builder,
+            boolean isLowPriority, boolean useLarge) {
+        if (isLowPriority) {
+            return builder.makeLowPriorityContentView(false /* useRegularSubtext */);
+        }
+        return builder.createContentView(useLarge);
+    }
+
+    // Returns true if the RemoteViews are the same.
+    private boolean compareRemoteViews(final RemoteViews a, final RemoteViews b) {
+        return (a == null && b == null) ||
+                (a != null && b != null
+                        && b.getPackage() != null
+                        && a.getPackage() != null
+                        && a.getPackage().equals(b.getPackage())
+                        && a.getLayoutId() == b.getLayoutId());
+    }
+
+    public void setInflateExceptionHandler(InflationExceptionHandler inflateExceptionHandler) {
+        mInflateExceptionHandler = inflateExceptionHandler;
+    }
+
+    public interface InflationExceptionHandler {
+        void handleInflationException(StatusBarNotification notification, InflationException e);
+    }
+    public void onDensityOrFontScaleChanged() {
+        NotificationData.Entry entry = mRow.getEntry();
+        entry.cachedAmbientContentView = null;
+        entry.cachedBigContentView = null;
+        entry.cachedContentView = null;
+        entry.cachedHeadsUpContentView = null;
+        entry.cachedPublicContentView = null;
+        try {
+            inflateNotificationViews();
+        } catch (InflationException e) {
+            mInflateExceptionHandler.handleInflationException(
+                    mRow.getStatusBarNotification(), e);
+        }
+    }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java
index 04ee6aa..ef5a25c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java
@@ -35,16 +35,16 @@
 
     View mActions;
 
-    private void resolveViews(StatusBarNotification notification) {
+    private void resolveViews() {
         mActions = mView.findViewById(com.android.internal.R.id.media_actions);
     }
 
     @Override
-    public void notifyContentUpdated(StatusBarNotification notification, boolean isLowPriority) {
+    public void notifyContentUpdated(ExpandableNotificationRow row) {
         // Reinspect the notification. Before the super call, because the super call also updates
         // the transformation types and we need to have our values set by then.
-        resolveViews(notification);
-        super.notifyContentUpdated(notification, isLowPriority);
+        resolveViews();
+        super.notifyContentUpdated(row);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMessagingTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMessagingTemplateViewWrapper.java
index defeab2..9631556 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMessagingTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMessagingTemplateViewWrapper.java
@@ -21,7 +21,6 @@
 import com.android.systemui.statusbar.TransformableView;
 
 import android.content.Context;
-import android.service.notification.StatusBarNotification;
 import android.text.TextUtils;
 import android.view.View;
 import android.widget.TextView;
@@ -71,11 +70,11 @@
     }
 
     @Override
-    public void notifyContentUpdated(StatusBarNotification notification, boolean isLowPriority) {
+    public void notifyContentUpdated(ExpandableNotificationRow row) {
         // Reinspect the notification. Before the super call, because the super call also updates
         // the transformation types and we need to have our values set by then.
         resolveViews();
-        super.notifyContentUpdated(notification, isLowPriority);
+        super.notifyContentUpdated(row);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
index e9956ff..846d03a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
@@ -133,11 +133,11 @@
     }
 
     @Override
-    public void notifyContentUpdated(StatusBarNotification notification, boolean isLowPriority) {
+    public void notifyContentUpdated(ExpandableNotificationRow row) {
         // Reinspect the notification. Before the super call, because the super call also updates
         // the transformation types and we need to have our values set by then.
-        resolveTemplateViews(notification);
-        super.notifyContentUpdated(notification, isLowPriority);
+        resolveTemplateViews(row.getStatusBarNotification());
+        super.notifyContentUpdated(row);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
index 5f5e1e4..c85e8d8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
@@ -48,6 +48,7 @@
     private int mBackgroundColor = 0;
     protected boolean mShouldInvertDark;
     protected boolean mDarkInitialized = false;
+    private boolean mForcedInvisible;
 
     public static NotificationViewWrapper wrap(Context ctx, View v, ExpandableNotificationRow row) {
         if (v.getId() == com.android.internal.R.id.status_bar_latest_event_content) {
@@ -87,10 +88,9 @@
 
     /**
      * Notifies this wrapper that the content of the view might have changed.
-     * @param notification the notification this is wrapped around
-     * @param isLowPriority is this notification low priority
+     * @param row the row this wrapper is attached to
      */
-    public void notifyContentUpdated(StatusBarNotification notification, boolean isLowPriority) {
+    public void notifyContentUpdated(ExpandableNotificationRow row) {
         mDarkInitialized = false;
         Drawable background = mView.getBackground();
         if (shouldClearBackgroundOnReapply()) {
@@ -185,7 +185,7 @@
         return mRow.isSummaryWithChildren() ? 0 : mBackgroundColor;
     }
 
-    public void setShowingLegacyBackground(boolean showing) {
+    public void setLegacy(boolean legacy) {
     }
 
     public void setContentHeight(int contentHeight, int minHeightHint) {
@@ -193,4 +193,7 @@
 
     public void setRemoteInputVisible(boolean visible) {
     }
+
+    public void setIsChildInGroup(boolean isChildInGroup) {
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
index 31cfa66..7512efa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
@@ -19,9 +19,12 @@
 import android.os.Looper;
 import android.provider.Settings.Secure;
 
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.app.NightDisplayController;
 import com.android.systemui.Dependency;
 import com.android.systemui.Prefs;
 import com.android.systemui.Prefs.Key;
+import com.android.systemui.qs.QSTileHost;
 import com.android.systemui.qs.SecureSetting;
 import com.android.systemui.statusbar.policy.DataSaverController;
 import com.android.systemui.statusbar.policy.DataSaverController.Listener;
@@ -64,6 +67,11 @@
         if (!Prefs.getBoolean(context, Key.QS_WORK_ADDED, false)) {
             Dependency.get(ManagedProfileController.class).addCallback(mProfileCallback);
         }
+
+        if (!Prefs.getBoolean(context, Key.QS_NIGHTDISPLAY_ADDED, false)
+                && NightDisplayController.isAvailable(mContext)) {
+            Dependency.get(NightDisplayController.class).setListener(mNightDisplayCallback);
+        }
     }
 
     public void destroy() {
@@ -71,6 +79,7 @@
         Dependency.get(HotspotController.class).removeCallback(mHotspotCallback);
         Dependency.get(DataSaverController.class).removeCallback(mDataSaverListener);
         Dependency.get(ManagedProfileController.class).removeCallback(mProfileCallback);
+        Dependency.get(NightDisplayController.class).setListener(null);
     }
 
     private final ManagedProfileController.Callback mProfileCallback =
@@ -115,4 +124,30 @@
             }
         }
     };
+
+    @VisibleForTesting
+    final NightDisplayController.Callback mNightDisplayCallback =
+            new NightDisplayController.Callback() {
+        @Override
+        public void onActivated(boolean activated) {
+            if (activated) {
+                addNightTile();
+            }
+        }
+
+        @Override
+        public void onAutoModeChanged(int autoMode) {
+            if (autoMode == NightDisplayController.AUTO_MODE_CUSTOM
+                    || autoMode == NightDisplayController.AUTO_MODE_TWILIGHT) {
+                addNightTile();
+            }
+        }
+
+        private void addNightTile() {
+            mHost.addTile("night");
+            Prefs.putBoolean(mContext, Key.QS_NIGHTDISPLAY_ADDED, true);
+            mHandler.post(() -> Dependency.get(NightDisplayController.class)
+                    .setListener(null));
+        }
+    };
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
index ed71e57..f3c2bc5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
@@ -33,6 +33,7 @@
 import android.util.Log;
 import android.view.View;
 
+import com.android.settingslib.Utils;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 
@@ -167,7 +168,7 @@
                 mSemiTransparent = context.getColor(
                         com.android.internal.R.color.system_bar_background_semi_transparent);
                 mTransparent = context.getColor(R.color.system_bar_background_transparent);
-                mWarning = context.getColor(com.android.internal.R.color.battery_saver_mode_color);
+                mWarning = Utils.getColorAttr(context, android.R.attr.colorError);
             }
             mGradient = context.getDrawable(gradientResourceId);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
index 1f56c56..6cd3eae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
@@ -153,7 +153,7 @@
     }
 
     private boolean shouldHideNotificationIcons() {
-        return !mStatusBar.isClosed() && mStatusBarComponent.shouldHideNotificationIcons();
+        return !mStatusBar.isClosed() && mStatusBarComponent.hideStatusBarIconsWhenExpanded();
     }
 
     public void hideSystemIconArea(boolean animate) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DoubleTapHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DoubleTapHelper.java
new file mode 100644
index 0000000..dcb6a38
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DoubleTapHelper.java
@@ -0,0 +1,174 @@
+/*
+ * 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 android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+
+import com.android.systemui.R;
+
+/**
+ * Detects a double tap.
+ */
+public class DoubleTapHelper {
+
+    private static final long DOUBLETAP_TIMEOUT_MS = 1200;
+
+    private final View mView;
+    private final ActivationListener mActivationListener;
+    private final DoubleTapListener mDoubleTapListener;
+    private final SlideBackListener mSlideBackListener;
+    private final DoubleTapLogListener mDoubleTapLogListener;
+
+    private float mTouchSlop;
+    private float mDoubleTapSlop;
+
+    private boolean mActivated;
+
+    private float mDownX;
+    private float mDownY;
+    private boolean mTrackTouch;
+
+    private float mActivationX;
+    private float mActivationY;
+    private Runnable mTapTimeoutRunnable = this::makeInactive;
+
+    public DoubleTapHelper(View view, ActivationListener activationListener,
+            DoubleTapListener doubleTapListener, SlideBackListener slideBackListener,
+            DoubleTapLogListener doubleTapLogListener) {
+        mTouchSlop = ViewConfiguration.get(view.getContext()).getScaledTouchSlop();
+        mDoubleTapSlop = view.getResources().getDimension(R.dimen.double_tap_slop);
+        mView = view;
+
+        mActivationListener = activationListener;
+        mDoubleTapListener = doubleTapListener;
+        mSlideBackListener = slideBackListener;
+        mDoubleTapLogListener = doubleTapLogListener;
+    }
+
+    public boolean onTouchEvent(MotionEvent event) {
+        return onTouchEvent(event, Integer.MAX_VALUE);
+    }
+
+    public boolean onTouchEvent(MotionEvent event, int maxTouchableHeight) {
+        int action = event.getActionMasked();
+        switch (action) {
+            case MotionEvent.ACTION_DOWN:
+                mDownX = event.getX();
+                mDownY = event.getY();
+                mTrackTouch = true;
+                if (mDownY > maxTouchableHeight) {
+                    mTrackTouch = false;
+                }
+                break;
+            case MotionEvent.ACTION_MOVE:
+                if (!isWithinTouchSlop(event)) {
+                    makeInactive();
+                    mTrackTouch = false;
+                }
+                break;
+            case MotionEvent.ACTION_UP:
+                if (isWithinTouchSlop(event)) {
+                    if (mSlideBackListener != null && mSlideBackListener.onSlideBack()) {
+                        return true;
+                    }
+                    if (!mActivated) {
+                        makeActive();
+                        mView.postDelayed(mTapTimeoutRunnable, DOUBLETAP_TIMEOUT_MS);
+                        mActivationX = event.getX();
+                        mActivationY = event.getY();
+                    } else {
+                        boolean withinDoubleTapSlop = isWithinDoubleTapSlop(event);
+                        if (mDoubleTapLogListener != null) {
+                            mDoubleTapLogListener.onDoubleTapLog(withinDoubleTapSlop,
+                                    event.getX() - mActivationX,
+                                    event.getY() - mActivationY);
+                        }
+                        if (withinDoubleTapSlop) {
+                            if (!mDoubleTapListener.onDoubleTap()) {
+                                return false;
+                            }
+                        } else {
+                            makeInactive();
+                            mTrackTouch = false;
+                        }
+                    }
+                } else {
+                    makeInactive();
+                    mTrackTouch = false;
+                }
+                break;
+            case MotionEvent.ACTION_CANCEL:
+                makeInactive();
+                mTrackTouch = false;
+                break;
+            default:
+                break;
+        }
+        return mTrackTouch;
+    }
+
+    private void makeActive() {
+        if (!mActivated) {
+            mActivated = true;
+            mActivationListener.onActiveChanged(true);
+        }
+    }
+
+    private void makeInactive() {
+        if (mActivated) {
+            mActivated = false;
+            mActivationListener.onActiveChanged(false);
+        }
+    }
+
+    private boolean isWithinTouchSlop(MotionEvent event) {
+        return Math.abs(event.getX() - mDownX) < mTouchSlop
+                && Math.abs(event.getY() - mDownY) < mTouchSlop;
+    }
+
+    private boolean isWithinDoubleTapSlop(MotionEvent event) {
+        if (!mActivated) {
+            // If we're not activated there's no double tap slop to satisfy.
+            return true;
+        }
+
+        return Math.abs(event.getX() - mActivationX) < mDoubleTapSlop
+                && Math.abs(event.getY() - mActivationY) < mDoubleTapSlop;
+    }
+
+    @FunctionalInterface
+    public interface ActivationListener {
+        void onActiveChanged(boolean active);
+    }
+
+    @FunctionalInterface
+    public interface DoubleTapListener {
+        boolean onDoubleTap();
+    }
+
+    @FunctionalInterface
+    public interface SlideBackListener {
+        boolean onSlideBack();
+    }
+
+    @FunctionalInterface
+    public interface DoubleTapLogListener {
+        void onDoubleTapLog(boolean accepted, float dx, float dy);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index 883a66b..4a2ec88 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -32,6 +32,7 @@
 public class DozeParameters {
     private static final int MAX_DURATION = 60 * 1000;
     public static final String DOZE_SENSORS_WAKE_UP_FULLY = "doze_sensors_wake_up_fully";
+    public static final boolean ALWAYS_ON_AVAILABLE = Build.IS_DEBUGGABLE;
 
     private final Context mContext;
 
@@ -57,7 +58,7 @@
         pw.print("    getPickupVibrationThreshold(): "); pw.println(getPickupVibrationThreshold());
         pw.print("    getPickupSubtypePerformsProxCheck(): ");pw.println(
                 dumpPickupSubtypePerformsProxCheck());
-        if (Build.IS_DEBUGGABLE) {
+        if (ALWAYS_ON_AVAILABLE) {
             pw.print("    getAlwaysOn(): "); pw.println(getAlwaysOn());
             pw.print("    getSensorsWakeUpFully(): "); pw.println(getSensorsWakeUpFully());
         }
@@ -118,15 +119,15 @@
     }
 
     public boolean getAlwaysOn() {
-        return Build.IS_DEBUGGABLE
+        return ALWAYS_ON_AVAILABLE
                 && Settings.Secure.getIntForUser(mContext.getContentResolver(),
                 Settings.Secure.DOZE_ALWAYS_ON, 0, UserHandle.USER_CURRENT) != 0;
     }
 
     public boolean getSensorsWakeUpFully() {
-        return Build.IS_DEBUGGABLE
+        return ALWAYS_ON_AVAILABLE
                 && Settings.Secure.getIntForUser(mContext.getContentResolver(),
-                DOZE_SENSORS_WAKE_UP_FULLY, 0, UserHandle.USER_CURRENT) != 0;
+                DOZE_SENSORS_WAKE_UP_FULLY, 1, UserHandle.USER_CURRENT) != 0;
     }
 
     private boolean getBoolean(String propName, int resId) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 8f63d45..9a49d67 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -19,9 +19,10 @@
 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
 import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
 
+import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_BUTTON;
 import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_UNLOCK;
+import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_RIGHT_BUTTON;
 import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_RIGHT_UNLOCK;
-import static com.android.systemui.tuner.LockscreenFragment.getIntentButton;
 
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
@@ -35,7 +36,6 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.content.res.AssetFileDescriptor.AutoCloseOutputStream;
 import android.content.res.Configuration;
 import android.graphics.drawable.Drawable;
 import android.os.AsyncTask;
@@ -63,7 +63,6 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
-import com.android.systemui.EventLogConstants;
 import com.android.systemui.EventLogTags;
 import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
@@ -74,14 +73,17 @@
 import com.android.systemui.plugins.IntentButtonProvider.IntentButton.IconState;
 import com.android.systemui.plugins.PluginListener;
 import com.android.systemui.plugins.PluginManager;
-import com.android.systemui.ActivityStarter;
+import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.KeyguardAffordanceView;
 import com.android.systemui.statusbar.KeyguardIndicationController;
 import com.android.systemui.statusbar.policy.AccessibilityController;
+import com.android.systemui.statusbar.policy.ExtensionController;
+import com.android.systemui.statusbar.policy.ExtensionController.Extension;
 import com.android.systemui.statusbar.policy.FlashlightController;
 import com.android.systemui.statusbar.policy.PreviewInflater;
 import com.android.systemui.tuner.LockscreenFragment;
+import com.android.systemui.tuner.LockscreenFragment.LockButtonFactory;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.tuner.TunerService.Tunable;
 
@@ -91,8 +93,7 @@
  */
 public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickListener,
         UnlockMethodCache.OnUnlockMethodChangedListener,
-        AccessibilityController.AccessibilityStateChangedCallback, View.OnLongClickListener,
-        Tunable {
+        AccessibilityController.AccessibilityStateChangedCallback, View.OnLongClickListener {
 
     final static String TAG = "StatusBar/KeyguardBottomAreaView";
 
@@ -159,12 +160,10 @@
     private Drawable mLeftAssistIcon;
 
     private IntentButton mRightButton = new DefaultRightButton();
-    private IntentButton mRightDefault = mRightButton;
-    private IntentButton mRightPlugin;
+    private Extension<IntentButton> mRightExtension;
     private String mRightButtonStr;
     private IntentButton mLeftButton = new DefaultLeftButton();
-    private IntentButton mLeftDefault = mLeftButton;
-    private IntentButton mLeftPlugin;
+    private Extension<IntentButton> mLeftExtension;
     private String mLeftButtonStr;
     private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
     private boolean mDozing;
@@ -261,21 +260,28 @@
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
         mAccessibilityController.addStateChangedCallback(this);
-        Dependency.get(PluginManager.class).addPluginListener(RIGHT_BUTTON_PLUGIN,
-                mRightListener, IntentButtonProvider.class, false /* Only allow one */);
-        Dependency.get(PluginManager.class).addPluginListener(LEFT_BUTTON_PLUGIN,
-                mLeftListener, IntentButtonProvider.class, false /* Only allow one */);
-        Dependency.get(TunerService.class).addTunable(this, LockscreenFragment.LOCKSCREEN_LEFT_BUTTON,
-                LockscreenFragment.LOCKSCREEN_RIGHT_BUTTON);
+        mRightExtension = Dependency.get(ExtensionController.class).newExtension(IntentButton.class)
+                .withPlugin(IntentButtonProvider.class, RIGHT_BUTTON_PLUGIN,
+                        p -> p.getIntentButton())
+                .withTunerFactory(new LockButtonFactory(mContext, LOCKSCREEN_RIGHT_BUTTON))
+                .withDefault(() -> new DefaultRightButton())
+                .withCallback(button -> setRightButton(button))
+                .build();
+        mLeftExtension = Dependency.get(ExtensionController.class).newExtension(IntentButton.class)
+                .withPlugin(IntentButtonProvider.class, LEFT_BUTTON_PLUGIN,
+                        p -> p.getIntentButton())
+                .withTunerFactory(new LockButtonFactory(mContext, LOCKSCREEN_LEFT_BUTTON))
+                .withDefault(() -> new DefaultLeftButton())
+                .withCallback(button -> setLeftButton(button))
+                .build();
     }
 
     @Override
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
         mAccessibilityController.removeStateChangedCallback(this);
-        Dependency.get(PluginManager.class).removePluginListener(mRightListener);
-        Dependency.get(PluginManager.class).removePluginListener(mLeftListener);
-        Dependency.get(TunerService.class).removeTunable(this);
+        mRightExtension.destroy();
+        mLeftExtension.destroy();
     }
 
     private void initAccessibility() {
@@ -790,63 +796,21 @@
         inflateCameraPreview();
     }
 
-    @Override
-    public void onTuningChanged(String key, String newValue) {
-        if (LockscreenFragment.LOCKSCREEN_LEFT_BUTTON.equals(key)) {
-            mLeftButtonStr = newValue;
-            mLeftIsVoiceAssist = TextUtils.isEmpty(mLeftButtonStr) && mLeftPlugin == null;
-            mLeftButton = getIntentButton(mContext, mLeftButtonStr, mLeftPlugin, mLeftDefault);
-            updateLeftAffordance();
-        } else {
-            mRightButtonStr = newValue;
-            mRightButton = getIntentButton(mContext, mRightButtonStr, mRightPlugin, mRightDefault);
-            updateRightAffordanceIcon();
-            updateCameraVisibility();
-            inflateCameraPreview();
-        }
-    }
-
     private void setRightButton(IntentButton button) {
-        mRightPlugin = button;
-        mRightButton = getIntentButton(mContext, mRightButtonStr, mRightPlugin, mRightDefault);
+        mRightButton = button;
         updateRightAffordanceIcon();
         updateCameraVisibility();
         inflateCameraPreview();
     }
 
     private void setLeftButton(IntentButton button) {
-        mLeftPlugin = button;
-        mLeftButton = getIntentButton(mContext, mLeftButtonStr, mLeftPlugin, mLeftDefault);
-        mLeftIsVoiceAssist = false;
+        mLeftButton = button;
+        if (!(mLeftButton instanceof DefaultLeftButton)) {
+            mLeftIsVoiceAssist = false;
+        }
         updateLeftAffordance();
     }
 
-    private final PluginListener<IntentButtonProvider> mRightListener =
-            new PluginListener<IntentButtonProvider>() {
-        @Override
-        public void onPluginConnected(IntentButtonProvider plugin, Context pluginContext) {
-            setRightButton(plugin.getIntentButton());
-        }
-
-        @Override
-        public void onPluginDisconnected(IntentButtonProvider plugin) {
-            setRightButton(null);
-        }
-    };
-
-    private final PluginListener<IntentButtonProvider> mLeftListener =
-            new PluginListener<IntentButtonProvider>() {
-        @Override
-        public void onPluginConnected(IntentButtonProvider plugin, Context pluginContext) {
-            setLeftButton(plugin.getIntentButton());
-        }
-
-        @Override
-        public void onPluginDisconnected(IntentButtonProvider plugin) {
-            setLeftButton(null);
-        }
-    };
-
     public void setDozing(boolean dozing, boolean animate) {
         mDozing = dozing;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index ff58e54..42b09df 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -28,6 +28,7 @@
 import android.widget.RelativeLayout;
 import android.widget.TextView;
 
+import com.android.systemui.BatteryMeterView;
 import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
@@ -39,8 +40,6 @@
 import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
 
-import java.text.NumberFormat;
-
 /**
  * The header group on Keyguard.
  */
@@ -55,7 +54,7 @@
     private View mSystemIconsSuperContainer;
     private MultiUserSwitch mMultiUserSwitch;
     private ImageView mMultiUserAvatar;
-    private TextView mBatteryLevel;
+    private BatteryMeterView mBatteryView;
 
     private BatteryController mBatteryController;
     private KeyguardUserSwitcher mKeyguardUserSwitcher;
@@ -76,8 +75,9 @@
         mSystemIconsContainer = findViewById(R.id.system_icons_container);
         mMultiUserSwitch = (MultiUserSwitch) findViewById(R.id.multi_user_switch);
         mMultiUserAvatar = (ImageView) findViewById(R.id.multi_user_avatar);
-        mBatteryLevel = (TextView) findViewById(R.id.battery_level);
         mCarrierLabel = (TextView) findViewById(R.id.keyguard_carrier_text);
+        mBatteryView = (BatteryMeterView) mSystemIconsContainer.findViewById(R.id.battery);
+
         loadDimens();
         updateUserSwitcher();
         mBatteryController = Dependency.get(BatteryController.class);
@@ -115,17 +115,6 @@
                 R.dimen.status_bar_height);
         mSystemIconsContainer.setLayoutParams(lp);
 
-        lp = (MarginLayoutParams) mBatteryLevel.getLayoutParams();
-        lp.setMarginStart(
-                getResources().getDimensionPixelSize(R.dimen.header_battery_margin_keyguard));
-        mBatteryLevel.setLayoutParams(lp);
-        mBatteryLevel.setPaddingRelative(mBatteryLevel.getPaddingStart(),
-                mBatteryLevel.getPaddingTop(),
-                getResources().getDimensionPixelSize(R.dimen.battery_level_padding_end),
-                mBatteryLevel.getPaddingBottom());
-        mBatteryLevel.setTextSize(TypedValue.COMPLEX_UNIT_PX,
-                getResources().getDimensionPixelSize(R.dimen.battery_level_text_size));
-
         // Respect font size setting.
         mCarrierLabel.setTextSize(TypedValue.COMPLEX_UNIT_PX,
                 getResources().getDimensionPixelSize(
@@ -168,7 +157,7 @@
                 mMultiUserSwitch.setVisibility(View.GONE);
             }
         }
-        mBatteryLevel.setVisibility(mBatteryCharging ? View.VISIBLE : View.GONE);
+        mBatteryView.setForceShowPercent(mBatteryCharging);
     }
 
     private void updateSystemIconsLayoutParams() {
@@ -233,11 +222,8 @@
 
     @Override
     public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
-        String percentage = NumberFormat.getPercentInstance().format((double) level / 100.0);
-        mBatteryLevel.setText(percentage);
-        boolean changed = mBatteryCharging != charging;
-        mBatteryCharging = charging;
-        if (changed) {
+        if (mBatteryCharging != charging) {
+            mBatteryCharging = charging;
             updateVisibilities();
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
index 3cbac17..820638c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
@@ -31,8 +31,8 @@
 
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.ActivityStarter;
-import com.android.systemui.plugins.qs.QS.DetailAdapter;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.qs.DetailAdapter;
 import com.android.systemui.qs.QSPanel;
 import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
@@ -74,7 +74,7 @@
         if (mUserListener == null) {
             return false;
         }
-        return mUserListener.getCount() != 0;
+        return mUserListener.getUserCount() > 1;
     }
 
     public void setUserSwitcherController(UserSwitcherController userSwitcherController) {
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 ad875f1..3f7e340 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -21,8 +21,8 @@
 import android.animation.ObjectAnimator;
 import android.animation.TimeInterpolator;
 import android.animation.ValueAnimator;
-import android.app.ActivityManager;
 import android.annotation.DrawableRes;
+import android.app.ActivityManager;
 import android.app.StatusBarManager;
 import android.content.Context;
 import android.content.res.Configuration;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index 707997d..4581204 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -79,7 +79,9 @@
         for (int i = 0; i < mNotificationIcons.getChildCount(); i++) {
             View child = mNotificationIcons.getChildAt(i);
             child.setLayoutParams(params);
-            child = mShelfIcons.getChildAt(i);
+        }
+        for (int i = 0; i < mShelfIcons.getChildCount(); i++) {
+            View child = mShelfIcons.getChildAt(i);
             child.setLayoutParams(params);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index dc5f98c..3706dc8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -227,6 +227,7 @@
             ViewState iconState = mIconStates.get(view);
             iconState.initFrom(view);
             iconState.alpha = 1.0f;
+            iconState.hidden = false;
         }
     }
 
@@ -524,11 +525,5 @@
                 iconColor = ((StatusBarIconView) view).getStaticDrawableColor();
             }
         }
-
-        protected void onYTranslationAnimationFinished(View view) {
-            if (hidden) {
-                view.setVisibility(INVISIBLE);
-            }
-        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 6da9e90..c24a2a0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -26,7 +26,6 @@
 import android.content.Context;
 import android.content.pm.ResolveInfo;
 import android.content.res.Configuration;
-import android.content.res.Resources;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
@@ -47,7 +46,6 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.keyguard.KeyguardStatusView;
 import com.android.systemui.DejankUtils;
-import com.android.systemui.EventLogConstants;
 import com.android.systemui.EventLogTags;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
@@ -179,7 +177,7 @@
     private boolean mKeyguardStatusViewAnimating;
     private ValueAnimator mQsSizeChangeAnimator;
 
-    private boolean mShadeEmpty;
+    private boolean mShowEmptyShadeView;
 
     private boolean mQsScrimEnabled = true;
     private boolean mLastAnnouncementWasQuickSettings;
@@ -211,11 +209,12 @@
         }
     };
     private NotificationGroupManager mGroupManager;
-    private boolean mOpening;
+    private boolean mShowIconsWhenExpanded;
     private int mIndicationBottomPadding;
     private boolean mIsFullWidth;
     private boolean mDark;
     private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
+    private boolean mNoVisibleNotifications = true;
 
     public NotificationPanelView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -292,15 +291,14 @@
         int panelGravity = getResources().getInteger(R.integer.notification_panel_layout_gravity);
         FrameLayout.LayoutParams lp =
                 (FrameLayout.LayoutParams) mQsFrame.getLayoutParams();
-        if (lp.width != panelWidth) {
+        if (lp.width != panelWidth || lp.gravity != panelGravity) {
             lp.width = panelWidth;
             lp.gravity = panelGravity;
             mQsFrame.setLayoutParams(lp);
-            post(mUpdateHeader);
         }
 
         lp = (FrameLayout.LayoutParams) mNotificationStackScroller.getLayoutParams();
-        if (lp.width != panelWidth) {
+        if (lp.width != panelWidth || lp.gravity != panelGravity) {
             lp.width = panelWidth;
             lp.gravity = panelGravity;
             mNotificationStackScroller.setLayoutParams(lp);
@@ -766,16 +764,17 @@
             mIsExpansionFromHeadsUp = true;
             MetricsLogger.count(mContext, COUNTER_PANEL_OPEN_PEEK, 1);
         }
+        boolean handled = false;
         if ((!mIsExpanding || mHintAnimationRunning)
                 && !mQsExpanded
                 && mStatusBar.getBarState() != StatusBarState.SHADE
                 && !mDozing) {
-            mAffordanceHelper.onTouchEvent(event);
+            handled |= mAffordanceHelper.onTouchEvent(event);
         }
         if (mOnlyAffordanceInThisMotion) {
             return true;
         }
-        mHeadsUpTouchHelper.onTouchEvent(event);
+        handled |= mHeadsUpTouchHelper.onTouchEvent(event);
 
         if (mQsOverscrollExpansionEnabled && !mHeadsUpTouchHelper.isTrackingHeadsUp()
                 && handleQsTouch(event)) {
@@ -784,9 +783,10 @@
         if (event.getActionMasked() == MotionEvent.ACTION_DOWN && isFullyCollapsed()) {
             MetricsLogger.count(mContext, COUNTER_PANEL_OPEN, 1);
             updateVerticalPanelPosition(event.getX());
+            handled = true;
         }
-        super.onTouchEvent(event);
-        return true;
+        handled |= super.onTouchEvent(event);
+        return mDozing ? handled : true;
     }
 
     private boolean handleQsTouch(MotionEvent event) {
@@ -1516,7 +1516,7 @@
         // it in expanded QS state as well so we don't run into troubles when fading the view in/out
         // and expanding/collapsing the whole panel from/to quick settings.
         if (mNotificationStackScroller.getNotGoneChildCount() == 0
-                && mShadeEmpty) {
+                && mShowEmptyShadeView) {
             notificationHeight = mNotificationStackScroller.getEmptyShadeViewHeight();
         }
         int maxQsHeight = mQsMaxExpansionHeight;
@@ -2116,15 +2116,15 @@
         return mDozing;
     }
 
-    public void setShadeEmpty(boolean shadeEmpty) {
-        mShadeEmpty = shadeEmpty;
+    public void showEmptyShadeView(boolean emptyShadeViewVisible) {
+        mShowEmptyShadeView = emptyShadeViewVisible;
         updateEmptyShadeView();
     }
 
     private void updateEmptyShadeView() {
 
         // Hide "No notifications" in QS.
-        mNotificationStackScroller.updateEmptyShadeView(mShadeEmpty && !mQsExpanded);
+        mNotificationStackScroller.updateEmptyShadeView(mShowEmptyShadeView && !mQsExpanded);
     }
 
     public void setQsScrimEnabled(boolean qsScrimEnabled) {
@@ -2139,13 +2139,6 @@
         mKeyguardUserSwitcher = keyguardUserSwitcher;
     }
 
-    private final Runnable mUpdateHeader = new Runnable() {
-        @Override
-        public void run() {
-            mQs.getHeader().updateEverything();
-        }
-    };
-
     public void onScreenTurningOn() {
         mKeyguardStatusView.refreshTime();
     }
@@ -2304,7 +2297,7 @@
         }
         mNotificationStackScroller.setExpandedHeight(expandedHeight);
         updateKeyguardBottomAreaAlpha();
-        setOpening(isFullWidth() && expandedHeight < getOpeningHeight());
+        updateStatusBarIcons();
     }
 
     /**
@@ -2315,13 +2308,21 @@
         return mIsFullWidth;
     }
 
-    private void setOpening(boolean opening) {
-        if (opening != mOpening) {
-            mOpening = opening;
+    private void updateStatusBarIcons() {
+        boolean showIconsWhenExpanded = isFullWidth() && getExpandedHeight() < getOpeningHeight();
+        if (showIconsWhenExpanded && mNoVisibleNotifications && isOnKeyguard()) {
+            showIconsWhenExpanded = false;
+        }
+        if (showIconsWhenExpanded != mShowIconsWhenExpanded) {
+            mShowIconsWhenExpanded = showIconsWhenExpanded;
             mStatusBar.recomputeDisableFlags(false);
         }
     }
 
+    private boolean isOnKeyguard() {
+        return mStatusBar.getBarState() == StatusBarState.KEYGUARD;
+    }
+
     public void setPanelScrimMinFraction(float minFraction) {
         mBar.panelScrimMinFractionChanged(minFraction);
     }
@@ -2424,12 +2425,8 @@
         mGroupManager = groupManager;
     }
 
-    public boolean shouldHideNotificationIcons() {
-        return !isFullWidth() || (!mOpening && !isFullyCollapsed());
-    }
-
-    public boolean shouldAnimateIconHiding() {
-        return !isFullWidth();
+    public boolean hideStatusBarIconsWhenExpanded() {
+        return !isFullWidth() || !mShowIconsWhenExpanded;
     }
 
     private final FragmentListener mFragmentListener = new FragmentListener() {
@@ -2437,7 +2434,7 @@
         public void onFragmentViewCreated(String tag, Fragment fragment) {
             mQs = (QS) fragment;
             mQs.setPanelView(NotificationPanelView.this);
-            mQs.getHeader().getExpandView().setOnClickListener(NotificationPanelView.this);
+            mQs.setExpandClickListener(NotificationPanelView.this);
             mQs.setHeaderClickable(mQsExpansionEnabled);
             mQs.setKeyguardShowing(mKeyguardShowing);
             mQs.setOverscrolling(mStackScrollerOverscrolling);
@@ -2471,4 +2468,8 @@
         mKeyguardStatusView.setDark(dark);
         positionClockAndNotifications();
     }
+
+    public void setNoVisibleNotifications(boolean noNotifications) {
+        mNoVisibleNotifications = noNotifications;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index aebc2c9..bb6c8f2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -17,7 +17,6 @@
 package com.android.systemui.statusbar.phone;
 
 import android.app.ActivityManager;
-import android.app.ActivityManager.RunningAppProcessInfo;
 import android.app.ActivityManager.StackId;
 import android.app.ActivityManager.StackInfo;
 import android.app.AlarmManager;
@@ -25,8 +24,6 @@
 import android.app.AppGlobals;
 import android.app.Notification;
 import android.app.Notification.Action;
-import android.app.Notification.BigTextStyle;
-import android.app.Notification.Style;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.app.SynchronousUserSwitchObserver;
@@ -37,7 +34,6 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.UserInfo;
 import android.graphics.drawable.Icon;
 import android.media.AudioManager;
@@ -51,7 +47,6 @@
 import android.provider.Settings.Global;
 import android.service.notification.StatusBarNotification;
 import android.telecom.TelecomManager;
-import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Log;
 import android.util.Pair;
@@ -61,11 +56,9 @@
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.R.string;
 import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.qs.tiles.DndTile;
 import com.android.systemui.qs.tiles.RotationLockTile;
-import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
 import com.android.systemui.statusbar.CommandQueue;
@@ -87,9 +80,6 @@
 import com.android.systemui.statusbar.policy.ZenModeController;
 import com.android.systemui.util.NotificationChannels;
 
-import java.util.ArrayList;
-import java.util.List;
-
 /**
  * This class contains all of the policy about which icons are installed in the status
  * bar at boot time.  It goes through the normal API for icons, even though it probably
@@ -137,8 +127,6 @@
     private boolean mVolumeVisible;
     private boolean mCurrentUserSetup;
 
-    private int mZen;
-
     private boolean mManagedProfileFocused = false;
     private boolean mManagedProfileIconVisible = false;
     private boolean mManagedProfileInQuietMode = false;
@@ -275,14 +263,14 @@
 
     @Override
     public void onZenChanged(int zen) {
-        mZen = zen;
         updateVolumeZen();
     }
 
     private void updateAlarm() {
         final AlarmClockInfo alarm = mAlarmManager.getNextAlarmClock(UserHandle.USER_CURRENT);
         final boolean hasAlarm = alarm != null && alarm.getTriggerTime() > 0;
-        final boolean zenNone = mZen == Global.ZEN_MODE_NO_INTERRUPTIONS;
+        int zen = mZenController.getZen();
+        final boolean zenNone = zen == Global.ZEN_MODE_NO_INTERRUPTIONS;
         mIconController.setIcon(mSlotAlarmClock, zenNone ? R.drawable.stat_sys_alarm_dim
                 : R.drawable.stat_sys_alarm, null);
         mIconController.setIconVisibility(mSlotAlarmClock, mCurrentUserSetup && hasAlarm);
@@ -323,17 +311,18 @@
         boolean volumeVisible = false;
         int volumeIconId = 0;
         String volumeDescription = null;
+        int zen = mZenController.getZen();
 
         if (DndTile.isVisible(mContext) || DndTile.isCombinedIcon(mContext)) {
-            zenVisible = mZen != Global.ZEN_MODE_OFF;
-            zenIconId = mZen == Global.ZEN_MODE_NO_INTERRUPTIONS
+            zenVisible = zen != Global.ZEN_MODE_OFF;
+            zenIconId = zen == Global.ZEN_MODE_NO_INTERRUPTIONS
                     ? R.drawable.stat_sys_dnd_total_silence : R.drawable.stat_sys_dnd;
             zenDescription = mContext.getString(R.string.quick_settings_dnd_label);
-        } else if (mZen == Global.ZEN_MODE_NO_INTERRUPTIONS) {
+        } else if (zen == Global.ZEN_MODE_NO_INTERRUPTIONS) {
             zenVisible = true;
             zenIconId = R.drawable.stat_sys_zen_none;
             zenDescription = mContext.getString(R.string.interruption_level_none);
-        } else if (mZen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
+        } else if (zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
             zenVisible = true;
             zenIconId = R.drawable.stat_sys_zen_important;
             zenDescription = mContext.getString(R.string.interruption_level_priority);
@@ -344,7 +333,7 @@
             volumeVisible = true;
             volumeIconId = R.drawable.stat_sys_ringer_silent;
             volumeDescription = mContext.getString(R.string.accessibility_ringer_silent);
-        } else if (mZen != Global.ZEN_MODE_NO_INTERRUPTIONS && mZen != Global.ZEN_MODE_ALARMS &&
+        } else if (zen != Global.ZEN_MODE_NO_INTERRUPTIONS && zen != Global.ZEN_MODE_ALARMS &&
                 audioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_VIBRATE) {
             volumeVisible = true;
             volumeIconId = R.drawable.stat_sys_ringer_vibrate;
@@ -509,7 +498,8 @@
                 if (!hasNotif(notifs, pkg, info.userId)) {
                     // TODO: Optimize by not always needing to get application info.
                     // Maybe cache non-ephemeral packages?
-                    ApplicationInfo appInfo = pm.getApplicationInfo(pkg, 0, info.userId);
+                    ApplicationInfo appInfo = pm.getApplicationInfo(pkg,
+                            PackageManager.MATCH_UNINSTALLED_PACKAGES, info.userId);
                     if (appInfo.isInstantApp()) {
                         postEphemeralNotif(pkg, info.userId, appInfo, noMan);
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index b52c26f..4dc593b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -188,9 +188,6 @@
     public void panelScrimMinFractionChanged(float minFraction) {
         if (mMinFraction != minFraction) {
             mMinFraction = minFraction;
-            if (minFraction != 0.0f) {
-                mScrimController.animateNextChange();
-            }
             updateScrimFraction();
         }
     }
@@ -203,7 +200,11 @@
     }
 
     private void updateScrimFraction() {
-        float scrimFraction = Math.max(mPanelFraction, mMinFraction);
+        float scrimFraction = mPanelFraction;
+        if (mMinFraction < 1.0f) {
+            scrimFraction = Math.max((mPanelFraction - mMinFraction) / (1.0f - mMinFraction),
+                    0);
+        }
         mScrimController.setPanelExpansion(scrimFraction);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
deleted file mode 100644
index ade1b0b..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
+++ /dev/null
@@ -1,469 +0,0 @@
-/*
- * 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.systemui.statusbar.phone;
-
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Color;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.RippleDrawable;
-import android.os.UserManager;
-import android.support.annotation.Nullable;
-import android.support.annotation.VisibleForTesting;
-import android.util.AttributeSet;
-import android.util.SparseBooleanArray;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto;
-import com.android.keyguard.KeyguardStatusView;
-import com.android.settingslib.Utils;
-import com.android.systemui.ActivityStarter;
-import com.android.systemui.BatteryMeterView;
-import com.android.systemui.Dependency;
-import com.android.systemui.FontSizeUtils;
-import com.android.systemui.R;
-import com.android.systemui.plugins.qs.QS.BaseStatusBarHeader;
-import com.android.systemui.plugins.qs.QS.Callback;
-import com.android.systemui.qs.QSPanel;
-import com.android.systemui.qs.QuickQSPanel;
-import com.android.systemui.qs.TouchAnimator;
-import com.android.systemui.qs.TouchAnimator.Builder;
-import com.android.systemui.statusbar.SignalClusterView;
-import com.android.systemui.statusbar.policy.NetworkController;
-import com.android.systemui.statusbar.policy.NetworkController.EmergencyListener;
-import com.android.systemui.statusbar.policy.NetworkController.IconState;
-import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
-import com.android.systemui.statusbar.policy.NextAlarmController;
-import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback;
-import com.android.systemui.statusbar.policy.UserInfoController;
-import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
-import com.android.systemui.tuner.TunerService;
-
-public class QuickStatusBarHeader extends BaseStatusBarHeader implements
-        NextAlarmChangeCallback, OnClickListener, OnUserInfoChangedListener, EmergencyListener,
-        SignalCallback {
-    private static final float EXPAND_INDICATOR_THRESHOLD = .93f;
-
-    private ActivityStarter mActivityStarter;
-    private NextAlarmController mNextAlarmController;
-    private UserInfoController mUserInfoController;
-    private SettingsButton mSettingsButton;
-    protected View mSettingsContainer;
-
-    private TextView mAlarmStatus;
-    private View mAlarmStatusCollapsed;
-    private ViewGroup mDateTimeGroup;
-    private ViewGroup mDateTimeAlarmGroup;
-
-    private QSPanel mQsPanel;
-
-    private boolean mExpanded;
-    private boolean mAlarmShowing;
-
-    private TextView mEmergencyOnly;
-
-    protected ExpandableIndicator mExpandIndicator;
-
-    private boolean mListening;
-    private AlarmManager.AlarmClockInfo mNextAlarm;
-
-    protected QuickQSPanel mHeaderQsPanel;
-    private boolean mShowEmergencyCallsOnly;
-    protected MultiUserSwitch mMultiUserSwitch;
-    private ImageView mMultiUserAvatar;
-    private boolean mAlwaysShowMultiUserSwitch;
-
-    private TouchAnimator mAnimator;
-    protected TouchAnimator mSettingsAlpha;
-    private float mExpansionAmount;
-    protected QSTileHost mHost;
-
-    protected View mEdit;
-    private boolean mShowEditIcon;
-
-    private boolean mShowFullAlarm;
-    private float mDateTimeTranslation;
-    private SparseBooleanArray mRoamingsBySubId = new SparseBooleanArray();
-    private boolean mIsRoaming;
-
-    public QuickStatusBarHeader(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        Resources res = getResources();
-
-        mEmergencyOnly = (TextView) findViewById(R.id.header_emergency_calls_only);
-
-        mShowEditIcon = res.getBoolean(R.bool.config_showQuickSettingsEditingIcon);
-
-        mEdit = findViewById(android.R.id.edit);
-        mEdit.setVisibility(mShowEditIcon ? VISIBLE : GONE);
-
-        if (mShowEditIcon) {
-            findViewById(android.R.id.edit).setOnClickListener(view ->
-                    Dependency.get(ActivityStarter.class).postQSRunnableDismissingKeyguard(() ->
-                            mQsPanel.showEdit(view)));
-        }
-
-        mDateTimeAlarmGroup = (ViewGroup) findViewById(R.id.date_time_alarm_group);
-        mDateTimeAlarmGroup.findViewById(R.id.empty_time_view).setVisibility(View.GONE);
-        mDateTimeGroup = (ViewGroup) findViewById(R.id.date_time_group);
-        mDateTimeGroup.setPivotX(0);
-        mDateTimeGroup.setPivotY(0);
-        mDateTimeTranslation = res.getDimension(R.dimen.qs_date_time_translation);
-        mShowFullAlarm = res.getBoolean(R.bool.quick_settings_show_full_alarm);
-
-        mExpandIndicator = (ExpandableIndicator) findViewById(R.id.expand_indicator);
-        mExpandIndicator.setVisibility(
-                res.getBoolean(R.bool.config_showQuickSettingsExpandIndicator)
-                ? VISIBLE : GONE);
-
-        mHeaderQsPanel = (QuickQSPanel) findViewById(R.id.quick_qs_panel);
-        mHeaderQsPanel.setVisibility(res.getBoolean(R.bool.config_showQuickSettingsRow)
-                ? VISIBLE : GONE);
-
-        mSettingsButton = (SettingsButton) findViewById(R.id.settings_button);
-        mSettingsContainer = findViewById(R.id.settings_button_container);
-        mSettingsButton.setOnClickListener(this);
-
-        mAlarmStatusCollapsed = findViewById(R.id.alarm_status_collapsed);
-        mAlarmStatus = (TextView) findViewById(R.id.alarm_status);
-        mAlarmStatus.setOnClickListener(this);
-
-        mMultiUserSwitch = (MultiUserSwitch) findViewById(R.id.multi_user_switch);
-        mMultiUserAvatar = (ImageView) mMultiUserSwitch.findViewById(R.id.multi_user_avatar);
-        mAlwaysShowMultiUserSwitch = res.getBoolean(R.bool.config_alwaysShowMultiUserSwitcher);
-
-        // RenderThread is doing more harm than good when touching the header (to expand quick
-        // settings), so disable it for this view
-        ((RippleDrawable) mSettingsButton.getBackground()).setForceSoftware(true);
-        ((RippleDrawable) mExpandIndicator.getBackground()).setForceSoftware(true);
-
-        updateResources();
-
-        // Set the light/dark theming on the header status UI to match the current theme.
-        SignalClusterView cluster = (SignalClusterView) findViewById(R.id.signal_cluster);
-        int colorForeground = Utils.getColorAttr(getContext(), android.R.attr.colorForeground);
-        float intensity = colorForeground == Color.WHITE ? 0 : 1;
-        cluster.onDarkChanged(new Rect(0, 0, 0, 0), intensity, colorForeground);
-
-        BatteryMeterView battery = (BatteryMeterView) findViewById(R.id.battery);
-        battery.forceShowPercent();
-        int colorSecondary = Utils.getColorAttr(getContext(), android.R.attr.textColorSecondary);
-        battery.setRawColors(colorForeground, colorSecondary);
-
-        mNextAlarmController = Dependency.get(NextAlarmController.class);
-        mUserInfoController = Dependency.get(UserInfoController.class);
-        mActivityStarter = Dependency.get(ActivityStarter.class);
-    }
-
-    @Override
-    protected void onConfigurationChanged(Configuration newConfig) {
-        super.onConfigurationChanged(newConfig);
-        updateResources();
-    }
-
-    @Override
-    public void onRtlPropertiesChanged(int layoutDirection) {
-        super.onRtlPropertiesChanged(layoutDirection);
-        updateResources();
-    }
-
-    private void updateResources() {
-        FontSizeUtils.updateFontSize(mAlarmStatus, R.dimen.qs_date_collapsed_size);
-        FontSizeUtils.updateFontSize(mEmergencyOnly, R.dimen.qs_emergency_calls_only_text_size);
-
-        Builder builder = new Builder()
-                .addFloat(mShowFullAlarm ? mAlarmStatus : findViewById(R.id.date), "alpha", 0, 1)
-                .addFloat(mEmergencyOnly, "alpha", 0, 1);
-        if (mShowFullAlarm) {
-            builder.addFloat(mAlarmStatusCollapsed, "alpha", 1, 0);
-        }
-        mAnimator = builder.build();
-
-        updateSettingsAnimator();
-    }
-
-    private void updateSettingsAnimator() {
-        mSettingsAlpha = createSettingsAlphaAnimator();
-
-        final boolean isRtl = isLayoutRtl();
-        if (isRtl && mDateTimeGroup.getWidth() == 0) {
-            mDateTimeGroup.addOnLayoutChangeListener(new OnLayoutChangeListener() {
-                @Override
-                public void onLayoutChange(View v, int left, int top, int right, int bottom,
-                        int oldLeft, int oldTop, int oldRight, int oldBottom) {
-                    mDateTimeGroup.setPivotX(getWidth());
-                    mDateTimeGroup.removeOnLayoutChangeListener(this);
-                }
-            });
-        } else {
-            mDateTimeGroup.setPivotX(isRtl ? mDateTimeGroup.getWidth() : 0);
-        }
-    }
-
-    @Nullable
-    private TouchAnimator createSettingsAlphaAnimator() {
-        // If the settings icon is not shown and the user switcher is always shown, then there
-        // is nothing to animate.
-        if (!mShowEditIcon && mAlwaysShowMultiUserSwitch) {
-            return null;
-        }
-
-        TouchAnimator.Builder animatorBuilder = new TouchAnimator.Builder();
-
-        if (mShowEditIcon) {
-            animatorBuilder.addFloat(mEdit, "alpha", 0, 1);
-        }
-
-        if (!mAlwaysShowMultiUserSwitch) {
-            animatorBuilder.addFloat(mMultiUserSwitch, "alpha", 0, 1);
-        }
-
-        return animatorBuilder.build();
-    }
-
-    @Override
-    public int getCollapsedHeight() {
-        return getHeight();
-    }
-
-    @Override
-    public int getExpandedHeight() {
-        return getHeight();
-    }
-
-    @Override
-    public void setExpanded(boolean expanded) {
-        if (mExpanded == expanded) return;
-        mExpanded = expanded;
-        mHeaderQsPanel.setExpanded(expanded);
-        updateEverything();
-    }
-
-    @Override
-    public void onNextAlarmChanged(AlarmManager.AlarmClockInfo nextAlarm) {
-        mNextAlarm = nextAlarm;
-        if (nextAlarm != null) {
-            String alarmString = KeyguardStatusView.formatNextAlarm(getContext(), nextAlarm);
-            mAlarmStatus.setText(alarmString);
-            mAlarmStatus.setContentDescription(mContext.getString(
-                    R.string.accessibility_quick_settings_alarm, alarmString));
-            mAlarmStatusCollapsed.setContentDescription(mContext.getString(
-                    R.string.accessibility_quick_settings_alarm, alarmString));
-        }
-        if (mAlarmShowing != (nextAlarm != null)) {
-            mAlarmShowing = nextAlarm != null;
-            updateEverything();
-        }
-    }
-
-    @Override
-    public void setExpansion(float headerExpansionFraction) {
-        mExpansionAmount = headerExpansionFraction;
-        updateDateTimePosition();
-        mAnimator.setPosition(headerExpansionFraction);
-
-        if (mSettingsAlpha != null) {
-            mSettingsAlpha.setPosition(headerExpansionFraction);
-        }
-
-        updateAlarmVisibilities();
-
-        mExpandIndicator.setExpanded(headerExpansionFraction > EXPAND_INDICATOR_THRESHOLD);
-    }
-
-    @Override
-    @VisibleForTesting
-    public void onDetachedFromWindow() {
-        setListening(false);
-        super.onDetachedFromWindow();
-    }
-
-    private void updateAlarmVisibilities() {
-        mAlarmStatus.setVisibility(mAlarmShowing && mShowFullAlarm ? View.VISIBLE : View.INVISIBLE);
-        mAlarmStatusCollapsed.setVisibility(mAlarmShowing ? View.VISIBLE : View.INVISIBLE);
-    }
-
-    public void setListening(boolean listening) {
-        if (listening == mListening) {
-            return;
-        }
-        mHeaderQsPanel.setListening(listening);
-        mListening = listening;
-        updateListeners();
-    }
-
-    @Override
-    public View getExpandView() {
-        return findViewById(R.id.expand_indicator);
-    }
-
-    @Override
-    public void updateEverything() {
-        post(() -> {
-            updateVisibilities();
-            setClickable(false);
-        });
-    }
-
-    private void updateVisibilities() {
-        updateAlarmVisibilities();
-        updateDateTimePosition();
-        mEmergencyOnly.setVisibility(mExpanded && (mShowEmergencyCallsOnly || mIsRoaming)
-                ? View.VISIBLE : View.INVISIBLE);
-        mSettingsContainer.findViewById(R.id.tuner_icon).setVisibility(
-                TunerService.isTunerEnabled(mContext) ? View.VISIBLE : View.INVISIBLE);
-        final boolean isDemo = UserManager.isDeviceInDemoMode(mContext);
-
-        mMultiUserSwitch.setVisibility((mExpanded || mAlwaysShowMultiUserSwitch)
-                && mMultiUserSwitch.hasMultipleUsers() && !isDemo
-                ? View.VISIBLE : View.INVISIBLE);
-
-        if (mShowEditIcon) {
-            mEdit.setVisibility(isDemo || !mExpanded ? View.INVISIBLE : View.VISIBLE);
-        }
-    }
-
-    private void updateDateTimePosition() {
-        mDateTimeAlarmGroup.setTranslationY(mShowEmergencyCallsOnly || mIsRoaming
-                ? mExpansionAmount * mDateTimeTranslation : 0);
-    }
-
-    private void updateListeners() {
-        if (mListening) {
-            mNextAlarmController.addCallback(this);
-            mUserInfoController.addCallback(this);
-            if (Dependency.get(NetworkController.class).hasVoiceCallingFeature()) {
-                Dependency.get(NetworkController.class).addEmergencyListener(this);
-                Dependency.get(NetworkController.class).addCallback(this);
-            }
-        } else {
-            mNextAlarmController.removeCallback(this);
-            mUserInfoController.removeCallback(this);
-            Dependency.get(NetworkController.class).removeEmergencyListener(this);
-            Dependency.get(NetworkController.class).removeCallback(this);
-        }
-    }
-
-    public void setQSPanel(final QSPanel qsPanel) {
-        mQsPanel = qsPanel;
-        setupHost(qsPanel.getHost());
-        if (mQsPanel != null) {
-            mMultiUserSwitch.setQsPanel(qsPanel);
-        }
-    }
-
-    public void setupHost(final QSTileHost host) {
-        mHost = host;
-        //host.setHeaderView(mExpandIndicator);
-        mHeaderQsPanel.setQSPanelAndHeader(mQsPanel, this);
-        mHeaderQsPanel.setHost(host, null /* No customization in header */);
-    }
-
-    @Override
-    public void onClick(View v) {
-        if (v == mSettingsButton) {
-            MetricsLogger.action(mContext,
-                    mExpanded ? MetricsProto.MetricsEvent.ACTION_QS_EXPANDED_SETTINGS_LAUNCH
-                            : MetricsProto.MetricsEvent.ACTION_QS_COLLAPSED_SETTINGS_LAUNCH);
-            if (mSettingsButton.isTunerClick()) {
-                Dependency.get(ActivityStarter.class).postQSRunnableDismissingKeyguard(() -> {
-                    if (TunerService.isTunerEnabled(mContext)) {
-                        TunerService.showResetRequest(mContext, () -> {
-                            // Relaunch settings so that the tuner disappears.
-                            startSettingsActivity();
-                        });
-                    } else {
-                        Toast.makeText(getContext(), R.string.tuner_toast,
-                                Toast.LENGTH_LONG).show();
-                        TunerService.setTunerEnabled(mContext, true);
-                    }
-                    startSettingsActivity();
-
-                });
-            } else {
-                startSettingsActivity();
-            }
-        } else if (v == mAlarmStatus && mNextAlarm != null) {
-            PendingIntent showIntent = mNextAlarm.getShowIntent();
-            mActivityStarter.startPendingIntentDismissingKeyguard(showIntent);
-        }
-    }
-
-    private void startSettingsActivity() {
-        mActivityStarter.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS),
-                true /* dismissShade */);
-    }
-
-    @Override
-    public void setCallback(Callback qsPanelCallback) {
-        mHeaderQsPanel.setCallback(qsPanelCallback);
-    }
-
-    @Override
-    public void setEmergencyCallsOnly(boolean show) {
-        boolean changed = show != mShowEmergencyCallsOnly;
-        if (changed) {
-            mShowEmergencyCallsOnly = show;
-            if (mExpanded) {
-                updateEverything();
-            }
-        }
-    }
-
-    public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
-            int qsType, boolean activityIn, boolean activityOut, String typeContentDescription,
-            String description, boolean isWide, int subId, boolean roaming) {
-        mRoamingsBySubId.put(subId, roaming);
-        boolean isRoaming = calculateRoaming();
-        if (mIsRoaming != isRoaming) {
-            mIsRoaming = isRoaming;
-            mEmergencyOnly.setText(mIsRoaming ? R.string.accessibility_data_connection_roaming
-                    : com.android.internal.R.string.emergency_calls_only);
-            if (mExpanded) {
-                updateEverything();
-            }
-        }
-    }
-
-    private boolean calculateRoaming() {
-        for (int i = 0; i < mRoamingsBySubId.size(); i++) {
-            if (mRoamingsBySubId.valueAt(i)) return true;
-        }
-        return false;
-    }
-
-    @Override
-    public void onUserInfoChanged(String name, Drawable picture, String userAccount) {
-        mMultiUserAvatar.setImageDrawable(picture);
-    }
-}
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 b30d3ab..dadb749 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -203,10 +203,6 @@
         scheduleUpdate();
     }
 
-    public void animateNextChange() {
-        mAnimateChange = true;
-    }
-
     public void setDozing(boolean dozing) {
         if (mDozing != dozing) {
             mDozing = dozing;
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 dd04741..005b701 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -23,6 +23,7 @@
 import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
 import static android.app.StatusBarManager.windowStateToString;
 
+import static com.android.systemui.statusbar.notification.NotificationInflater.InflationExceptionHandler;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
@@ -124,7 +125,6 @@
 import com.android.systemui.ActivityStarterDelegate;
 import com.android.systemui.DemoMode;
 import com.android.systemui.Dependency;
-import com.android.systemui.EventLogConstants;
 import com.android.systemui.EventLogTags;
 import com.android.systemui.Interpolators;
 import com.android.systemui.Prefs;
@@ -139,12 +139,12 @@
 import com.android.systemui.fragments.PluginFragmentListener;
 import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.plugins.qs.QS;
-import com.android.systemui.ActivityStarter;
-import com.android.systemui.plugins.qs.QS.BaseStatusBarHeader;
+import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowProvider.SnoozeListener;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowProvider.SnoozeOption;
 import com.android.systemui.qs.QSFragment;
 import com.android.systemui.qs.QSPanel;
+import com.android.systemui.qs.QSTileHost;
 import com.android.systemui.recents.ScreenPinningRequest;
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.activity.AppTransitionFinishedEvent;
@@ -161,7 +161,6 @@
 import com.android.systemui.statusbar.GestureRecorder;
 import com.android.systemui.statusbar.KeyboardShortcuts;
 import com.android.systemui.statusbar.KeyguardIndicationController;
-import com.android.systemui.statusbar.NotificationContentView;
 import com.android.systemui.statusbar.NotificationData;
 import com.android.systemui.statusbar.NotificationData.Entry;
 import com.android.systemui.statusbar.NotificationGuts;
@@ -172,6 +171,7 @@
 import com.android.systemui.statusbar.ScrimView;
 import com.android.systemui.statusbar.SignalClusterView;
 import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.notification.InflationException;
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
 import com.android.systemui.statusbar.phone.StatusBarIconController.IconManager;
 import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChangedListener;
@@ -204,10 +204,8 @@
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.ArrayList;
-import java.util.Calendar;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.GregorianCalendar;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -299,7 +297,7 @@
             "com.android.systemui.statusbar.banner_action_setup";
     private static final String NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION
             = "com.android.systemui.statusbar.work_challenge_unlocked_notification_action";
-    static final String TAG = "StatusBar";
+    public static final String TAG = "StatusBar";
     public static final boolean DEBUG = false;
     public static final boolean SPEW = false;
     public static final boolean DUMPTRUCK = true; // extra dumpsys info
@@ -436,7 +434,6 @@
     private QSPanel mQSPanel;
 
     // top bar
-    BaseStatusBarHeader mHeader;
     protected KeyguardStatusBarView mKeyguardStatusBar;
     KeyguardStatusView mKeyguardStatusView;
     KeyguardBottomAreaView mKeyguardBottomArea;
@@ -716,7 +713,9 @@
     private LogMaker mStatusBarStateLog;
     private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
     private NotificationIconAreaController mNotificationIconAreaController;
-    private ConfigurationListener mDensityChangeListener;
+    private ConfigurationListener mConfigurationListener;
+    private InflationExceptionHandler mInflationExceptionHandler = this::handleInflationException;
+    private boolean mReinflateNotificationsOnUserSwitched;
 
     private void recycleAllVisibilityObjects(ArraySet<NotificationVisibility> array) {
         final int N = array.size();
@@ -943,13 +942,18 @@
 
         Dependency.get(ActivityStarterDelegate.class).setActivityStarterImpl(this);
 
-        mDensityChangeListener = new ConfigurationListener() {
+        mConfigurationListener = new ConfigurationListener() {
+            @Override
+            public void onConfigChanged(Configuration newConfig) {
+                StatusBar.this.onConfigurationChanged(newConfig);
+            }
+
             @Override
             public void onDensityOrFontScaleChanged() {
                 StatusBar.this.onDensityOrFontScaleChanged();
             }
         };
-        Dependency.get(ConfigurationController.class).addCallback(mDensityChangeListener);
+        Dependency.get(ConfigurationController.class).addCallback(mConfigurationListener);
     }
 
     protected void createIconController() {
@@ -1271,17 +1275,10 @@
 
     protected void onDensityOrFontScaleChanged() {
         // start old BaseStatusBar.onDensityOrFontScaleChanged().
-        ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications();
-        for (int i = 0; i < activeNotifications.size(); i++) {
-            Entry entry = activeNotifications.get(i);
-            boolean exposedGuts = mNotificationGutsExposed != null
-                    && entry.row.getGuts() == mNotificationGutsExposed;
-            entry.row.reInflateViews();
-            if (exposedGuts) {
-                mNotificationGutsExposed = entry.row.getGuts();
-                bindGuts(entry.row, mGutsMenuItem);
-            }
-            inflateViews(entry, mStackScroller);
+        if (!KeyguardUpdateMonitor.getInstance(mContext).isSwitchingUser()) {
+            updateNotificationsOnDensityOrFontScaleChanged();
+        } else {
+            mReinflateNotificationsOnUserSwitched = true;
         }
         // end old BaseStatusBar.onDensityOrFontScaleChanged().
         mScrimController.onDensityOrFontScaleChanged();
@@ -1306,6 +1303,20 @@
         }
     }
 
+    private void updateNotificationsOnDensityOrFontScaleChanged() {
+        ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications();
+        for (int i = 0; i < activeNotifications.size(); i++) {
+            Entry entry = activeNotifications.get(i);
+            boolean exposedGuts = mNotificationGutsExposed != null
+                    && entry.row.getGuts() == mNotificationGutsExposed;
+            entry.row.onDensityOrFontScaleChanged();
+            if (exposedGuts) {
+                mNotificationGutsExposed = entry.row.getGuts();
+                bindGuts(entry.row, mGutsMenuItem);
+            }
+        }
+    }
+
     private void inflateSignalClusters() {
         reinflateSignalCluster(mKeyguardStatusBar);
     }
@@ -1550,14 +1561,11 @@
     }
 
     public void addNotification(StatusBarNotification notification, RankingMap ranking,
-            Entry oldEntry) {
+            Entry oldEntry) throws InflationException {
         if (DEBUG) Log.d(TAG, "addNotification key=" + notification.getKey());
 
         mNotificationData.updateRanking(ranking);
         Entry shadeEntry = createNotificationViews(notification);
-        if (shadeEntry == null) {
-            return;
-        }
         boolean isHeadsUped = shouldPeek(shadeEntry);
         if (isHeadsUped) {
             mHeadsUpManager.showNotification(shadeEntry);
@@ -1599,6 +1607,10 @@
         setAreThereNotifications();
     }
 
+    public void handleInflationException(StatusBarNotification notification, InflationException e) {
+        handleNotificationError(notification, e.getMessage());
+    }
+
     private boolean shouldSuppressFullScreenIntent(String key) {
         if (isDeviceInVrMode()) {
             return true;
@@ -1663,10 +1675,17 @@
                     sbn.getOpPkg(),
                     sbn.getId(), sbn.getTag(), sbn.getUid(), sbn.getInitialPid(),
                     newNotification, sbn.getUser(), sbn.getOverrideGroupKey(), sbn.getPostTime());
-
-            updateNotification(newSbn, null);
-            mKeysKeptForRemoteInput.add(entry.key);
-            return;
+            boolean updated = false;
+            try {
+                updateNotification(newSbn, null);
+                updated = true;
+            } catch (InflationException e) {
+                deferRemoval = false;
+            }
+            if (updated) {
+                mKeysKeptForRemoteInput.add(entry.key);
+                return;
+            }
         }
         if (deferRemoval) {
             mLatestRankingMap = ranking;
@@ -1684,6 +1703,7 @@
 
         if (entry != null && entry.row != null) {
             entry.row.setRemoved();
+            mStackScroller.cleanUpViewState(entry.row);
         }
         // Let's remove the children if this was a summary
         handleGroupSummaryRemoved(key, ranking);
@@ -1740,12 +1760,6 @@
                 // animations
                 toRemove.get(i).setRemoved();
             }
-            for (int i = 0; i < toRemove.size(); i++) {
-                removeNotification(toRemove.get(i).getStatusBarNotification().getKey(), ranking);
-                // we need to ensure that the view is actually properly removed from the viewstate
-                // as this won't happen anymore when kept in the parent.
-                mStackScroller.removeViewStateForView(toRemove.get(i));
-            }
         }
     }
 
@@ -1813,15 +1827,6 @@
                 updatePublicContentView(ent, ent.notification);
             }
             ent.row.setSensitive(sensitive, deviceSensitive);
-            if (ent.autoRedacted && ent.legacy) {
-                // TODO: Also fade this? Or, maybe easier (and better), provide a dark redacted form
-                // for legacy auto redacted notifications.
-                if (showingPublic) {
-                    ent.row.setShowingLegacyBackground(false);
-                } else {
-                    ent.row.setShowingLegacyBackground(true);
-                }
-            }
             if (mGroupManager.isChildInGroupWithSummary(ent.row.getStatusBarNotification())) {
                 ExpandableNotificationRow summary = mGroupManager.getGroupSummary(
                         ent.row.getStatusBarNotification());
@@ -2039,10 +2044,10 @@
     }
 
     private void updateEmptyShadeView() {
-        boolean showEmptyShade =
+        boolean showEmptyShadeView =
                 mState != StatusBarState.KEYGUARD &&
                         mNotificationData.getActiveNotifications().size() == 0;
-        mNotificationPanel.setShadeEmpty(showEmptyShade);
+        mNotificationPanel.showEmptyShadeView(showEmptyShadeView);
     }
 
     private void updateSpeedBumpIndex() {
@@ -2511,7 +2516,7 @@
      * This needs to be called if state used by {@link #adjustDisableFlags} changes.
      */
     public void recomputeDisableFlags(boolean animate) {
-        mCommandQueue.disable(mDisabledUnmodified1, mDisabledUnmodified2, animate);
+        mCommandQueue.recomputeDisableFlags(animate);
     }
 
     protected H createHandler() {
@@ -2725,8 +2730,8 @@
         return mLaunchTransitionFadingAway;
     }
 
-    public boolean shouldHideNotificationIcons() {
-        return mNotificationPanel.shouldHideNotificationIcons();
+    public boolean hideStatusBarIconsWhenExpanded() {
+        return mNotificationPanel.hideStatusBarIconsWhenExpanded();
     }
 
     /**
@@ -2968,7 +2973,7 @@
         runPostCollapseRunnables();
         setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
         showBouncerIfKeyguard();
-        recomputeDisableFlags(shouldAnimatIconHiding() /* animate */);
+        recomputeDisableFlags(mNotificationPanel.hideStatusBarIconsWhenExpanded() /* animate */);
 
         // Trimming will happen later if Keyguard is showing - doing it here might cause a jank in
         // the bouncer appear animation.
@@ -2977,10 +2982,6 @@
         }
     }
 
-    private boolean shouldAnimatIconHiding() {
-        return mNotificationPanel.shouldAnimateIconHiding();
-    }
-
     public boolean interceptTouchEvent(MotionEvent event) {
         if (DEBUG_GESTURES) {
             if (event.getActionMasked() != MotionEvent.ACTION_MOVE) {
@@ -3606,7 +3607,12 @@
         if (MULTIUSER_DEBUG) mNotificationPanelDebugText.setText("USER " + newUserId);
         animateCollapsePanels();
         updatePublicMode();
-        updateNotifications();
+        mNotificationData.filterAndSort();
+        if (mReinflateNotificationsOnUserSwitched) {
+            updateNotificationsOnDensityOrFontScaleChanged();
+            mReinflateNotificationsOnUserSwitched = false;
+        }
+        updateNotificationShade();
         clearCurrentMediaNotification();
         setLockscreenUser(newUserId);
     }
@@ -3915,7 +3921,7 @@
         }
         Dependency.get(ActivityStarterDelegate.class).setActivityStarterImpl(null);
         mDeviceProvisionedController.removeCallback(mUserSetupObserver);
-        Dependency.get(ConfigurationController.class).removeCallback(mDensityChangeListener);
+        Dependency.get(ConfigurationController.class).removeCallback(mConfigurationListener);
     }
 
     private boolean mDemoModeAllowed;
@@ -4877,7 +4883,7 @@
     }
 
     public void wakeUpIfDozing(long time, View where) {
-        if (mDozing && mDozeScrimController.isPulsing()) {
+        if (mDozing) {
             PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
             pm.wakeUp(time, "com.android.systemui:NODOZE");
             mWakeUpComingFromTouch = true;
@@ -5518,7 +5524,11 @@
                 @Override
                 public void run() {
                     for (StatusBarNotification sbn : notifications) {
-                        addNotification(sbn, currentRanking, null /* oldEntry */);
+                        try {
+                            addNotification(sbn, currentRanking, null /* oldEntry */);
+                        } catch (InflationException e) {
+                            handleInflationException(sbn, e);
+                        }
                     }
                 }
             });
@@ -5554,10 +5564,14 @@
                             }
                             return;
                         }
-                        if (isUpdate) {
-                            updateNotification(sbn, rankingMap);
-                        } else {
-                            addNotification(sbn, rankingMap, null /* oldEntry */);
+                        try {
+                            if (isUpdate) {
+                                updateNotification(sbn, rankingMap);
+                            } else {
+                                addNotification(sbn, rankingMap, null /* oldEntry */);
+                            }
+                        } catch (InflationException e) {
+                            handleInflationException(sbn, e);
                         }
                     }
                 });
@@ -5687,26 +5701,6 @@
         return mGroupManager;
     }
 
-    protected void bindDismissRunnable(final ExpandableNotificationRow row) {
-        row.setOnDismissRunnable(() -> performRemoveNotification(row.getStatusBarNotification()));
-    }
-
-    protected void applyColorsAndBackgrounds(StatusBarNotification sbn,
-            NotificationData.Entry entry) {
-
-        if (entry.getContentView().getId()
-                != com.android.internal.R.id.status_bar_latest_event_content) {
-            // Using custom RemoteViews
-            if (entry.targetSdk >= Build.VERSION_CODES.GINGERBREAD
-                    && entry.targetSdk < Build.VERSION_CODES.LOLLIPOP) {
-                entry.row.setShowingLegacyBackground(true);
-                entry.legacy = true;
-            }
-        }
-
-        entry.setIconTag(R.id.icon_is_pre_L, entry.targetSdk < Build.VERSION_CODES.LOLLIPOP);
-    }
-
     public boolean isMediaNotification(NotificationData.Entry entry) {
         // TODO: confirm that there's a valid media key
         return entry.getExpandedContentView() != null &&
@@ -5747,9 +5741,8 @@
         if (snoozeOption.criterion != null) {
             mNotificationListener.snoozeNotification(sbn.getKey(), snoozeOption.criterion.getId());
         } else {
-            GregorianCalendar snoozeUntil = new GregorianCalendar();
-            snoozeUntil.add(Calendar.MINUTE, snoozeOption.snoozeForMinutes);
-            mNotificationListener.snoozeNotification(sbn.getKey(), snoozeUntil.getTimeInMillis());
+            mNotificationListener.snoozeNotification(sbn.getKey(),
+                    snoozeOption.snoozeForMinutes * 60 * 1000);
         }
     }
 
@@ -6089,55 +6082,16 @@
         }
     }
 
-    protected boolean inflateViews(Entry entry, ViewGroup parent) {
+    protected void inflateViews(Entry entry, ViewGroup parent) throws
+            InflationException {
         PackageManager pmUser = getPackageManagerForUser(mContext,
                 entry.notification.getUser().getIdentifier());
 
         final StatusBarNotification sbn = entry.notification;
-        boolean isLowPriority = mNotificationData.isAmbient(sbn.getKey());
-        boolean useIncreasedCollapsedHeight = mMessagingUtil.isImportantMessaging(sbn,
-                mNotificationData.getImportance(sbn.getKey()));
-        boolean useIncreasedHeadsUp = useIncreasedCollapsedHeight && mPanelExpanded;
-        try {
-            entry.cacheContentViews(mContext, null, isLowPriority, useIncreasedCollapsedHeight,
-                    useIncreasedHeadsUp);
-        } catch (RuntimeException e) {
-            Log.e(TAG, "Unable to get notification remote views", e);
-            return false;
-        }
-
-        final RemoteViews contentView = entry.cachedContentView;
-        final RemoteViews bigContentView = entry.cachedBigContentView;
-        final RemoteViews headsUpContentView = entry.cachedHeadsUpContentView;
-        final RemoteViews publicContentView = entry.cachedPublicContentView;
-        final RemoteViews ambientContentView = entry.cachedAmbientContentView;
-
-        if (contentView == null) {
-            Log.v(TAG, "no contentView for: " + sbn.getNotification());
-            return false;
-        }
-
-        if (DEBUG) {
-            Log.v(TAG, "publicContentView: " + publicContentView);
-        }
-
         ExpandableNotificationRow row;
-
-        // Stash away previous user expansion state so we can restore it at
-        // the end.
-        boolean hasUserChangedExpansion = false;
-        boolean userExpanded = false;
-        boolean userLocked = false;
-
         if (entry.row != null) {
             row = entry.row;
-            hasUserChangedExpansion = row.hasUserChangedExpansion();
-            userExpanded = row.isUserExpanded();
-            userLocked = row.isUserLocked();
             entry.reset();
-            if (hasUserChangedExpansion) {
-                row.setUserExpanded(userExpanded);
-            }
         } else {
             // create the row view
             LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
@@ -6149,6 +6103,8 @@
             row.setHeadsUpManager(mHeadsUpManager);
             row.setRemoteInputController(mRemoteInputController);
             row.setOnExpandClickListener(this);
+            row.setRemoteViewClickHandler(mOnClickHandler);
+            row.setInflateExceptionHandler(mInflationExceptionHandler);
 
             // Get the app name.
             // Note that Notification.Builder#bindHeaderAppName has similar logic
@@ -6168,86 +6124,19 @@
                 // Do nothing
             }
             row.setAppName(appname);
+            row.setOnDismissRunnable(() ->
+                    performRemoveNotification(row.getStatusBarNotification()));
+            row.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
+            if (ENABLE_REMOTE_INPUT) {
+                row.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
+            }
         }
 
-        bindDismissRunnable(row);
+        boolean isLowPriority = mNotificationData.isAmbient(sbn.getKey());
         row.setIsLowPriority(isLowPriority);
-
-        // NB: the large icon is now handled entirely by the template
-
         // bind the click event to the content area
-        NotificationContentView contentContainer = row.getPrivateLayout();
-        NotificationContentView contentContainerPublic = row.getPublicLayout();
-
-        row.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
-        if (ENABLE_REMOTE_INPUT) {
-            row.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
-        }
-
         mNotificationClicker.register(row, sbn);
 
-        // set up the adaptive layout
-        View contentViewLocal = null;
-        View bigContentViewLocal = null;
-        View headsUpContentViewLocal = null;
-        View publicViewLocal = null;
-        View ambientViewLocal = null;
-        try {
-            contentViewLocal = contentView.apply(
-                    sbn.getPackageContext(mContext),
-                    contentContainer,
-                    mOnClickHandler);
-            if (bigContentView != null) {
-                bigContentViewLocal = bigContentView.apply(
-                        sbn.getPackageContext(mContext),
-                        contentContainer,
-                        mOnClickHandler);
-            }
-            if (headsUpContentView != null) {
-                headsUpContentViewLocal = headsUpContentView.apply(
-                        sbn.getPackageContext(mContext),
-                        contentContainer,
-                        mOnClickHandler);
-            }
-            if (publicContentView != null) {
-                publicViewLocal = publicContentView.apply(
-                        sbn.getPackageContext(mContext),
-                        contentContainerPublic, mOnClickHandler);
-            }
-            if (ambientContentView != null) {
-                ambientViewLocal = ambientContentView.apply(
-                        sbn.getPackageContext(mContext),
-                        contentContainer, mOnClickHandler);
-            }
-
-            if (contentViewLocal != null) {
-                contentViewLocal.setIsRootNamespace(true);
-                contentContainer.setContractedChild(contentViewLocal);
-            }
-            if (bigContentViewLocal != null) {
-                bigContentViewLocal.setIsRootNamespace(true);
-                contentContainer.setExpandedChild(bigContentViewLocal);
-            }
-            if (headsUpContentViewLocal != null) {
-                headsUpContentViewLocal.setIsRootNamespace(true);
-                contentContainer.setHeadsUpChild(headsUpContentViewLocal);
-            }
-            if (publicViewLocal != null) {
-                publicViewLocal.setIsRootNamespace(true);
-                contentContainerPublic.setContractedChild(publicViewLocal);
-            }
-
-            if (ambientViewLocal != null) {
-                ambientViewLocal.setIsRootNamespace(true);
-                contentContainer.setAmbientChild(ambientViewLocal);
-            }
-        }
-        catch (RuntimeException e) {
-            final String ident = sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId());
-            Log.e(TAG, "couldn't inflate view for notification " + ident, e);
-            return false;
-        }
-
         // Extract target SDK version.
         try {
             ApplicationInfo info = pmUser.getApplicationInfo(sbn.getPackageName(), 0);
@@ -6255,25 +6144,20 @@
         } catch (NameNotFoundException ex) {
             Log.e(TAG, "Failed looking up ApplicationInfo for " + sbn.getPackageName(), ex);
         }
+        row.setLegacy(entry.targetSdk >= Build.VERSION_CODES.GINGERBREAD
+                && entry.targetSdk < Build.VERSION_CODES.LOLLIPOP);
+        entry.setIconTag(R.id.icon_is_pre_L, entry.targetSdk < Build.VERSION_CODES.LOLLIPOP);
         entry.autoRedacted = entry.notification.getNotification().publicVersion == null;
 
         entry.row = row;
         entry.row.setOnActivatedListener(this);
-        entry.row.setExpandable(bigContentViewLocal != null);
 
-        applyColorsAndBackgrounds(sbn, entry);
-
-        // Restore previous flags.
-        if (hasUserChangedExpansion) {
-            // Note: setUserExpanded() conveniently ignores calls with
-            //       userExpanded=true if !isExpandable().
-            row.setUserExpanded(userExpanded);
-        }
-        row.setUserLocked(userLocked);
+        boolean useIncreasedCollapsedHeight = mMessagingUtil.isImportantMessaging(sbn,
+                mNotificationData.getImportance(sbn.getKey()));
+        boolean useIncreasedHeadsUp = useIncreasedCollapsedHeight && mPanelExpanded;
         row.setUseIncreasedCollapsedHeight(useIncreasedCollapsedHeight);
         row.setUseIncreasedHeadsUpHeight(useIncreasedHeadsUp);
-        row.onNotificationUpdated(entry);
-        return true;
+        row.updateNotification(entry);
     }
 
     /**
@@ -6611,23 +6495,17 @@
         return entry.notification;
     }
 
-    protected NotificationData.Entry createNotificationViews(StatusBarNotification sbn) {
+    protected NotificationData.Entry createNotificationViews(StatusBarNotification sbn)
+            throws InflationException {
         if (DEBUG) {
             Log.d(TAG, "createNotificationViews(notification=" + sbn);
         }
         NotificationData.Entry entry = new NotificationData.Entry(sbn);
         Dependency.get(LeakDetector.class).trackInstance(entry);
-        try {
-            entry.createIcons(mContext, sbn);
-        } catch (NotificationData.IconException exception) {
-            handleNotificationError(sbn, exception.getMessage());
-        }
+        entry.createIcons(mContext, sbn);
 
         // Construct the expanded view.
-        if (!inflateViews(entry, mStackScroller)) {
-            handleNotificationError(sbn, "Couldn't expand RemoteViews for: " + sbn);
-            return null;
-        }
+        inflateViews(entry, mStackScroller);
         return entry;
     }
 
@@ -6703,6 +6581,7 @@
                 }
             }
         }
+        mNotificationPanel.setNoVisibleNotifications(visibleNotifications == 0);
 
         mStackScroller.changeViewPosition(mDismissView, mStackScroller.getChildCount() - 1);
         mStackScroller.changeViewPosition(mEmptyShadeView, mStackScroller.getChildCount() - 2);
@@ -6748,7 +6627,8 @@
         }
     }
 
-    public void updateNotification(StatusBarNotification notification, RankingMap ranking) {
+    public void updateNotification(StatusBarNotification notification, RankingMap ranking)
+            throws InflationException {
         if (DEBUG) Log.d(TAG, "updateNotification(" + notification + ")");
 
         final String key = notification.getKey();
@@ -6763,56 +6643,16 @@
         Notification n = notification.getNotification();
         mNotificationData.updateRanking(ranking);
 
-        boolean useIncreasedCollapsedHeight = mMessagingUtil.isImportantMessaging(notification,
-                mNotificationData.getImportance(notification.getKey()));
-        entry.row.setUseIncreasedCollapsedHeight(useIncreasedCollapsedHeight);
-        boolean useIncreasedHeadsUp = useIncreasedCollapsedHeight && mPanelExpanded;
-        entry.row.setUseIncreasedHeadsUpHeight(useIncreasedHeadsUp);
-        boolean applyInPlace;
-        try {
-            applyInPlace = entry.cacheContentViews(mContext, notification.getNotification(),
-                    mNotificationData.isAmbient(key), useIncreasedCollapsedHeight,
-                    useIncreasedHeadsUp);
-        } catch (RuntimeException e) {
-            Log.e(TAG, "Unable to get notification remote views", e);
-            applyInPlace = false;
-        }
-        boolean shouldPeek = shouldPeek(entry, notification);
-        boolean alertAgain = alertAgain(entry, n);
-        if (DEBUG) {
-            Log.d(TAG, "applyInPlace=" + applyInPlace
-                    + " shouldPeek=" + shouldPeek
-                    + " alertAgain=" + alertAgain);
-        }
-
         final StatusBarNotification oldNotification = entry.notification;
         entry.notification = notification;
         mGroupManager.onEntryUpdated(entry, oldNotification);
 
-        boolean updateSuccessful = false;
-        try {
-            if (applyInPlace) {
-                if (DEBUG) Log.d(TAG, "reusing notification for key: " + key);
-                try {
-                    entry.updateIcons(mContext, n);
-                    updateNotificationViews(entry, notification);
-                    updateSuccessful = true;
-                } catch (RuntimeException e) {
-                    // It failed to apply cleanly.
-                    Log.w(TAG, "Couldn't reapply views for package " +
-                            notification.getPackageName(), e);
-                }
-            }
-            if (!updateSuccessful) {
-                entry.updateIcons(mContext, n);
-                if (!inflateViews(entry, mStackScroller)) {
-                    handleNotificationError(notification, "Couldn't update remote views for: "
-                            + notification);
-                }
-            }
-        } catch (NotificationData.IconException e) {
-            handleNotificationError(notification, e.getMessage());
-        }
+        entry.updateIcons(mContext, n);
+        inflateViews(entry, mStackScroller);
+
+        boolean shouldPeek = shouldPeek(entry, notification);
+        boolean alertAgain = alertAgain(entry, n);
+
         updateHeadsUp(key, entry, shouldPeek, alertAgain);
         updateNotifications();
 
@@ -6827,44 +6667,9 @@
             boolean isForCurrentUser = isNotificationForCurrentProfiles(notification);
             Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you");
         }
-
         setAreThereNotifications();
     }
 
-    private void updateNotificationViews(Entry entry, StatusBarNotification sbn) {
-        final RemoteViews contentView = entry.cachedContentView;
-        final RemoteViews bigContentView = entry.cachedBigContentView;
-        final RemoteViews headsUpContentView = entry.cachedHeadsUpContentView;
-        final RemoteViews publicContentView = entry.cachedPublicContentView;
-        final RemoteViews ambientContentView = entry.cachedAmbientContentView;
-
-        // Reapply the RemoteViews
-        contentView.reapply(mContext, entry.getContentView(), mOnClickHandler);
-        if (bigContentView != null && entry.getExpandedContentView() != null) {
-            bigContentView.reapply(sbn.getPackageContext(mContext),
-                    entry.getExpandedContentView(),
-                    mOnClickHandler);
-        }
-        View headsUpChild = entry.getHeadsUpContentView();
-        if (headsUpContentView != null && headsUpChild != null) {
-            headsUpContentView.reapply(sbn.getPackageContext(mContext),
-                    headsUpChild, mOnClickHandler);
-        }
-        if (publicContentView != null && entry.getPublicContentView() != null) {
-            publicContentView.reapply(sbn.getPackageContext(mContext),
-                    entry.getPublicContentView(), mOnClickHandler);
-        }
-        if (ambientContentView != null && entry.getAmbientContentView() != null) {
-            ambientContentView.reapply(sbn.getPackageContext(mContext),
-                    entry.getAmbientContentView(), mOnClickHandler);
-        }
-        // update the contentIntent
-        mNotificationClicker.register(entry.row, sbn);
-
-        entry.row.onNotificationUpdated(entry);
-        entry.row.resetHeight();
-    }
-
     protected void updatePublicContentView(Entry entry,
             StatusBarNotification sbn) {
         final RemoteViews publicContentView = entry.cachedPublicContentView;
@@ -6878,10 +6683,7 @@
             TextView titleView = (TextView) inflatedView.findViewById(android.R.id.title);
             if (titleView != null
                     && !titleView.getText().toString().equals(notificationHiddenText)) {
-                publicContentView.setTextViewText(android.R.id.title, notificationHiddenText);
-                publicContentView.reapply(sbn.getPackageContext(mContext),
-                        inflatedView, mOnClickHandler);
-                entry.row.onNotificationUpdated(entry);
+                titleView.setText(notificationHiddenText);
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 7c42d00..1848d4e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -34,6 +34,7 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.os.SystemClock;
 import android.util.AttributeSet;
 import android.view.ActionMode;
 import android.view.InputQueue;
@@ -65,6 +66,7 @@
     public static final boolean DEBUG = StatusBar.DEBUG;
 
     private DragDownHelper mDragDownHelper;
+    private DoubleTapHelper mDoubleTapHelper;
     private NotificationStackScrollLayout mStackScrollLayout;
     private NotificationPanelView mNotificationPanel;
     private View mBrightnessMirror;
@@ -89,6 +91,10 @@
         mTransparentSrcPaint.setColor(0);
         mTransparentSrcPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
         mFalsingManager = FalsingManager.getInstance(context);
+        mDoubleTapHelper = new DoubleTapHelper(this, active -> {}, () -> {
+            mService.wakeUpIfDozing(SystemClock.uptimeMillis(), this);
+            return true;
+        }, null, null);
     }
 
     @Override
@@ -256,7 +262,7 @@
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         if (mService.isDozing() && !mService.isPulsing()) {
-            // Discard all touch events in always-on.
+            // Capture all touch events in always-on.
             return true;
         }
         boolean intercept = false;
@@ -282,7 +288,11 @@
 
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
-        boolean handled = mService.isDozing() && !mService.isPulsing();
+        boolean handled = false;
+        if (mService.isDozing()) {
+            mDoubleTapHelper.onTouchEvent(ev);
+            handled = true;
+        }
         if (mService.getBarState() == StatusBarState.KEYGUARD
                 && (!handled || mDragDownHelper.isDraggingDown())) {
             // we still want to finish our drag down gesture when locking the screen
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
index bb0748c..f0af77d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
@@ -81,6 +81,7 @@
     private static final int AM_PM_STYLE_GONE    = 2;
 
     private final int mAmPmStyle;
+    private final boolean mShowDark;
     private boolean mShowSeconds;
     private Handler mSecondsHandler;
 
@@ -100,6 +101,7 @@
                 0, 0);
         try {
             mAmPmStyle = a.getInt(R.styleable.Clock_amPmStyle, AM_PM_STYLE_GONE);
+            mShowDark = a.getBoolean(R.styleable.Clock_showDark, true);
         } finally {
             a.recycle();
         }
@@ -124,7 +126,9 @@
             Dependency.get(TunerService.class).addTunable(this, CLOCK_SECONDS,
                     StatusBarIconController.ICON_BLACKLIST);
             SysUiServiceProvider.getComponent(getContext(), CommandQueue.class).addCallbacks(this);
-            Dependency.get(DarkIconDispatcher.class).addDarkReceiver(this);
+            if (mShowDark) {
+                Dependency.get(DarkIconDispatcher.class).addDarkReceiver(this);
+            }
         }
 
         // NOTE: It's safe to do these after registering the receiver since the receiver always runs
@@ -147,7 +151,9 @@
             Dependency.get(TunerService.class).removeTunable(this);
             SysUiServiceProvider.getComponent(getContext(), CommandQueue.class)
                     .removeCallbacks(this);
-            Dependency.get(DarkIconDispatcher.class).removeDarkReceiver(this);
+            if (mShowDark) {
+                Dependency.get(DarkIconDispatcher.class).removeDarkReceiver(this);
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedController.java
index aa4eaa7..21f9a79 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedController.java
@@ -26,7 +26,9 @@
 
     interface DeviceProvisionedListener {
         default void onDeviceProvisionedChanged() { }
-        default void onUserSwitched() { }
+        default void onUserSwitched() {
+            onUserSetupChanged();
+        }
         default void onUserSetupChanged() { }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
index 528fefe..cfaca0d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
@@ -66,6 +66,8 @@
         if (mListeners.size() == 1) {
             startListening(getCurrentUser());
         }
+        listener.onUserSetupChanged();
+        listener.onDeviceProvisionedChanged();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionController.java
new file mode 100644
index 0000000..eaf8925
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionController.java
@@ -0,0 +1,56 @@
+/*
+ * 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 com.android.systemui.Dependency;
+import com.android.systemui.plugins.Plugin;
+
+import java.util.Map;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+/**
+ * Utility class used to select between a plugin, tuner settings, and a default implementation
+ * of an interface.
+ */
+public interface ExtensionController {
+
+    <T> ExtensionBuilder<T> newExtension(Class<T> cls);
+
+    interface Extension<T> {
+        T get();
+        void destroy();
+    }
+
+    interface ExtensionBuilder<T> {
+        ExtensionBuilder<T> withTunerFactory(TunerFactory<T> factory);
+        <P extends T> ExtensionBuilder<T> withPlugin(Class<P> cls);
+        <P extends T> ExtensionBuilder<T> withPlugin(Class<P> cls, String action);
+        <P> ExtensionBuilder<T> withPlugin(Class<P> cls, String action,
+                PluginConverter<T, P> converter);
+        ExtensionBuilder<T> withDefault(Supplier<T> def);
+        ExtensionBuilder<T> withCallback(Consumer<T> callback);
+        Extension build();
+    }
+
+    public interface PluginConverter<T, P> {
+        T getInterfaceFromPlugin(P plugin);
+    }
+
+    public interface TunerFactory<T> {
+        String[] keys();
+        T create(Map<String, String> settings);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java
new file mode 100644
index 0000000..fefbaa3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java
@@ -0,0 +1,236 @@
+/*
+ * 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 com.android.systemui.Dependency;
+import com.android.systemui.plugins.Plugin;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.tuner.TunerService;
+import com.android.systemui.tuner.TunerService.Tunable;
+
+import android.content.Context;
+import android.util.ArrayMap;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+public class ExtensionControllerImpl implements ExtensionController {
+
+    @Override
+    public <T> ExtensionBuilder<T> newExtension(Class<T> cls) {
+        return new ExtensionBuilder<>();
+    }
+
+    private interface Producer<T> {
+        T get();
+        void destroy();
+    }
+
+    private class ExtensionBuilder<T> implements ExtensionController.ExtensionBuilder<T> {
+
+        private ExtensionImpl<T> mExtension = new ExtensionImpl<>();
+
+        @Override
+        public ExtensionController.ExtensionBuilder<T> withTunerFactory(TunerFactory<T> factory) {
+            mExtension.addTunerFactory(factory, factory.keys());
+            return this;
+        }
+
+        @Override
+        public <P extends T> ExtensionController.ExtensionBuilder<T> withPlugin(Class<P> cls) {
+            return withPlugin(cls, PluginManager.getAction(cls));
+        }
+
+        @Override
+        public <P extends T> ExtensionController.ExtensionBuilder<T> withPlugin(Class<P> cls,
+                String action) {
+            return withPlugin(cls, action, null);
+        }
+
+        @Override
+        public <P> ExtensionController.ExtensionBuilder<T> withPlugin(Class<P> cls,
+                String action, PluginConverter<T, P> converter) {
+            mExtension.addPlugin(action, cls, converter);
+            return this;
+        }
+
+        @Override
+        public ExtensionController.ExtensionBuilder<T> withDefault(Supplier<T> def) {
+            mExtension.addDefault(def);
+            return this;
+        }
+
+        @Override
+        public ExtensionController.ExtensionBuilder<T> withCallback(
+                Consumer<T> callback) {
+            mExtension.mCallbacks.add(callback);
+            return this;
+        }
+
+        @Override
+        public ExtensionController.Extension build() {
+            // Manually sort, plugins first, tuners second, defaults last.
+            Collections.sort(mExtension.mProducers, (o1, o2) -> {
+                if (o1 instanceof ExtensionImpl.PluginItem) {
+                    if (o2 instanceof ExtensionImpl.PluginItem) {
+                        return 0;
+                    } else {
+                        return -1;
+                    }
+                }
+                if (o1 instanceof ExtensionImpl.TunerItem) {
+                    if (o2 instanceof ExtensionImpl.PluginItem) {
+                        return 1;
+                    } else if (o2 instanceof ExtensionImpl.TunerItem) {
+                        return 0;
+                    } else {
+                        return -1;
+                    }
+                }
+                return 0;
+            });
+            mExtension.notifyChanged();
+            return mExtension;
+        }
+    }
+
+    private class ExtensionImpl<T> implements ExtensionController.Extension<T> {
+        private final ArrayList<Producer<T>> mProducers = new ArrayList<>();
+        private final ArrayList<Consumer<T>> mCallbacks = new ArrayList<>();
+        private T mItem;
+
+        @Override
+        public T get() {
+            return mItem;
+        }
+
+        @Override
+        public void destroy() {
+            for (int i = 0; i < mProducers.size(); i++) {
+                mProducers.get(i).destroy();
+            }
+        }
+
+        private void notifyChanged() {
+            for (int i = 0; i < mProducers.size(); i++) {
+                final T item = mProducers.get(i).get();
+                if (item != null) {
+                    mItem = item;
+                    break;
+                }
+            }
+            for (int i = 0; i < mCallbacks.size(); i++) {
+                mCallbacks.get(i).accept(mItem);
+            }
+        }
+
+        public void addDefault(Supplier<T> def) {
+            mProducers.add(new Default(def));
+        }
+
+        public <P> void addPlugin(String action, Class<P> cls, PluginConverter<T, P> converter) {
+            mProducers.add(new PluginItem(action, cls, converter));
+        }
+
+        public void addTunerFactory(TunerFactory<T> factory, String[] keys) {
+            mProducers.add(new TunerItem(factory, factory.keys()));
+        }
+
+        private class PluginItem<P extends Plugin> implements Producer<T>, PluginListener<P> {
+            private final PluginConverter<T, P> mConverter;
+            private T mItem;
+
+            public PluginItem(String action, Class<P> cls, PluginConverter<T, P> converter) {
+                mConverter = converter;
+                Dependency.get(PluginManager.class).addPluginListener(action, this, cls);
+            }
+
+            @Override
+            public void onPluginConnected(P plugin, Context pluginContext) {
+                if (mConverter != null) {
+                    mItem = mConverter.getInterfaceFromPlugin(plugin);
+                } else {
+                    mItem = (T) plugin;
+                }
+                notifyChanged();
+            }
+
+            @Override
+            public void onPluginDisconnected(P plugin) {
+                mItem = null;
+                notifyChanged();
+            }
+
+            @Override
+            public T get() {
+                return mItem;
+            }
+
+            @Override
+            public void destroy() {
+                Dependency.get(PluginManager.class).removePluginListener(this);
+            }
+        }
+
+        private class TunerItem<T> implements Producer<T>, Tunable {
+            private final TunerFactory<T> mFactory;
+            private final ArrayMap<String, String> mSettings = new ArrayMap<>();
+            private T mItem;
+
+            public TunerItem(TunerFactory<T> factory, String... setting) {
+                mFactory = factory;
+                Dependency.get(TunerService.class).addTunable(this, setting);
+            }
+
+            @Override
+            public T get() {
+                return mItem;
+            }
+
+            @Override
+            public void destroy() {
+                Dependency.get(TunerService.class).removeTunable(this);
+            }
+
+            @Override
+            public void onTuningChanged(String key, String newValue) {
+                mSettings.put(key, newValue);
+                mItem = mFactory.create(mSettings);
+                notifyChanged();
+            }
+        }
+
+        private class Default<T> implements Producer<T> {
+            private final Supplier<T> mSupplier;
+
+            public Default(Supplier<T> supplier) {
+                mSupplier = supplier;
+            }
+
+            @Override
+            public T get() {
+                return mSupplier.get();
+            }
+
+            @Override
+            public void destroy() {
+
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
index 821e635..a87b50a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
@@ -116,19 +116,20 @@
     }
 
     private void notifyKeyguardChanged() {
-        mCallbacks.forEach(Callback::onKeyguardShowingChanged);
+        // Copy the list to allow removal during callback.
+        new ArrayList<Callback>(mCallbacks).forEach(Callback::onKeyguardShowingChanged);
     }
 
     public void notifyKeyguardFadingAway(long delay, long fadeoutDuration) {
         mKeyguardFadingAway = true;
         mKeyguardFadingAwayDelay = delay;
         mKeyguardFadingAwayDuration = fadeoutDuration;
-        mCallbacks.forEach(Callback::onKeyguardShowingChanged);
+        notifyKeyguardChanged();
     }
 
     public void notifyKeyguardDoneFading() {
         mKeyguardFadingAway = false;
-        mCallbacks.forEach(Callback::onKeyguardShowingChanged);
+        notifyKeyguardChanged();
     }
 
     @Override
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 03c46e8..91acf04 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -17,8 +17,11 @@
 
 import android.content.Context;
 import android.content.Intent;
+import android.database.ContentObserver;
 import android.net.NetworkCapabilities;
+import android.os.Handler;
 import android.os.Looper;
+import android.provider.Settings.Global;
 import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
@@ -49,6 +52,7 @@
     private final SubscriptionDefaults mDefaults;
     private final String mNetworkNameDefault;
     private final String mNetworkNameSeparator;
+    private final ContentObserver mObserver;
     @VisibleForTesting
     final PhoneStateListener mPhoneStateListener;
     // Save entire info for logging, we only use the id.
@@ -97,6 +101,12 @@
         mLastState.iconGroup = mCurrentState.iconGroup = mDefaultIcons;
         // Get initial data sim state.
         updateDataSim();
+        mObserver = new ContentObserver(new Handler(receiverLooper)) {
+            @Override
+            public void onChange(boolean selfChange) {
+                updateTelephony();
+            }
+        };
     }
 
     public void setConfiguration(Config config) {
@@ -144,6 +154,11 @@
                         | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
                         | PhoneStateListener.LISTEN_DATA_ACTIVITY
                         | PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE);
+        mContext.getContentResolver().registerContentObserver(Global.getUriFor(Global.MOBILE_DATA),
+                true, mObserver);
+        mContext.getContentResolver().registerContentObserver(Global.getUriFor(
+                Global.MOBILE_DATA + mSubscriptionInfo.getSubscriptionId()),
+                true, mObserver);
     }
 
     /**
@@ -151,6 +166,7 @@
      */
     public void unregisterListener() {
         mPhone.listen(mPhoneStateListener, 0);
+        mContext.getContentResolver().unregisterContentObserver(mObserver);
     }
 
     /**
@@ -242,11 +258,11 @@
             description = mCurrentState.isEmergency ? null : mCurrentState.networkName;
         }
         boolean activityIn = mCurrentState.dataConnected
-                        && !mCurrentState.carrierNetworkChangeMode
-                        && mCurrentState.activityIn;
+                && !mCurrentState.carrierNetworkChangeMode
+                && mCurrentState.activityIn;
         boolean activityOut = mCurrentState.dataConnected
-                        && !mCurrentState.carrierNetworkChangeMode
-                        && mCurrentState.activityOut;
+                && !mCurrentState.carrierNetworkChangeMode
+                && mCurrentState.activityOut;
         showDataIcon &= mCurrentState.isDefault || dataDisabled;
         int typeIcon = showDataIcon ? icons.mDataType : 0;
         callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
@@ -294,7 +310,7 @@
             final int iconMode = mServiceState.getCdmaEriIconMode();
             return mServiceState.getCdmaEriIconIndex() != EriInfo.ROAMING_INDICATOR_OFF
                     && (iconMode == EriInfo.ROAMING_ICON_MODE_NORMAL
-                        || iconMode == EriInfo.ROAMING_ICON_MODE_FLASH);
+                    || iconMode == EriInfo.ROAMING_ICON_MODE_FLASH);
         } else {
             return mServiceState != null && mServiceState.getRoaming();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index eb47a3c..5657560 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -43,7 +43,6 @@
 
     void addEmergencyListener(EmergencyListener listener);
     void removeEmergencyListener(EmergencyListener listener);
-    void setUserSetupComplete(boolean userSetup);
     boolean hasEmergencyCryptKeeperText();
     boolean isRadioOn();
 
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 d7c919d..bc3eec9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -39,6 +39,7 @@
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.MathUtils;
+import android.util.SparseArray;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.PhoneConstants;
@@ -78,6 +79,7 @@
     private static final int EMERGENCY_FIRST_CONTROLLER = 100;
     private static final int EMERGENCY_VOICE_CONTROLLER = 200;
     private static final int EMERGENCY_NO_SUB = 300;
+    private static final int EMERGENCY_ASSUMED_VOICE_CONTROLLER = 400;
 
     private final Context mContext;
     private final TelephonyManager mPhone;
@@ -99,8 +101,7 @@
     final EthernetSignalController mEthernetSignalController;
 
     @VisibleForTesting
-    final Map<Integer, MobileSignalController> mMobileSignalControllers =
-            new HashMap<Integer, MobileSignalController>();
+    final SparseArray<MobileSignalController> mMobileSignalControllers = new SparseArray<>();
     // When no SIMs are around at setup, and one is added later, it seems to default to the first
     // SIM for most actions.  This may be null if there aren't any SIMs around.
     private MobileSignalController mDefaultSignalController;
@@ -232,7 +233,8 @@
     }
 
     private void registerListeners() {
-        for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
+        for (int i = 0; i < mMobileSignalControllers.size(); i++) {
+            MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
             mobileSignalController.registerListener();
         }
         if (mSubscriptionListener == null) {
@@ -261,7 +263,8 @@
 
     private void unregisterListeners() {
         mListening = false;
-        for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
+        for (int i = 0; i < mMobileSignalControllers.size(); i++) {
+            MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
             mobileSignalController.unregisterListener();
         }
         mSubscriptionManager.removeOnSubscriptionsChangedListener(mSubscriptionListener);
@@ -305,7 +308,7 @@
             if (DEBUG) Log.e(TAG, "No data sim selected");
             return mDefaultSignalController;
         }
-        if (mMobileSignalControllers.containsKey(dataSubId)) {
+        if (mMobileSignalControllers.indexOfKey(dataSubId) >= 0) {
             return mMobileSignalControllers.get(dataSubId);
         }
         if (DEBUG) Log.e(TAG, "Cannot find controller for data sub: " + dataSubId);
@@ -326,8 +329,8 @@
         }
         int voiceSubId = mSubDefaults.getDefaultVoiceSubId();
         if (!SubscriptionManager.isValidSubscriptionId(voiceSubId)) {
-            for (MobileSignalController mobileSignalController :
-                                            mMobileSignalControllers.values()) {
+            for (int i = 0; i < mMobileSignalControllers.size(); i++) {
+                MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
                 if (!mobileSignalController.getState().isEmergency) {
                     mEmergencySource = EMERGENCY_FIRST_CONTROLLER
                             + mobileSignalController.mSubscriptionInfo.getSubscriptionId();
@@ -336,11 +339,20 @@
                 }
             }
         }
-        if (mMobileSignalControllers.containsKey(voiceSubId)) {
+        if (mMobileSignalControllers.indexOfKey(voiceSubId) >= 0) {
             mEmergencySource = EMERGENCY_VOICE_CONTROLLER + voiceSubId;
             if (DEBUG) Log.d(TAG, "Getting emergency from " + voiceSubId);
             return mMobileSignalControllers.get(voiceSubId).getState().isEmergency;
         }
+        // If we have the wrong subId but there is only one sim anyway, assume it should be the
+        // default.
+        if (mMobileSignalControllers.size() == 1) {
+            mEmergencySource = EMERGENCY_ASSUMED_VOICE_CONTROLLER
+                    + mMobileSignalControllers.keyAt(0);
+            if (DEBUG) Log.d(TAG, "Getting assumed emergency from "
+                    + mMobileSignalControllers.keyAt(0));
+            return mMobileSignalControllers.valueAt(0).getState().isEmergency;
+        }
         if (DEBUG) Log.e(TAG, "Cannot find controller for voice sub: " + voiceSubId);
         mEmergencySource = EMERGENCY_NO_SUB + voiceSubId;
         // Something is wrong, better assume we can't make calls...
@@ -363,7 +375,8 @@
         cb.setNoSims(mHasNoSims);
         mWifiSignalController.notifyListeners(cb);
         mEthernetSignalController.notifyListeners(cb);
-        for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
+        for (int i = 0; i < mMobileSignalControllers.size(); i++) {
+            MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
             mobileSignalController.notifyListeners(cb);
         }
         mCallbackHandler.setListening(cb, true);
@@ -416,7 +429,8 @@
         } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) {
             // Notify every MobileSignalController so they can know whether they are the
             // data sim or not.
-            for (MobileSignalController controller : mMobileSignalControllers.values()) {
+            for (int i = 0; i < mMobileSignalControllers.size(); i++) {
+                MobileSignalController controller = mMobileSignalControllers.valueAt(i);
                 controller.handleBroadcast(intent);
             }
         } else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
@@ -433,7 +447,7 @@
             int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
                     SubscriptionManager.INVALID_SUBSCRIPTION_ID);
             if (SubscriptionManager.isValidSubscriptionId(subId)) {
-                if (mMobileSignalControllers.containsKey(subId)) {
+                if (mMobileSignalControllers.indexOfKey(subId) >= 0) {
                     mMobileSignalControllers.get(subId).handleBroadcast(intent);
                 } else {
                     // Can't find this subscription...  We must be out of date.
@@ -458,8 +472,9 @@
 
     @VisibleForTesting
     void handleConfigurationChanged() {
-        for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
-            mobileSignalController.setConfiguration(mConfig);
+        for (int i = 0; i < mMobileSignalControllers.size(); i++) {
+            MobileSignalController controller = mMobileSignalControllers.valueAt(i);
+            controller.setConfiguration(mConfig);
         }
         refreshLocale();
     }
@@ -511,15 +526,20 @@
         });
         mCurrentSubscriptions = subscriptions;
 
-        HashMap<Integer, MobileSignalController> cachedControllers =
-                new HashMap<Integer, MobileSignalController>(mMobileSignalControllers);
+        SparseArray<MobileSignalController> cachedControllers =
+                new SparseArray<MobileSignalController>();
+        for (int i = 0; i < mMobileSignalControllers.size(); i++) {
+            cachedControllers.put(mMobileSignalControllers.keyAt(i),
+                    mMobileSignalControllers.valueAt(i));
+        }
         mMobileSignalControllers.clear();
         final int num = subscriptions.size();
         for (int i = 0; i < num; i++) {
             int subId = subscriptions.get(i).getSubscriptionId();
             // If we have a copy of this controller already reuse it, otherwise make a new one.
-            if (cachedControllers.containsKey(subId)) {
-                mMobileSignalControllers.put(subId, cachedControllers.remove(subId));
+            if (cachedControllers.indexOfKey(subId) >= 0) {
+                mMobileSignalControllers.put(subId, cachedControllers.get(subId));
+                cachedControllers.remove(subId);
             } else {
                 MobileSignalController controller = new MobileSignalController(mContext, mConfig,
                         mHasMobileDataFeature, mPhone, mCallbackHandler,
@@ -535,7 +555,8 @@
             }
         }
         if (mListening) {
-            for (Integer key : cachedControllers.keySet()) {
+            for (int i = 0; i < cachedControllers.size(); i++) {
+                int key = cachedControllers.keyAt(i);
                 if (cachedControllers.get(key) == mDefaultSignalController) {
                     mDefaultSignalController = null;
                 }
@@ -551,19 +572,14 @@
         updateAirplaneMode(true /* force */);
     }
 
-    public void setUserSetupComplete(final boolean userSetup) {
-        mReceiverHandler.post(new Runnable() {
-            @Override
-            public void run() {
-                handleSetUserSetupComplete(userSetup);
-            }
-        });
+    private void setUserSetupComplete(final boolean userSetup) {
+        mReceiverHandler.post(() -> handleSetUserSetupComplete(userSetup));
     }
 
-    @VisibleForTesting
-    void handleSetUserSetupComplete(boolean userSetup) {
+    private void handleSetUserSetupComplete(boolean userSetup) {
         mUserSetup = userSetup;
-        for (MobileSignalController controller : mMobileSignalControllers.values()) {
+        for (int i = 0; i < mMobileSignalControllers.size(); i++) {
+            MobileSignalController controller = mMobileSignalControllers.valueAt(i);
             controller.setUserSetupComplete(mUserSetup);
         }
     }
@@ -574,7 +590,7 @@
             return false;
         }
         for (SubscriptionInfo info : allSubscriptions) {
-            if (!mMobileSignalControllers.containsKey(info.getSubscriptionId())) {
+            if (mMobileSignalControllers.indexOfKey(info.getSubscriptionId()) < 0) {
                 return false;
             }
         }
@@ -586,7 +602,8 @@
                 Settings.Global.AIRPLANE_MODE_ON, 0) == 1);
         if (airplaneMode != mAirplaneMode || force) {
             mAirplaneMode = airplaneMode;
-            for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
+            for (int i = 0; i < mMobileSignalControllers.size(); i++) {
+                MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
                 mobileSignalController.setAirplaneMode(mAirplaneMode);
             }
             notifyListeners();
@@ -607,7 +624,8 @@
      */
     private void notifyAllListeners() {
         notifyListeners();
-        for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
+        for (int i = 0; i < mMobileSignalControllers.size(); i++) {
+            MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
             mobileSignalController.notifyListeners();
         }
         mWifiSignalController.notifyListeners();
@@ -656,7 +674,8 @@
      */
     private void pushConnectivityToSignals() {
         // We want to update all the icons, all at once, for any condition change
-        for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
+        for (int i = 0; i < mMobileSignalControllers.size(); i++) {
+            MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
             mobileSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports);
         }
         mWifiSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports);
@@ -688,7 +707,8 @@
         pw.print("  mEmergencySource=");
         pw.println(emergencyToString(mEmergencySource));
 
-        for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
+        for (int i = 0; i < mMobileSignalControllers.size(); i++) {
+            MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
             mobileSignalController.dump(pw);
         }
         mWifiSignalController.dump(pw);
@@ -700,6 +720,9 @@
 
     private static final String emergencyToString(int emergencySource) {
         if (emergencySource > EMERGENCY_NO_SUB) {
+            return "ASSUMED_VOICE_CONTROLLER(" + (emergencySource - EMERGENCY_VOICE_CONTROLLER)
+                    + ")";
+        } else if (emergencySource > EMERGENCY_NO_SUB) {
             return "NO_SUB(" + (emergencySource - EMERGENCY_NO_SUB) + ")";
         } else if (emergencySource > EMERGENCY_VOICE_CONTROLLER) {
             return "VOICE_CONTROLLER(" + (emergencySource - EMERGENCY_VOICE_CONTROLLER) + ")";
@@ -723,13 +746,15 @@
             mDemoMode = true;
             mDemoInetCondition = mInetCondition;
             mDemoWifiState = mWifiSignalController.getState();
+            mDemoWifiState.ssid = "DemoMode";
         } else if (mDemoMode && command.equals(COMMAND_EXIT)) {
             if (DEBUG) Log.d(TAG, "Exiting demo mode");
             mDemoMode = false;
             // Update what MobileSignalControllers, because they may change
             // to set the number of sim slots.
             updateMobileControllers();
-            for (MobileSignalController controller : mMobileSignalControllers.values()) {
+            for (int i = 0; i < mMobileSignalControllers.size(); i++) {
+                MobileSignalController controller = mMobileSignalControllers.valueAt(i);
                 controller.resetLastState();
             }
             mWifiSignalController.resetLastState();
@@ -752,7 +777,8 @@
                     connected.set(mWifiSignalController.mTransportType);
                 }
                 mWifiSignalController.updateConnectivity(connected, connected);
-                for (MobileSignalController controller : mMobileSignalControllers.values()) {
+                for (int i = 0; i < mMobileSignalControllers.size(); i++) {
+                    MobileSignalController controller = mMobileSignalControllers.valueAt(i);
                     if (mDemoInetCondition) {
                         connected.set(controller.mTransportType);
                     }
@@ -768,6 +794,25 @@
                             : Math.min(Integer.parseInt(level), WifiIcons.WIFI_LEVEL_COUNT - 1);
                     mDemoWifiState.connected = mDemoWifiState.level >= 0;
                 }
+                String activity = args.getString("activity");
+                if (activity != null) {
+                    switch (activity) {
+                        case "inout":
+                            mWifiSignalController.setActivity(WifiManager.DATA_ACTIVITY_INOUT);
+                            break;
+                        case "in":
+                            mWifiSignalController.setActivity(WifiManager.DATA_ACTIVITY_IN);
+                            break;
+                        case "out":
+                            mWifiSignalController.setActivity(WifiManager.DATA_ACTIVITY_OUT);
+                            break;
+                        default:
+                            mWifiSignalController.setActivity(WifiManager.DATA_ACTIVITY_NONE);
+                            break;
+                    }
+                } else {
+                    mWifiSignalController.setActivity(WifiManager.DATA_ACTIVITY_NONE);
+                }
                 mDemoWifiState.enabled = show;
                 mWifiSignalController.notifyListeners();
             }
@@ -806,8 +851,7 @@
                     mCallbackHandler.setSubs(subs);
                 }
                 // Hack to index linearly for easy use.
-                MobileSignalController controller = mMobileSignalControllers
-                        .values().toArray(new MobileSignalController[0])[slot];
+                MobileSignalController controller = mMobileSignalControllers.valueAt(slot);
                 controller.getState().dataSim = datatype != null;
                 controller.getState().isDefault = datatype != null;
                 controller.getState().dataConnected = datatype != null;
@@ -837,7 +881,23 @@
                 }
                 String activity = args.getString("activity");
                 if (activity != null) {
-                    controller.setActivity(Integer.parseInt(activity));
+                    controller.getState().dataConnected = true;
+                    switch (activity) {
+                        case "inout":
+                            controller.setActivity(TelephonyManager.DATA_ACTIVITY_INOUT);
+                            break;
+                        case "in":
+                            controller.setActivity(TelephonyManager.DATA_ACTIVITY_IN);
+                            break;
+                        case "out":
+                            controller.setActivity(TelephonyManager.DATA_ACTIVITY_OUT);
+                            break;
+                        default:
+                            controller.setActivity(TelephonyManager.DATA_ACTIVITY_NONE);
+                            break;
+                    }
+                } else {
+                    controller.setActivity(TelephonyManager.DATA_ACTIVITY_NONE);
                 }
                 controller.getState().enabled = show;
                 controller.notifyListeners();
@@ -845,7 +905,8 @@
             String carrierNetworkChange = args.getString("carriernetworkchange");
             if (carrierNetworkChange != null) {
                 boolean show = carrierNetworkChange.equals("show");
-                for (MobileSignalController controller : mMobileSignalControllers.values()) {
+                for (int i = 0; i < mMobileSignalControllers.size(); i++) {
+                    MobileSignalController controller = mMobileSignalControllers.valueAt(i);
                     controller.setCarrierNetworkChangeMode(show);
                 }
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 6df4a21..53671a1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -57,9 +57,9 @@
 import com.android.systemui.R;
 import com.android.systemui.SystemUI;
 import com.android.systemui.SystemUISecondaryUserService;
-import com.android.systemui.plugins.qs.QS.DetailAdapter;
+import com.android.systemui.plugins.qs.DetailAdapter;
 import com.android.systemui.qs.tiles.UserDetailView;
-import com.android.systemui.ActivityStarter;
+import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
 import com.android.systemui.util.NotificationChannels;
 
@@ -664,6 +664,27 @@
             controller.addAdapter(new WeakReference<>(this));
         }
 
+        public int getUserCount() {
+            boolean secureKeyguardShowing = mKeyguardMonitor.isShowing()
+                    && mKeyguardMonitor.isSecure()
+                    && !mKeyguardMonitor.canSkipBouncer();
+            if (!secureKeyguardShowing) {
+                return mController.getUsers().size();
+            }
+            // The lock screen is secure and showing. Filter out restricted records.
+            final int N = mController.getUsers().size();
+            int count = 0;
+            for (int i = 0; i < N; i++) {
+                if (mController.getUsers().get(i).isGuest) continue;
+                if (mController.getUsers().get(i).isRestricted) {
+                    break;
+                } else {
+                    count++;
+                }
+            }
+            return count;
+        }
+
         @Override
         public int getCount() {
             boolean secureKeyguardShowing = mKeyguardMonitor.isShowing()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
index 886b8be..12b7098 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
@@ -15,10 +15,10 @@
  */
 package com.android.systemui.statusbar.policy;
 
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.database.ContentObserver;
+import android.net.NetworkBadging;
 import android.net.NetworkCapabilities;
 import android.net.NetworkKey;
 import android.net.NetworkScoreManager;
@@ -155,7 +155,7 @@
 
     @Override
     public int getCurrentIconId() {
-        if (mCurrentState.badgeEnum != ScoredNetwork.BADGING_NONE) {
+        if (mCurrentState.badgeEnum != NetworkBadging.BADGING_NONE) {
             return Utils.WIFI_PIE_FOR_BADGING[mCurrentState.level];
         }
         return super.getCurrentIconId();
@@ -201,14 +201,14 @@
      */
     private int getWifiBadgeEnum() {
         if (!mScoringUiEnabled || mWifiTracker.networkKey == null) {
-            return ScoredNetwork.BADGING_NONE;
+            return NetworkBadging.BADGING_NONE;
         }
         ScoredNetwork score = mScoreCache.getScoredNetwork(mWifiTracker.networkKey);
 
         if (score != null) {
             return score.calculateBadge(mWifiTracker.rssi);
         }
-        return ScoredNetwork.BADGING_NONE;
+        return NetworkBadging.BADGING_NONE;
     }
 
     @VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
index e6a3add..fe249a6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
@@ -52,6 +52,14 @@
     private static final int NUMBER_OF_CHILDREN_WHEN_COLLAPSED = 2;
     private static final int NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED = 5;
     private static final int NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED = 8;
+    private static final AnimationProperties ALPHA_FADE_IN = new AnimationProperties() {
+        private AnimationFilter mAnimationFilter = new AnimationFilter().animateAlpha();
+
+        @Override
+        public AnimationFilter getAnimationFilter() {
+            return mAnimationFilter;
+        }
+    }.setDuration(200);
 
     private final List<View> mDividers = new ArrayList<>();
     private final List<ExpandableNotificationRow> mChildren = new ArrayList<>();
@@ -64,7 +72,7 @@
     private float mCollapsedBottompadding;
     private ViewInvertHelper mOverflowInvertHelper;
     private boolean mChildrenExpanded;
-    private ExpandableNotificationRow mNotificationParent;
+    private ExpandableNotificationRow mContainingNotification;
     private TextView mOverflowNumber;
     private ViewState mGroupOverFlowState;
     private int mRealHeight;
@@ -75,10 +83,14 @@
 
     private NotificationHeaderView mNotificationHeader;
     private NotificationViewWrapper mNotificationHeaderWrapper;
+    private NotificationHeaderView mNotificationHeaderLowPriority;
+    private NotificationViewWrapper mNotificationHeaderWrapperLowPriority;
     private NotificationHeaderUtil mHeaderUtil;
     private ViewState mHeaderViewState;
     private int mClipBottomAmount;
     private boolean mIsLowPriority;
+    private OnClickListener mHeaderClickListener;
+    private boolean mShowingNormalHeader;
 
     public NotificationChildrenContainer(Context context) {
         this(context, null);
@@ -135,6 +147,11 @@
             mNotificationHeader.layout(0, 0, mNotificationHeader.getMeasuredWidth(),
                     mNotificationHeader.getMeasuredHeight());
         }
+        if (mNotificationHeaderLowPriority != null) {
+            mNotificationHeaderLowPriority.layout(0, 0,
+                    mNotificationHeaderLowPriority.getMeasuredWidth(),
+                    mNotificationHeaderLowPriority.getMeasuredHeight());
+        }
     }
 
     @Override
@@ -178,10 +195,14 @@
             height = Math.min(height, size);
         }
 
+        int headerHeightSpec = MeasureSpec.makeMeasureSpec(mHeaderHeight, MeasureSpec.EXACTLY);
         if (mNotificationHeader != null) {
-            int headerHeightSpec = MeasureSpec.makeMeasureSpec(mHeaderHeight, MeasureSpec.EXACTLY);
             mNotificationHeader.measure(widthMeasureSpec, headerHeightSpec);
         }
+        if (mNotificationHeaderLowPriority != null) {
+            headerHeightSpec = MeasureSpec.makeMeasureSpec(mHeaderHeight, MeasureSpec.EXACTLY);
+            mNotificationHeaderLowPriority.measure(widthMeasureSpec, headerHeightSpec);
+        }
 
         setMeasuredDimension(width, height);
     }
@@ -247,30 +268,67 @@
         return mChildren.size();
     }
 
-    public void recreateNotificationHeader(OnClickListener listener,
-            StatusBarNotification notification) {
+    public void recreateNotificationHeader(OnClickListener listener) {
+        mHeaderClickListener = listener;
+        StatusBarNotification notification = mContainingNotification.getStatusBarNotification();
         final Notification.Builder builder = Notification.Builder.recoverBuilder(getContext(),
-                mNotificationParent.getStatusBarNotification().getNotification());
-        final RemoteViews header = mIsLowPriority
-                ? builder.makeLowPriorityContentView(true /* useRegularSubtext */)
-                : builder.makeNotificationHeader();
+                notification.getNotification());
+        RemoteViews header = builder.makeNotificationHeader();
         if (mNotificationHeader == null) {
             mNotificationHeader = (NotificationHeaderView) header.apply(getContext(), this);
             final View expandButton = mNotificationHeader.findViewById(
                     com.android.internal.R.id.expand_button);
             expandButton.setVisibility(VISIBLE);
-            mNotificationHeader.setOnClickListener(listener);
+            mNotificationHeader.setOnClickListener(mHeaderClickListener);
             mNotificationHeaderWrapper = NotificationViewWrapper.wrap(getContext(),
-                    mNotificationHeader, mNotificationParent);
+                    mNotificationHeader, mContainingNotification);
             addView(mNotificationHeader, 0);
             invalidate();
         } else {
             header.reapply(getContext(), mNotificationHeader);
-            mNotificationHeaderWrapper.notifyContentUpdated(notification, mIsLowPriority);
         }
+        mNotificationHeaderWrapper.notifyContentUpdated(mContainingNotification);
+        recreateLowPriorityHeader(builder);
+        updateHeaderVisibility(false /* animate */);
         updateChildrenHeaderAppearance();
     }
 
+    /**
+     * Recreate the low-priority header.
+     *
+     * @param builder a builder to reuse. Otherwise the builder will be recovered.
+     */
+    private void recreateLowPriorityHeader(Notification.Builder builder) {
+        RemoteViews header;
+        StatusBarNotification notification = mContainingNotification.getStatusBarNotification();
+        if (mIsLowPriority) {
+            if (builder == null) {
+                builder = Notification.Builder.recoverBuilder(getContext(),
+                        notification.getNotification());
+            }
+            header = builder.makeLowPriorityContentView(true /* useRegularSubtext */);
+            if (mNotificationHeaderLowPriority == null) {
+                mNotificationHeaderLowPriority = (NotificationHeaderView) header.apply(getContext(),
+                        this);
+                final View expandButton = mNotificationHeaderLowPriority.findViewById(
+                        com.android.internal.R.id.expand_button);
+                expandButton.setVisibility(VISIBLE);
+                mNotificationHeaderLowPriority.setOnClickListener(mHeaderClickListener);
+                mNotificationHeaderWrapperLowPriority = NotificationViewWrapper.wrap(getContext(),
+                        mNotificationHeaderLowPriority, mContainingNotification);
+                addView(mNotificationHeaderLowPriority, 0);
+                invalidate();
+            } else {
+                header.reapply(getContext(), mNotificationHeaderLowPriority);
+            }
+            mNotificationHeaderWrapperLowPriority.notifyContentUpdated(mContainingNotification);
+        } else {
+            removeView(mNotificationHeaderLowPriority);
+            mNotificationHeaderLowPriority = null;
+            mNotificationHeaderWrapperLowPriority = null;
+        }
+    }
+
     public void updateChildrenHeaderAppearance() {
         mHeaderUtil.updateChildrenHeaderAppearance();
     }
@@ -371,9 +429,6 @@
      * @return the intrinsic size of this children container, i.e the natural fully expanded state
      */
     public int getIntrinsicHeight() {
-        if (mIsLowPriority && !mChildrenExpanded) {
-            return mNotificationHeader.getHeight();
-        }
         int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren();
         return getIntrinsicHeight(maxAllowedVisibleChildren);
     }
@@ -383,6 +438,9 @@
      *         in @param maxAllowedVisibleChildren
      */
     private int getIntrinsicHeight(float maxAllowedVisibleChildren) {
+        if (showingAsLowPriority()) {
+            return mNotificationHeaderLowPriority.getHeight();
+        }
         int intrinsicHeight = mNotificationHeaderMargin;
         int visibleChildren = 0;
         int childCount = mChildren.size();
@@ -442,24 +500,25 @@
         int lastVisibleIndex = maxAllowedVisibleChildren - 1;
         int firstOverflowIndex = lastVisibleIndex + 1;
         float expandFactor = 0;
+        boolean expandingToExpandedGroup = mUserLocked && !showingAsLowPriority();
         if (mUserLocked) {
             expandFactor = getGroupExpandFraction();
             firstOverflowIndex = getMaxAllowedVisibleChildren(true /* likeCollapsed */);
         }
 
-        boolean childrenExpanded = !mNotificationParent.isGroupExpansionChanging()
+        boolean childrenExpanded = !mContainingNotification.isGroupExpansionChanging()
                 && mChildrenExpanded;
         for (int i = 0; i < childCount; i++) {
             ExpandableNotificationRow child = mChildren.get(i);
             if (!firstChild) {
-                if (mUserLocked) {
+                if (expandingToExpandedGroup) {
                     yPosition += NotificationUtils.interpolate(mChildPadding, mDividerHeight,
                             expandFactor);
                 } else {
                     yPosition += mChildrenExpanded ? mDividerHeight : mChildPadding;
                 }
             } else {
-                if (mUserLocked) {
+                if (expandingToExpandedGroup) {
                     yPosition += NotificationUtils.interpolate(
                             0,
                             mNotificatonTopPadding + mDividerHeight,
@@ -478,7 +537,7 @@
             // When the group is expanded, the children cast the shadows rather than the parent
             // so use the parent's elevation here.
             childState.zTranslation = childrenExpanded
-                    ? mNotificationParent.getTranslationZ()
+                    ? mContainingNotification.getTranslationZ()
                     : 0;
             childState.dimmed = parentState.dimmed;
             childState.dark = parentState.dark;
@@ -487,7 +546,7 @@
             childState.clipTopAmount = 0;
             childState.alpha = 0;
             if (i < firstOverflowIndex) {
-                childState.alpha = mIsLowPriority && !mChildrenExpanded ? expandFactor : 1.0f;
+                childState.alpha = showingAsLowPriority() ? expandFactor : 1.0f;
             } else if (expandFactor == 1.0f && i <= lastVisibleIndex) {
                 childState.alpha = (mActualHeight - childState.yTranslation) / childState.height;
                 childState.alpha = Math.max(0.0f, Math.min(1.0f, childState.alpha));
@@ -526,7 +585,7 @@
             }
             mHeaderViewState.initFrom(mNotificationHeader);
             mHeaderViewState.zTranslation = childrenExpanded
-                    ? mNotificationParent.getTranslationZ()
+                    ? mContainingNotification.getTranslationZ()
                     : 0;
         }
     }
@@ -561,11 +620,11 @@
     }
 
     private int getMaxAllowedVisibleChildren(boolean likeCollapsed) {
-        if (!likeCollapsed && (mChildrenExpanded || mNotificationParent.isUserLocked())) {
+        if (!likeCollapsed && (mChildrenExpanded || mContainingNotification.isUserLocked())) {
             return NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED;
         }
-        if (!mNotificationParent.isOnKeyguard()
-                && (mNotificationParent.isExpanded() || mNotificationParent.isHeadsUp())) {
+        if (mIsLowPriority || !mContainingNotification.isOnKeyguard()
+                && (mContainingNotification.isExpanded() || mContainingNotification.isHeadsUp())) {
             return NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED;
         }
         return NUMBER_OF_CHILDREN_WHEN_COLLAPSED;
@@ -578,8 +637,8 @@
         if (mUserLocked) {
             expandFraction = getGroupExpandFraction();
         }
-        final boolean dividersVisible = mUserLocked
-                || mNotificationParent.isGroupExpansionChanging();
+        final boolean dividersVisible = mUserLocked && !showingAsLowPriority()
+                || mContainingNotification.isGroupExpansionChanging();
         for (int i = 0; i < childCount; i++) {
             ExpandableNotificationRow child = mChildren.get(i);
             ExpandableViewState viewState = state.getViewStateForView(child);
@@ -590,7 +649,7 @@
             tmpState.initFrom(divider);
             tmpState.yTranslation = viewState.yTranslation - mDividerHeight;
             float alpha = mChildrenExpanded && viewState.alpha != 0 ? 0.5f : 0;
-            if (mUserLocked && viewState.alpha != 0) {
+            if (mUserLocked && !showingAsLowPriority() && viewState.alpha != 0) {
                 alpha = NotificationUtils.interpolate(0, 0.5f,
                         Math.min(viewState.alpha, expandFraction));
             }
@@ -612,7 +671,7 @@
 
     private void updateChildrenClipping() {
         int childCount = mChildren.size();
-        int layoutEnd = mNotificationParent.getActualHeight() - mClipBottomAmount;
+        int layoutEnd = mContainingNotification.getActualHeight() - mClipBottomAmount;
         for (int i = 0; i < childCount; i++) {
             ExpandableNotificationRow child = mChildren.get(i);
             if (child.getVisibility() == GONE) {
@@ -652,8 +711,8 @@
         int childCount = mChildren.size();
         ViewState tmpState = new ViewState();
         float expandFraction = getGroupExpandFraction();
-        final boolean dividersVisible = mUserLocked
-                || mNotificationParent.isGroupExpansionChanging();
+        final boolean dividersVisible = mUserLocked && !showingAsLowPriority()
+                || mContainingNotification.isGroupExpansionChanging();
         for (int i = childCount - 1; i >= 0; i--) {
             ExpandableNotificationRow child = mChildren.get(i);
             ExpandableViewState viewState = state.getViewStateForView(child);
@@ -664,7 +723,7 @@
             tmpState.initFrom(divider);
             tmpState.yTranslation = viewState.yTranslation - mDividerHeight;
             float alpha = mChildrenExpanded && viewState.alpha != 0 ? 0.5f : 0;
-            if (mUserLocked && viewState.alpha != 0) {
+            if (mUserLocked && !showingAsLowPriority() && viewState.alpha != 0) {
                 alpha = NotificationUtils.interpolate(0, 0.5f,
                         Math.min(viewState.alpha, expandFraction));
             }
@@ -718,23 +777,95 @@
         }
     }
 
-    public void setNotificationParent(ExpandableNotificationRow parent) {
-        mNotificationParent = parent;
-        mHeaderUtil = new NotificationHeaderUtil(mNotificationParent);
+    public void setContainingNotification(ExpandableNotificationRow parent) {
+        mContainingNotification = parent;
+        mHeaderUtil = new NotificationHeaderUtil(mContainingNotification);
     }
 
-    public ExpandableNotificationRow getNotificationParent() {
-        return mNotificationParent;
+    public ExpandableNotificationRow getContainingNotification() {
+        return mContainingNotification;
     }
 
     public NotificationHeaderView getHeaderView() {
         return mNotificationHeader;
     }
 
-    public void updateHeaderVisibility(int visiblity) {
-        if (mNotificationHeader != null) {
-            mNotificationHeader.setVisibility(visiblity);
+    public NotificationHeaderView getLowPriorityHeaderView() {
+        return mNotificationHeaderLowPriority;
+    }
+
+    private void updateHeaderVisibility(boolean animate) {
+        NotificationHeaderView visibleHeader = mNotificationHeader;
+        NotificationHeaderView hiddenHeader = mNotificationHeaderLowPriority;
+        boolean normalHeaderVisible = true;
+        if (showingAsLowPriority()) {
+            visibleHeader = mNotificationHeaderLowPriority;
+            hiddenHeader = mNotificationHeader;
+            normalHeaderVisible = false;
         }
+        if (animate) {
+            if (visibleHeader != null && hiddenHeader != null
+                    && mShowingNormalHeader != normalHeaderVisible) {
+                hiddenHeader.setVisibility(VISIBLE);
+                visibleHeader.setVisibility(VISIBLE);
+                NotificationViewWrapper visibleWrapper = getWrapperForView(visibleHeader);
+                NotificationViewWrapper hiddenWrapper = getWrapperForView(hiddenHeader);
+                visibleWrapper.transformFrom(hiddenWrapper);
+                hiddenWrapper.transformTo(visibleWrapper, () -> updateHeaderVisibility(false));
+                startChildAlphaAnimations(normalHeaderVisible);
+            } else {
+                animate = false;
+            }
+        }
+        if (!animate) {
+            if (visibleHeader != null) {
+                getWrapperForView(visibleHeader).setVisible(true);
+                visibleHeader.setVisibility(VISIBLE);
+            }
+            if (hiddenHeader != null) {
+                getWrapperForView(hiddenHeader).setVisible(false);
+                hiddenHeader.setVisibility(INVISIBLE);
+            }
+        }
+        mShowingNormalHeader = normalHeaderVisible;
+    }
+
+    private void startChildAlphaAnimations(boolean toVisible) {
+        float target = toVisible ? 1.0f : 0.0f;
+        float start = 1.0f - target;
+        int childCount = mChildren.size();
+        for (int i = 0; i < childCount; i++) {
+            if (i >= NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED) {
+                break;
+            }
+            ExpandableNotificationRow child = mChildren.get(i);
+            child.setAlpha(start);
+            ViewState viewState = new ViewState();
+            viewState.initFrom(child);
+            viewState.alpha = target;
+            ALPHA_FADE_IN.setDelay(i * 50);
+            viewState.animateTo(child, ALPHA_FADE_IN);
+        }
+    }
+
+
+    private void updateHeaderTransformation() {
+        if (mUserLocked && showingAsLowPriority()) {
+            float fraction = getGroupExpandFraction();
+            mNotificationHeaderWrapper.transformFrom(mNotificationHeaderWrapperLowPriority,
+                    fraction);
+            mNotificationHeader.setVisibility(VISIBLE);
+            mNotificationHeaderWrapperLowPriority.transformTo(mNotificationHeaderWrapper,
+                    fraction);
+        }
+
+    }
+
+    private NotificationViewWrapper getWrapperForView(NotificationHeaderView visibleHeader) {
+        if (visibleHeader == mNotificationHeader) {
+            return mNotificationHeaderWrapper;
+        }
+        return mNotificationHeaderWrapperLowPriority;
     }
 
     /**
@@ -746,7 +877,7 @@
         if (mNotificationHeader != null) {
             if (expanded) {
                 ColorDrawable cd = new ColorDrawable();
-                cd.setColor(mNotificationParent.calculateBgColor());
+                cd.setColor(mContainingNotification.calculateBgColor());
                 mNotificationHeader.setHeaderBackgroundDrawable(cd);
             } else {
                 mNotificationHeader.setHeaderBackgroundDrawable(null);
@@ -755,6 +886,10 @@
     }
 
     public int getMaxContentHeight() {
+        if (showingAsLowPriority()) {
+            return getMinHeight(NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED, true
+                    /* likeHighPriority */);
+        }
         int maxContentHeight = mNotificationHeaderMargin + mNotificatonTopPadding;
         int visibleChildren = 0;
         int childCount = mChildren.size();
@@ -781,13 +916,21 @@
         }
         mActualHeight = actualHeight;
         float fraction = getGroupExpandFraction();
+        boolean showingLowPriority = showingAsLowPriority();
+        updateHeaderTransformation();
         int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* forceCollapsed */);
         int childCount = mChildren.size();
         for (int i = 0; i < childCount; i++) {
             ExpandableNotificationRow child = mChildren.get(i);
-            float childHeight = child.isExpanded(true /* allowOnKeyguard */)
-                    ? child.getMaxExpandHeight()
-                    : child.getShowingLayout().getMinHeight(true /* likeGroupExpanded */);
+            float childHeight;
+            if (showingLowPriority) {
+                childHeight = child.getShowingLayout().getMinHeight(false /* likeGroupExpanded */);
+            } else if (child.isExpanded(true /* allowOnKeyguard */)) {
+                childHeight = child.getMaxExpandHeight();
+            } else {
+                childHeight = child.getShowingLayout().getMinHeight(
+                        true /* likeGroupExpanded */);
+            }
             if (i < maxAllowedVisibleChildren) {
                 float singleLineHeight = child.getShowingLayout().getMinHeight(
                         false /* likeGroupExpanded */);
@@ -800,7 +943,8 @@
     }
 
     public float getGroupExpandFraction() {
-        int visibleChildrenExpandedHeight = getVisibleChildrenExpandHeight();
+        int visibleChildrenExpandedHeight = showingAsLowPriority() ? getMaxContentHeight()
+                : getVisibleChildrenExpandHeight();
         int minExpandHeight = getCollapsedHeight();
         float factor = (mActualHeight - minExpandHeight)
                 / (float) (visibleChildrenExpandedHeight - minExpandHeight);
@@ -827,16 +971,23 @@
     }
 
     public int getMinHeight() {
-        return getMinHeight(NUMBER_OF_CHILDREN_WHEN_COLLAPSED);
+        return getMinHeight(NUMBER_OF_CHILDREN_WHEN_COLLAPSED, false /* likeHighPriority */);
     }
 
     public int getCollapsedHeight() {
-        return getMinHeight(getMaxAllowedVisibleChildren(true /* forceCollapsed */));
+        return getMinHeight(getMaxAllowedVisibleChildren(true /* forceCollapsed */),
+                false /* likeHighPriority */);
     }
 
-    private int getMinHeight(int maxAllowedVisibleChildren) {
-        if (mIsLowPriority && !mChildrenExpanded) {
-            return mNotificationHeader.getHeight();
+    /**
+     * Get the minimum Height for this group.
+     *
+     * @param maxAllowedVisibleChildren the number of children that should be visible
+     * @param likeHighPriority if the height should be calculated as if it were not low priority
+     */
+    private int getMinHeight(int maxAllowedVisibleChildren, boolean likeHighPriority) {
+        if (!likeHighPriority && showingAsLowPriority()) {
+            return mNotificationHeaderLowPriority.getHeight();
         }
         int minExpandHeight = mNotificationHeaderMargin;
         int visibleChildren = 0;
@@ -859,6 +1010,10 @@
         return minExpandHeight;
     }
 
+    public boolean showingAsLowPriority() {
+        return mIsLowPriority && !mContainingNotification.isExpanded();
+    }
+
     public void setDark(boolean dark, boolean fade, long delay) {
         if (mOverflowNumber != null) {
             mOverflowInvertHelper.setInverted(dark, fade, delay);
@@ -867,9 +1022,15 @@
     }
 
     public void reInflateViews(OnClickListener listener, StatusBarNotification notification) {
-        removeView(mNotificationHeader);
-        mNotificationHeader = null;
-        recreateNotificationHeader(listener, notification);
+        if (mNotificationHeader != null) {
+            removeView(mNotificationHeader);
+            mNotificationHeader = null;
+        }
+        if (mNotificationHeaderLowPriority != null) {
+            removeView(mNotificationHeaderLowPriority);
+            mNotificationHeaderLowPriority = null;
+        }
+        recreateNotificationHeader(listener);
         initDimens();
         for (int i = 0; i < mDividers.size(); i++) {
             View prevDivider = mDividers.get(i);
@@ -888,16 +1049,19 @@
 
     public void setUserLocked(boolean userLocked) {
         mUserLocked = userLocked;
+        if (!mUserLocked) {
+            updateHeaderVisibility(false /* animate */);
+        }
         int childCount = mChildren.size();
         for (int i = 0; i < childCount; i++) {
             ExpandableNotificationRow child = mChildren.get(i);
-            child.setUserLocked(userLocked);
+            child.setUserLocked(userLocked && !showingAsLowPriority());
         }
     }
 
     public void onNotificationUpdated() {
         mHybridGroupManager.setOverflowNumberColor(mOverflowNumber,
-                mNotificationParent.getNotificationColor());
+                mContainingNotification.getNotificationColor());
     }
 
     public int getPositionInLinearLayout(View childInGroup) {
@@ -926,6 +1090,13 @@
                 header.getIcon().setForceHidden(!iconsVisible);
             }
         }
+        if (mNotificationHeaderWrapperLowPriority != null) {
+            NotificationHeaderView header
+                    = mNotificationHeaderWrapperLowPriority.getNotificationHeader();
+            if (header != null) {
+                header.getIcon().setForceHidden(!iconsVisible);
+            }
+        }
     }
 
     public void setClipBottomAmount(int clipBottomAmount) {
@@ -935,5 +1106,36 @@
 
     public void setIsLowPriority(boolean isLowPriority) {
         mIsLowPriority = isLowPriority;
+        if (mContainingNotification != null) { /* we're not yet set up yet otherwise */
+            recreateLowPriorityHeader(null /* existingBuilder */);
+            updateHeaderVisibility(false /* animate */);
+        }
+        if (mUserLocked) {
+            setUserLocked(mUserLocked);
+        }
+    }
+
+    public NotificationHeaderView getVisibleHeader() {
+        NotificationHeaderView header = mNotificationHeader;
+        if (showingAsLowPriority()) {
+            header = mNotificationHeaderLowPriority;
+        }
+        return header;
+    }
+
+    public void onExpansionChanged() {
+        if (mIsLowPriority) {
+            if (mUserLocked) {
+                setUserLocked(mUserLocked);
+            }
+            updateHeaderVisibility(true /* animate */);
+        }
+    }
+
+    public float getIncreasedPaddingAmount() {
+        if (showingAsLowPriority()) {
+            return 0.0f;
+        }
+        return getGroupExpandFraction();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 67cc5e3..d3b336b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -2473,6 +2473,17 @@
         }
     }
 
+    /**
+     * Called when a notification is removed from the shade. This cleans up the state for a given
+     * view.
+     */
+    public void cleanUpViewState(View child) {
+        if (child == mTranslatingParentView) {
+            mTranslatingParentView = null;
+        }
+        mCurrentStackScrollState.removeViewStateForView(child);
+    }
+
     @Override
     public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
         super.requestDisallowInterceptTouchEvent(disallowIntercept);
@@ -2803,7 +2814,7 @@
             }
             mNeedsAnimation = true;
         }
-        if (isHeadsUp(child) && !mChangePositionInProgress) {
+        if (isHeadsUp(child) && mAnimationsEnabled && !mChangePositionInProgress) {
             mAddedHeadsUpChildren.add(child);
             mChildrenToAddAnimated.remove(child);
         }
@@ -3405,6 +3416,7 @@
         for (View view : mClearOverlayViewsWhenFinished) {
             StackStateAnimator.removeFromOverlay(view);
         }
+        mClearOverlayViewsWhenFinished.clear();
     }
 
     private void runAnimationFinishedRunnables() {
@@ -4070,15 +4082,6 @@
         setFadingOut(alpha != 1.0f);
     }
 
-    /**
-     * Remove the a given view from the viewstate. This is currently used when the children are
-     * kept in the parent artificially to have a nicer animation.
-     * @param view the view to remove
-     */
-    public void removeViewStateForView(View view) {
-        mCurrentStackScrollState.removeViewStateForView(view);
-    }
-
     public void setQsExpanded(boolean qsExpanded) {
         mQsExpanded = qsExpanded;
         updateAlgorithmLayoutMinHeight();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/ViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/ViewState.java
index e0a6159..c8659fb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/ViewState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/ViewState.java
@@ -136,7 +136,7 @@
         yTranslation = view.getTranslationY();
         zTranslation = view.getTranslationZ();
         gone = view.getVisibility() == View.GONE;
-        hidden = false;
+        hidden = view.getVisibility() == View.INVISIBLE;
         scaleX = view.getScaleX();
         scaleY = view.getScaleY();
     }
@@ -594,7 +594,7 @@
     }
 
     protected void onYTranslationAnimationFinished(View view) {
-        if (hidden) {
+        if (hidden && !gone) {
             view.setVisibility(View.INVISIBLE);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
index 0a962f1..7c98e13 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
@@ -163,7 +163,7 @@
         intent.putExtra("sims", "1");
         intent.putExtra("nosim", "false");
         intent.putExtra("level", "4");
-        intent.putExtra("datatypel", "");
+        intent.putExtra("datatype", "lte");
         getContext().sendBroadcast(intent);
 
         // Need to send this after so that the sim controller already exists.
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java
index 410d3d2..2df1793 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java
@@ -52,11 +52,13 @@
 import com.android.systemui.plugins.IntentButtonProvider.IntentButton;
 import com.android.systemui.statusbar.ScalingDrawableWrapper;
 import com.android.systemui.statusbar.phone.ExpandableIndicator;
+import com.android.systemui.statusbar.policy.ExtensionController.TunerFactory;
 import com.android.systemui.tuner.ShortcutParser.Shortcut;
 import com.android.systemui.tuner.TunerService.Tunable;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 import java.util.function.Consumer;
 
 public class LockscreenFragment extends PreferenceFragment {
@@ -313,26 +315,39 @@
         }
     }
 
-    public static IntentButton getIntentButton(Context context, String buttonStr,
-            IntentButton plugin, IntentButton def) {
-        // Plugin wins.
-        if (plugin != null) return plugin;
-        // Then tuner options.
-        if (!TextUtils.isEmpty(buttonStr)) {
-            if (buttonStr.contains("::")) {
-                Shortcut shortcut = getShortcutInfo(context, buttonStr);
-                if (shortcut != null) {
-                    return new ShortcutButton(context, shortcut);
-                }
-            } else if (buttonStr.contains("/")) {
-                ActivityInfo info = getActivityinfo(context, buttonStr);
-                if (info != null) {
-                    return new ActivityButton(context, info);
+    public static class LockButtonFactory implements TunerFactory<IntentButton> {
+
+        private final String mKey;
+        private final Context mContext;
+
+        public LockButtonFactory(Context context, String key) {
+            mContext = context;
+            mKey = key;
+        }
+
+        @Override
+        public String[] keys() {
+            return new String[]{mKey};
+        }
+
+        @Override
+        public IntentButton create(Map<String, String> settings) {
+            String buttonStr = settings.get(mKey);
+            if (!TextUtils.isEmpty(buttonStr)) {
+                if (buttonStr.contains("::")) {
+                    Shortcut shortcut = getShortcutInfo(mContext, buttonStr);
+                    if (shortcut != null) {
+                        return new ShortcutButton(mContext, shortcut);
+                    }
+                } else if (buttonStr.contains("/")) {
+                    ActivityInfo info = getActivityinfo(mContext, buttonStr);
+                    if (info != null) {
+                        return new ActivityButton(mContext, info);
+                    }
                 }
             }
+            return null;
         }
-        // Then default.
-        return def;
     }
 
     private static class ShortcutButton implements IntentButton {
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
index f835e7d..209b439 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
@@ -30,6 +30,7 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.plugins.PluginPrefs;
+import com.android.systemui.statusbar.phone.DozeParameters;
 
 public class TunerFragment extends PreferenceFragment {
 
@@ -37,6 +38,7 @@
 
     private static final String KEY_BATTERY_PCT = "battery_pct";
     private static final String KEY_PLUGINS = "plugins";
+    private static final CharSequence KEY_DOZE = "doze";
 
     public static final String SETTING_SEEN_TUNER_WARNING = "seen_tuner_warning";
 
@@ -63,6 +65,9 @@
         if (!PluginPrefs.hasPlugins(getContext())) {
             getPreferenceScreen().removePreference(findPreference(KEY_PLUGINS));
         }
+        if (!DozeParameters.ALWAYS_ON_AVAILABLE) {
+            getPreferenceScreen().removePreference(findPreference(KEY_DOZE));
+        }
 
         if (Settings.Secure.getInt(getContext().getContentResolver(), SETTING_SEEN_TUNER_WARNING,
                 0) == 0) {
diff --git a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
index 15ad0ce..5911766 100644
--- a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
+++ b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
@@ -36,19 +36,19 @@
         nm.createNotificationChannels(Arrays.asList(
                 new NotificationChannel(
                         ALERTS,
-                        context.getString(R.string.notification_channel_alerts),
+                        R.string.notification_channel_alerts,
                         NotificationManager.IMPORTANCE_HIGH),
                 new NotificationChannel(
                         SCREENSHOTS,
-                        context.getString(R.string.notification_channel_screenshot),
+                        R.string.notification_channel_screenshot,
                         NotificationManager.IMPORTANCE_LOW),
                 new NotificationChannel(
                         GENERAL,
-                        context.getString(R.string.notification_channel_general),
+                        R.string.notification_channel_general,
                         NotificationManager.IMPORTANCE_MIN),
                 new NotificationChannel(
                         STORAGE,
-                        context.getString(R.string.notification_channel_storage),
+                        R.string.notification_channel_storage,
                         NotificationManager.IMPORTANCE_LOW)
                 ));
     }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
index b9cb575..1933349a 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
@@ -426,34 +426,37 @@
         });
         row.icon = (ImageButton) row.view.findViewById(R.id.volume_row_icon);
         row.icon.setImageResource(iconRes);
-        row.icon.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                Events.writeEvent(mContext, Events.EVENT_ICON_CLICK, row.stream, row.iconState);
-                mController.setActiveStream(row.stream);
-                if (row.stream == AudioManager.STREAM_RING) {
-                    final boolean hasVibrator = mController.hasVibrator();
-                    if (mState.ringerModeInternal == AudioManager.RINGER_MODE_NORMAL) {
-                        if (hasVibrator) {
-                            mController.setRingerMode(AudioManager.RINGER_MODE_VIBRATE, false);
+        if (row.stream != AudioSystem.STREAM_ACCESSIBILITY) {
+            row.icon.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    Events.writeEvent(mContext, Events.EVENT_ICON_CLICK, row.stream, row.iconState);
+                    mController.setActiveStream(row.stream);
+                    if (row.stream == AudioManager.STREAM_RING) {
+                        final boolean hasVibrator = mController.hasVibrator();
+                        if (mState.ringerModeInternal == AudioManager.RINGER_MODE_NORMAL) {
+                            if (hasVibrator) {
+                                mController.setRingerMode(AudioManager.RINGER_MODE_VIBRATE, false);
+                            } else {
+                                final boolean wasZero = row.ss.level == 0;
+                                mController.setStreamVolume(stream,
+                                        wasZero ? row.lastAudibleLevel : 0);
+                            }
                         } else {
-                            final boolean wasZero = row.ss.level == 0;
-                            mController.setStreamVolume(stream, wasZero ? row.lastAudibleLevel : 0);
+                            mController.setRingerMode(AudioManager.RINGER_MODE_NORMAL, false);
+                            if (row.ss.level == 0) {
+                                mController.setStreamVolume(stream, 1);
+                            }
                         }
                     } else {
-                        mController.setRingerMode(AudioManager.RINGER_MODE_NORMAL, false);
-                        if (row.ss.level == 0) {
-                            mController.setStreamVolume(stream, 1);
-                        }
+                        final boolean vmute = row.ss.level == row.ss.levelMin;
+                        mController.setStreamVolume(stream,
+                                vmute ? row.lastAudibleLevel : row.ss.levelMin);
                     }
-                } else {
-                    final boolean vmute = row.ss.level == row.ss.levelMin;
-                    mController.setStreamVolume(stream,
-                            vmute ? row.lastAudibleLevel : row.ss.levelMin);
+                    row.userAttempt = 0;  // reset the grace period, slider updates immediately
                 }
-                row.userAttempt = 0;  // reset the grace period, slider should update immediately
-            }
-        });
+            });
+        }
     }
 
     public void destroy() {
@@ -622,7 +625,6 @@
         if (!mShowing) {
             trimObsoleteH();
         }
-        Util.setVisOrGone(mDialogRowsView.findViewById(R.id.spacer), mExpanded);
         // apply changes to all rows
         for (final VolumeRow row : mRows) {
             final boolean isActive = row == activeRow;
@@ -723,6 +725,7 @@
         if (ss.level == row.requestedLevel) {
             row.requestedLevel = -1;
         }
+        final boolean isA11yStream = row.stream == AudioManager.STREAM_ACCESSIBILITY;
         final boolean isRingStream = row.stream == AudioManager.STREAM_RING;
         final boolean isSystemStream = row.stream == AudioManager.STREAM_SYSTEM;
         final boolean isAlarmStream = row.stream == AudioManager.STREAM_ALARM;
@@ -782,14 +785,20 @@
                 } else {
                     if (mController.hasVibrator()) {
                         row.icon.setContentDescription(mContext.getString(
-                                R.string.volume_stream_content_description_vibrate,
+                                mShowA11yStream
+                                        ? R.string.volume_stream_content_description_vibrate_a11y
+                                        : R.string.volume_stream_content_description_vibrate,
                                 getStreamLabelH(ss)));
                     } else {
                         row.icon.setContentDescription(mContext.getString(
-                                R.string.volume_stream_content_description_mute,
+                                mShowA11yStream
+                                        ? R.string.volume_stream_content_description_mute_a11y
+                                        : R.string.volume_stream_content_description_mute,
                                 getStreamLabelH(ss)));
                     }
                 }
+            } else if (isA11yStream) {
+                row.icon.setContentDescription(getStreamLabelH(ss));
             } else {
                 if (ss.muted || mAutomute && ss.level == 0) {
                    row.icon.setContentDescription(mContext.getString(
@@ -797,7 +806,9 @@
                            getStreamLabelH(ss)));
                 } else {
                     row.icon.setContentDescription(mContext.getString(
-                            R.string.volume_stream_content_description_mute,
+                            mShowA11yStream
+                                    ? R.string.volume_stream_content_description_mute_a11y
+                                    : R.string.volume_stream_content_description_mute,
                             getStreamLabelH(ss)));
                 }
             }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
index 0a1d34f..9d0ecec 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
@@ -25,7 +25,7 @@
 import android.os.Handler;
 import android.view.WindowManager;
 
-import com.android.systemui.ActivityStarter;
+import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.Dependency;
 import com.android.systemui.SystemUI;
 import com.android.systemui.SystemUIFactory;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogMotion.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogMotion.java
index 8144ea4..d6d0f75 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogMotion.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogMotion.java
@@ -140,7 +140,17 @@
                         final float v = (Float) mChevronPositionAnimator.getAnimatedValue();
                         final int posY = chevronPosY();
                         mChevron.setTranslationY(posY + v + -mDialogView.getTranslationY());
-                    }})
+                    }
+                })
+                .withEndAction(new Runnable() {
+                    @Override
+                    public void run() {
+                        if (mChevronPositionAnimator == null) return;
+                        // reposition chevron
+                        final int posY = chevronPosY();
+                        mChevron.setTranslationY(posY + -mDialogView.getTranslationY());
+                    }
+                })
                 .start();
 
         mContentsPositionAnimator = ValueAnimator.ofFloat(-chevronDistance(), 0)
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index 8f5df7b..760d875 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -19,6 +19,7 @@
 LOCAL_MODULE_TAGS := tests
 
 LOCAL_JACK_FLAGS := --multi-dex native
+LOCAL_DX_FLAGS := --multi-dex
 
 LOCAL_PROTOC_OPTIMIZE_TYPE := nano
 LOCAL_PROTOC_FLAGS := -I$(LOCAL_PATH)/..
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysUIRunner.java b/packages/SystemUI/tests/src/com/android/systemui/SysUIRunner.java
index 1607b70..fd99d1d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysUIRunner.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysUIRunner.java
@@ -46,7 +46,7 @@
 
     @Override
     protected Statement methodInvoker(FrameworkMethod method, Object test) {
-        return UiThreadStatement.shouldRunOnUiThread(method) ? new UiThreadStatement(
+        return shouldRunOnUiThread(method) ? new UiThreadStatement(
                 methodInvokerInt(method, test), true) : methodInvokerInt(method, test);
     }
 
@@ -84,4 +84,12 @@
     private long getTimeout(Test annotation) {
         return annotation == null ? 0L : annotation.timeout();
     }
+
+    public boolean shouldRunOnUiThread(FrameworkMethod method) {
+        if (mKlass.getAnnotation(UiThreadTest.class) != null) {
+            return true;
+        } else {
+            return UiThreadStatement.shouldRunOnUiThread(method);
+        }
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
index 6c454e1..c0e7e80 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
@@ -23,7 +23,6 @@
 import android.os.MessageQueue;
 import android.support.test.InstrumentationRegistry;
 import android.util.ArrayMap;
-import android.util.Log;
 
 import com.android.systemui.Dependency.DependencyKey;
 import com.android.systemui.utils.TestableContext;
@@ -32,8 +31,6 @@
 import org.junit.After;
 import org.junit.Before;
 
-import java.lang.Thread.UncaughtExceptionHandler;
-
 /**
  * Base class that does System UI specific setup.
  */
@@ -92,8 +89,10 @@
         return null;
     }
 
-    public <T> void injectMockDependency(Class<T> cls) {
-        injectTestDependency(cls, mock(cls));
+    public <T> T injectMockDependency(Class<T> cls) {
+        final T mock = mock(cls);
+        mDependency.injectTestDependency(cls, mock);
+        return mock;
     }
 
     public <T> void injectTestDependency(Class<T> cls, T obj) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/UiThreadTest.java b/packages/SystemUI/tests/src/com/android/systemui/UiThreadTest.java
new file mode 100644
index 0000000..58369b1
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/UiThreadTest.java
@@ -0,0 +1,29 @@
+/*
+ * 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;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * When applied to a class, all tests, befores, and afters will behave as if
+ * they have @UiThreadTest applied to them.
+ */
+@Target({ElementType.METHOD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface UiThreadTest {
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
index 32afee9..0cccbe1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
@@ -37,11 +37,12 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.support.test.annotation.UiThreadTest;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.view.Display;
 
+import com.android.systemui.SysUIRunner;
+import com.android.systemui.UiThreadTest;
 import com.android.systemui.statusbar.phone.DozeParameters;
 
 import org.junit.Before;
@@ -49,7 +50,8 @@
 import org.junit.runner.RunWith;
 
 @SmallTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(SysUIRunner.class)
+@UiThreadTest
 public class DozeMachineTest {
 
     DozeMachine mMachine;
@@ -72,7 +74,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testInitialize_initializesParts() {
         mMachine.requestState(INITIALIZED);
 
@@ -80,7 +81,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testInitialize_goesToDoze() {
         when(mParamsMock.getAlwaysOn()).thenReturn(false);
 
@@ -91,7 +91,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testInitialize_goesToAod() {
         when(mParamsMock.getAlwaysOn()).thenReturn(true);
 
@@ -102,7 +101,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testPulseDone_goesToDoze() {
         when(mParamsMock.getAlwaysOn()).thenReturn(false);
         mMachine.requestState(INITIALIZED);
@@ -116,7 +114,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testPulseDone_goesToAoD() {
         when(mParamsMock.getAlwaysOn()).thenReturn(true);
         mMachine.requestState(INITIALIZED);
@@ -130,7 +127,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testFinished_staysFinished() {
         mMachine.requestState(INITIALIZED);
         mMachine.requestState(FINISH);
@@ -143,7 +139,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testFinish_finishesService() {
         mMachine.requestState(INITIALIZED);
 
@@ -153,7 +148,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testWakeLock_heldInTransition() {
         doAnswer((inv) -> {
             assertTrue(mWakeLockFake.isHeld());
@@ -164,7 +158,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testWakeLock_heldInPulseStates() {
         mMachine.requestState(INITIALIZED);
 
@@ -176,7 +169,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testWakeLock_notHeldInDozeStates() {
         mMachine.requestState(INITIALIZED);
 
@@ -188,7 +180,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testWakeLock_releasedAfterPulse() {
         mMachine.requestState(INITIALIZED);
 
@@ -201,7 +192,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testPulseDuringPulse_doesntCrash() {
         mMachine.requestState(INITIALIZED);
 
@@ -213,7 +203,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testSuppressingPulse_doesntCrash() {
         mMachine.requestState(INITIALIZED);
 
@@ -223,7 +212,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testScreen_offInDoze() {
         mMachine.requestState(INITIALIZED);
 
@@ -233,7 +221,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testScreen_onInAod() {
         mMachine.requestState(INITIALIZED);
 
@@ -243,7 +230,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testScreen_onInPulse() {
         mMachine.requestState(INITIALIZED);
 
@@ -254,7 +240,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testScreen_offInRequestPulseWithoutAoD() {
         mMachine.requestState(INITIALIZED);
 
@@ -265,7 +250,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testScreen_onInRequestPulseWithoutAoD() {
         mMachine.requestState(INITIALIZED);
 
@@ -276,7 +260,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testTransitions_canRequestTransitions() {
         mMachine.requestState(INITIALIZED);
         mMachine.requestState(DOZE);
@@ -291,7 +274,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testWakeUp_wakesUp() {
         mMachine.wakeUp();
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStatePreventingAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStatePreventingAdapterTest.java
new file mode 100644
index 0000000..ada8ac0
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStatePreventingAdapterTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.doze;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.support.test.filters.SmallTest;
+import android.view.Display;
+
+import com.android.systemui.statusbar.phone.DozeParameters;
+
+import org.junit.Before;
+import org.junit.Test;
+
+@SmallTest
+public class DozeScreenStatePreventingAdapterTest {
+
+    private DozeMachine.Service mInner;
+    private DozeScreenStatePreventingAdapter mWrapper;
+
+    @Before
+    public void setup() throws Exception {
+        mInner = mock(DozeMachine.Service.class);
+        mWrapper = new DozeScreenStatePreventingAdapter(mInner);
+    }
+
+    @Test
+    public void forwards_finish() throws Exception {
+        mWrapper.finish();
+        verify(mInner).finish();
+    }
+
+    @Test
+    public void forwards_setDozeScreenState_on() throws Exception {
+        mWrapper.setDozeScreenState(Display.STATE_ON);
+        verify(mInner).setDozeScreenState(Display.STATE_ON);
+    }
+
+    @Test
+    public void forwards_setDozeScreenState_off() throws Exception {
+        mWrapper.setDozeScreenState(Display.STATE_OFF);
+        verify(mInner).setDozeScreenState(Display.STATE_OFF);
+    }
+
+    @Test
+    public void forwards_setDozeScreenState_doze() throws Exception {
+        mWrapper.setDozeScreenState(Display.STATE_DOZE);
+        verify(mInner).setDozeScreenState(Display.STATE_ON);
+    }
+
+    @Test
+    public void forwards_setDozeScreenState_doze_suspend() throws Exception {
+        mWrapper.setDozeScreenState(Display.STATE_DOZE_SUSPEND);
+        verify(mInner).setDozeScreenState(Display.STATE_ON);
+    }
+
+    @Test
+    public void forwards_requestWakeUp() throws Exception {
+        mWrapper.requestWakeUp();
+        verify(mInner).requestWakeUp();
+    }
+
+    @Test
+    public void wrapIfNeeded_needed() throws Exception {
+        DozeParameters params = mock(DozeParameters.class);
+        when(params.getDisplayStateSupported()).thenReturn(false);
+
+        assertEquals(DozeScreenStatePreventingAdapter.class,
+                DozeScreenStatePreventingAdapter.wrapIfNeeded(mInner, params).getClass());
+    }
+
+    @Test
+    public void wrapIfNeeded_not_needed() throws Exception {
+        DozeParameters params = mock(DozeParameters.class);
+        when(params.getDisplayStateSupported()).thenReturn(true);
+
+        assertSame(mInner, DozeScreenStatePreventingAdapter.wrapIfNeeded(mInner, params));
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notification/PropertyAnimatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/notification/PropertyAnimatorTest.java
index 193250f..53053fa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notification/PropertyAnimatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/notification/PropertyAnimatorTest.java
@@ -16,7 +16,6 @@
 
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
-import android.support.test.annotation.UiThreadTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
 
@@ -28,7 +27,9 @@
 import android.view.View;
 import android.view.animation.Interpolator;
 
+import com.android.systemui.SysUIRunner;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.UiThreadTest;
 import com.android.systemui.statusbar.notification.PropertyAnimator;
 import com.android.systemui.statusbar.stack.AnimationFilter;
 import com.android.systemui.statusbar.stack.AnimationProperties;
@@ -49,7 +50,8 @@
 import static org.mockito.Mockito.when;
 
 @SmallTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(SysUIRunner.class)
+@UiThreadTest
 public class PropertyAnimatorTest extends SysuiTestCase {
 
     private View mView;
@@ -106,13 +108,11 @@
 
 
     @Before
-    @UiThreadTest
     public void setUp() {
         mView = new View(getContext());
     }
 
     @Test
-    @UiThreadTest
     public void testAnimationStarted() {
         mAnimationFilter.reset();
         mAnimationFilter.animate(mProperty.getProperty());
@@ -121,7 +121,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testNoAnimationStarted() {
         mAnimationFilter.reset();
         PropertyAnimator.startAnimation(mView, mProperty, 200, mAnimationProperties);
@@ -129,7 +128,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testEndValueUpdated() {
         mAnimationFilter.reset();
         mAnimationFilter.animate(mProperty.getProperty());
@@ -139,7 +137,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testStartTagUpdated() {
         mEffectiveProperty.set(mView, 100f);
         mAnimationFilter.reset();
@@ -150,7 +147,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testValueIsSetUnAnimated() {
         mAnimationFilter.reset();
         PropertyAnimator.startAnimation(mView, mProperty, 200f, mAnimationProperties);
@@ -158,7 +154,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testAnimationToRightValueUpdated() {
         mAnimationFilter.reset();
         mAnimationFilter.animate(mProperty.getProperty());
@@ -171,7 +166,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testAnimationToRightValueUpdateAnimated() {
         mAnimationFilter.reset();
         mAnimationFilter.animate(mProperty.getProperty());
@@ -185,7 +179,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testStartTagShiftedWhenChanging() {
         mEffectiveProperty.set(mView, 100f);
         mAnimationFilter.reset();
@@ -198,7 +191,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testUsingDuration() {
         mAnimationFilter.reset();
         mAnimationFilter.animate(mProperty.getProperty());
@@ -210,7 +202,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testUsingDelay() {
         mAnimationFilter.reset();
         mAnimationFilter.animate(mProperty.getProperty());
@@ -222,7 +213,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testUsingInterpolator() {
         mAnimationFilter.reset();
         mAnimationFilter.animate(mProperty.getProperty());
@@ -234,7 +224,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testUsingListener() {
         mAnimationFilter.reset();
         mAnimationFilter.animate(mProperty.getProperty());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginManagerTest.java
index 09ac5a6..053e5cf2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginManagerTest.java
@@ -76,7 +76,7 @@
     public void testOneShot() {
         Plugin mockPlugin = mock(Plugin.class);
         when(mMockPluginInstance.getPlugin()).thenReturn(new PluginInfo(null, null, mockPlugin,
-                null));
+                null, null));
         Plugin result = mPluginManager.getOneShotPlugin("myAction", TestPlugin.class);
         assertTrue(result == mockPlugin);
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/plugins/VersionInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/plugins/VersionInfoTest.java
index 0d87d6b..9849800 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/plugins/VersionInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/plugins/VersionInfoTest.java
@@ -21,8 +21,7 @@
 import com.android.systemui.plugins.VersionInfo.InvalidVersionException;
 import com.android.systemui.plugins.annotations.Requires;
 import com.android.systemui.plugins.qs.QS;
-import com.android.systemui.plugins.qs.QS.Callback;
-import com.android.systemui.plugins.qs.QS.DetailAdapter;
+import com.android.systemui.plugins.qs.DetailAdapter;
 import com.android.systemui.plugins.qs.QS.HeightListener;
 
 import org.junit.Rule;
@@ -95,7 +94,6 @@
     }
 
     @Requires(target = QS.class, version = QS.VERSION)
-    @Requires(target = Callback.class, version = Callback.VERSION)
     @Requires(target = HeightListener.class, version = HeightListener.VERSION)
     @Requires(target = DetailAdapter.class, version = DetailAdapter.VERSION)
     public static class QSImpl {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index e7fa799..7153340 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -19,15 +19,13 @@
 
 import android.os.Looper;
 
+import com.android.keyguard.CarrierText;
 import com.android.systemui.Dependency;
 import com.android.systemui.FragmentTestCase;
 import com.android.systemui.R;
 import com.android.systemui.SysUIRunner;
-import com.android.systemui.statusbar.phone.QSTileHost;
-import com.android.systemui.statusbar.phone.QuickStatusBarHeader;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
-import com.android.systemui.tuner.TunerService;
 import com.android.systemui.util.LayoutInflaterBuilder;
 import com.android.systemui.utils.TestableLooper;
 import com.android.systemui.utils.TestableLooper.RunWithLooper;
@@ -37,9 +35,6 @@
 import org.junit.runner.RunWith;
 
 import android.content.Context;
-import android.os.Handler;
-import android.os.Looper;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.View;
 import android.widget.FrameLayout;
 
@@ -58,6 +53,7 @@
                         .replace("com.android.systemui.statusbar.policy.SplitClockView",
                                 FrameLayout.class)
                         .replace("TextClock", View.class)
+                        .replace(CarrierText.class, View.class)
                         .build());
 
         injectTestDependency(Dependency.BG_LOOPER, TestableLooper.get(this).getLooper());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
similarity index 98%
rename from packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
index 2f6487b..e38c30f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
@@ -42,7 +42,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class QSFooterTest extends SysuiTestCase {
+public class QSSecurityFooterTest extends SysuiTestCase {
 
     private final String MANAGING_ORGANIZATION = "organization";
     private final String DEVICE_OWNER_PACKAGE = "TestDPC";
@@ -52,7 +52,7 @@
     private TextView mFooterText;
     private TestableImageView mFooterIcon;
     private TestableImageView mFooterIcon2;
-    private QSFooter mFooter;
+    private QSSecurityFooter mFooter;
     private SecurityController mSecurityController = mock(SecurityController.class);
 
     @Before
@@ -64,7 +64,7 @@
                         .replace("ImageView", TestableImageView.class)
                         .build());
         Handler h = new Handler(Looper.getMainLooper());
-        h.post(() -> mFooter = new QSFooter(null, mContext));
+        h.post(() -> mFooter = new QSSecurityFooter(null, mContext));
         waitForIdleSync(h);
         mRootView = (ViewGroup) mFooter.getView();
         mFooterText = (TextView) mRootView.findViewById(R.id.footer_text);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java
index 95190e3..11491a75 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java
@@ -32,6 +32,10 @@
 
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.qs.QSIconView;
+import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.qs.tileimpl.QSIconViewImpl;
+import com.android.systemui.qs.tileimpl.QSTileView;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -56,7 +60,7 @@
     private QSPanel.TileRecord createTileRecord() {
         QSPanel.TileRecord tileRecord = new QSPanel.TileRecord();
         tileRecord.tile = mock(QSTile.class);
-        tileRecord.tileView = spy(new QSTileBaseView(mContext, new QSIconView(mContext)));
+        tileRecord.tileView = spy(new QSTileView(mContext, new QSIconViewImpl(mContext)));
         return tileRecord;
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
new file mode 100644
index 0000000..d1e17f4
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.qs.customize;
+
+import static junit.framework.Assert.assertEquals;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.SysUIRunner;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.plugins.qs.QSTile.State;
+import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.utils.TestableLooper;
+import com.android.systemui.utils.TestableLooper.RunWithLooper;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import android.os.Message;
+import android.test.suitebuilder.annotation.SmallTest;
+
+@SmallTest
+@RunWith(SysUIRunner.class)
+@RunWithLooper
+public class TileQueryHelperTest extends SysuiTestCase {
+    private TestableLooper mBGLooper;
+    private Runnable mLastCallback;
+
+    @Before
+    public void setup() {
+        mBGLooper = TestableLooper.get(this);
+        injectTestDependency(Dependency.BG_LOOPER, mBGLooper.getLooper());
+    }
+
+    @Test
+    public void testCompletionCalled() {
+        QSTileHost mockHost = mock(QSTileHost.class);
+        TileAdapter mockAdapter = mock(TileAdapter.class);
+        Runnable mockCompletion = mock(Runnable.class);
+        new TileQueryHelper(mContext, mockHost, mockAdapter, mockCompletion);
+        mBGLooper.processAllMessages();
+        verify(mockCompletion).run();
+    }
+
+    @Test
+    public void testCompletionCalledAfterTilesFetched() {
+        QSTile mockTile = mock(QSTile.class);
+        State mockState = mock(State.class);
+        when(mockState.copy()).thenReturn(mockState);
+        when(mockTile.getState()).thenReturn(mockState);
+        when(mockTile.isAvailable()).thenReturn(true);
+
+        QSTileHost mockHost = mock(QSTileHost.class);
+        when(mockHost.createTile(any())).thenReturn(mockTile);
+
+        mBGLooper.setMessageHandler((Message m) -> {
+            mLastCallback = m.getCallback();
+            return true;
+        });
+        TileAdapter mockAdapter = mock(TileAdapter.class);
+        Runnable mockCompletion = mock(Runnable.class);
+        new TileQueryHelper(mContext, mockHost, mockAdapter, mockCompletion);
+
+        // Verify that the last thing in the queue was our callback
+        mBGLooper.processAllMessages();
+        assertEquals(mockCompletion, mLastCallback);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
index 70c7d3e..6d7b50f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
@@ -27,7 +27,7 @@
 
 import com.android.systemui.SysUIRunner;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.phone.QSTileHost;
+import com.android.systemui.qs.QSTileHost;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.utils.TestableLooper;
 import com.android.systemui.utils.TestableLooper.RunWithLooper;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
new file mode 100644
index 0000000..3db2440
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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;
+
+import static org.mockito.Mockito.mock;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.View;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ExpandableNotificationRowTest {
+
+    private Context mContext;
+    private ExpandableNotificationRow mGroup;
+    private NotificationTestHelper mNotificationTestHelper;
+
+    @Before
+    @UiThreadTest
+    public void setUp() {
+        mContext = InstrumentationRegistry.getTargetContext();
+        mNotificationTestHelper = new NotificationTestHelper(mContext);
+        mGroup = mNotificationTestHelper.createGroup();
+    }
+
+    @Test
+    public void testGroupSummaryNotShowingIconWhenPublic() {
+        mGroup.setSensitive(true, true);
+        mGroup.setHideSensitive(true, false, 0, 0);
+        Assert.assertTrue(mGroup.isSummaryWithChildren());
+        Assert.assertFalse(mGroup.isShowingIcon());
+    }
+
+    @Test
+    public void testNotificationHeaderVisibleWhenAnimating() {
+        mGroup.setSensitive(true, true);
+        mGroup.setHideSensitive(true, false, 0, 0);
+        mGroup.setHideSensitive(false, true, 0, 0);
+        Assert.assertTrue(mGroup.getChildrenContainer().getVisibleHeader().getVisibility()
+                == View.VISIBLE);
+    }
+
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationCustomViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationCustomViewWrapperTest.java
index d07cea1..f016aa1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationCustomViewWrapperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationCustomViewWrapperTest.java
@@ -52,11 +52,11 @@
         RemoteViews views = new RemoteViews(mContext.getPackageName(), R.layout.custom_view_dark);
         View v = views.apply(mContext, null);
         NotificationViewWrapper wrap = NotificationCustomViewWrapper.wrap(mContext, v, mRow);
-        wrap.notifyContentUpdated(null, false /* isLowPriority */);
+        wrap.notifyContentUpdated(mRow);
         Assert.assertTrue(wrap.getCustomBackgroundColor() != 0);
         views.reapply(mContext, v);
-        wrap.notifyContentUpdated(null, false /* isLowPriority */);
+        wrap.notifyContentUpdated(mRow);
         Assert.assertTrue(wrap.getCustomBackgroundColor() != 0);
     }
 
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
index 0491fc4..8520bdb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
@@ -19,6 +19,8 @@
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.Matchers.anyObject;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyBoolean;
 import static org.mockito.Mockito.anyInt;
@@ -42,7 +44,6 @@
 import android.graphics.drawable.Drawable;
 import android.service.notification.StatusBarNotification;
 import android.support.test.InstrumentationRegistry;
-import android.support.test.annotation.UiThreadTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Log;
@@ -53,7 +54,10 @@
 import android.widget.TextView;
 import com.android.internal.util.CharSequences;
 import com.android.systemui.R;
+import com.android.systemui.SysUIRunner;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.UiThreadTest;
+
 import org.junit.Before;
 import org.junit.runner.RunWith;
 import org.junit.Test;
@@ -63,7 +67,8 @@
 import java.util.concurrent.CountDownLatch;
 
 @SmallTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(SysUIRunner.class)
+@UiThreadTest
 public class NotificationInfoTest extends SysuiTestCase {
     private static final String TEST_PACKAGE_NAME = "test_package";
     private static final String TEST_CHANNEL = "test_channel";
@@ -77,7 +82,6 @@
             mock(StatusBarNotification.class);
 
     @Before
-    @UiThreadTest
     public void setUp() throws Exception {
         // Inflate the layout
         final LayoutInflater layoutInflater =
@@ -98,7 +102,6 @@
         mNotificationChannel = new NotificationChannel(
                 TEST_CHANNEL, TEST_CHANNEL_NAME, NotificationManager.IMPORTANCE_LOW);
         when(mMockStatusBarNotification.getPackageName()).thenReturn(TEST_PACKAGE_NAME);
-
         when(mMockINotificationManager.getNumNotificationChannelsForPackage(
                 eq(TEST_PACKAGE_NAME), anyInt(), anyBoolean())).thenReturn(1);
     }
@@ -115,7 +118,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testBindNotification_SetsTextApplicationName() throws Exception {
         when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -125,7 +127,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testBindNotification_SetsPackageIcon() throws Exception {
         final Drawable iconDrawable = mock(Drawable.class);
         when(mMockPackageManager.getApplicationIcon(any(ApplicationInfo.class)))
@@ -137,7 +138,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testBindNotification_GroupNameHiddenIfNoGroup() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel, null, null, null);
@@ -149,7 +149,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testBindNotification_SetsGroupNameIfNonNull() throws Exception {
         mNotificationChannel.setGroup("test_group_id");
         final NotificationChannelGroup notificationChannelGroup =
@@ -168,7 +167,27 @@
     }
 
     @Test
-    @UiThreadTest
+    public void testBindNotification_SetsGroupName_resId() throws Exception {
+        when(mMockPackageManager.getText(eq(TEST_PACKAGE_NAME),
+                eq(R.string.legacy_vpn_name), anyObject())).thenReturn(
+                getContext().getString(R.string.legacy_vpn_name));
+        mNotificationChannel.setGroup("test_group_id");
+        final NotificationChannelGroup notificationChannelGroup =
+                new NotificationChannelGroup("test_group_id", R.string.legacy_vpn_name);
+        when(mMockINotificationManager.getNotificationChannelGroupForPackage(
+                eq("test_group_id"), eq(TEST_PACKAGE_NAME), anyInt()))
+                .thenReturn(notificationChannelGroup);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                mMockStatusBarNotification, mNotificationChannel, null, null, null);
+        final TextView groupNameView = (TextView) mNotificationInfo.findViewById(R.id.group_name);
+        assertEquals(View.VISIBLE, groupNameView.getVisibility());
+        assertEquals(mContext.getString(R.string.legacy_vpn_name), groupNameView.getText());
+        final TextView groupDividerView =
+                (TextView) mNotificationInfo.findViewById(R.id.pkg_group_divider);
+        assertEquals(View.VISIBLE, groupDividerView.getVisibility());
+    }
+
+    @Test
     public void testBindNotification_SetsTextChannelName() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel, null, null, null);
@@ -177,7 +196,21 @@
     }
 
     @Test
-    @UiThreadTest
+    public void testBindNotification_SetsTextChannelName_resId() throws Exception {
+        when(mMockPackageManager.getText(eq(TEST_PACKAGE_NAME),
+                eq(R.string.notification_menu_accessibility), anyObject())).thenReturn(
+                getContext().getString(R.string.notification_menu_accessibility));
+        NotificationChannel notificationChannelResId = new NotificationChannel(
+                TEST_CHANNEL, R.string.notification_menu_accessibility,
+                NotificationManager.IMPORTANCE_LOW);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                mMockStatusBarNotification, notificationChannelResId, null, null, null);
+        final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
+        assertEquals(getContext().getString(R.string.notification_menu_accessibility),
+                textView.getText());
+    }
+
+    @Test
     public void testBindNotification_SetsOnClickListenerForSettings() throws Exception {
         final CountDownLatch latch = new CountDownLatch(1);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -192,7 +225,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testBindNotification_SettingsTextWithOneChannel() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel, (View v, int appUid) -> {}, null,
@@ -203,7 +235,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testBindNotification_SettingsTextWithMultipleChannels() throws Exception {
         when(mMockINotificationManager.getNumNotificationChannelsForPackage(
                 eq(TEST_PACKAGE_NAME), anyInt(), anyBoolean())).thenReturn(2);
@@ -216,7 +247,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testBindNotification_SetsOnClickListenerForDone() throws Exception {
         final CountDownLatch latch = new CountDownLatch(1);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -231,7 +261,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testBindNotification_NumChannelsTextHiddenWhenDefaultChannel() throws Exception {
         final NotificationChannel defaultChannel = new NotificationChannel(
                 NotificationChannel.DEFAULT_CHANNEL_ID, TEST_CHANNEL_NAME,
@@ -244,7 +273,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testBindNotification_NumChannelsTextDisplaysWhenNotDefaultChannel()
             throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -256,7 +284,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testBindNotification_NumChannelsTextScalesWithNumberOfChannels()
             throws Exception {
         when(mMockINotificationManager.getNumNotificationChannelsForPackage(
@@ -269,7 +296,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testbindNotification_ChannelDisabledTextGoneWhenNotDisabled() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel, null, null, null);
@@ -279,7 +305,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testbindNotification_ChannelDisabledTextVisibleWhenDisabled() throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_NONE);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -294,7 +319,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testHasImportanceChanged_DefaultsToFalse() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel, null, null, null);
@@ -302,7 +326,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testHasImportanceChanged_ReturnsTrueAfterChannelDisabled() throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -314,7 +337,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testBindNotification_DoesNotUpdateNotificationChannel() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel, null, null, null);
@@ -323,7 +345,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testDoesNotUpdateNotificationChannelAfterImportanceChanged() throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -336,7 +357,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testHandleCloseControls_DoesNotUpdateNotificationChannelIfUnchanged()
             throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -348,7 +368,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testHandleCloseControls_DoesNotUpdateNotificationChannelIfUnspecified()
             throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_UNSPECIFIED);
@@ -361,7 +380,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testEnabledSwitchOnByDefault() throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -372,7 +390,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testEnabledButtonOffWhenAlreadyBanned() throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_NONE);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -383,7 +400,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testEnabledSwitchVisibleByDefault() throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -394,7 +410,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testEnabledSwitchInvisibleIfNonBlockable() throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -406,7 +421,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testEnabledSwitchChangedCallsUpdateNotificationChannel() throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -421,7 +435,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testCloseControlsDoesNotUpdateIfSaveIsFalse() throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
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 72f6ca8..b8be4fa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java
@@ -25,7 +25,7 @@
 import org.junit.runner.RunWith;
 
 @RunWith(SysUIRunner.class)
-@RunWithLooper
+@RunWithLooper(setAsMainLooper = true)
 public class NotificationMenuRowTest extends LeakCheckedTest {
 
     @Before
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
new file mode 100644
index 0000000..96dbdb3
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
@@ -0,0 +1,83 @@
+/*
+ * 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;
+
+import android.app.ActivityManager;
+import android.app.Notification;
+import android.content.Context;
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
+import android.view.LayoutInflater;
+import android.widget.RemoteViews;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.InflationException;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
+
+/**
+ * A helper class to create {@link ExpandableNotificationRow}
+ */
+public class NotificationTestHelper {
+
+    private final Context mContext;
+    private int mId;
+    private final NotificationGroupManager mGroupManager = new NotificationGroupManager();
+
+    public NotificationTestHelper(Context context) {
+        mContext = context;
+    }
+
+    public ExpandableNotificationRow createRow() {
+        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
+                mContext.LAYOUT_INFLATER_SERVICE);
+        ExpandableNotificationRow row = (ExpandableNotificationRow) inflater.inflate(
+                R.layout.status_bar_notification_row,
+                null, false);
+        row.setGroupManager(mGroupManager);
+        Notification publicVersion = new Notification.Builder(mContext).setSmallIcon(
+                R.drawable.ic_person)
+                .setCustomContentView(new RemoteViews(mContext.getPackageName(),
+                        R.layout.custom_view_dark))
+                .build();
+        Notification notification = new Notification.Builder(mContext).setSmallIcon(
+                R.drawable.ic_person)
+                .setContentTitle("Title")
+                .setContentText("Text")
+                .setPublicVersion(publicVersion)
+                .build();
+        UserHandle mUser = UserHandle.of(ActivityManager.getCurrentUser());
+        StatusBarNotification sbn = new StatusBarNotification("com.android.systemui",
+                "com.android.systemui", mId++, null, 1000,
+                2000, notification, mUser, null, System.currentTimeMillis());
+        NotificationData.Entry entry = new NotificationData.Entry(sbn);
+        entry.row = row;
+        try {
+            entry.createIcons(mContext, sbn);
+            row.updateNotification(entry);
+        } catch (InflationException e) {
+            throw new RuntimeException(e.getMessage());
+        }
+        return row;
+    }
+
+    public ExpandableNotificationRow createGroup() {
+        ExpandableNotificationRow row = createRow();
+        row.addChildNotification(createRow());
+        row.addChildNotification(createRow());
+        return row;
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
new file mode 100644
index 0000000..3ccb160
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
@@ -0,0 +1,100 @@
+/*
+ * 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 org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import com.android.internal.app.NightDisplayController;
+import com.android.systemui.Prefs;
+import com.android.systemui.Prefs.Key;
+import com.android.systemui.SysUIRunner;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.qs.QSTileHost;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+
+@RunWith(SysUIRunner.class)
+public class AutoTileManagerTest extends SysuiTestCase {
+
+    private QSTileHost mQsTileHost;
+    private AutoTileManager mAutoTileManager;
+
+    @Before
+    public void setUp() throws Exception {
+        Prefs.putBoolean(mContext, Key.QS_NIGHTDISPLAY_ADDED, false);
+        mQsTileHost = Mockito.mock(QSTileHost.class);
+        mAutoTileManager = new AutoTileManager(mContext, mQsTileHost);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        mAutoTileManager = null;
+    }
+
+    @Test
+    public void nightTileAdded_whenActivated() {
+        if (!NightDisplayController.isAvailable(mContext)) {
+            return;
+        }
+        mAutoTileManager.mNightDisplayCallback.onActivated(true);
+        verify(mQsTileHost).addTile("night");
+    }
+
+    @Test
+    public void nightTileNotAdded_whenDeactivated() {
+        if (!NightDisplayController.isAvailable(mContext)) {
+            return;
+        }
+        mAutoTileManager.mNightDisplayCallback.onActivated(false);
+        verify(mQsTileHost, never()).addTile("night");
+    }
+
+    @Test
+    public void nightTileAdded_whenNightModeTwilight() {
+        if (!NightDisplayController.isAvailable(mContext)) {
+            return;
+        }
+        mAutoTileManager.mNightDisplayCallback.onAutoModeChanged(
+                NightDisplayController.AUTO_MODE_TWILIGHT);
+        verify(mQsTileHost).addTile("night");
+    }
+
+    @Test
+    public void nightTileAdded_whenNightModeCustom() {
+        if (!NightDisplayController.isAvailable(mContext)) {
+            return;
+        }
+        mAutoTileManager.mNightDisplayCallback.onAutoModeChanged(
+                NightDisplayController.AUTO_MODE_CUSTOM);
+        verify(mQsTileHost).addTile("night");
+    }
+
+    @Test
+    public void nightTileNotAdded_whenNightModeDisabled() {
+        if (!NightDisplayController.isAvailable(mContext)) {
+            return;
+        }
+        mAutoTileManager.mNightDisplayCallback.onAutoModeChanged(
+                NightDisplayController.AUTO_MODE_DISABLED);
+        verify(mQsTileHost, never()).addTile("night");
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerTest.java
new file mode 100644
index 0000000..e3a5ef0
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerTest.java
@@ -0,0 +1,105 @@
+/*
+ * 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.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.OverlayPlugin;
+import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.statusbar.policy.ExtensionController.Extension;
+import com.android.systemui.statusbar.policy.ExtensionController.TunerFactory;
+import com.android.systemui.tuner.TunerService;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Map;
+import java.util.function.Consumer;
+
+public class ExtensionControllerTest extends SysuiTestCase {
+
+    private PluginManager mPluginManager;
+    private TunerService mTunerService;
+    private ExtensionController mExtensionController;
+
+    @Before
+    public void setup() {
+        mPluginManager = injectMockDependency(PluginManager.class);
+        mTunerService = injectMockDependency(TunerService.class);
+        mExtensionController = Dependency.get(ExtensionController.class);
+    }
+
+    @Test
+    public void testPlugin() {
+        Extension ext = mExtensionController.newExtension(OverlayPlugin.class)
+                .withPlugin(OverlayPlugin.class)
+                .build();
+        verify(mPluginManager).addPluginListener(eq(OverlayPlugin.ACTION), any(),
+                eq(OverlayPlugin.class));
+
+        ext.destroy();
+        verify(mPluginManager).removePluginListener(any());
+    }
+
+    @Test
+    public void testTuner() {
+        String[] keys = new String[] { "key1", "key2" };
+        TunerFactory<Object> factory = new ExtensionController.TunerFactory() {
+            @Override
+            public String[] keys() {
+                return keys;
+            }
+
+            @Override
+            public Object create(Map settings) {
+                return null;
+            }
+        };
+        Extension ext = mExtensionController.newExtension(Object.class)
+                .withTunerFactory(factory)
+                .build();
+        verify(mTunerService).addTunable(any(), eq(keys[0]), eq(keys[1]));
+
+        ext.destroy();
+        verify(mTunerService).removeTunable(any());
+    }
+
+    @Test
+    public void testDefault() {
+        Object o = new Object();
+        Extension ext = mExtensionController.newExtension(Object.class)
+                .withDefault(() -> o)
+                .build();
+        assertEquals(o, ext.get());
+    }
+
+    @Test
+    public void testCallback() {
+        Consumer<Object> callback = mock(Consumer.class);
+        final Object o = new Object();
+        mExtensionController.newExtension(Object.class)
+                .withDefault(() -> o)
+                .withCallback(callback)
+                .build();
+        verify(callback).accept(eq(o));
+    }
+
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index 0e5f513..19b4b17 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -31,6 +31,7 @@
 import android.util.Log;
 import com.android.internal.telephony.cdma.EriInfo;
 import com.android.settingslib.net.DataUsageController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
@@ -43,6 +44,8 @@
 import org.junit.runner.Description;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
@@ -56,6 +59,7 @@
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
@@ -82,6 +86,8 @@
     protected CallbackHandler mCallbackHandler;
     protected SubscriptionDefaults mMockSubDefaults;
     protected NetworkScoreManager mMockNetworkScoreManager;
+    protected DeviceProvisionedController mMockProvisionController;
+    protected DeviceProvisionedListener mUserCallback;
 
     protected int mSubId;
 
@@ -120,11 +126,21 @@
         mConfig = new Config();
         mConfig.hspaDataDistinguishable = true;
         mCallbackHandler = mock(CallbackHandler.class);
+
+        mMockProvisionController = mock(DeviceProvisionedController.class);
+        when(mMockProvisionController.isUserSetup(anyInt())).thenReturn(true);
+        doAnswer(invocation -> {
+            mUserCallback = (DeviceProvisionedListener) invocation.getArguments()[0];
+            mUserCallback.onUserSetupChanged();
+            mUserCallback.onDeviceProvisionedChanged();
+            return null;
+        }).when(mMockProvisionController).addCallback(any());
+
         mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockNetworkScoreManager,
                 mMockTm, mMockWm, mMockSm,
                 mConfig, Looper.getMainLooper(), mCallbackHandler,
                 mock(AccessPointControllerImpl.class), mock(DataUsageController.class),
-                mMockSubDefaults, mock(DeviceProvisionedController.class));
+                mMockSubDefaults, mMockProvisionController);
         setupNetworkController();
 
         // Trigger blank callbacks to always get the current state (some tests don't trigger
@@ -139,7 +155,6 @@
         when(mMockTm.getDataEnabled(mSubId)).thenReturn(true);
         setDefaultSubId(mSubId);
         setSubscriptions(mSubId);
-        mNetworkController.handleSetUserSetupComplete(true);
         mMobileSignalController = mNetworkController.mMobileSignalControllers.get(mSubId);
         mPhoneStateListener = mMobileSignalController.mPhoneStateListener;
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
index d7f961c..e47f750 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
@@ -1,16 +1,20 @@
 package com.android.systemui.statusbar.policy;
 
+import static org.mockito.Matchers.anyInt;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 import android.net.NetworkCapabilities;
 import android.os.Looper;
 import android.support.test.runner.AndroidJUnit4;
 import android.telephony.TelephonyManager;
 import android.test.suitebuilder.annotation.SmallTest;
+
 import com.android.settingslib.net.DataUsageController;
+
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Mockito;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
@@ -103,10 +107,11 @@
                 TelephonyIcons.QS_DATA_4G);
     }
 
+    @Ignore("Flaky")
     @Test
     public void testDataDisabledIcon() {
         setupNetworkController();
-        Mockito.when(mMockTm.getDataEnabled(mSubId)).thenReturn(false);
+        when(mMockTm.getDataEnabled(mSubId)).thenReturn(false);
         setupDefaultSignal();
         updateDataConnectionState(TelephonyManager.DATA_DISCONNECTED, 0);
         setConnectivity(NetworkCapabilities.TRANSPORT_CELLULAR, false, false);
@@ -118,11 +123,12 @@
     @Test
     public void testDataDisabledIcon_UserNotSetup() {
         setupNetworkController();
-        Mockito.when(mMockTm.getDataEnabled(mSubId)).thenReturn(false);
+        when(mMockTm.getDataEnabled(mSubId)).thenReturn(false);
         setupDefaultSignal();
         updateDataConnectionState(TelephonyManager.DATA_DISCONNECTED, 0);
         setConnectivity(NetworkCapabilities.TRANSPORT_CELLULAR, false, false);
-        mNetworkController.handleSetUserSetupComplete(false);
+        when(mMockProvisionController.isUserSetup(anyInt())).thenReturn(false);
+        mUserCallback.onUserSetupChanged();
 
         // Don't show the X until the device is setup.
         verifyDataIndicators(0, 0);
@@ -154,7 +160,7 @@
         verifyDataIndicators(TelephonyIcons.DATA_LTE[1][0 /* No direction */],
                 TelephonyIcons.QS_DATA_LTE);
 
-        Mockito.when(mServiceState.getDataNetworkType())
+        when(mServiceState.getDataNetworkType())
                 .thenReturn(TelephonyManager.NETWORK_TYPE_HSPA);
         updateServiceState();
         verifyDataIndicators(TelephonyIcons.DATA_H[1][0 /* No direction */],
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 2c0f9c9..1555856 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
@@ -94,6 +94,14 @@
     }
 
     @Test
+    public void testNoEmergencyOnlyWrongSubscription() {
+        setupDefaultSignal();
+        setDefaultSubId(42);
+        mNetworkController.recalculateEmergency();
+        verifyEmergencyOnly(false);
+    }
+
+    @Test
     public void testNoEmengencyNoSubscriptions() {
         setupDefaultSignal();
         setSubscriptions();
@@ -286,12 +294,12 @@
         for (int i = 0; i < testSubscriptions.length; i++) {
             if (i == indexToSkipController) {
                 // Make sure a controller was created despite us not adding one.
-                assertTrue(mNetworkController.mMobileSignalControllers.containsKey(
-                        testSubscriptions[i]));
+                assertTrue(mNetworkController.mMobileSignalControllers.indexOfKey(
+                        testSubscriptions[i]) >= 0);
             } else if (i == indexToSkipSubscription) {
                 // Make sure the controller that did exist was removed
-                assertFalse(mNetworkController.mMobileSignalControllers.containsKey(
-                        testSubscriptions[i]));
+                assertFalse(mNetworkController.mMobileSignalControllers.indexOfKey(
+                        testSubscriptions[i]) >= 0);
             } else {
                 // If a MobileSignalController is around it needs to not be unregistered.
                 Mockito.verify(mobileSignalControllers[i], Mockito.never())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
index 9b382f6..8cbf95b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
@@ -1,6 +1,7 @@
 package com.android.systemui.statusbar.policy;
 
 import android.content.Intent;
+import android.net.NetworkBadging;
 import android.net.NetworkCapabilities;
 import android.net.NetworkInfo;
 import android.net.NetworkKey;
@@ -12,7 +13,6 @@
 import android.net.wifi.WifiNetworkScoreCache;
 import android.os.Bundle;
 import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
 import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
 
@@ -106,7 +106,7 @@
         setWifiState(true, TEST_SSID, TEST_BSSID);
         mRequestScoresLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
 
-        when(mockBadgeCurve.lookupScore(anyInt())).thenReturn((byte) ScoredNetwork.BADGING_SD);
+        when(mockBadgeCurve.lookupScore(anyInt())).thenReturn((byte) NetworkBadging.BADGING_SD);
 
         ArgumentCaptor<WifiNetworkScoreCache> scoreCacheCaptor =
                 ArgumentCaptor.forClass(WifiNetworkScoreCache.class);
@@ -129,7 +129,7 @@
                 Utils.WIFI_PIE_FOR_BADGING[testLevel],
                 iconState.icon);
         assertEquals("SD Badge is set",
-                Utils.getWifiBadgeResource(ScoredNetwork.BADGING_SD),
+                Utils.getWifiBadgeResource(NetworkBadging.BADGING_SD),
                 iconState.iconOverlay);
 
         settingsOverrider.release();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationChildrenContainerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationChildrenContainerTest.java
new file mode 100644
index 0000000..dbe0de4
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationChildrenContainerTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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.stack;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.NotificationHeaderView;
+import android.view.View;
+
+import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.NotificationTestHelper;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class NotificationChildrenContainerTest {
+
+    private Context mContext;
+    private ExpandableNotificationRow mGroup;
+    private int mId;
+    private NotificationTestHelper mNotificationTestHelper;
+
+    @Before
+    @UiThreadTest
+    public void setUp() {
+        mContext = InstrumentationRegistry.getTargetContext();
+        mNotificationTestHelper = new NotificationTestHelper(mContext);
+        mGroup = mNotificationTestHelper.createGroup();
+    }
+
+    @Test
+    public void testLowPriorityHeaderCleared() {
+        mGroup.setIsLowPriority(true);
+        NotificationChildrenContainer childrenContainer = mGroup.getChildrenContainer();
+        NotificationHeaderView lowPriorityHeaderView = childrenContainer.getLowPriorityHeaderView();
+        Assert.assertTrue(lowPriorityHeaderView.getVisibility() == View.VISIBLE);
+        Assert.assertTrue(lowPriorityHeaderView.getParent() == childrenContainer);
+        mGroup.setIsLowPriority(false);
+        Assert.assertTrue(lowPriorityHeaderView.getParent() == null);
+        Assert.assertTrue(childrenContainer.getLowPriorityHeaderView() == null);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/TestableLooper.java b/packages/SystemUI/tests/src/com/android/systemui/utils/TestableLooper.java
index d275973..8902e0c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/TestableLooper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/TestableLooper.java
@@ -244,9 +244,11 @@
                 mLooper.setAsMainLooper();
             }
 
-            mBase.evaluate();
-
-            mLooper.destroy();
+            try {
+                mBase.evaluate();
+            } finally {
+                mLooper.destroy();
+            }
         }
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/ViewUtils.java b/packages/SystemUI/tests/src/com/android/systemui/utils/ViewUtils.java
index 07e5f66..678b9f4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/ViewUtils.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/ViewUtils.java
@@ -14,9 +14,11 @@
 
 package com.android.systemui.utils;
 
+import android.content.pm.ApplicationInfo;
 import android.graphics.PixelFormat;
 import android.os.Handler;
 import android.os.Looper;
+import android.util.Log;
 import android.view.View;
 import android.view.WindowManager;
 import android.view.WindowManager.LayoutParams;
@@ -27,18 +29,19 @@
 public class ViewUtils {
 
     public static void attachView(View view) {
+        // Make sure hardware acceleration isn't turned on.
+        view.getContext().getApplicationInfo().flags &=
+                ~(ApplicationInfo.FLAG_HARDWARE_ACCELERATED);
         WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
                 LayoutParams.TYPE_APPLICATION_OVERLAY,
                 0, PixelFormat.TRANSLUCENT);
-        Handler handler = new Handler(Looper.getMainLooper());
-        handler.post(() -> InstrumentationRegistry.getContext()
-                .getSystemService(WindowManager.class).addView(view, lp));
+        InstrumentationRegistry.getContext()
+                .getSystemService(WindowManager.class).addView(view, lp);
     }
 
     public static void detachView(View view) {
-        Handler handler = new Handler(Looper.getMainLooper());
-        handler.post(() -> InstrumentationRegistry.getContext()
-                .getSystemService(WindowManager.class).removeView(view));
+        InstrumentationRegistry.getContext()
+                .getSystemService(WindowManager.class).removeViewImmediate(view);
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeExtensionController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeExtensionController.java
new file mode 100644
index 0000000..c0f5783
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeExtensionController.java
@@ -0,0 +1,100 @@
+/*
+ * 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.utils.leaks;
+
+import static org.mockito.Mockito.mock;
+
+import com.android.systemui.statusbar.policy.ExtensionController;
+
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+public class FakeExtensionController implements ExtensionController {
+
+    private final Tracker mTracker;
+
+    public FakeExtensionController(LeakCheckedTest test) {
+        mTracker = test.getTracker("extension");
+    }
+
+    @Override
+    public <T> ExtensionBuilder<T> newExtension(Class<T> cls) {
+        final Object o = new Object();
+        mTracker.getLeakInfo(o).addAllocation(new Throwable());
+        return new FakeExtensionBuilder(o);
+    }
+
+    private class FakeExtensionBuilder<T> implements ExtensionBuilder<T> {
+        private final Object mAllocation;
+
+        public FakeExtensionBuilder(Object o) {
+            mAllocation = o;
+        }
+
+        @Override
+        public ExtensionBuilder<T> withTunerFactory(TunerFactory<T> factory) {
+            return this;
+        }
+
+        @Override
+        public <P extends T> ExtensionBuilder<T> withPlugin(Class<P> cls) {
+            return this;
+        }
+
+        @Override
+        public <P extends T> ExtensionBuilder<T> withPlugin(Class<P> cls, String action) {
+            return this;
+        }
+
+        @Override
+        public <P> ExtensionBuilder<T> withPlugin(Class<P> cls, String action, PluginConverter<T, P> converter) {
+            return this;
+        }
+
+        @Override
+        public ExtensionBuilder<T> withDefault(Supplier<T> def) {
+            return this;
+        }
+
+        @Override
+        public ExtensionBuilder<T> withCallback(Consumer<T> callback) {
+            return this;
+        }
+
+        @Override
+        public Extension build() {
+            return new FakeExtension(mAllocation);
+        }
+    }
+
+    private class FakeExtension<T> implements Extension<T> {
+        private final Object mAllocation;
+
+        public FakeExtension(Object allocation) {
+            mAllocation = allocation;
+        }
+
+        @Override
+        public T get() {
+            // TODO: Support defaults or things.
+            return null;
+        }
+
+        @Override
+        public void destroy() {
+            mTracker.getLeakInfo(mAllocation).clearAllocations();
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNetworkController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNetworkController.java
index 5497686..47ed5ca 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNetworkController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNetworkController.java
@@ -47,11 +47,6 @@
     }
 
     @Override
-    public void setUserSetupComplete(boolean userSetup) {
-
-    }
-
-    @Override
     public boolean hasEmergencyCryptKeeperText() {
         return false;
     }
diff --git a/packages/WallpaperCropper/Android.mk b/packages/WallpaperCropper/Android.mk
index d8fb7a4..09b41fd 100644
--- a/packages/WallpaperCropper/Android.mk
+++ b/packages/WallpaperCropper/Android.mk
@@ -6,7 +6,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_JAVA_LIBRARIES := telephony-common
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 junit
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4
 
 LOCAL_PACKAGE_NAME := WallpaperCropper
 LOCAL_CERTIFICATE := platform
diff --git a/packages/WallpaperCropper/src/com/android/gallery3d/glrenderer/BitmapTexture.java b/packages/WallpaperCropper/src/com/android/gallery3d/glrenderer/BitmapTexture.java
index 100b0b3b..f8b01cb 100644
--- a/packages/WallpaperCropper/src/com/android/gallery3d/glrenderer/BitmapTexture.java
+++ b/packages/WallpaperCropper/src/com/android/gallery3d/glrenderer/BitmapTexture.java
@@ -18,7 +18,7 @@
 
 import android.graphics.Bitmap;
 
-import junit.framework.Assert;
+import com.android.gallery3d.common.Utils;
 
 // BitmapTexture is a texture whose content is specified by a fixed Bitmap.
 //
@@ -34,7 +34,7 @@
 
     public BitmapTexture(Bitmap bitmap, boolean hasBorder) {
         super(hasBorder);
-        Assert.assertTrue(bitmap != null && !bitmap.isRecycled());
+        Utils.assertTrue(bitmap != null && !bitmap.isRecycled());
         mContentBitmap = bitmap;
     }
 
diff --git a/packages/WallpaperCropper/src/com/android/gallery3d/glrenderer/GLPaint.java b/packages/WallpaperCropper/src/com/android/gallery3d/glrenderer/GLPaint.java
index 16b2206..b26e9ab 100644
--- a/packages/WallpaperCropper/src/com/android/gallery3d/glrenderer/GLPaint.java
+++ b/packages/WallpaperCropper/src/com/android/gallery3d/glrenderer/GLPaint.java
@@ -16,7 +16,7 @@
 
 package com.android.gallery3d.glrenderer;
 
-import junit.framework.Assert;
+import com.android.gallery3d.common.Utils;
 
 public class GLPaint {
     private float mLineWidth = 1f;
@@ -31,7 +31,7 @@
     }
 
     public void setLineWidth(float width) {
-        Assert.assertTrue(width >= 0);
+        Utils.assertTrue(width >= 0);
         mLineWidth = width;
     }
 
diff --git a/packages/WallpaperCropper/src/com/android/gallery3d/glrenderer/UploadedTexture.java b/packages/WallpaperCropper/src/com/android/gallery3d/glrenderer/UploadedTexture.java
index f41a979..417102a 100644
--- a/packages/WallpaperCropper/src/com/android/gallery3d/glrenderer/UploadedTexture.java
+++ b/packages/WallpaperCropper/src/com/android/gallery3d/glrenderer/UploadedTexture.java
@@ -20,7 +20,7 @@
 import android.graphics.Bitmap.Config;
 import android.opengl.GLUtils;
 
-import junit.framework.Assert;
+import com.android.gallery3d.common.Utils;
 
 import java.util.HashMap;
 
@@ -144,7 +144,7 @@
     }
 
     private void freeBitmap() {
-        Assert.assertTrue(mBitmap != null);
+        Utils.assertTrue(mBitmap != null);
         onFreeBitmap(mBitmap);
         mBitmap = null;
     }
@@ -219,7 +219,7 @@
                 int texWidth = getTextureWidth();
                 int texHeight = getTextureHeight();
 
-                Assert.assertTrue(bWidth <= texWidth && bHeight <= texHeight);
+                Utils.assertTrue(bWidth <= texWidth && bHeight <= texHeight);
 
                 // Upload the bitmap to a new texture.
                 mId = canvas.getGLId().generateTexture();
diff --git a/pathmap.mk b/pathmap.mk
new file mode 100644
index 0000000..c241d99
--- /dev/null
+++ b/pathmap.mk
@@ -0,0 +1,64 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+#
+# A central place to define mappings to paths used by the framework build, to
+# avoid hard-coding them in Android.mk files. Not meant for header file include
+# directories, despite the fact that it was historically used for that!
+#
+
+# Import path mappings from the support library project. This will set up
+# FRAMEWORKS_SUPPORT_JAVA_SRC_DIRS and FRAMEWORKS_SUPPORT_JAVA_LIBRARIES for
+# use later in this file.
+include $(LOCAL_PATH)/../support/pathmap.mk
+
+#
+# A list of all source roots under frameworks/multidex.
+#
+FRAMEWORKS_MULTIDEX_SUBDIRS := \
+    multidex/library/src \
+    multidex/instrumentation/src
+
+#
+# A version of FRAMEWORKS_SUPPORT_SUBDIRS that is expanded to full paths from
+# the root of the tree.
+#
+FRAMEWORKS_SUPPORT_JAVA_SRC_DIRS += \
+    $(addprefix frameworks/,$(FRAMEWORKS_MULTIDEX_SUBDIRS)) \
+    frameworks/rs/support
+
+#
+# A list of support library modules.
+#
+FRAMEWORKS_SUPPORT_JAVA_LIBRARIES += \
+    android-support-v8-renderscript \
+    android-support-multidex \
+    android-support-multidex-instrumentation
+
+#
+# A list of all documented source roots under frameworks/data-binding.
+#
+FRAMEWORKS_DATA_BINDING_SUBDIRS := \
+    baseLibrary/src/main \
+    extensions/library/src/main \
+    extensions/library/src/doc
+
+#
+# A version of FRAMEWORKS_DATA_BINDING_SUBDIRS that is expanded to full paths from
+# the root of the tree.
+#
+FRAMEWORKS_DATA_BINDING_JAVA_SRC_DIRS := \
+    $(addprefix frameworks/data-binding/,$(FRAMEWORKS_DATA_BINDING_SUBDIRS))
diff --git a/preloaded-classes b/preloaded-classes
index 7dc5a25..a72a042 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -3919,6 +3919,18 @@
 org.apache.http.message.BasicHttpResponse
 org.apache.http.message.BasicStatusLine
 org.apache.http.message.HeaderGroup
+org.ccil.cowan.tagsoup.AttributesImpl
+org.ccil.cowan.tagsoup.AutoDetector
+org.ccil.cowan.tagsoup.Element
+org.ccil.cowan.tagsoup.ElementType
+org.ccil.cowan.tagsoup.HTMLModels
+org.ccil.cowan.tagsoup.HTMLScanner
+org.ccil.cowan.tagsoup.HTMLSchema
+org.ccil.cowan.tagsoup.Parser
+org.ccil.cowan.tagsoup.Parser$1
+org.ccil.cowan.tagsoup.ScanHandler
+org.ccil.cowan.tagsoup.Scanner
+org.ccil.cowan.tagsoup.Schema
 org.json.JSON
 org.json.JSONArray
 org.json.JSONException
diff --git a/proto/src/ipconnectivity.proto b/proto/src/ipconnectivity.proto
index b5afc40..76c5418 100644
--- a/proto/src/ipconnectivity.proto
+++ b/proto/src/ipconnectivity.proto
@@ -9,6 +9,8 @@
 // NetworkId represents the id given by the system to a physical network on the
 // Android device. It is used to relates events to each other for devices with
 // multiple networks (WiFi, 4G, ...).
+// Deprecated since version 3, replaced by top-level network_id field in
+// IpConnectivityEvent.
 message NetworkId {
   // Every network gets assigned a network_id on creation based on order of
   // creation. Thus network_id N is assigned to the network created directly
@@ -91,7 +93,8 @@
 // This message is associated to android.net.metrics.NetworkEvent.
 message NetworkEvent {
   // The id of the network on which this event happened.
-  optional NetworkId network_id = 1;
+  // Deprecated since version 3.
+  optional NetworkId network_id = 1 [deprecated = true];
 
   // The type of network event, represented by NETWORK_* constants defined in
   // android.net.metrics.NetworkEvent.
@@ -107,7 +110,8 @@
 // This message is associated to android.net.metrics.ValidationProbeEvent.
 message ValidationProbeEvent {
   // The id of the network for which the probe was sent.
-  optional NetworkId network_id = 1;
+  // Deprecated since version 3.
+  optional NetworkId network_id = 1 [deprecated = true];
 
   // The time it took for that probe to complete or time out.
   optional int32 latency_ms = 2;
@@ -167,18 +171,28 @@
 
 // Represents latency and errno statistics of the connect() system call.
 // Since version 2.
+// Next tag: 7
 message ConnectStatistics {
   // The number of connect() operations recorded.
   optional int32 connect_count = 1;
 
+  // The number of connect() operations done in blocking mode.
+  // Since version 3.
+  optional int32 connect_blocking_count = 5;
+
   // The number of connect() operations with IPv6 socket address.
   optional int32 ipv6_addr_count = 2;
 
-  // The time it took for each successful connect() operation to complete.
-  // The number of repeated values can be less than connect_count in case of
-  // event rate-limiting.
+  // The time it took for successful blocking connect() operations to complete
+  // The number of repeated values can be less than connect_blocking_count in
+  // case of event rate-limiting.
   repeated int32 latencies_ms = 3;
 
+  // The time it took for successful connect() operation to complete in
+  // non-blocking mode. The number of repeated values can be less than
+  // connect_count - connect_blocking_count in case of event rate-limiting.
+  repeated int32 non_blocking_latencies_ms = 6;
+
   // Counts of all error values returned by failed connect() operations.
   // The Pair key field is the errno code. The Pair value field is the count
   // for that errno code.
@@ -212,10 +226,15 @@
 
 // Represents the generation of an Android Packet Filter program.
 // Since version 1.
+// Next tag: 8
 message ApfProgramEvent {
-  // Lifetime of the program in seconds.
+  // Maximum lifetime of the program in seconds.
   optional int64 lifetime = 1;
 
+  // Effective lifetime of the program in seconds from the time the
+  // program was installed to the time it was replaced or removed.
+  optional int64 effective_lifetime = 7;
+
   // Number of RAs filtered by the APF program.
   optional int32 filtered_ras = 2;
 
@@ -236,6 +255,7 @@
 // Represents Router Advertisement listening statistics for an interface with
 // Android Packet Filter enabled.
 // Since version 1.
+// Next tag: 12
 message ApfStatistics {
   // The time interval in milliseconds these stastistics cover.
   optional int64 duration_ms = 1;
@@ -261,6 +281,14 @@
 
   // The maximum APF program size in byte advertised by hardware.
   optional int32 max_program_size = 9;
+
+  // The total number of successful APF program updates triggered by any state
+  // change in ApfFilter. Since version 3.
+  optional int32 program_updates_all = 10;
+
+  // The total number of APF program updates triggered when disabling the
+  // multicast filter. Since version 3.
+  optional int32 program_updates_allowing_multicast = 11;
 }
 
 // Represents the reception of a Router Advertisement packet for an interface
@@ -308,7 +336,7 @@
 }
 
 // Represents one of the IP connectivity event defined in this file.
-// Next tag: 16
+// Next tag: 19
 message IpConnectivityEvent {
   // Time in ms when the event was recorded.
   optional int64 time_ms = 1;
@@ -318,7 +346,27 @@
   // Since version 2.
   optional LinkLayer link_layer = 15;
 
-  // Event type.
+  // Represents the id given by the system to a physical network on the device.
+  // Every network gets assigned a unique id on creation from a monotonic
+  // counter. The value 0 is never assigned to a network and means no network.
+  // It is used to correlate different types of events to each other for devices
+  // with multiple networks (WiFi, 4G, ...).
+  // Since version 3.
+  optional int32 network_id = 16;
+
+  // The interface name (wlan, rmnet, lo, ...) on which the event happened.
+  // Present if the link_layer field was not inferred from the if_name on
+  // the device, so that post-processing of the serialized proto can backfill
+  // link_layer. Since version 3.
+  optional string if_name = 17;
+
+  // The transport types of the network on which the event happened, expressed
+  // as a bit field of TRANSPORT_* constants as defined in NetworkCapabilities.
+  // Present if the link_layer field was not inferred from the transport types,
+  // so that post-processing of the serialized proto can backfill link_layer
+  // Since version 3.
+  optional int64 transports = 18;
+
   oneof event {
 
     // An event about the system default network.
@@ -371,9 +419,10 @@
   optional int32 dropped_events = 2;
 
   // The version number of the metrics events being collected.
-  //  nyc-dev: not populated, implicitly 0.
+  //  nyc:     not populated, implicitly 0.
   //  nyc-dr1: not populated, implicitly 1 (sailfish and marlin only).
   //  nyc-mr1: not populated, implicitly 1.
   //  nyc-mr2: 2.
+  //  oc:      3.
   optional int32 version = 3;
 };
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index c822652..c45de0d 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -2157,7 +2157,7 @@
 
     // ACTION: Settings -> Select summary tab.
     // CATEGORY: SETTINGS
-    ACTION_SELECT_SUMMARY=476;
+    ACTION_SELECT_SUMMARY = 476;
 
     // ACTION: Settings -> Select support tab.
     // CATEGORY: SETTINGS
@@ -2208,7 +2208,7 @@
     NIGHT_DISPLAY_SETTINGS = 488;
 
     // ACTION: Settings -> Storage -> Manage storage -> Click Storage Manager
-        //   SUBTYPE: false is off, true is on
+    //   SUBTYPE: false is off, true is on
     ACTION_TOGGLE_STORAGE_MANAGER = 489;
 
     // Settings launched from collapsed quick settings.
@@ -3449,6 +3449,97 @@
     // OS: O
     STORAGE_FILES = 841;
 
+    // FIELD - Rank of the clicked Settings search result
+    FIELD_SETTINGS_SERACH_RESULT_RANK = 842;
+
+    // OPEN: Settings > Apps > Default Apps > Assist >  Default assist
+    DEFAULT_ASSIST_PICKER = 843;
+
+    // OPEN: Settings > Apps > Default Apps > Assist >  Default voice input
+    DEFAULT_VOICE_INPUT_PICKER = 844;
+
+    // OPEN: Settings > Storage > [Profile]
+    SETTINGS_STORAGE_PROFILE = 845;
+
+    // OPEN: Settings > Security & screen lock -> Encryption & crendentials
+    // CATEGORY: SETTINGS
+    // OS: O
+    ENCRYPTION_AND_CREDENTIAL = 846;
+
+    // ACTION: Settings > About device > Build number
+    ACTION_SETTINGS_BUILD_NUMBER_PREF = 847;
+
+    // FIELD: Whether developer mode has already been enabled when clicking build number preference
+    FIELD_SETTINGS_BUILD_NUMBER_DEVELOPER_MODE_ENABLED = 848;
+
+    // OPEN: Settings > Wi-Fi > Network Details (click on Access Point)
+    // CATEGORY: SETTINGS
+    // OS: O
+    WIFI_NETWORK_DETAILS = 849;
+
+    // ACTION: Settings > Battery > Menu > Usage Alerts
+    ACTION_SETTINGS_MENU_BATTERY_USAGE_ALERTS = 850;
+
+    // ACTION: Settings > Battery > Menu > Optimization
+    ACTION_SETTINGS_MENU_BATTERY_OPTIMIZATION = 851;
+
+    // ACTION: Settings > Battery > Menu > Apps Toggle
+    ACTION_SETTINGS_MENU_BATTERY_APPS_TOGGLE = 852;
+
+    // ACTION: Settings > Any preference is changed
+    ACTION_SETTINGS_PREFERENCE_CHANGE = 853;
+
+    // FIELD: The name of preference when it is changed in Settings
+    FIELD_SETTINGS_PREFERENCE_CHANGE_NAME = 854;
+
+    // FIELD: The new value of preference when it is changed in Settings
+    FIELD_SETTINGS_PREFERENCE_CHANGE_VALUE = 855;
+
+    // OPEN: Notification channel created. CLOSE: Notification channel deleted. UPDATE: notification
+    // channel updated
+    // PACKAGE: the package the channel belongs too
+    // CATEGORY: NOTIFICATION
+    // OS: O
+    ACTION_NOTIFICATION_CHANNEL = 856;
+
+    // Tagged data for notification channel. String.
+    FIELD_NOTIFICATION_CHANNEL_ID = 857;
+
+    // Tagged data for notification channel. int.
+    FIELD_NOTIFICATION_CHANNEL_IMPORTANCE = 858;
+
+    // OPEN: Notification channel group created.
+    // PACKAGE: the package the group belongs to
+    // CATEGORY: NOTIFICATION
+    // OS: O
+    ACTION_NOTIFICATION_CHANNEL_GROUP = 859;
+
+    // Tagged data for notification channel group. String.
+    FIELD_NOTIFICATION_CHANNEL_GROUP_ID = 860;
+
+    // OPEN: Settings > Wi-Fi > Wifi Preferences -> Advanced -> Network Scorer
+    // CATEGORY: SETTINGS
+    // OS: O
+    SETTINGS_NETWORK_SCORER = 861;
+
+    // OPEN: Settings > About device > Model > Hardware info dialog
+    DIALOG_SETTINGS_HARDWARE_INFO = 862;
+
+    // ACTION: Checks whether a contact's phone still exists
+    // Value 0: It doesn't exist anymore
+    // Value 1: It still exists
+    // Value 2: A SecurityException was thrown
+    // CATEGORY: SETTINGS
+    // OS: N
+    ACTION_PHONE_EXISTS = 863;
+
+    // ACTION: Retrieves a contact from CP2
+    // Value 0: Contact retrieved without issues
+    // Value 1: An IllegalArgumentException was thrown
+    // CATEGORY: SETTINGS
+    // OS: N
+    ACTION_GET_CONTACT = 864;
+
     // ---- End O Constants, all O constants go above this line ----
 
     // Add new aosp constants above this line.
diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto
index 9416ac1..7eefb7e 100644
--- a/proto/src/wifi.proto
+++ b/proto/src/wifi.proto
@@ -435,9 +435,28 @@
 
 // Number of occurrences of a soft AP session return code
 message SoftApReturnCodeCount {
-  // Return code of the soft AP session
-  optional int32 return_code = 1;
+
+  enum SoftApStartResult {
+
+    // SoftApManager return code unknown
+    SOFT_AP_RETURN_CODE_UNKNOWN = 0;
+
+    // SoftAp started successfully
+    SOFT_AP_STARTED_SUCCESSFULLY = 1;
+
+    // Catch all for failures with no specific failure reason
+    SOFT_AP_FAILED_GENERAL_ERROR = 2;
+
+    // SoftAp failed to start due to NO_CHANNEL error
+    SOFT_AP_FAILED_NO_CHANNEL = 3;
+  }
+
+  // Historical, no longer used for writing as of 01/2017.
+  optional int32 return_code = 1 [deprecated = true];
 
   // Occurrences of this soft AP return code
   optional int32 count = 2;
+
+  // Result of attempt to start SoftAp
+  optional SoftApStartResult start_result = 3;
 }
diff --git a/rs/java/android/renderscript/Element.java b/rs/java/android/renderscript/Element.java
index 9d2f750..667bf71 100644
--- a/rs/java/android/renderscript/Element.java
+++ b/rs/java/android/renderscript/Element.java
@@ -1071,7 +1071,6 @@
             mSize += mElements[ct].mSize * mArraySizes[ct];
         }
         updateVisibleSubElements();
-        guard.open("destroy");
     }
 
     Element(long id, RenderScript rs, DataType dt, DataKind dk, boolean norm, int size) {
@@ -1091,7 +1090,6 @@
         mKind = dk;
         mNormalized = norm;
         mVectorSize = size;
-        guard.open("destroy");
     }
 
     Element(long id, RenderScript rs) {
diff --git a/rs/java/android/renderscript/Type.java b/rs/java/android/renderscript/Type.java
index 9252898..dc23785 100644
--- a/rs/java/android/renderscript/Type.java
+++ b/rs/java/android/renderscript/Type.java
@@ -227,7 +227,6 @@
 
     Type(long id, RenderScript rs) {
         super(id, rs);
-        guard.open("destroy");
     }
 
     @Override
diff --git a/rs/jni/Android.mk b/rs/jni/Android.mk
index bf3681b..447a47d 100644
--- a/rs/jni/Android.mk
+++ b/rs/jni/Android.mk
@@ -19,22 +19,17 @@
 
 LOCAL_STATIC_LIBRARIES :=
 
-rs_generated_include_dir := $(call intermediates-dir-for,SHARED_LIBRARIES,libRS,,)
-
 LOCAL_C_INCLUDES += \
     $(JNI_H_INCLUDE) \
     frameworks/rs \
     frameworks/base/core/jni \
-    frameworks/base/libs/hwui \
-    $(rs_generated_include_dir)
+    frameworks/base/libs/hwui
 
 LOCAL_CFLAGS += -Wno-unused-parameter
 LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
 
-LOCAL_ADDITIONAL_DEPENDENCIES := $(addprefix $(rs_generated_include_dir)/,rsgApiFuncDecl.h)
 LOCAL_MODULE:= librs_jni
-LOCAL_ADDITIONAL_DEPENDENCIES += $(rs_generated_source)
 LOCAL_MODULE_TAGS := optional
-LOCAL_REQUIRED_MODULES := libRS libRSDriver
+LOCAL_REQUIRED_MODULES := libRS
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index af370ff..2300da3 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -35,8 +35,8 @@
 #include "android_runtime/android_util_AssetManager.h"
 #include "android/graphics/GraphicsJNI.h"
 
-#include <rs.h>
 #include <rsEnv.h>
+#include <rsApiStubs.h>
 #include <gui/Surface.h>
 #include <gui/GLConsumer.h>
 #include <android_runtime/android_graphics_SurfaceTexture.h>
@@ -1134,7 +1134,7 @@
     // we will pack mType; mKind; mNormalized; mVectorSize; NumSubElements
     assert(dataSize == 5);
 
-    uintptr_t elementData[5];
+    uint32_t elementData[5];
     rsaElementGetNativeData((RsContext)con, (RsElement)id, elementData, dataSize);
 
     for(jint i = 0; i < dataSize; i ++) {
@@ -1157,7 +1157,7 @@
 
     uintptr_t *ids = (uintptr_t*)malloc(dataSize * sizeof(uintptr_t));
     const char **names = (const char **)malloc(dataSize * sizeof(const char *));
-    uint32_t *arraySizes = (uint32_t *)malloc(dataSize * sizeof(uint32_t));
+    size_t *arraySizes = (size_t *)malloc(dataSize * sizeof(size_t));
 
     rsaElementGetSubElements((RsContext)con, (RsElement)id, ids, names, arraySizes,
                              (uint32_t)dataSize);
diff --git a/services/Android.mk b/services/Android.mk
index e760fe2..4452543 100644
--- a/services/Android.mk
+++ b/services/Android.mk
@@ -5,6 +5,9 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := services
+LOCAL_DEX_PREOPT_APP_IMAGE := true
+LOCAL_DEX_PREOPT_GENERATE_PROFILE := true
+LOCAL_DEX_PREOPT_PROFILE_CLASS_LISTING := $(LOCAL_PATH)/profile-classes
 
 LOCAL_SRC_FILES := $(call all-java-files-under,java)
 
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index aae5dd8..44afe1d 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -912,8 +912,21 @@
      */
     // TODO: (multi-display) Make sure this works for multiple displays.
     boolean getAccessibilityFocusClickPointInScreen(Point outPoint) {
-        return getInteractionBridgeLocked()
-                .getAccessibilityFocusClickPointInScreenNotLocked(outPoint);
+        return getInteractionBridge().getAccessibilityFocusClickPointInScreenNotLocked(outPoint);
+    }
+
+    /**
+     * Perform an accessibility action on the view that currently has accessibility focus.
+     * Has no effect if no item has accessibility focus, if the item with accessibility
+     * focus does not expose the specified action, or if the action fails.
+     *
+     * @param actionId The id of the action to perform.
+     *
+     * @return {@code true} if the action was performed. {@code false} if it was not.
+     */
+    public boolean performActionOnAccessibilityFocusedItem(
+            AccessibilityNodeInfo.AccessibilityAction action) {
+        return getInteractionBridge().performActionOnAccessibilityFocusedItemNotLocked(action);
     }
 
     /**
@@ -1029,11 +1042,13 @@
         onUserStateChangedLocked(userState);
     }
 
-    private InteractionBridge getInteractionBridgeLocked() {
-        if (mInteractionBridge == null) {
-            mInteractionBridge = new InteractionBridge();
+    private InteractionBridge getInteractionBridge() {
+        synchronized (mLock) {
+            if (mInteractionBridge == null) {
+                mInteractionBridge = new InteractionBridge();
+            }
+            return mInteractionBridge;
         }
-        return mInteractionBridge;
     }
 
     private boolean notifyGestureLocked(int gestureId, boolean isDefault) {
@@ -1991,23 +2006,26 @@
     private void updateFingerprintGestureHandling(UserState userState) {
         final List<Service> services;
         synchronized (mLock) {
-            // Only create the controller when a service wants to use the feature
             services = userState.mBoundServices;
-            int numServices = services.size();
-            for (int i = 0; i < numServices; i++) {
-                if (services.get(i).isCapturingFingerprintGestures()) {
-                    final long identity = Binder.clearCallingIdentity();
-                    IFingerprintService service = null;
-                    try {
-                        service = IFingerprintService.Stub.asInterface(
-                                ServiceManager.getService(Context.FINGERPRINT_SERVICE));
-                    } finally {
-                        Binder.restoreCallingIdentity(identity);
-                    }
-                    if (service != null) {
-                        mFingerprintGestureDispatcher = new FingerprintGestureDispatcher(
-                                service, mLock);
-                        break;
+            if ((mFingerprintGestureDispatcher == null)
+                    &&  mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
+                // Only create the controller when a service wants to use the feature
+                int numServices = services.size();
+                for (int i = 0; i < numServices; i++) {
+                    if (services.get(i).isCapturingFingerprintGestures()) {
+                        final long identity = Binder.clearCallingIdentity();
+                        IFingerprintService service = null;
+                        try {
+                            service = IFingerprintService.Stub.asInterface(
+                                    ServiceManager.getService(Context.FINGERPRINT_SERVICE));
+                        } finally {
+                            Binder.restoreCallingIdentity(identity);
+                        }
+                        if (service != null) {
+                            mFingerprintGestureDispatcher = new FingerprintGestureDispatcher(
+                                    service, mLock);
+                            break;
+                        }
                     }
                 }
             }
@@ -2274,11 +2292,7 @@
 
                 case MSG_CLEAR_ACCESSIBILITY_FOCUS: {
                     final int windowId = msg.arg1;
-                    InteractionBridge bridge;
-                    synchronized (mLock) {
-                        bridge = getInteractionBridgeLocked();
-                    }
-                    bridge.clearAccessibilityFocusNotLocked(windowId);
+                    getInteractionBridge().clearAccessibilityFocusNotLocked(windowId);
                 } break;
 
                 case MSG_SEND_SERVICES_STATE_CHANGED_TO_CLIENTS: {
@@ -4051,6 +4065,24 @@
             }
         }
 
+        /**
+         * Perform an accessibility action on the view that currently has accessibility focus.
+         * Has no effect if no item has accessibility focus, if the item with accessibility
+         * focus does not expose the specified action, or if the action fails.
+         *
+         * @param actionId The id of the action to perform.
+         *
+         * @return {@code true} if the action was performed. {@code false} if it was not.
+         */
+        public boolean performActionOnAccessibilityFocusedItemNotLocked(
+                AccessibilityNodeInfo.AccessibilityAction action) {
+            AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked();
+            if ((focus == null) || !focus.getActionList().contains(action)) {
+                return false;
+            }
+            return focus.performAction(action.getId());
+        }
+
         public boolean getAccessibilityFocusClickPointInScreenNotLocked(Point outPoint) {
             AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked();
             if (focus == null) {
diff --git a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
index ecba245..6e87f88 100644
--- a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
@@ -29,6 +29,7 @@
 import android.view.WindowManagerPolicy;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -407,6 +408,13 @@
             mSendTouchInteractionEndDelayed.forceSendAndRemove();
         }
 
+        // Try to use the standard accessibility API to click
+        if (mAms.performActionOnAccessibilityFocusedItem(
+                AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK)) {
+            return true;
+        }
+        Slog.e(LOG_TAG, "ACTION_CLICK failed. Dispatching motion events to simulate click.");
+
         final int pointerIndex = event.getActionIndex();
         final int pointerId = event.getPointerId(pointerIndex);
 
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 4d2b106..8aa37ef 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -709,7 +709,7 @@
     }
 
     private boolean isUserRunningAndUnlocked(@UserIdInt int userId) {
-        return mUserManager.isUserRunning(userId) && StorageManager.isUserKeyUnlocked(userId);
+        return mUserManager.isUserUnlockingOrUnlocked(userId);
     }
 
     @Override
@@ -1603,7 +1603,7 @@
 
     @Override
     public boolean requestPinAppWidget(String callingPackage, ComponentName componentName,
-            IntentSender resultSender) {
+            Bundle extras, IntentSender resultSender) {
         final int callingUid = Binder.getCallingUid();
         final int userId = UserHandle.getUserId(callingUid);
 
@@ -1628,7 +1628,7 @@
         }
 
         return LocalServices.getService(ShortcutServiceInternal.class)
-                .requestPinAppWidget(callingPackage, info, resultSender, userId);
+                .requestPinAppWidget(callingPackage, info, extras, resultSender, userId);
     }
 
     @Override
diff --git a/services/autofill/java/com/android/server/autofill/AnchoredWindow.java b/services/autofill/java/com/android/server/autofill/AnchoredWindow.java
deleted file mode 100644
index 64c6abd..0000000
--- a/services/autofill/java/com/android/server/autofill/AnchoredWindow.java
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * 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.autofill;
-
-import static com.android.server.autofill.Helper.DEBUG;
-
-import android.annotation.Nullable;
-import android.content.Context;
-import android.graphics.PixelFormat;
-import android.graphics.Rect;
-import android.os.IBinder;
-import android.util.Slog;
-import android.view.Gravity;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.View.MeasureSpec;
-import android.view.WindowManager;
-import android.view.WindowManager.LayoutParams;
-import android.widget.FrameLayout;
-
-/**
- * A window above the application that is smartly anchored to a rectangular region.
- */
-final class AnchoredWindow implements View.OnLayoutChangeListener, View.OnTouchListener {
-    private static final String TAG = "AutoFill";
-
-    private static final int NULL_HEIGHT = -1;
-
-    private final WindowManager mWm;
-    private final IBinder mAppToken;
-    private final View mContentView;
-
-    private final View mWindowSizeListenerView;
-    private final int mMinMargin;
-
-    private int mLastHeight = NULL_HEIGHT;
-    @Nullable
-    private Rect mLastBounds;
-    @Nullable
-    private Rect mLastDisplayBounds;
-
-    /**
-     * Constructor.
-     *
-     * @param wm window manager that draws the content on a window
-     * @param appToken token to pass to window manager
-     * @param contentView content of the window
-     */
-    AnchoredWindow(WindowManager wm, IBinder appToken, View contentView) {
-        mWm = wm;
-        mAppToken = appToken;
-        mContentView = contentView;
-
-        mContentView.addOnLayoutChangeListener(this);
-
-        Context context = contentView.getContext();
-
-        mWindowSizeListenerView = new FrameLayout(context);
-        mWindowSizeListenerView.addOnLayoutChangeListener(this);
-
-        mMinMargin = context.getResources().getDimensionPixelSize(
-                com.android.internal.R.dimen.autofill_fill_min_margin);
-    }
-
-    /**
-     * Shows the window.
-     *
-     * @param bounds the region the window should be anchored to
-     */
-    void show(Rect bounds) {
-        if (DEBUG) Slog.d(TAG, "show bounds=" + bounds);
-
-        if (!mWindowSizeListenerView.isAttachedToWindow()) {
-            if (DEBUG) Slog.d(TAG, "adding mWindowSizeListenerView");
-            LayoutParams params = createWindowLayoutParams(
-                    mAppToken,
-                    LayoutParams.FLAG_NOT_TOUCHABLE); // not touchable
-            params.gravity = Gravity.LEFT | Gravity.TOP;
-            params.x = 0;
-            params.y = 0;
-            params.width = LayoutParams.MATCH_PARENT;
-            params.height = LayoutParams.MATCH_PARENT;
-            mWm.addView(mWindowSizeListenerView, params);
-        }
-
-        updateBounds(bounds);
-    }
-
-    /**
-     * Hides the window.
-     */
-    void hide() {
-        if (DEBUG) Slog.d(TAG, "hide");
-
-        mLastHeight = NULL_HEIGHT;
-        mLastBounds = null;
-        mLastDisplayBounds = null;
-
-        if (mWindowSizeListenerView.isAttachedToWindow()) {
-            if (DEBUG) Slog.d(TAG, "removing mWindowSizeListenerView");
-            mWm.removeView(mWindowSizeListenerView);
-        }
-
-        if (mContentView.isAttachedToWindow()) {
-            if (DEBUG) Slog.d(TAG, "removing mContentView");
-            mContentView.setOnTouchListener(null);
-            mWm.removeView(mContentView);
-        }
-    }
-
-    @Override
-    public void onLayoutChange(View view, int left, int top, int right, int bottom,
-            int oldLeft, int oldTop, int oldRight, int oldBottom) {
-        if (view == mWindowSizeListenerView) {
-            if (DEBUG) Slog.d(TAG, "onLayoutChange() for mWindowSizeListenerView");
-            // mWindowSizeListenerView layout changed, get the size of the display bounds and updateLocked
-            // the window.
-            final Rect displayBounds = new Rect();
-            view.getBoundsOnScreen(displayBounds);
-            updateDisplayBounds(displayBounds);
-        } else if (view == mContentView) {
-            // mContentView layout changed, updateLocked the window in case its height changed.
-            if (DEBUG) Slog.d(TAG, "onLayoutChange() for mContentView");
-            updateHeight();
-        }
-    }
-
-    // When the window is touched outside, hide the window.
-    @Override
-    public boolean onTouch(View view, MotionEvent event) {
-        if (view == mContentView && event.getAction() == MotionEvent.ACTION_OUTSIDE) {
-            hide();
-            return true;
-        }
-        return false;
-    }
-
-    private boolean updateHeight() {
-        final Rect displayBounds = mLastDisplayBounds;
-        if (displayBounds == null) {
-            return false;
-        }
-
-        mContentView.measure(
-                MeasureSpec.makeMeasureSpec(displayBounds.width(), MeasureSpec.AT_MOST),
-                MeasureSpec.makeMeasureSpec(displayBounds.height(), MeasureSpec.AT_MOST));
-        int height = mContentView.getMeasuredHeight();
-        if (height != mLastHeight) {
-            if (DEBUG) Slog.d(TAG, "updateLocked height=" + height);
-            mLastHeight = height;
-            update(height, mLastBounds, displayBounds);
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    private void updateBounds(Rect bounds) {
-        if (!bounds.equals(mLastBounds)) {
-            if (DEBUG) Slog.d(TAG, "updateLocked bounds=" + bounds);
-            mLastBounds = bounds;
-
-            update(mLastHeight, bounds, mLastDisplayBounds);
-        }
-    }
-
-    private void updateDisplayBounds(Rect displayBounds) {
-        if (!displayBounds.equals(mLastDisplayBounds)) {
-            if (DEBUG) Slog.d(TAG, "updateLocked displayBounds=" + displayBounds);
-            mLastDisplayBounds = displayBounds;
-
-            if (!updateHeight()) {
-                update(mLastHeight, mLastBounds, displayBounds);
-            }
-        }
-    }
-
-    // Updates the window if height, bounds, and displayBounds are not null.
-    // Caller should ensure that something changed before calling.
-    private void update(int height, @Nullable Rect bounds, @Nullable Rect displayBounds) {
-        if (height == NULL_HEIGHT || bounds == null || displayBounds == null) {
-            return;
-        }
-
-        if (DEBUG) Slog.d(TAG, "updateLocked height=" + height + ", bounds=" + bounds
-                + ", displayBounds=" + displayBounds);
-
-        final LayoutParams params = createWindowLayoutParams(mAppToken,
-                LayoutParams.FLAG_NOT_TOUCH_MODAL // outside touches go to windows behind us
-                | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH); // outside touches trigger MotionEvent
-        params.setTitle("AutoFill Fill"); // used for debugging
-        updatePosition(params, height, mMinMargin, bounds, displayBounds);
-        if (!mContentView.isAttachedToWindow()) {
-            if (DEBUG) Slog.d(TAG, "adding mContentView");
-            mWm.addView(mContentView, params);
-            mContentView.setOnTouchListener(this);
-        } else {
-            if (DEBUG) Slog.d(TAG, "updating mContentView");
-            mWm.updateViewLayout(mContentView, params);
-        }
-    }
-
-    /**
-     * Updates the position of the window by altering the {@link LayoutParams}.
-     *
-     * <p>The window can be anchored either above or below the bounds. Anchoring the window below
-     * the bounds is preferred, if it fits. Otherwise, anchor the window on the side with more
-     * space.
-     *
-     * @param params the params to updateLocked
-     * @param height the requested height of the window
-     * @param minMargin the minimum margin between the window and the display bounds
-     * @param bounds the region the window should be anchored to
-     * @param displayBounds the region in which the window may be displayed
-     */
-    private static void updatePosition(
-            LayoutParams params,
-            int height,
-            int minMargin,
-            Rect bounds,
-            Rect displayBounds) {
-        boolean below;
-        int verticalSpace;
-        final int verticalSpaceBelow = displayBounds.bottom - bounds.bottom - minMargin;
-        if (height <= verticalSpaceBelow) {
-            // Fits below bounds.
-            below = true;
-            verticalSpace = height;
-        } else {
-            final int verticalSpaceAbove = bounds.top - displayBounds.top - minMargin;
-            if (height <= verticalSpaceAbove) {
-                // Fits above bounds.
-                below = false;
-                verticalSpace = height;
-            } else {
-                // Pick above/below based on which has the most space.
-                if (verticalSpaceBelow >= verticalSpaceAbove) {
-                    below = true;
-                    verticalSpace = verticalSpaceBelow;
-                } else {
-                    below = false;
-                    verticalSpace = verticalSpaceAbove;
-                }
-            }
-        }
-
-        int gravity;
-        int y;
-        if (below) {
-            if (DEBUG) Slog.d(TAG, "anchorBelow");
-            gravity = Gravity.TOP | Gravity.LEFT;
-            y = bounds.bottom - displayBounds.top;
-        } else {
-            if (DEBUG) Slog.d(TAG, "anchorAbove");
-            gravity = Gravity.BOTTOM | Gravity.LEFT;
-            y = displayBounds.bottom - bounds.top;
-        }
-
-        final int x = bounds.left - displayBounds.left;
-
-        params.gravity = gravity;
-        params.x = x;
-        params.y = y;
-        params.width = bounds.width();
-        params.height = verticalSpace;
-    }
-
-    private static LayoutParams createWindowLayoutParams(IBinder appToken, int flags) {
-        final LayoutParams params = new LayoutParams();
-        params.token = appToken;
-        params.type = LayoutParams.TYPE_PHONE;
-        params.flags =
-                flags
-                | LayoutParams.FLAG_NOT_FOCUSABLE // don't receive input events
-                | LayoutParams.FLAG_ALT_FOCUSABLE_IM; // resize for soft input
-        params.format = PixelFormat.TRANSLUCENT;
-        return params;
-    }
-}
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
index 3257812..e943c4c 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
@@ -18,7 +18,6 @@
 
 import static android.Manifest.permission.MANAGE_AUTO_FILL;
 import static android.content.Context.AUTO_FILL_MANAGER_SERVICE;
-import static com.android.server.autofill.Helper.DEBUG;
 import static com.android.server.autofill.Helper.VERBOSE;
 
 import android.Manifest;
@@ -57,6 +56,7 @@
 import com.android.server.FgThread;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
+import com.android.server.autofill.ui.AutoFillUI;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -100,14 +100,16 @@
     private SparseArray<AutoFillManagerServiceImpl> mServicesCache = new SparseArray<>();
 
     // TODO(b/33197203): set a different max (or disable it) on low-memory devices.
-    private final LocalLog mRequestsHistory = new LocalLog(100);
+    private final LocalLog mRequestsHistory = new LocalLog(20);
 
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
             if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
                 final String reason = intent.getStringExtra("reason");
-                if (DEBUG) Slog.d(TAG, "close system dialogs: " + reason);
+                if (VERBOSE) {
+                    Slog.v(TAG, "close system dialogs: " + reason);
+                }
                 mUi.hideAll();
             }
         }
@@ -184,6 +186,29 @@
     }
 
     // Called by Shell command.
+    void destroySessions(int userId, IResultReceiver receiver) {
+        Slog.i(TAG, "destroySessions() for userId " + userId);
+        mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
+
+        synchronized (mLock) {
+            if (userId != UserHandle.USER_ALL) {
+                mServicesCache.get(userId).destroySessionsLocked();
+            } else {
+                final int size = mServicesCache.size();
+                for (int i = 0; i < size; i++) {
+                    mServicesCache.valueAt(i).destroySessionsLocked();
+                }
+            }
+        }
+
+        try {
+            receiver.send(0, new Bundle());
+        } catch (RemoteException e) {
+            // Just ignore it...
+        }
+    }
+
+    // Called by Shell command.
     void listSessions(int userId, IResultReceiver receiver) {
         Slog.i(TAG, "listSessions() for userId " + userId);
         mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
@@ -222,6 +247,13 @@
         }
     }
 
+    // Called by Shell command.
+    public void setSaveTimeout(int timeout) {
+        Slog.i(TAG, "setSaveTimeout("  + timeout + ")");
+        mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
+        mUi.setSaveTimeout(timeout);
+    }
+
     /**
      * Removes a cached service for a given user.
      */
@@ -246,7 +278,9 @@
     private IBinder getTopActivityForUser() {
         final List<IBinder> topActivities = LocalServices
                 .getService(ActivityManagerInternal.class).getTopVisibleActivities();
-        if (DEBUG) Slog.d(TAG, "Top activities (" + topActivities.size() + "): " + topActivities);
+        if (VERBOSE) {
+            Slog.v(TAG, "Top activities (" + topActivities.size() + "): " + topActivities);
+        }
         if (topActivities.isEmpty()) {
             Slog.w(TAG, "Could not get top activity");
             return null;
@@ -271,29 +305,29 @@
         }
 
         @Override
-        public void startSession(IBinder activityToken, IBinder appCallback, AutoFillId autoFillId,
-                Rect bounds, AutoFillValue value, int userId) {
-            // TODO(b/33197203): make sure it's called by resumed / focused activity
-
-            if (VERBOSE) {
-                Slog.v(TAG, "startSession: autoFillId=" + autoFillId + ", bounds=" + bounds
-                        + ", value=" + value);
+        public void setHasCallback(IBinder activityToken, int userId, boolean hasIt) {
+            synchronized (mLock) {
+                final AutoFillManagerServiceImpl service = getServiceForUserLocked(userId);
+                service.setHasCallback(activityToken, hasIt);
             }
+        }
+
+        @Override
+        public void startSession(IBinder activityToken, IBinder windowToken, IBinder appCallback,
+                AutoFillId autoFillId, Rect bounds, AutoFillValue value, int userId,
+                boolean hasCallback) {
+            // TODO(b/33197203): make sure it's called by resumed / focused activity
 
             synchronized (mLock) {
                 final AutoFillManagerServiceImpl service = getServiceForUserLocked(userId);
-                service.startSessionLocked(activityToken, appCallback, autoFillId, bounds, value);
+                service.startSessionLocked(activityToken, windowToken, appCallback,
+                        autoFillId, bounds, value, hasCallback);
             }
         }
 
         @Override
         public void updateSession(IBinder activityToken, AutoFillId id, Rect bounds,
                 AutoFillValue value, int flags, int userId) {
-            if (DEBUG) {
-                Slog.d(TAG, "updateSession: flags=" + flags + ", autoFillId=" + id
-                        + ", bounds=" + bounds + ", value=" + value);
-            }
-
             synchronized (mLock) {
                 final AutoFillManagerServiceImpl service = mServicesCache.get(
                         UserHandle.getCallingUserId());
@@ -305,8 +339,6 @@
 
         @Override
         public void finishSession(IBinder activityToken, int userId) {
-            if (VERBOSE) Slog.v(TAG, "finishSession(): " + activityToken);
-
             synchronized (mLock) {
                 final AutoFillManagerServiceImpl service = mServicesCache.get(
                         UserHandle.getCallingUserId());
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
index a697a8e..aa0840c 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
@@ -56,9 +56,9 @@
 import android.service.autofill.Dataset;
 import android.service.autofill.FillResponse;
 import android.service.autofill.IAutoFillService;
+import android.service.autofill.SaveInfo;
 import android.text.TextUtils;
 import android.util.ArrayMap;
-import android.util.ArraySet;
 import android.util.LocalLog;
 import android.util.PrintWriterPrinter;
 import android.util.Slog;
@@ -70,6 +70,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.os.HandlerCaller;
 import com.android.internal.os.IResultReceiver;
+import com.android.server.autofill.ui.AutoFillUI;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -103,7 +104,7 @@
                 handleSessionSave((IBinder) msg.obj);
                 break;
             default:
-                Slog.d(TAG, "invalid msg: " + msg);
+                Slog.w(TAG, "invalid msg on handler: " + msg);
         }
     };
 
@@ -127,17 +128,18 @@
     private final IResultReceiver mAssistReceiver = new IResultReceiver.Stub() {
         @Override
         public void send(int resultCode, Bundle resultData) throws RemoteException {
-            if (DEBUG) Slog.d(TAG, "resultCode on mAssistReceiver: " + resultCode);
+            if (VERBOSE) {
+                Slog.v(TAG, "resultCode on mAssistReceiver: " + resultCode);
+            }
 
             final AssistStructure structure = resultData.getParcelable(KEY_STRUCTURE);
             if (structure == null) {
-                Slog.w(TAG, "no assist structure for id " + resultCode);
+                Slog.wtf(TAG, "no assist structure for id " + resultCode);
                 return;
             }
 
             final Bundle receiverExtras = resultData.getBundle(KEY_RECEIVER_EXTRAS);
             if (receiverExtras == null) {
-                // Should not happen
                 Slog.wtf(TAG, "No " + KEY_RECEIVER_EXTRAS + " on receiver");
                 return;
             }
@@ -194,7 +196,7 @@
             final ApplicationInfo info = pm.getApplicationInfo(packageName, 0);
             return pm.getApplicationLabel(info);
         } catch (Exception e) {
-            Slog.w(TAG, "Could not get label for " + packageName + ": " + e);
+            Slog.e(TAG, "Could not get label for " + packageName + ": " + e);
             return packageName;
         }
     }
@@ -210,7 +212,7 @@
                 serviceInfo = AppGlobals.getPackageManager().getServiceInfo(serviceComponent,
                         0, mUserId);
             } catch (RuntimeException | RemoteException e) {
-                Slog.e(TAG, "Bad auto-fill service name " + componentName, e);
+                Slog.e(TAG, "Bad auto-fill service name " + componentName + ": " + e);
                 return;
             }
         }
@@ -234,7 +236,7 @@
                 sendStateToClients();
             }
         } catch (PackageManager.NameNotFoundException e) {
-            Slog.e(TAG, "Bad auto-fill service name " + componentName, e);
+            Slog.e(TAG, "Bad auto-fill service name " + componentName + ": " + e);
         }
     }
 
@@ -272,15 +274,25 @@
         }
     }
 
-    void startSessionLocked(IBinder activityToken, IBinder appCallbackToken, AutoFillId autoFillId,
-            Rect bounds, AutoFillValue value) {
+    void setHasCallback(IBinder activityToken, boolean hasIt) {
+        if (!hasService()) {
+            return;
+        }
+        final Session session = mSessions.get(activityToken);
+        if (session != null) {
+            session.setHasCallback(hasIt);
+        }
+    }
+
+    void startSessionLocked(IBinder activityToken, IBinder windowToken, IBinder appCallbackToken,
+            AutoFillId autoFillId,  Rect bounds, AutoFillValue value, boolean hasCallback) {
         if (!hasService()) {
             return;
         }
 
-        final String historyItem = "s=" + new ComponentName(mInfo.getServiceInfo().packageName,
-                mInfo.getServiceInfo().name) + " u=" + mUserId + " a=" + activityToken
-                + " i=" + autoFillId + " b=" + bounds + " v=" + value;
+        final String historyItem = "s=" + mInfo.getServiceInfo().packageName
+                + " u=" + mUserId + " a=" + activityToken
+                + " i=" + autoFillId + " b=" + bounds + " hc=" + hasCallback;
         mRequestsHistory.log(historyItem);
 
         // TODO(b/33197203): Handle partitioning
@@ -290,7 +302,8 @@
             return;
         }
 
-        final Session newSession = createSessionByTokenLocked(activityToken, appCallbackToken);
+        final Session newSession = createSessionByTokenLocked(activityToken,
+                windowToken, appCallbackToken, hasCallback);
         newSession.updateLocked(autoFillId, bounds, value, FLAG_START_SESSION);
     }
 
@@ -308,8 +321,10 @@
         session.showSaveLocked();
     }
 
-    private Session createSessionByTokenLocked(IBinder activityToken, IBinder appCallbackToken) {
-        final Session newSession = new Session(mContext, activityToken, appCallbackToken);
+    private Session createSessionByTokenLocked(IBinder activityToken, IBinder windowToken,
+            IBinder appCallbackToken, boolean hasCallback) {
+        final Session newSession = new Session(mContext, activityToken,
+                windowToken, appCallbackToken, hasCallback);
         mSessions.put(activityToken, newSession);
 
         /*
@@ -327,8 +342,6 @@
             try {
                 if (!ActivityManager.getService().requestAutoFillData(mAssistReceiver,
                         receiverExtras, activityToken)) {
-                    // TODO(b/33197203): might need a way to warn user (perhaps a new method on
-                    // AutoFillService).
                     Slog.w(TAG, "failed to request auto-fill data for " + activityToken);
                 }
             } finally {
@@ -345,7 +358,9 @@
         // TODO(b/33197203): add MetricsLogger call
         final Session session = mSessions.get(activityToken);
         if (session == null) {
-            Slog.w(TAG, "updateSessionLocked(): session gone for " + activityToken);
+            if (VERBOSE) {
+                Slog.v(TAG, "updateSessionLocked(): session gone for " + activityToken);
+            }
             return;
         }
 
@@ -365,7 +380,9 @@
     }
 
     void destroyLocked() {
-        if (VERBOSE) Slog.v(TAG, "destroyLocked()");
+        if (VERBOSE) {
+            Slog.v(TAG, "destroyLocked()");
+        }
 
         for (Session session : mSessions.values()) {
             session.destroyLocked();
@@ -376,7 +393,7 @@
     void dumpLocked(String prefix, PrintWriter pw) {
         final String prefix2 = prefix + "  ";
 
-        pw.print(prefix); pw.println("Component:"); pw.println(mInfo != null
+        pw.print(prefix); pw.print("Component:"); pw.println(mInfo != null
                 ? mInfo.getServiceInfo().getComponentName() : null);
 
         if (VERBOSE) {
@@ -397,6 +414,12 @@
         }
     }
 
+    void destroySessionsLocked() {
+        for (Session session : mSessions.values()) {
+            session.removeSelf();
+        }
+    }
+
     void listSessionsLocked(ArrayList<String> output) {
         for (IBinder activityToken : mSessions.keySet()) {
             output.add((mInfo != null ? mInfo.getServiceInfo().getComponentName()
@@ -451,7 +474,7 @@
              * Called when the fill UI is ready to be shown for this view.
              */
             void onFillReady(ViewState viewState, FillResponse fillResponse, Rect bounds,
-                    @Nullable AutoFillValue value);
+                    AutoFillId focusedId, @Nullable AutoFillValue value);
         }
 
         final AutoFillId mId;
@@ -509,19 +532,19 @@
         }
 
         /**
-         * Calls {@link Listener#onFillReady(ViewState, FillResponse, Rect, AutoFillValue)} if the
+         * Calls {@link
+         * Listener#onFillReady(ViewState, FillResponse, Rect, AutoFillId, AutoFillValue)} if the
          * fill UI is ready to be displayed (i.e. when response and bounds are set).
          */
         void maybeCallOnFillReady() {
-            if (mResponse != null && mBounds != null) {
-                mListener.onFillReady(this, mResponse, mBounds, mAutoFillValue);
+            if (mResponse != null && (mResponse.getAuthentication() != null
+                    || mResponse.getDatasets() != null) && mBounds != null) {
+                mListener.onFillReady(this, mResponse, mBounds, mId, mAutoFillValue);
             }
         }
 
         @Override
         public String toString() {
-            if (!DEBUG) return super.toString();
-
             return "ViewState: [id=" + mId + ", value=" + mAutoFillValue + ", bounds=" + mBounds
                     + ", updated = " + mValueUpdated + "]";
         }
@@ -554,6 +577,7 @@
     final class Session implements RemoteFillService.FillServiceCallbacks, ViewState.Listener,
             AutoFillUI.AutoFillUiCallback {
         private final IBinder mActivityToken;
+        private final IBinder mWindowToken;
 
         @GuardedBy("mLock")
         private final Map<AutoFillId, ViewState> mViewStates = new ArrayMap<>();
@@ -585,15 +609,25 @@
         @GuardedBy("mLock")
         private AssistStructure mStructure;
 
-        private Session(Context context, IBinder activityToken, IBinder client) {
+        /**
+         * Whether the client has an {@link android.view.autofill.AutoFillManager.AutofillCallback}.
+         */
+        private boolean mHasCallback;
+
+        private Session(Context context, IBinder activityToken, IBinder windowToken,
+                IBinder client, boolean hasCallback) {
             mRemoteFillService = new RemoteFillService(context,
                     mInfo.getServiceInfo().getComponentName(), mUserId, this);
             mActivityToken = activityToken;
+            mWindowToken = windowToken;
+            mHasCallback = hasCallback;
 
             mClient = IAutoFillManagerClient.Stub.asInterface(client);
             try {
                 client.linkToDeath(() -> {
-                    if (DEBUG) Slog.d(TAG, "app binder died");
+                    if (DEBUG) {
+                        Slog.d(TAG, "app binder died");
+                    }
 
                     removeSelf();
                 }, 0);
@@ -641,8 +675,36 @@
 
         // FillServiceCallbacks
         @Override
-        public void authenticate(IntentSender intent, Intent fillInIntent) {
-            startAuthentication(intent, fillInIntent);
+        public void authenticate(IntentSender intent) {
+            final Intent fillInIntent;
+            synchronized (mLock) {
+                fillInIntent = createAuthFillInIntent(mStructure);
+            }
+            mHandlerCaller.getHandler().post(() -> {
+                startAuthentication(intent, fillInIntent);
+            });
+        }
+
+        // FillServiceCallbacks
+        @Override
+        public void onDisableSelf() {
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                final String autoFillService = Settings.Secure.getStringForUser(
+                        mContext.getContentResolver(),
+                        Settings.Secure.AUTO_FILL_SERVICE, mUserId);
+                if (mInfo.getServiceInfo().getComponentName().equals(
+                        ComponentName.unflattenFromString(autoFillService))) {
+                    Settings.Secure.putStringForUser(mContext.getContentResolver(),
+                            Settings.Secure.AUTO_FILL_SERVICE, null, mUserId);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+            synchronized (mLock) {
+                destroyLocked();
+                mSessions.remove(this);
+            }
         }
 
         // FillServiceCallbacks
@@ -654,7 +716,9 @@
         // AutoFillUiCallback
         @Override
         public void fill(Dataset dataset) {
-            autoFill(dataset);
+            mHandlerCaller.getHandler().post(() -> {
+                autoFill(dataset);
+            });
         }
 
         // AutoFillUiCallback
@@ -664,6 +728,22 @@
                     .sendToTarget();
         }
 
+        // AutoFillUiCallback
+        @Override
+        public void cancelSave() {
+            mHandlerCaller.getHandler().post(() -> {
+                removeSelf();
+            });
+        }
+
+        // AutoFillUiCallback
+        @Override
+        public void onEvent(AutoFillId id, int event) {
+            mHandlerCaller.getHandler().post(() -> {
+                notifyChangeToClient(id, event);
+            });
+        }
+
         public void setAuthenticationResultLocked(Bundle data) {
             if (mCurrentResponse == null || data == null) {
                 removeSelf();
@@ -675,44 +755,47 @@
                     processResponseLocked(mCurrentResponse);
                 } else if (result instanceof Dataset) {
                     Dataset dataset = (Dataset) result;
-                    final int datasetIndex = Helper.indexOfDataset(
-                            dataset.getName(), mCurrentResponse);
-                    if (datasetIndex <= 0) {
-                        Slog.e(TAG, "Response for a dataset auth has"
-                                + " an invalid dataset result: " + dataset.getName());
-                    }
-                    mCurrentResponse.getDatasets().removeAt(datasetIndex);
+                    mCurrentResponse.getDatasets().remove(mAutoFilledDataset);
                     mCurrentResponse.getDatasets().add(dataset);
-                    autoFill(dataset);
+                    mAutoFilledDataset = dataset;
+                    processResponseLocked(mCurrentResponse);
                 }
             }
         }
 
+        public void setHasCallback(boolean hasIt) {
+            mHasCallback = hasIt;
+        }
+
         /**
          * Show the save UI, when session can be saved.
          */
         public void showSaveLocked() {
             if (mStructure == null) {
-                // Sanity check; should not happen...
                 Slog.wtf(TAG, "showSaveLocked(): no mStructure");
                 return;
             }
             if (mCurrentResponse == null) {
-                // Happens when the activity / session was finished before the service replied.
-                Slog.d(TAG, "showSaveLocked(): no mCurrentResponse yet");
+                // Happens when the activity / session was finished before the service replied, or
+                // when the service cannot auto-fill it (and returned a null response).
+                if (DEBUG) {
+                    Slog.d(TAG, "showSaveLocked(): no mCurrentResponse");
+                }
                 return;
             }
-            final ArraySet<AutoFillId> savableIds = mCurrentResponse.getSavableIds();
-            if (VERBOSE) Slog.v(TAG, "showSaveLocked(): savableIds=" + savableIds);
+            final SaveInfo saveInfo = mCurrentResponse.getSaveInfo();
+            if (DEBUG) {
+                Slog.d(TAG, "showSaveLocked(): saveInfo=" + saveInfo);
+            }
 
-            if (savableIds.isEmpty()) {
-                if (DEBUG) Slog.d(TAG, "showSaveLocked(): service doesn't want to save");
+            if (saveInfo == null || saveInfo.getSavableIds() == null
+                    || saveInfo.getSavableIds().isEmpty()) {
                 return;
             }
 
-            final int size = savableIds.size();
+            final int size = saveInfo.getSavableIds().size();
             for (int i = 0; i < size; i++) {
-                final AutoFillId id = savableIds.valueAt(i);
+                final AutoFillId id = saveInfo.getSavableIds().valueAt(i);
                 final ViewState state = mViewStates.get(id);
                 if (state != null && state.mValueUpdated) {
                     final AutoFillValue filledValue = findValue(mAutoFilledDataset, id);
@@ -723,26 +806,35 @@
                         Slog.d(TAG, "finishSessionLocked(): found a change on " + id + ": "
                                 + state.mAutoFillValue);
                     }
-                    mUi.showSaveUi();
+                    getUiForShowing().showSaveUi(
+                            mInfo.getServiceInfo().loadLabel(mContext.getPackageManager()),
+                            saveInfo);
                     return;
                 }
             }
+
             // Nothing changed...
-            if (DEBUG) Slog.d(TAG, "showSaveLocked(): with no changes, comes no responsibilities");
+            if (DEBUG) {
+                Slog.d(TAG, "showSaveLocked(): with no changes, comes no responsibilities");
+            }
         }
 
         /**
          * Calls service when user requested save.
          */
         private void callSaveLocked() {
-            if (DEBUG) Slog.d(TAG, "callSaveLocked(): mViewStates=" + mViewStates);
+            if (DEBUG) {
+                Slog.d(TAG, "callSaveLocked(): mViewStates=" + mViewStates);
+            }
 
             final Bundle extras = this.mCurrentResponse.getExtras();
 
             for (Entry<AutoFillId, ViewState> entry : mViewStates.entrySet()) {
                 final AutoFillValue value = entry.getValue().mAutoFillValue;
                 if (value == null) {
-                    if (VERBOSE) Slog.v(TAG, "callSaveLocked(): skipping " + entry.getKey());
+                    if (VERBOSE) {
+                        Slog.v(TAG, "callSaveLocked(): skipping " + entry.getKey());
+                    }
                     continue;
                 }
                 final AutoFillId id = entry.getKey();
@@ -751,11 +843,14 @@
                     Slog.w(TAG, "callSaveLocked(): did not find node with id " + id);
                     continue;
                 }
-                if (DEBUG) Slog.d(TAG, "callSaveLocked(): updating " + id + " to " + value);
+                if (VERBOSE) {
+                    Slog.v(TAG, "callSaveLocked(): updating " + id + " to " + value);
+                }
 
                 node.updateAutoFillValue(value);
             }
 
+            // Sanitize structure before it's sent to service.
             mStructure.sanitizeForParceling(false);
 
             if (VERBOSE) {
@@ -767,11 +862,9 @@
         }
 
         void updateLocked(AutoFillId id, Rect bounds, AutoFillValue value, int flags) {
-            if (DEBUG) Slog.d(TAG, "updateLocked(): id=" + id + ", flags=" + flags);
-
             if (mAutoFilledDataset != null && (flags & FLAG_VALUE_CHANGED) == 0) {
                 // TODO(b/33197203): ignoring because we don't support partitions yet
-                if (DEBUG) Slog.d(TAG, "updateLocked(): ignoring " + flags + " after auto-filled");
+                Slog.d(TAG, "updateLocked(): ignoring " + flags + " after app was auto-filled");
                 return;
             }
 
@@ -788,29 +881,34 @@
                 return;
             }
 
-            if ((flags & FLAG_VALUE_CHANGED) != 0 && value != null &&
-                    !value.equals(viewState.mAutoFillValue)) {
-                viewState.mValueUpdated = true;
+            if ((flags & FLAG_VALUE_CHANGED) != 0) {
+                if (value != null && !value.equals(viewState.mAutoFillValue)) {
+                    viewState.mValueUpdated = true;
 
-                // Must check if this update was caused by auto-filling the view, in which
-                // case we just update the value, but not the UI.
-                if (mAutoFilledDataset != null) {
-                    final AutoFillValue filledValue = findValue(mAutoFilledDataset, id);
-                    if (value.equals(filledValue)) {
-                        viewState.mAutoFillValue = value;
-                        return;
+                    // Must check if this update was caused by auto-filling the view, in which
+                    // case we just update the value, but not the UI.
+                    if (mAutoFilledDataset != null) {
+                        final AutoFillValue filledValue = findValue(mAutoFilledDataset, id);
+                        if (value.equals(filledValue)) {
+                            viewState.mAutoFillValue = value;
+                            return;
+                        }
                     }
+
+                    // Change value
+                    viewState.mAutoFillValue = value;
+
+                    // Update the chooser UI
+                    getUiForShowing().filterFillUi(value.coerceToString());
                 }
 
-                // Just change value, don't update the UI
-                viewState.mAutoFillValue = value;
                 return;
             }
 
             if ((flags & FLAG_FOCUS_GAINED) != 0) {
                 // Remove the UI if the ViewState has changed.
                 if (mCurrentViewState != viewState) {
-                    mUi.hideFillUi();
+                    mUi.hideFillUi(mCurrentViewState != null ? mCurrentViewState.mId : null);
                     mCurrentViewState = viewState;
                 }
 
@@ -827,18 +925,18 @@
 
             if ((flags & FLAG_FOCUS_LOST) != 0) {
                 if (mCurrentViewState == viewState) {
-                    mUi.hideFillUi();
+                    mUi.hideFillUi(viewState.mId);
                     mCurrentViewState = null;
                 }
                 return;
             }
 
-            Slog.w(TAG, "unknown flags " + flags);
+            Slog.w(TAG, "updateLocked(): unknown flags " + flags);
         }
 
         @Override
         public void onFillReady(ViewState viewState, FillResponse response, Rect bounds,
-                @Nullable AutoFillValue value) {
+                AutoFillId filledId, @Nullable AutoFillValue value) {
             String filterText = "";
             if (value != null) {
                 // TODO(b/33197203): Handle other AutoFillValue types
@@ -848,13 +946,23 @@
                 }
             }
 
-            getUiForShowing().showFillUi(mActivityToken, viewState, response.getDatasets(),
-                    bounds, filterText);
+            getUiForShowing().showFillUi(filledId, response, bounds, filterText);
+        }
+
+        private void notifyChangeToClient(AutoFillId id, int event) {
+            if (!mHasCallback) return;
+            try {
+                mClient.onAutofillEvent(mWindowToken, id, event);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Error notifying client on change: id=" + id + ", event=" + event, e);
+            }
         }
 
         private void processResponseLocked(FillResponse response) {
-            if (DEBUG) Slog.d(TAG, "processResponseLocked(authRequired="
-                    + response.getAuthentication() + "):" + response);
+            if (DEBUG) {
+                Slog.d(TAG, "processResponseLocked(auth=" + response.getAuthentication()
+                    + "):" + response);
+            }
 
             // TODO(b/33197203): add MetricsLogger calls
 
@@ -869,26 +977,17 @@
             if (mCurrentResponse.getAuthentication() != null) {
                 // Handle authentication.
                 final Intent fillInIntent = createAuthFillInIntent(mStructure);
-
                 mCurrentViewState.setResponse(mCurrentResponse, fillInIntent);
                 return;
             }
 
-            final ArraySet<AutoFillId> savableIds = mCurrentResponse.getSavableIds();
-            if (savableIds == null || savableIds.isEmpty()) {
-                // NOTE: it's assuming the response has no datasets, since when a dataset is added
-                // it's view id is automatically added to savable_ids
-                if (DEBUG) Slog.d(TAG, "processResponseLocked(): nothing to do");
-
-                removeSelf();
-                return;
-            }
-
             mCurrentViewState.setResponse(mCurrentResponse);
         }
 
         void autoFill(Dataset dataset) {
             synchronized (mLock) {
+                mAutoFilledDataset = dataset;
+
                 // Autofill it directly...
                 if (dataset.getAuthentication() == null) {
                     autoFillApp(dataset);
@@ -940,17 +1039,17 @@
                     pw.println("null");
                 }
             }
-
+            pw.print(prefix); pw.print("mHasCallback: "); pw.println(mHasCallback);
             mRemoteFillService.dump(prefix, pw);
         }
 
         void autoFillApp(Dataset dataset) {
             synchronized (mLock) {
                 try {
-                    if (DEBUG) Slog.d(TAG, "autoFillApp(): the buck is on the app: " + dataset);
-
+                    if (DEBUG) {
+                        Slog.d(TAG, "autoFillApp(): the buck is on the app: " + dataset);
+                    }
                     mClient.autoFill(dataset.getFieldIds(), dataset.getFieldValues());
-                    mAutoFilledDataset = dataset;
                 } catch (RemoteException e) {
                     Slog.w(TAG, "Error auto-filling activity: " + e);
                 }
@@ -959,7 +1058,7 @@
 
         private AutoFillUI getUiForShowing() {
             synchronized (mLock) {
-                mUi.setCallbackLocked(this, mActivityToken);
+                mUi.setCallback(this, mWindowToken);
                 return mUi;
             }
         }
@@ -999,12 +1098,13 @@
 
         private void destroyLocked() {
             mRemoteFillService.destroy();
-            mUi.hideAll();
-            mUi.setCallbackLocked(null, null);
+            mUi.setCallback(null, null);
         }
 
         private void removeSelf() {
-            if (VERBOSE) Slog.v(TAG, "removeSelf()");
+            if (VERBOSE) {
+                Slog.v(TAG, "removeSelf()");
+            }
 
             synchronized (mLock) {
                 destroyLocked();
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java
index cfa4a1d..76d9aea 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java
@@ -20,7 +20,6 @@
 
 import android.app.ActivityManager;
 import android.os.Bundle;
-import android.os.RemoteException;
 import android.os.ShellCommand;
 import android.os.UserHandle;
 
@@ -48,8 +47,12 @@
         switch (cmd) {
             case "save":
                 return requestSave();
+            case "set":
+                return requestSet();
             case "list":
                 return requestList(pw);
+            case "destroy":
+                return requestDestroy(pw);
             case "reset":
                 return requestReset();
             default:
@@ -67,8 +70,14 @@
             pw.println("  list sessions [--user USER_ID]");
             pw.println("    List all pending sessions.");
             pw.println("");
+            pw.println("  destroy sessions [--user USER_ID]");
+            pw.println("    Destroy all pending sessions.");
+            pw.println("");
             pw.println("  save [--user USER_ID]");
-            pw.println("    Request provider to save contents of the top activity. ");
+            pw.println("    Request provider to save contents of the top activity.");
+            pw.println("");
+            pw.println("  set save_timeout MS");
+            pw.println("    Sets how long (in ms) the save snack bar is shown.");
             pw.println("");
             pw.println("  reset");
             pw.println("    Reset all pending sessions and cached service connections.");
@@ -82,30 +91,67 @@
         return 0;
     }
 
-    private int requestList(PrintWriter pw) {
+    private int requestSet() {
         final String type = getNextArgRequired();
-        if (!type.equals("sessions")) {
-            pw.println("Error: invalid list type");
-            return -1;
-
+        switch (type) {
+            case "save_timeout":
+                mService.setSaveTimeout(Integer.parseInt(getNextArgRequired()));
+                break;
+            default:
+                throw new IllegalArgumentException("Invalid 'set' type: " + type);
         }
+        return 0;
+    }
+
+    private int requestDestroy(PrintWriter pw) {
+        if (!isNextArgSessions(pw)) {
+            return -1;
+        }
+
         final int userId = getUserIdFromArgsOrAllUsers();
         final CountDownLatch latch = new CountDownLatch(1);
         final IResultReceiver receiver = new IResultReceiver.Stub() {
-
             @Override
-            public void send(int resultCode, Bundle resultData) throws RemoteException {
+            public void send(int resultCode, Bundle resultData) {
+                latch.countDown();
+            }
+        };
+        return requestSessionCommon(pw, latch, () -> mService.destroySessions(userId, receiver));
+    }
+
+    private int requestList(PrintWriter pw) {
+        if (!isNextArgSessions(pw)) {
+            return -1;
+        }
+
+        final int userId = getUserIdFromArgsOrAllUsers();
+        final CountDownLatch latch = new CountDownLatch(1);
+        final IResultReceiver receiver = new IResultReceiver.Stub() {
+            @Override
+            public void send(int resultCode, Bundle resultData) {
                 final ArrayList<String> sessions = resultData
                         .getStringArrayList(RECEIVER_BUNDLE_EXTRA_SESSIONS);
-
                 for (String session : sessions) {
                     pw.println(session);
                 }
                 latch.countDown();
             }
         };
+        return requestSessionCommon(pw, latch, () -> mService.listSessions(userId, receiver));
+    }
 
-        mService.listSessions(userId, receiver);
+    private boolean isNextArgSessions(PrintWriter pw) {
+        final String type = getNextArgRequired();
+        if (!type.equals("sessions")) {
+            pw.println("Error: invalid list type");
+            return false;
+        }
+        return true;
+    }
+
+    private int requestSessionCommon(PrintWriter pw, CountDownLatch latch,
+            Runnable command) {
+        command.run();
 
         try {
             final boolean received = latch.await(5, TimeUnit.SECONDS);
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/AutoFillUI.java
deleted file mode 100644
index e83dc1e..0000000
--- a/services/autofill/java/com/android/server/autofill/AutoFillUI.java
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.server.autofill;
-
-import static com.android.server.autofill.Helper.DEBUG;
-
-import android.annotation.Nullable;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.app.StatusBarManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.IntentSender;
-import android.graphics.Rect;
-import android.os.Binder;
-import android.os.IBinder;
-import android.service.autofill.Dataset;
-import android.util.ArraySet;
-import android.os.Looper;
-import android.text.format.DateUtils;
-import android.util.Slog;
-import android.view.Gravity;
-import android.view.View;
-import android.view.WindowManager;
-import android.view.WindowManager.LayoutParams;
-import android.widget.Toast;
-
-import com.android.internal.os.HandlerCaller;
-import com.android.server.UiThread;
-import com.android.server.autofill.AutoFillManagerServiceImpl.ViewState;
-
-import java.io.PrintWriter;
-
-/**
- * Handles all auto-fill related UI tasks.
- */
-// TODO(b/33197203): document exactly what once the auto-fill bar is implemented
-final class AutoFillUI {
-    private static final String TAG = "AutoFillUI";
-    private static final long SNACK_BAR_LIFETIME_MS = 30 * DateUtils.SECOND_IN_MILLIS;
-    private static final int MSG_HIDE_SNACK_BAR = 1;
-
-    private final Context mContext;
-    private final WindowManager mWm;
-
-    // TODO(b/33197203) Fix locking - some state requires lock and some not - requires refactoring
-    private final Object mLock = new Object();
-
-    // Fill UI variables
-    private AnchoredWindow mFillWindow;
-    private View mFillView;
-    private ViewState mViewState;
-
-    private AutoFillUiCallback mCallback;
-    private IBinder mActivityToken;
-
-    private final HandlerCaller.Callback mHandlerCallback = (msg) -> {
-        switch (msg.what) {
-            case MSG_HIDE_SNACK_BAR: {
-                hideSnackbarUiThread();
-                return;
-            }
-            default: {
-                Slog.w(TAG, "Invalid message: " + msg);
-            }
-        }
-    };
-    private final HandlerCaller mHandlerCaller = new HandlerCaller(null, Looper.getMainLooper(),
-            mHandlerCallback, true);
-
-    /**
-     * Custom snackbar UI used for saving autofill or other informational messages.
-     */
-    private View mSnackbar;
-
-    AutoFillUI(Context context) {
-        mContext = context;
-        mWm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
-    }
-
-    void setCallbackLocked(AutoFillUiCallback callback, IBinder activityToken) {
-        hideAll();
-        mCallback = callback;
-        mActivityToken = activityToken;
-    }
-
-    /**
-     * Displays an error message to the user.
-     */
-    void showError(CharSequence message) {
-        if (!hasCallback()) {
-            return;
-        }
-        hideAll();
-        // TODO(b/33197203): proper implementation
-        UiThread.getHandler().runWithScissors(() -> {
-            Toast.makeText(mContext, "AutoFill error: " + message, Toast.LENGTH_LONG).show();
-        }, 0);
-    }
-
-    /**
-     * Hides the fill UI.
-     */
-    void hideFillUi() {
-        UiThread.getHandler().runWithScissors(() -> {
-            hideFillUiUiThread();
-        }, 0);
-    }
-
-    @android.annotation.UiThread
-    private void hideFillUiUiThread() {
-        if (mFillWindow != null) {
-            if (DEBUG) Slog.d(TAG, "hideFillUiUiThread(): hide" + mFillWindow);
-            mFillWindow.hide();
-        }
-
-        mViewState = null;
-        mFillView = null;
-        mFillWindow = null;
-    }
-
-    /**
-     * Shows the fill UI, removing the previous fill UI if the has changed.
-     *
-     * @param appToken the token of the app to be autofilled
-     * @param viewState the view state, compared by reference to know if new UI should be shown
-     * @param datasets the datasets to show, not used if viewState is the same
-     * @param bounds bounds of the view to be filled, used if changed
-     * @param filterText text of the view to be filled, used if changed
-     */
-    void showFillUi(IBinder appToken, ViewState viewState, @Nullable ArraySet<Dataset> datasets,
-            Rect bounds, String filterText) {
-        if (!hasCallback()) {
-            return;
-        }
-
-        UiThread.getHandler().runWithScissors(() -> {
-            hideSnackbarUiThread();
-        }, 0);
-
-        if (datasets == null && viewState.mAuthIntent == null) {
-            // TODO(b/33197203): shouldn't be called, but keeping the WTF for a while just to be
-            // safe, otherwise it would crash system server...
-            Slog.wtf(TAG, "showFillUI(): no dataset");
-            return;
-        }
-
-        // TODO(b/33197203): should not display UI after we launched an authentication intent, since
-        // we have no warranty the provider will call onFailure() if the authentication failed or
-        // user dismissed the auth window
-        // because if the service does not handle calling the callback,
-
-
-        UiThread.getHandler().runWithScissors(() -> {
-            // The dataset picker is only shown when authentication is not required...
-            DatasetPicker datasetPicker = null;
-
-            if (mViewState == null || !mViewState.mId.equals(viewState.mId)) {
-                hideFillUiUiThread();
-
-                mViewState = viewState;
-                if (viewState.mAuthIntent != null) {
-                    final CharSequence serviceName = viewState.getServiceName();
-
-                    mFillView = new SignInPrompt(mContext, serviceName, (e) -> {
-                        final IntentSender intentSender = viewState.mResponse.getAuthentication();
-                        final AutoFillUiCallback callback;
-                        final Intent authIntent;
-                        synchronized (mLock) {
-                            callback = mCallback;
-                            authIntent = viewState.mAuthIntent;
-                            // Must reset the authentication intent so UI display the datasets after
-                            // the user authenticated.
-                            viewState.mAuthIntent = null;
-                        }
-                        if (callback != null) {
-                            callback.authenticate(intentSender, authIntent);
-                        } else {
-                            // TODO(b/33197203): need to figure out why it's null sometimes
-                            Slog.w(TAG, "no callback on showFillUi().auth for " + viewState.mId);
-                        }
-                    });
-
-                } else {
-                    mFillView = datasetPicker = new DatasetPicker(mContext, datasets,
-                            (dataset) -> {
-                                final AutoFillUiCallback callback;
-                                synchronized (mLock) {
-                                    callback = mCallback;
-                                }
-                                if (callback != null) {
-                                    callback.fill(dataset);
-                                } else {
-                                    // TODO(b/33197203): need to figure out why it's null sometimes
-                                    Slog.w(TAG, "no callback on showFillUi() for " + viewState.mId);
-                                }
-                                hideFillUiUiThread();
-                            });
-                }
-                mFillWindow = new AnchoredWindow(mWm, appToken, mFillView);
-
-                if (DEBUG) Slog.d(TAG, "showFillUi(): view changed for: " + viewState.mId);
-            }
-            if (datasetPicker != null) {
-                datasetPicker.update(filterText);
-            }
-            mFillWindow.show(bounds);
-
-        }, 0);
-    }
-
-    /**
-     * Shows the UI asking the user to save for auto-fill.
-     */
-    void showSaveUi() {
-        if (!hasCallback()) {
-            return;
-        }
-        hideAll();
-        UiThread.getHandler().runWithScissors(() -> {
-            showSnackbarUiThread(new SavePrompt(mContext,
-                    new SavePrompt.OnSaveListener() {
-                @Override
-                public void onSaveClick() {
-                    hideSnackbarUiThread();
-                    // TODO(b/33197203): add MetricsLogger call
-                    mCallback.save();
-                }
-
-                @Override
-                public void onCancelClick() {
-                    // TODO(b/33197203): add MetricsLogger call
-                    hideSnackbarUiThread();
-                }
-            }));
-        }, 0);
-    }
-
-    /**
-     * Hides all UI affordances.
-     */
-    void hideAll() {
-        UiThread.getHandler().runWithScissors(() -> {
-            hideSnackbarUiThread();
-            hideFillUiUiThread();
-        }, 0);
-    }
-
-    void dump(PrintWriter pw) {
-        pw.println("AufoFill UI");
-        final String prefix = "  ";
-        pw.print(prefix); pw.print("mActivityToken: "); pw.println(mActivityToken);
-        pw.print(prefix); pw.print("mSnackBar: "); pw.println(mSnackbar);
-        pw.print(prefix); pw.print("mViewState: "); pw.println(mViewState);
-    }
-
-    //similar to a snackbar, but can be a bit custom since it is more than just text. This will
-    //allow two buttons for saving or not saving the autofill for instance as well.
-    private void showSnackbarUiThread(View snackBar) {
-        final LayoutParams params = new LayoutParams();
-        params.setTitle("AutoFill Save");
-        params.type = LayoutParams.TYPE_PHONE; // TODO(b/33197203) use app window token
-        params.flags =
-                LayoutParams.FLAG_NOT_FOCUSABLE // don't receive input events,
-                | LayoutParams.FLAG_ALT_FOCUSABLE_IM // resize for soft input
-                | LayoutParams.FLAG_NOT_TOUCH_MODAL; // outside touches go to windows behind us
-        params.softInputMode =
-                LayoutParams.SOFT_INPUT_ADJUST_PAN; // pan with soft input
-        params.gravity = Gravity.BOTTOM | Gravity.START;
-        params.width = LayoutParams.MATCH_PARENT;
-        params.height = LayoutParams.WRAP_CONTENT;
-
-        UiThread.getHandler().runWithScissors(() -> {
-            mSnackbar = snackBar;
-            mWm.addView(mSnackbar, params);
-        }, 0);
-
-        if (DEBUG) {
-            Slog.d(TAG, "showSnackbar(): auto dismissing it in " + SNACK_BAR_LIFETIME_MS + " ms");
-        }
-        mHandlerCaller.sendMessageDelayed(mHandlerCaller.obtainMessage(MSG_HIDE_SNACK_BAR),
-                SNACK_BAR_LIFETIME_MS);
-    }
-
-    private void hideSnackbarUiThread() {
-        mHandlerCaller.getHandler().removeMessages(MSG_HIDE_SNACK_BAR);
-        if (mSnackbar != null) {
-            mWm.removeView(mSnackbar);
-            mSnackbar = null;
-        }
-    }
-
-    private boolean hasCallback() {
-        synchronized (mLock) {
-            return mCallback != null;
-        }
-    }
-
-    interface AutoFillUiCallback {
-        void authenticate(IntentSender intent, Intent fillInIntent);
-        void fill(Dataset dataset);
-        void save();
-    }
-}
diff --git a/services/autofill/java/com/android/server/autofill/DatasetPicker.java b/services/autofill/java/com/android/server/autofill/DatasetPicker.java
deleted file mode 100644
index a54cab9..0000000
--- a/services/autofill/java/com/android/server/autofill/DatasetPicker.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * 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.autofill;
-
-import android.content.Context;
-import android.graphics.Color;
-import android.service.autofill.Dataset;
-import android.text.TextUtils;
-import android.util.ArraySet;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.ArrayAdapter;
-import android.widget.Filter.FilterListener;
-import android.widget.ListView;
-import android.widget.TextView;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * View for dataset picker.
- *
- * <p>A fill session starts when a View is clicked and FillResponse is supplied.
- * <p>A fill session ends when 1) the user takes action in the UI, 2) another View is clicked, or
- * 3) the View is detached.
- */
-final class DatasetPicker extends ListView implements OnItemClickListener {
-    interface Listener {
-        void onDatasetPicked(Dataset dataset);
-    }
-
-    private final Listener mListener;
-
-    DatasetPicker(Context context, ArraySet<Dataset> datasets, Listener listener) {
-        super(context);
-        mListener = listener;
-
-        final List<ViewItem> items = new ArrayList<>(datasets.size());
-        for (Dataset dataset : datasets) {
-            items.add(new ViewItem(dataset));
-        }
-
-        final ArrayAdapter<ViewItem> adapter = new ArrayAdapter<ViewItem>(
-            context,
-            android.R.layout.simple_list_item_1,
-            android.R.id.text1,
-            items) {
-            @Override
-            public View getView(int position, View convertView, ViewGroup parent) {
-                final TextView textView = (TextView) super.getView(position, convertView, parent);
-                textView.setSingleLine();
-                textView.setEllipsize(TextUtils.TruncateAt.END);
-                textView.setMinHeight(
-                        getDimen(com.android.internal.R.dimen.autofill_fill_item_height));
-                return textView;
-            }
-        };
-        setAdapter(adapter);
-        setBackgroundColor(Color.WHITE);
-        setDivider(null);
-        setElevation(getDimen(com.android.internal.R.dimen.autofill_fill_elevation));
-        setOnItemClickListener(this);
-    }
-
-    public void update(String prefix) {
-        final ArrayAdapter<ViewItem> adapter = (ArrayAdapter) getAdapter();
-        adapter.getFilter().filter(prefix, new FilterListener() {
-            @Override
-            public void onFilterComplete(int count) {
-                setVisibility(count > 0 ? View.VISIBLE : View.GONE);
-            }
-        });
-    }
-
-    @Override
-    public void onItemClick(AdapterView<?> adapterView, View view, int pos, long id) {
-        if (mListener != null) {
-            final ViewItem vi = (ViewItem) adapterView.getItemAtPosition(pos);
-            mListener.onDatasetPicked(vi.getData());
-        }
-    }
-
-    private int getDimen(int resId) {
-        return getContext().getResources().getDimensionPixelSize(resId);
-    }
-
-    private static class ViewItem {
-        private final Dataset mData;
-
-        ViewItem(Dataset data) {
-            mData = data;
-        }
-
-        public Dataset getData() {
-            return mData;
-        }
-
-        @Override
-        public String toString() {
-            // used by ArrayAdapter
-            return mData.getName().toString();
-        }
-    }
-}
diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java
index 48ae635..2f600c2 100644
--- a/services/autofill/java/com/android/server/autofill/Helper.java
+++ b/services/autofill/java/com/android/server/autofill/Helper.java
@@ -19,8 +19,6 @@
 import android.annotation.Nullable;
 import android.os.Bundle;
 import android.service.autofill.Dataset;
-import android.service.autofill.FillResponse;
-import android.util.ArraySet;
 import android.view.autofill.AutoFillId;
 import android.view.autofill.AutoFillValue;
 
@@ -77,28 +75,6 @@
         return null;
     }
 
-    /**
-     * Finds the index of a data set given its name.
-     *
-     * @param name The dataset name.
-     * @param response The response to search.
-     * @return The index of dataset if found or -1.
-     */
-    static int indexOfDataset(CharSequence name, FillResponse response) {
-        ArraySet<Dataset> datasets = response.getDatasets();
-        if (datasets == null || datasets.isEmpty()) {
-            return -1;
-        }
-        final int datasetCount = datasets.size();
-        for (int i = 0; i < datasetCount; i++) {
-            Dataset dataset = datasets.valueAt(i);
-            if (dataset.getName().toString().equals(name.toString())) {
-                return i;
-            }
-        }
-        return -1;
-    }
-
     private Helper() {
         throw new UnsupportedOperationException("contains static members only");
     }
diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
index c469718..d9f9721 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
@@ -33,6 +33,7 @@
 import android.service.autofill.AutoFillService;
 import android.service.autofill.FillResponse;
 import android.service.autofill.IAutoFillService;
+import android.service.autofill.IAutoFillServiceConnection;
 import android.service.autofill.IFillCallback;
 import android.service.autofill.ISaveCallback;
 import android.text.format.DateUtils;
@@ -57,7 +58,7 @@
     private static final boolean DEBUG = Helper.DEBUG;
 
     // How long after the last interaction with the service we would unbind
-    private static final long TIMEOUT_IDLE_BIND_MILLIS = 5 * DateUtils.MINUTE_IN_MILLIS;
+    private static final long TIMEOUT_IDLE_BIND_MILLIS = 5 * DateUtils.SECOND_IN_MILLIS;
 
     private final Context mContext;
 
@@ -91,6 +92,7 @@
         void onSaveRequestSuccess();
         void onSaveRequestFailure(CharSequence message);
         void onServiceDied(RemoteFillService service);
+        void onDisableSelf();
     }
 
     public RemoteFillService(Context context, ComponentName componentName,
@@ -133,13 +135,13 @@
 
     public void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle extras) {
         cancelScheduledUnbind();
-        PendingFillRequest request = new PendingFillRequest(structure, extras, this);
+        final PendingFillRequest request = new PendingFillRequest(structure, extras, this);
         mHandler.obtainMessageO(MyHandler.MSG_ON_PENDING_REQUEST, request).sendToTarget();
     }
 
     public void onSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle extras) {
         cancelScheduledUnbind();
-        PendingSaveRequest request = new PendingSaveRequest(structure, extras, this);
+        final PendingSaveRequest request = new PendingSaveRequest(structure, extras, this);
         mHandler.obtainMessageO(MyHandler.MSG_ON_PENDING_REQUEST, request).sendToTarget();
     }
 
@@ -180,11 +182,8 @@
         if (mDestroyed || mCompleted) {
             return;
         }
-        if (pendingRequest.isFinal()) {
-            mCompleted = true;
-        }
         if (!isBound()) {
-            if (mPendingRequest != null) {
+            if (mPendingRequest != null && mPendingRequest != pendingRequest) {
                 mPendingRequest.cancel();
             }
             mPendingRequest = pendingRequest;
@@ -194,9 +193,16 @@
                 Slog.d(LOG_TAG, "[user: " + mUserId + "] handlePendingRequest()");
             }
             pendingRequest.run();
+            if (pendingRequest.isFinal()) {
+                mCompleted = true;
+            }
         }
     }
 
+    private void handleDisableSelf() {
+        mCallbacks.onDisableSelf();
+    }
+
     private boolean isBound() {
         return mAutoFillService != null;
     }
@@ -239,7 +245,7 @@
             // Need to double check if it's null, since it could be set on onServiceDisconnected()
             if (mAutoFillService != null) {
                 try {
-                    mAutoFillService.onDisconnected();
+                    mAutoFillService.onInit(null);
                 } catch (Exception e) {
                     Slog.w(LOG_TAG, "Exception calling onDisconnected(): " + e);
                 }
@@ -321,7 +327,12 @@
                 // Need to double check if it's null, since it could be set on
                 // onServiceDisconnected()
                 if (mAutoFillService != null) {
-                    mAutoFillService.onConnected();
+                    mAutoFillService.onInit(new IAutoFillServiceConnection.Stub() {
+                        @Override
+                        public void disableSelf() {
+                            mHandler.obtainMessage(MyHandler.MSG_ON_DISABLE_SELF).sendToTarget();
+                        }
+                    });
                 }
             } catch (RemoteException e) {
                 Slog.w(LOG_TAG, "Exception calling onConnected(): " + e);
@@ -347,6 +358,7 @@
         public static final int MSG_BINDER_DIED = 2;
         public static final int MSG_UNBIND = 3;
         public static final int MSG_ON_PENDING_REQUEST = 4;
+        public static final int MSG_ON_DISABLE_SELF = 5;
 
         public MyHandler(Context context) {
             // Cannot use lambda - doesn't compile
@@ -374,6 +386,10 @@
                         case MSG_ON_PENDING_REQUEST: {
                             handlePendingRequest((PendingRequest) message.obj);
                         } break;
+
+                        case MSG_ON_DISABLE_SELF: {
+                            handleDisableSelf();
+                        } break;
                     }
                 }
             }, false);
diff --git a/services/autofill/java/com/android/server/autofill/SavePrompt.java b/services/autofill/java/com/android/server/autofill/SavePrompt.java
deleted file mode 100644
index f0b51e2..0000000
--- a/services/autofill/java/com/android/server/autofill/SavePrompt.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.autofill;
-
-import android.content.Context;
-import android.graphics.Color;
-import android.widget.RelativeLayout;
-import android.widget.RelativeLayout.LayoutParams;
-import android.widget.TextView;
-import android.view.LayoutInflater;
-import android.view.View;
-
-import com.android.internal.R;
-
-/**
- * Autofill Save Prompt
- */
-final class SavePrompt extends RelativeLayout {
-    public interface OnSaveListener {
-        void onSaveClick();
-        void onCancelClick();
-    }
-
-    private final TextView mNoButton;
-    private final TextView mYesButton;
-    private final OnSaveListener mListener;
-
-    SavePrompt(Context context, OnSaveListener listener) {
-        super(context);
-        mListener = listener;
-        LayoutInflater inflater = LayoutInflater.from(context);
-        View view = inflater.inflate(R.layout.autofill_save, this);
-
-        mNoButton = (TextView) view.findViewById(R.id.autofill_save_no);
-        mNoButton.setOnClickListener((v) -> {
-            mListener.onCancelClick();
-        });
-
-        mYesButton = (TextView) view.findViewById(R.id.autofill_save_yes);
-        mYesButton.setOnClickListener((v) -> {
-            mListener.onSaveClick();
-        });
-
-        //addView(view);
-    }
-}
diff --git a/services/autofill/java/com/android/server/autofill/SignInPrompt.java b/services/autofill/java/com/android/server/autofill/SignInPrompt.java
deleted file mode 100644
index 6d17acd..0000000
--- a/services/autofill/java/com/android/server/autofill/SignInPrompt.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.autofill;
-
-import android.content.Context;
-import android.view.View;
-import android.widget.Button;
-
-/**
- * A view displaying the sign-in prompt for an auto-fill service.
- */
-final class SignInPrompt extends Button {
-
-    SignInPrompt(Context context, CharSequence serviceName, View.OnClickListener listener) {
-        super(context);
-        // TODO(b/33197203): use strings.xml
-        final String text = serviceName != null
-                ? "Sign in to " + serviceName + " to autofill"
-                : "Sign in to autofill";
-
-        // TODO(b/33197203): polish UI / use better altenative than a button...
-        setText(text);
-        setOnClickListener(listener);
-    }
-}
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
new file mode 100644
index 0000000..599bbfe
--- /dev/null
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.autofill.ui;
+
+import static android.view.autofill.AutoFillManager.AutofillCallback.EVENT_INPUT_HIDDEN;
+import static android.view.autofill.AutoFillManager.AutofillCallback.EVENT_INPUT_SHOWN;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.IntentSender;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.os.IBinder;
+import android.service.autofill.Dataset;
+import android.service.autofill.FillResponse;
+import android.service.autofill.SaveInfo;
+import android.text.TextUtils;
+import android.text.format.DateUtils;
+import android.util.Slog;
+import android.view.autofill.AutoFillId;
+import android.widget.Toast;
+
+import com.android.server.UiThread;
+
+import java.io.PrintWriter;
+
+/**
+ * Handles all auto-fill related UI tasks. The UI has two components:
+ * fill UI that shows a popup style window anchored at the focused
+ * input field for choosing a dataset to fill or trigger the response
+ * authentication flow; save UI that shows a toast style window for
+ * managing saving of user edits.
+ */
+public final class AutoFillUI {
+    private static final String TAG = "AutoFillUI";
+
+    private static final int MAX_SAVE_TIMEOUT_MS = (int) (30 * DateUtils.SECOND_IN_MILLIS);
+
+    private final Handler mHandler = UiThread.getHandler();
+    private final @NonNull Context mContext;
+
+    private @Nullable FillUi mFillUi;
+    private @Nullable SaveUi mSaveUi;
+
+    private @Nullable AutoFillUiCallback mCallback;
+    private @Nullable IBinder mWindowToken;
+
+    private int mSaveTimeoutMs = (int) (5 * DateUtils.SECOND_IN_MILLIS);
+
+    public interface AutoFillUiCallback {
+        void authenticate(@NonNull IntentSender intent);
+        void fill(@NonNull Dataset dataset);
+        void save();
+        void cancelSave();
+        void onEvent(AutoFillId id, int event);
+    }
+
+    public AutoFillUI(@NonNull Context context) {
+        mContext = context;
+    }
+
+    public void setCallback(@Nullable AutoFillUiCallback callback,
+            @Nullable IBinder windowToken) {
+        mHandler.post(() -> {
+            if (mCallback != callback || mWindowToken != windowToken) {
+                hideAllUiThread();
+                mCallback = callback;
+                mWindowToken = windowToken;
+            }
+        });
+    }
+
+    /**
+     * Displays an error message to the user.
+     */
+    public void showError(@Nullable CharSequence message) {
+        mHandler.post(() -> {
+            if (!hasCallback()) {
+                return;
+            }
+            hideAllUiThread();
+            if (!TextUtils.isEmpty(message)) {
+                Toast.makeText(mContext, message, Toast.LENGTH_LONG).show();
+            }
+        });
+    }
+
+    /**
+     * Hides the fill UI.
+     */
+    public void hideFillUi(AutoFillId id) {
+        mHandler.post(() -> {
+            hideFillUiUiThread();
+            if (mCallback != null) {
+                mCallback.onEvent(id, EVENT_INPUT_HIDDEN);
+            }
+        });
+    }
+
+    /**
+     * Filters the options in the fill UI.
+     *
+     * @param filterText The filter prefix.
+     */
+    public void filterFillUi(@Nullable String filterText) {
+        mHandler.post(() -> {
+            if (!hasCallback()) {
+                return;
+            }
+            hideSaveUiUiThread();
+            if (mFillUi != null) {
+                mFillUi.filter(filterText);
+            }
+        });
+    }
+
+    /**
+     * Updates the position of the fill UI.
+     *
+     * @param anchoredBounds The bounds of the anchor view.
+     */
+    public void updateFillUi(@NonNull Rect anchoredBounds) {
+        mHandler.post(() -> {
+            if (!hasCallback()) {
+                return;
+            }
+            hideSaveUiUiThread();
+            if (mFillUi != null) {
+                mFillUi.update(anchoredBounds);
+            }
+        });
+    }
+
+    /**
+     * Shows the fill UI, removing the previous fill UI if the has changed.
+     *
+     * @param focusedId the currently focused field
+     * @param response the current fill response
+     * @param anchorBounds bounds of the focused view
+     * @param filterText text of the view to be filled
+     */
+    public void showFillUi(@NonNull AutoFillId focusedId, @NonNull FillResponse response,
+            @NonNull Rect anchorBounds, @Nullable String filterText) {
+        mHandler.post(() -> {
+            if (!hasCallback()) {
+                return;
+            }
+            hideAllUiThread();
+            mFillUi = new FillUi(mContext, response, focusedId,
+                    mWindowToken, anchorBounds, filterText, new FillUi.Callback() {
+                @Override
+                public void onResponsePicked(FillResponse response) {
+                    hideFillUiUiThread();
+                    if (mCallback != null) {
+                        mCallback.authenticate(response.getAuthentication());
+                    }
+                }
+
+                @Override
+                public void onDatasetPicked(Dataset dataset) {
+                    hideFillUiUiThread();
+                    if (mCallback != null) {
+                        mCallback.fill(dataset);
+                    }
+                    // TODO(b/33197203): add MetricsLogger call
+                }
+
+                @Override
+                public void onCanceled() {
+                    hideFillUiUiThread();
+                    // TODO(b/33197203): add MetricsLogger call
+                }
+            });
+            mCallback.onEvent(focusedId, EVENT_INPUT_SHOWN);
+        });
+    }
+
+    /**
+     * Shows the UI asking the user to save for auto-fill.
+     */
+    public void showSaveUi(@NonNull CharSequence providerLabel, @NonNull SaveInfo info) {
+        mHandler.post(() -> {
+            if (!hasCallback()) {
+                return;
+            }
+            hideAllUiThread();
+            mSaveUi = new SaveUi(mContext, providerLabel, info,
+                    new SaveUi.OnSaveListener() {
+                @Override
+                public void onSave() {
+                    hideSaveUiUiThread();
+                    if (mCallback != null) {
+                        mCallback.save();
+                    }
+                    // TODO(b/33197203): add MetricsLogger call
+                }
+
+                @Override
+                public void onCancel(IntentSender listener) {
+                    // TODO(b/33197203): add MetricsLogger call
+                    hideSaveUiUiThread();
+                    if (listener != null) {
+                        try {
+                            listener.sendIntent(mContext, 0, null, null, null);
+                        } catch (IntentSender.SendIntentException e) {
+                            Slog.e(TAG, "Error starting negative action listener: "
+                                    + listener, e);
+                        }
+                    }
+                    if (mCallback != null) {
+                        mCallback.cancelSave();
+                    }
+                }
+            }, mSaveTimeoutMs);
+        });
+    }
+
+    /**
+     * Hides all UI affordances.
+     */
+    public void hideAll() {
+        mHandler.post(this::hideAllUiThread);
+    }
+
+    public void setSaveTimeout(int timeout) {
+        if (timeout > MAX_SAVE_TIMEOUT_MS) {
+            throw new IllegalArgumentException("Maximum value is " + MAX_SAVE_TIMEOUT_MS + "ms");
+        }
+        if (timeout <= 0) {
+            throw new IllegalArgumentException("Must be a positive value");
+        }
+        mSaveTimeoutMs = timeout;
+    }
+
+    public void dump(PrintWriter pw) {
+        pw.println("AufoFill UI");
+        final String prefix = "  ";
+        pw.print(prefix); pw.print("showsFillUi: "); pw.println(mFillUi != null);
+        pw.print(prefix); pw.print("showsSaveUi: "); pw.println(mSaveUi != null);
+        pw.print(prefix); pw.print("save timeout: "); pw.println(mSaveTimeoutMs);
+    }
+
+    @android.annotation.UiThread
+    private void hideFillUiUiThread() {
+        if (mFillUi != null) {
+            mFillUi.destroy();
+            mFillUi = null;
+        }
+    }
+
+    @android.annotation.UiThread
+    private void hideSaveUiUiThread() {
+        if (mSaveUi != null) {
+            mSaveUi.destroy();
+            mSaveUi = null;
+        }
+    }
+
+    @android.annotation.UiThread
+    private void hideAllUiThread() {
+        hideFillUiUiThread();
+        hideSaveUiUiThread();
+    }
+
+    private boolean hasCallback() {
+        return mCallback != null;
+    }
+}
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
new file mode 100644
index 0000000..0d5fbbe
--- /dev/null
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -0,0 +1,348 @@
+/*
+ * 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.autofill.ui;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.os.IBinder;
+import android.service.autofill.Dataset;
+import android.service.autofill.FillResponse;
+import android.util.Slog;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.MeasureSpec;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.view.autofill.AutoFillId;
+import android.view.autofill.AutoFillValue;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import com.android.internal.R;
+import com.android.internal.R;
+import libcore.util.Objects;
+
+import java.util.ArrayList;
+
+final class FillUi {
+    private static final String TAG = "FillUi";
+
+    interface Callback {
+        void onResponsePicked(@NonNull FillResponse response);
+        void onDatasetPicked(@NonNull Dataset dataset);
+        void onCanceled();
+    }
+
+    private final Rect mAnchorBounds = new Rect();
+
+    private final @NonNull AnchoredWindow mWindow;
+
+    private final @NonNull Callback mCallback;
+
+    private final @Nullable ArrayAdapter<ViewItem> mAdapter;
+
+    private @Nullable String mFilterText;
+
+    private int mContentWidth;
+    private int mContentHeight;
+
+    private boolean mDestroyed;
+
+    FillUi(@NonNull Context context, @NonNull FillResponse response,
+            @NonNull AutoFillId focusedViewId, @NonNull IBinder windowToken,
+            @NonNull Rect anchorBounds, @Nullable String filterText,
+            @NonNull Callback callback) {
+        mAnchorBounds.set(anchorBounds);
+        mCallback = callback;
+
+        if (response.getAuthentication() != null) {
+            final View content;
+            try {
+                content = response.getPresentation().apply(context, null);
+            } catch (RuntimeException e) {
+                callback.onCanceled();
+                Slog.e(TAG, "Error inflating remote views", e);
+                mWindow = null;
+                mAdapter = null;
+                return;
+            }
+            final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, 0);
+            final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, 0);
+            content.measure(widthMeasureSpec, heightMeasureSpec);
+            content.setOnClickListener(v -> mCallback.onResponsePicked(response));
+            mContentWidth = content.getMeasuredWidth();
+            mContentHeight = content.getMeasuredHeight();
+            mAdapter = null;
+
+            mWindow = new AnchoredWindow(windowToken, content);
+            mWindow.update(mContentWidth, mContentHeight, mAnchorBounds);
+        } else {
+            final int datasetCount = response.getDatasets().size();
+            final ArrayList<ViewItem> items = new ArrayList<>(datasetCount);
+            for (int i = 0; i < datasetCount; i++) {
+                final Dataset dataset = response.getDatasets().get(i);
+                final int index = dataset.getFieldIds().indexOf(focusedViewId);
+                if (index >= 0) {
+                    AutoFillValue value = dataset.getFieldValues().get(index);
+                    final View view;
+                    try {
+                        view = dataset.getPresentation().apply(context, null);
+                    } catch (RuntimeException e) {
+                        Slog.e(TAG, "Error inflating remote views", e);
+                        continue;
+                    }
+                    items.add(new ViewItem(dataset, value.coerceToString()
+                            .toLowerCase(), view));
+                }
+            }
+
+            mAdapter = new ArrayAdapter<ViewItem>(context, 0, items) {
+                @Override
+                public View getView(int position, View convertView, ViewGroup parent) {
+                    return getItem(position).getView();
+                }
+            };
+
+            final LayoutInflater inflater = LayoutInflater.from(context);
+            final ListView listView = (ListView) inflater.inflate(
+                    com.android.internal.R.layout.autofill_dataset_picker, null);
+            listView.setAdapter(mAdapter);
+            listView.setOnItemClickListener((adapter, view, position, id) -> {
+                final ViewItem vi = mAdapter.getItem(position);
+                mCallback.onDatasetPicked(vi.getDataset());
+            });
+
+            filter(filterText);
+            mWindow = new AnchoredWindow(windowToken, listView);
+        }
+    }
+
+    public void update(@NonNull Rect anchorBounds) {
+        throwIfDestroyed();
+        if (!mAnchorBounds.equals(anchorBounds)) {
+            mAnchorBounds.set(anchorBounds);
+            mWindow.update(mContentWidth, mContentHeight, anchorBounds);
+        }
+    }
+
+    public void filter(@Nullable String filterText) {
+        throwIfDestroyed();
+        if (mAdapter == null) {
+            return;
+        }
+        if (Objects.equal(mFilterText, filterText)) {
+            return;
+        }
+        mFilterText = filterText;
+        mAdapter.getFilter().filter(filterText, (count) -> {
+            if (mDestroyed) {
+                return;
+            }
+            if (count <= 0) {
+                mCallback.onCanceled();
+            } else {
+                if (updateContentSize()) {
+                    mWindow.update(mContentWidth, mContentHeight, mAnchorBounds);
+                }
+            }
+        });
+    }
+
+    public void destroy() {
+        throwIfDestroyed();
+        mWindow.destroy();
+        mDestroyed = true;
+    }
+
+    private boolean updateContentSize() {
+        if (mAdapter == null) {
+            return false;
+        }
+        boolean changed = false;
+        if (mAdapter.getCount() <= 0) {
+            if (mContentWidth != 0) {
+                mContentWidth = 0;
+                changed = true;
+            }
+            if (mContentHeight != 0) {
+                mContentHeight = 0;
+                changed = true;
+            }
+            return changed;
+        }
+
+        mContentWidth = 0;
+        mContentHeight = 0;
+
+        final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, 0);
+        final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, 0);
+        final int itemCount = mAdapter.getCount();
+        for (int i = 0; i < itemCount; i++) {
+            View view = mAdapter.getItem(i).getView();
+            view.measure(widthMeasureSpec, heightMeasureSpec);
+            final int newContentWidth = Math.max(mContentWidth, view.getMeasuredWidth());
+            if (newContentWidth != mContentWidth) {
+                mContentWidth = newContentWidth;
+                changed = true;
+            }
+            final int newContentHeight = mContentHeight + view.getMeasuredHeight();
+            if (newContentHeight != mContentHeight) {
+                mContentHeight = newContentHeight;
+                changed = true;
+            }
+        }
+        return changed;
+    }
+
+    private void throwIfDestroyed() {
+        if (mDestroyed) {
+            throw new IllegalStateException("cannot interact with a destroyed instance");
+        }
+    }
+
+    private static class ViewItem {
+        private final String mValue;
+        private final Dataset mDataset;
+        private final View mView;
+
+        ViewItem(Dataset dataset, String value, View view) {
+            mDataset = dataset;
+            mValue = value.toLowerCase();
+            mView = view;
+        }
+
+        public View getView() {
+            return mView;
+        }
+
+        public Dataset getDataset() {
+            return mDataset;
+        }
+
+        @Override
+        public String toString() {
+            // Used for filtering in the adapter
+            return mValue;
+        }
+    }
+
+    final class AnchoredWindow implements View.OnTouchListener {
+        private final Point mTempPoint = new Point();
+
+        private final WindowManager mWm;
+
+        private final IBinder mActivityToken;
+        private final View mContentView;
+
+        /**
+         * Constructor.
+         *
+         * @param activityToken token to pass to window manager
+         * @param contentView content of the window
+         */
+        AnchoredWindow(IBinder activityToken, View contentView) {
+            mWm = contentView.getContext().getSystemService(WindowManager.class);
+            mActivityToken = activityToken;
+            mContentView = contentView;
+        }
+
+        /**
+         * Hides the window.
+         */
+        void destroy() {
+            if (mContentView.isAttachedToWindow()) {
+                mContentView.setOnTouchListener(null);
+                mWm.removeView(mContentView);
+            }
+        }
+
+        @Override
+        public boolean onTouch(View view, MotionEvent event) {
+            // When the window is touched outside, hide the window.
+            if (view == mContentView && event.getAction() == MotionEvent.ACTION_OUTSIDE) {
+                mCallback.onCanceled();
+                return true;
+            }
+            return false;
+        }
+
+        public void update(int desiredWidth, int desiredHeight, Rect anchorBounds) {
+            final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
+            params.setTitle("FillUi");
+            params.token = mActivityToken;
+            params.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
+            params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                    | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+                    | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                    | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+                    | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+            params.format = PixelFormat.TRANSLUCENT;
+
+            mWm.getDefaultDisplay().getRealSize(mTempPoint);
+            final int screenWidth = mTempPoint.x;
+            final int screenHeight = mTempPoint.y;
+
+            // Try to place the window at the start of the anchor view if
+            // there is space to fit the content, otherwise fit as much of
+            // the window as possible moving it to the left using all available
+            // screen width.
+            params.x = Math.min(anchorBounds.left, Math.max(screenWidth - desiredWidth, 0));
+            params.width = Math.min(screenWidth, desiredWidth);
+
+            // Try to fit below using all available space with top-start gravity
+            // and if that fails try to fit above using all available space with
+            // bottom-start gravity.
+            final int verticalSpaceBelow = screenHeight - anchorBounds.bottom;
+            if (desiredHeight <= verticalSpaceBelow) {
+                // Fits below bounds.
+                params.height = desiredHeight;
+                params.gravity = Gravity.TOP | Gravity.START;
+                params.y = anchorBounds.bottom;
+            } else {
+                final int verticalSpaceAbove = anchorBounds.top;
+                if (desiredHeight <= verticalSpaceAbove) {
+                    // Fits above bounds.
+                    params.height = desiredHeight;
+                    params.gravity = Gravity.BOTTOM | Gravity.START;
+                    params.y = anchorBounds.top + desiredHeight;
+                } else {
+                    // Pick above/below based on which has the most space.
+                    if (verticalSpaceBelow >= verticalSpaceAbove) {
+                        params.height = verticalSpaceBelow;
+                        params.gravity = Gravity.TOP | Gravity.START;
+                        params.y = anchorBounds.bottom;
+                    } else {
+                        params.height = verticalSpaceAbove;
+                        params.gravity = Gravity.BOTTOM | Gravity.START;
+                        params.y = anchorBounds.top + desiredHeight;
+                    }
+                }
+            }
+
+            if (!mContentView.isAttachedToWindow()) {
+                mWm.addView(mContentView, params);
+                mContentView.setOnTouchListener(this);
+            } else {
+                mWm.updateViewLayout(mContentView, params);
+            }
+        }
+    }
+}
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
new file mode 100644
index 0000000..3f409ad
--- /dev/null
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -0,0 +1,135 @@
+/*
+ * 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.autofill.ui;
+
+import android.annotation.NonNull;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.IntentSender;
+import android.os.Handler;
+import android.service.autofill.SaveInfo;
+import android.text.format.DateUtils;
+import android.view.Gravity;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.TextView;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import com.android.internal.R;
+import com.android.server.UiThread;
+
+/**
+ * Autofill Save Prompt
+ */
+final class SaveUi {
+    public interface OnSaveListener {
+        void onSave();
+        void onCancel(IntentSender listener);
+    }
+
+    private final Handler mHandler = UiThread.getHandler();
+
+    private final @NonNull Dialog mDialog;
+
+    private final @NonNull OnSaveListener mListener;
+
+    private boolean mDestroyed;
+
+    SaveUi(@NonNull Context context, @NonNull CharSequence providerLabel, @NonNull SaveInfo info,
+            @NonNull OnSaveListener listener, int lifeTimeMs) {
+        mListener = listener;
+
+        final LayoutInflater inflater = LayoutInflater.from(context);
+        final View view = inflater.inflate(R.layout.autofill_save, null);
+
+        final TextView titleView = (TextView) view.findViewById(R.id.autofill_save_title);
+        final String type;
+
+        switch(info.getType()) {
+            case SaveInfo.SAVE_DATA_TYPE_PASSWORD:
+                type = context.getString(R.string.autofill_save_type_password);
+                break;
+            case SaveInfo.SAVE_DATA_TYPE_ADDRESS:
+                type = context.getString(R.string.autofill_save_type_address);
+                break;
+            case SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD:
+                type = context.getString(R.string.autofill_save_type_credit_card);
+                break;
+            default:
+                type = null;
+        }
+
+        final String title = (type == null)
+                ? context.getString(R.string.autofill_save_title, providerLabel)
+                : context.getString(R.string.autofill_save_title_with_type, type, providerLabel);
+
+        titleView.setText(title);
+        final CharSequence subTitle = info.getDescription();
+        if (subTitle != null) {
+            final TextView subTitleView = (TextView) view.findViewById(R.id.autofill_save_subtitle);
+            subTitleView.setText(subTitle);
+            subTitleView.setVisibility(View.VISIBLE);
+        }
+
+        final TextView noButton = view.findViewById(R.id.autofill_save_no);
+        if (info.getNegativeActionTitle() != null) {
+            noButton.setText(info.getNegativeActionTitle());
+            noButton.setOnClickListener((v) -> mListener.onCancel(
+                    info.getNegativeActionListener()));
+        } else {
+            noButton.setOnClickListener((v) -> mListener.onCancel(null));
+        }
+
+        final View yesButton = view.findViewById(R.id.autofill_save_yes);
+        yesButton.setOnClickListener((v) -> mListener.onSave());
+
+        final View closeButton = view.findViewById(R.id.autofill_save_close);
+        closeButton.setOnClickListener((v) -> mListener.onCancel(null));
+
+        mDialog = new Dialog(context, R.style.Theme_Material_Panel);
+        mDialog.setContentView(view);
+
+        final Window window = mDialog.getWindow();
+        window.setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
+        window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+                | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
+        window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
+        window.setGravity(Gravity.BOTTOM | Gravity.CENTER);
+        window.setCloseOnTouchOutside(true);
+        window.getAttributes().width = WindowManager.LayoutParams.MATCH_PARENT;
+
+        mDialog.show();
+
+        mHandler.postDelayed(() -> mListener.onCancel(null), lifeTimeMs);
+    }
+
+    void destroy() {
+        throwIfDestroyed();
+        mHandler.removeCallbacksAndMessages(mListener);
+        mDialog.dismiss();
+        mDestroyed = true;
+    }
+
+    private void throwIfDestroyed() {
+        if (mDestroyed) {
+            throw new IllegalStateException("cannot interact with a destroyed instance");
+        }
+    }
+}
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 9b55c7a..8f2b428 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -16,6 +16,23 @@
 
 package com.android.server.backup;
 
+import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_NAME;
+import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_VERSION;
+import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_OLD_VERSION;
+import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_POLICY_ALLOW_APKS;
+import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_MANIFEST_PACKAGE_NAME;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_FULL_RESTORE_SIGNATURE_MISMATCH;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_SYSTEM_APP_NO_AGENT;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_FULL_RESTORE_ALLOW_BACKUP_FALSE;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_APK_NOT_INSTALLED;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_CANNOT_RESTORE_WITHOUT_APK;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_MISSING_SIGNATURE;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_EXPECTED_DIFFERENT_PACKAGE;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_RESTORE_ANY_VERSION;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_VERSIONS_MATCH;
 import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND;
 
 import android.app.ActivityManager;
@@ -35,15 +52,15 @@
 import android.app.backup.BackupTransport;
 import android.app.backup.FullBackup;
 import android.app.backup.FullBackupDataOutput;
-import android.app.backup.IBackupObserver;
-import android.app.backup.IBackupManagerMonitor;
-import android.app.backup.RestoreDescription;
-import android.app.backup.RestoreSet;
 import android.app.backup.IBackupManager;
+import android.app.backup.IBackupManagerMonitor;
+import android.app.backup.IBackupObserver;
 import android.app.backup.IFullBackupRestoreObserver;
 import android.app.backup.IRestoreObserver;
 import android.app.backup.IRestoreSession;
 import android.app.backup.ISelectBackupTransportCallback;
+import android.app.backup.RestoreDescription;
+import android.app.backup.RestoreSet;
 import android.app.backup.SelectBackupTransportCallback;
 import android.content.ActivityNotFoundException;
 import android.content.BroadcastReceiver;
@@ -63,6 +80,7 @@
 import android.content.pm.Signature;
 import android.database.ContentObserver;
 import android.net.Uri;
+import android.os.PowerSaveState;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
@@ -105,6 +123,7 @@
 import com.android.server.SystemService;
 import com.android.server.backup.PackageManagerBackupAgent.Metadata;
 
+import com.android.server.power.BatterySaverPolicy.ServiceType;
 import libcore.io.IoUtils;
 
 import java.io.BufferedInputStream;
@@ -133,6 +152,7 @@
 import java.security.spec.InvalidKeySpecException;
 import java.security.spec.KeySpec;
 import java.text.SimpleDateFormat;
+import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -143,6 +163,7 @@
 import java.util.List;
 import java.util.Map.Entry;
 import java.util.Objects;
+import java.util.Queue;
 import java.util.Random;
 import java.util.Set;
 import java.util.TreeMap;
@@ -324,6 +345,11 @@
     final Object mClearDataLock = new Object();
     volatile boolean mClearingData;
 
+    @GuardedBy("mPendingRestores")
+    private boolean mIsRestoreInProgress;
+    @GuardedBy("mPendingRestores")
+    private final Queue<PerformUnifiedRestoreTask> mPendingRestores = new ArrayDeque<>();
+
     ActiveRestoreSession mActiveRestoreSession;
 
     // Watch the device provisioning operation during setup
@@ -832,13 +858,15 @@
                     try {
                         String dirName = transport.transportDirName();
                         PerformBackupTask pbt = new PerformBackupTask(transport, dirName, queue,
-                                oldJournal, null, null, null, false, false /* nonIncremental */);
+                                oldJournal, null, null, Collections.<String>emptyList(), false,
+                                false /* nonIncremental */);
                         Message pbtMessage = obtainMessage(MSG_BACKUP_RESTORE_STEP, pbt);
                         sendMessage(pbtMessage);
                     } catch (Exception e) {
                         // unable to ask the transport its dir name -- transient failure, since
                         // the above check succeeded.  Try again next time.
-                        Slog.e(TAG, "Transport became unavailable attempting backup");
+                        Slog.e(TAG, "Transport became unavailable attempting backup"
+                                + " or error initializing backup task", e);
                         staged = false;
                     }
                 } else {
@@ -906,11 +934,28 @@
             {
                 RestoreParams params = (RestoreParams)msg.obj;
                 Slog.d(TAG, "MSG_RUN_RESTORE observer=" + params.observer);
-                BackupRestoreTask task = new PerformUnifiedRestoreTask(params.transport,
+
+                PerformUnifiedRestoreTask task = new PerformUnifiedRestoreTask(params.transport,
                         params.observer, params.monitor, params.token, params.pkgInfo,
                         params.pmToken, params.isSystemRestore, params.filterSet);
-                Message restoreMsg = obtainMessage(MSG_BACKUP_RESTORE_STEP, task);
-                sendMessage(restoreMsg);
+
+                synchronized (mPendingRestores) {
+                    if (mIsRestoreInProgress) {
+                        if (DEBUG) {
+                            Slog.d(TAG, "Restore in progress, queueing.");
+                        }
+                        mPendingRestores.add(task);
+                        // This task will be picked up and executed when the the currently running
+                        // restore task finishes.
+                    } else {
+                        if (DEBUG) {
+                            Slog.d(TAG, "Starting restore.");
+                        }
+                        mIsRestoreInProgress = true;
+                        Message restoreMsg = obtainMessage(MSG_BACKUP_RESTORE_STEP, task);
+                        sendMessage(restoreMsg);
+                    }
+                }
                 break;
             }
 
@@ -2340,13 +2385,15 @@
             Slog.e(TAG, "No packages named for backup request");
             sendBackupFinished(observer, BackupManager.ERROR_TRANSPORT_ABORTED);
             monitor = monitorEvent(monitor, BackupManagerMonitor.LOG_EVENT_ID_NO_PACKAGES,
-                    null, BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT);
+                    null, BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT, null);
             throw new IllegalArgumentException("No packages are provided for backup");
         }
 
         IBackupTransport transport = mTransportManager.getCurrentTransportBinder();
         if (transport == null) {
             sendBackupFinished(observer, BackupManager.ERROR_TRANSPORT_ABORTED);
+            monitor = monitorEvent(monitor, BackupManagerMonitor.LOG_EVENT_ID_TRANSPORT_IS_NULL,
+                    null, BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT, null);
             return BackupManager.ERROR_TRANSPORT_ABORTED;
         }
 
@@ -2417,12 +2464,10 @@
                         operationsToCancel.add(token);
                     }
                 }
-
-                for (Integer token : operationsToCancel) {
-                    handleCancel(token, true /* cancelAll */);
-                }
             }
-
+            for (Integer token : operationsToCancel) {
+                handleCancel(token, true /* cancelAll */);
+            }
             // We don't want the backup jobs to kick in any time soon.
             // Reschedules them to run in the distant future.
             KeyValueBackupJob.schedule(mContext, BUSY_BACKOFF_MIN_MILLIS);
@@ -2614,7 +2659,7 @@
         File mStateDir;
         File mJournal;
         BackupState mCurrentState;
-        ArrayList<String> mPendingFullBackups;
+        List<String> mPendingFullBackups;
         IBackupObserver mObserver;
         IBackupManagerMonitor mMonitor;
 
@@ -2640,7 +2685,7 @@
 
         public PerformBackupTask(IBackupTransport transport, String dirName,
                 ArrayList<BackupRequest> queue, File journal, IBackupObserver observer,
-                IBackupManagerMonitor monitor, ArrayList<String> pendingFullBackups,
+                IBackupManagerMonitor monitor, List<String> pendingFullBackups,
                 boolean userInitiated, boolean nonIncremental) {
             mTransport = transport;
             mOriginalQueue = queue;
@@ -2655,19 +2700,32 @@
             mStateDir = new File(mBaseStateDir, dirName);
             mCurrentOpToken = generateToken();
 
-            mCurrentState = BackupState.INITIAL;
             mFinished = false;
 
-            CountDownLatch latch = new CountDownLatch(1);
-            String[] fullBackups =
-                    mPendingFullBackups.toArray(new String[mPendingFullBackups.size()]);
-            mFullBackupTask =
-                    new PerformFullTransportBackupTask(/*fullBackupRestoreObserver*/ null,
-                            fullBackups, /*updateSchedule*/ false, /*runningJob*/ null, latch,
-                            mObserver, mMonitor,mUserInitiated);
+            synchronized (mCurrentOpLock) {
+                if (isBackupOperationInProgress()) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "Skipping backup since one is already in progress.");
+                    }
+                    mCancelAll = true;
+                    mFullBackupTask = null;
+                    mCurrentState = BackupState.FINAL;
+                    addBackupTrace("Skipped. Backup already in progress.");
+                } else {
+                    mCurrentState = BackupState.INITIAL;
+                    CountDownLatch latch = new CountDownLatch(1);
+                    String[] fullBackups =
+                            mPendingFullBackups.toArray(new String[mPendingFullBackups.size()]);
+                    mFullBackupTask =
+                            new PerformFullTransportBackupTask(/*fullBackupRestoreObserver*/ null,
+                                    fullBackups, /*updateSchedule*/ false, /*runningJob*/ null,
+                                    latch,
+                                    mObserver, mMonitor, mUserInitiated);
 
-            registerTask();
-            addBackupTrace("STATE => INITIAL");
+                    registerTask();
+                    addBackupTrace("STATE => INITIAL");
+                }
+            }
         }
 
         /**
@@ -3050,7 +3108,9 @@
                 mWakelock.acquire();
                 (new Thread(mFullBackupTask, "full-transport-requested")).start();
             } else if (mCancelAll) {
-                mFullBackupTask.unregisterTask();
+                if (mFullBackupTask != null) {
+                    mFullBackupTask.unregisterTask();
+                }
                 sendBackupFinished(mObserver, BackupManager.ERROR_BACKUP_CANCELLED);
             } else {
                 mFullBackupTask.unregisterTask();
@@ -3296,6 +3356,14 @@
                                     addBackupTrace("illegal key " + key + " from " + pkgName);
                                     EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, pkgName,
                                             "bad key");
+                                    mMonitor = monitorEvent(mMonitor,
+                                            BackupManagerMonitor.LOG_EVENT_ID_ILLEGAL_KEY,
+                                            mCurrentPackage,
+                                            BackupManagerMonitor
+                                                    .LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                                            putMonitoringExtra(null,
+                                                    BackupManagerMonitor.EXTRA_LOG_ILLEGAL_KEY,
+                                                    key));
                                     mBackupHandler.removeMessages(MSG_BACKUP_OPERATION_TIMEOUT);
                                     sendBackupOnPackageResult(mObserver, pkgName,
                                             BackupManager.ERROR_AGENT_FAILURE);
@@ -3365,6 +3433,11 @@
                         if (MORE_DEBUG) Slog.i(TAG,
                                 "no backup data written; not calling transport");
                         addBackupTrace("no data to send");
+                        mMonitor = monitorEvent(mMonitor,
+                                BackupManagerMonitor.LOG_EVENT_ID_NO_DATA_TO_SEND,
+                                mCurrentPackage,
+                                BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                                null);
                     }
 
                     if (mStatus == BackupTransport.TRANSPORT_OK) {
@@ -3459,6 +3532,11 @@
                 // fail repeatedly (i.e. have proved themselves to be buggy).
                 Slog.e(TAG, "Cancel backing up " + mCurrentPackage.packageName);
                 EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, mCurrentPackage.packageName);
+                mMonitor = monitorEvent(mMonitor,
+                        BackupManagerMonitor.LOG_EVENT_ID_KEY_VALUE_BACKUP_CANCEL,
+                        mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT,
+                        putMonitoringExtra(null, BackupManagerMonitor.EXTRA_LOG_CANCEL_ALL,
+                                mCancelAll));
                 addBackupTrace(
                         "cancel of " + mCurrentPackage.packageName + ", cancelAll=" + cancelAll);
                 errorCleanup();
@@ -3531,6 +3609,18 @@
         }
     }
 
+    private boolean isBackupOperationInProgress() {
+        synchronized (mCurrentOpLock) {
+            for (int i = 0; i < mCurrentOperations.size(); i++) {
+                Operation op = mCurrentOperations.valueAt(i);
+                if (op.type == OP_TYPE_BACKUP && op.state == OP_PENDING) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
 
     // ----- Full backup/restore to a file/socket -----
 
@@ -4513,6 +4603,14 @@
             mCurrentOpToken = generateToken();
             mBackupRunnerOpToken = generateToken();
 
+            if (isBackupOperationInProgress()) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Skipping full backup. A backup is already in progress.");
+                }
+                mCancelAll = true;
+                return;
+            }
+
             registerTask();
 
             for (String pkg : whichPackages) {
@@ -4528,6 +4626,11 @@
                         if (MORE_DEBUG) {
                             Slog.d(TAG, "Ignoring ineligible package " + pkg);
                         }
+                        mMonitor = monitorEvent(mMonitor,
+                                BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_INELIGIBLE,
+                                mCurrentPackage,
+                                BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                                null);
                         sendBackupOnPackageResult(mBackupObserver, pkg,
                             BackupManager.ERROR_BACKUP_NOT_ALLOWED);
                         continue;
@@ -4538,6 +4641,11 @@
                             Slog.d(TAG, "Ignoring full-data backup of key/value participant "
                                     + pkg);
                         }
+                        mMonitor = monitorEvent(mMonitor,
+                                BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_KEY_VALUE_PARTICIPANT,
+                                mCurrentPackage,
+                                BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                                null);
                         sendBackupOnPackageResult(mBackupObserver, pkg,
                                 BackupManager.ERROR_BACKUP_NOT_ALLOWED);
                         continue;
@@ -4548,6 +4656,11 @@
                         if (MORE_DEBUG) {
                             Slog.d(TAG, "Ignoring stopped package " + pkg);
                         }
+                        mMonitor = monitorEvent(mMonitor,
+                                BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_STOPPED,
+                                mCurrentPackage,
+                                BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                                null);
                         sendBackupOnPackageResult(mBackupObserver, pkg,
                                 BackupManager.ERROR_BACKUP_NOT_ALLOWED);
                         continue;
@@ -4555,6 +4668,11 @@
                     mPackages.add(info);
                 } catch (NameNotFoundException e) {
                     Slog.i(TAG, "Requested package " + pkg + " not found; ignoring");
+                    mMonitor = monitorEvent(mMonitor,
+                            BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_NOT_FOUND,
+                            mCurrentPackage,
+                            BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                            null);
                 }
             }
         }
@@ -4626,9 +4744,17 @@
                 if (!mEnabled || !mProvisioned) {
                     // Backups are globally disabled, so don't proceed.
                     if (DEBUG) {
-                        Slog.i(TAG, "full backup requested but e=" + mEnabled
-                                + " p=" + mProvisioned + "; ignoring");
+                        Slog.i(TAG, "full backup requested but enabled=" + mEnabled
+                                + " provisioned=" + mProvisioned + "; ignoring");
                     }
+                    int monitoringEvent;
+                    if (!mEnabled) {
+                        monitoringEvent = BackupManagerMonitor.LOG_EVENT_ID_BACKUP_DISABLED;
+                    } else {
+                        monitoringEvent = BackupManagerMonitor.LOG_EVENT_ID_DEVICE_NOT_PROVISIONED;
+                    }
+                    mMonitor = monitorEvent(mMonitor, monitoringEvent, null,
+                            BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null);
                     mUpdateSchedule = false;
                     backupRunStatus = BackupManager.ERROR_BACKUP_NOT_ALLOWED;
                     return;
@@ -4638,6 +4764,10 @@
                 if (mTransport == null) {
                     Slog.w(TAG, "Transport not present; full data backup not performed");
                     backupRunStatus = BackupManager.ERROR_TRANSPORT_ABORTED;
+                    mMonitor = monitorEvent(mMonitor,
+                            BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_TRANSPORT_NOT_PRESENT,
+                            mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT,
+                            null);
                     return;
                 }
 
@@ -4648,7 +4778,8 @@
                     PackageInfo currentPackage = mPackages.get(i);
                     String packageName = currentPackage.packageName;
                     if (DEBUG) {
-                        Slog.i(TAG, "Initiating full-data transport backup of " + packageName);
+                        Slog.i(TAG, "Initiating full-data transport backup of " + packageName
+                                + " token: " + mCurrentOpToken);
                     }
                     EventLog.writeEvent(EventLogTags.FULL_BACKUP_PACKAGE, packageName);
 
@@ -4707,6 +4838,13 @@
                                         + packageName + ": " + preflightResult
                                         + ", not running backup.");
                             }
+                            mMonitor = monitorEvent(mMonitor,
+                                    BackupManagerMonitor.LOG_EVENT_ID_ERROR_PREFLIGHT,
+                                    mCurrentPackage,
+                                    BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                                    putMonitoringExtra(null,
+                                            BackupManagerMonitor.EXTRA_LOG_PREFLIGHT_ERROR,
+                                            preflightResult));
                             backupPackageStatus = (int) preflightResult;
                         } else {
                             int nRead = 0;
@@ -4734,6 +4872,11 @@
                             if (backupPackageStatus == BackupTransport.TRANSPORT_QUOTA_EXCEEDED) {
                                 Slog.w(TAG, "Package hit quota limit in-flight " + packageName
                                         + ": " + totalRead + " of " + quota);
+                                mMonitor = monitorEvent(mMonitor,
+                                        BackupManagerMonitor.LOG_EVENT_ID_QUOTA_HIT_PREFLIGHT,
+                                        mCurrentPackage,
+                                        BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT,
+                                        null);
                                 mBackupRunner.sendQuotaExceeded(totalRead, quota);
                             }
                         }
@@ -4868,6 +5011,14 @@
             } catch (Exception e) {
                 backupRunStatus = BackupManager.ERROR_TRANSPORT_ABORTED;
                 Slog.w(TAG, "Exception trying full transport backup", e);
+                mMonitor = monitorEvent(mMonitor,
+                        BackupManagerMonitor.LOG_EVENT_ID_EXCEPTION_FULL_BACKUP,
+                        mCurrentPackage,
+                        BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                        putMonitoringExtra(null,
+                                BackupManagerMonitor.EXTRA_LOG_EXCEPTION_FULL_BACKUP,
+                                Log.getStackTraceString(e)));
+
             } finally {
 
                 if (mCancelAll) {
@@ -5147,8 +5298,8 @@
                 }
 
                 mMonitor = monitorEvent(mMonitor,
-                        BackupManagerMonitor.LOG_EVENT_ID_FULL_BACKUP_TIMEOUT,
-                        mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT);
+                        BackupManagerMonitor.LOG_EVENT_ID_FULL_BACKUP_CANCEL,
+                        mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT, null);
                 mIsCancelled = true;
                 // Cancel tasks spun off by this task.
                 BackupManagerService.this.handleCancel(mEphemeralToken, cancelAll);
@@ -5291,7 +5442,9 @@
 
         // Don't run the backup if we're in battery saver mode, but reschedule
         // to try again in the not-so-distant future.
-        if (mPowerManager.isPowerSaveMode()) {
+        final PowerSaveState result =
+                mPowerManager.getPowerSaveState(ServiceType.FULL_BACKUP);
+        if (result.batterySaverEnabled) {
             if (DEBUG) Slog.i(TAG, "Deferring scheduled full backups in battery saver mode");
             FullBackupJob.schedule(mContext, KeyValueBackupJob.BATCH_INTERVAL);
             return false;
@@ -5525,6 +5678,8 @@
         // Dedicated observer, if any
         IFullBackupRestoreObserver mObserver;
 
+        IBackupManagerMonitor mMonitor;
+
         // Where we're delivering the file data as we go
         IBackupAgent mAgent;
 
@@ -5606,11 +5761,12 @@
         }
 
         public FullRestoreEngine(BackupRestoreTask monitorTask, IFullBackupRestoreObserver observer,
-                PackageInfo onlyPackage, boolean allowApks, boolean allowObbs,
-                int ephemeralOpToken) {
+                IBackupManagerMonitor monitor, PackageInfo onlyPackage, boolean allowApks,
+                boolean allowObbs, int ephemeralOpToken) {
             mEphemeralOpToken = ephemeralOpToken;
             mMonitorTask = monitorTask;
             mObserver = observer;
+            mMonitor = monitor;
             mOnlyPackage = onlyPackage;
             mAllowApks = allowApks;
             mAllowObbs = allowObbs;
@@ -6232,9 +6388,29 @@
                 } else {
                     Slog.w(TAG, "Metadata mismatch: package " + info.packageName
                             + " but widget data for " + pkg);
+
+                    Bundle monitoringExtras = putMonitoringExtra(null,
+                            EXTRA_LOG_EVENT_PACKAGE_NAME, info.packageName);
+                    monitoringExtras = putMonitoringExtra(monitoringExtras,
+                            BackupManagerMonitor.EXTRA_LOG_WIDGET_PACKAGE_NAME, pkg);
+                    mMonitor = monitorEvent(mMonitor,
+                            BackupManagerMonitor.LOG_EVENT_ID_WIDGET_METADATA_MISMATCH,
+                            null,
+                            LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                            monitoringExtras);
                 }
             } else {
                 Slog.w(TAG, "Unsupported metadata version " + version);
+
+                Bundle monitoringExtras = putMonitoringExtra(null, EXTRA_LOG_EVENT_PACKAGE_NAME,
+                        info.packageName);
+                monitoringExtras = putMonitoringExtra(monitoringExtras,
+                        EXTRA_LOG_EVENT_PACKAGE_VERSION, version);
+                mMonitor = monitorEvent(mMonitor,
+                        BackupManagerMonitor.LOG_EVENT_ID_WIDGET_UNKNOWN_VERSION,
+                        null,
+                        LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                        monitoringExtras);
             }
         }
 
@@ -6309,10 +6485,20 @@
                                             if ((pkgInfo.applicationInfo.flags
                                                     & ApplicationInfo.FLAG_RESTORE_ANY_VERSION) != 0) {
                                                 Slog.i(TAG, "Package has restoreAnyVersion; taking data");
+                                                mMonitor = monitorEvent(mMonitor,
+                                                        LOG_EVENT_ID_RESTORE_ANY_VERSION,
+                                                        pkgInfo,
+                                                        LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                                                        null);
                                                 policy = RestorePolicy.ACCEPT;
                                             } else if (pkgInfo.versionCode >= version) {
                                                 Slog.i(TAG, "Sig + version match; taking data");
                                                 policy = RestorePolicy.ACCEPT;
+                                                mMonitor = monitorEvent(mMonitor,
+                                                        LOG_EVENT_ID_VERSIONS_MATCH,
+                                                        pkgInfo,
+                                                        LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                                                        null);
                                             } else {
                                                 // The data is from a newer version of the app than
                                                 // is presently installed.  That means we can only
@@ -6326,20 +6512,43 @@
                                                 } else {
                                                     Slog.i(TAG, "Data requires newer version "
                                                             + version + "; ignoring");
+                                                    mMonitor = monitorEvent(mMonitor,
+                                                            LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER,
+                                                            pkgInfo,
+                                                            LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                                                            putMonitoringExtra(null,
+                                                                    EXTRA_LOG_OLD_VERSION,
+                                                                    version));
+
                                                     policy = RestorePolicy.IGNORE;
                                                 }
                                             }
                                         } else {
                                             Slog.w(TAG, "Restore manifest signatures do not match "
                                                     + "installed application for " + info.packageName);
+                                            mMonitor = monitorEvent(mMonitor,
+                                                    LOG_EVENT_ID_FULL_RESTORE_SIGNATURE_MISMATCH,
+                                                    pkgInfo,
+                                                    LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                                                    null);
                                         }
                                     } else {
                                         Slog.w(TAG, "Package " + info.packageName
                                                 + " is system level with no agent");
+                                        mMonitor = monitorEvent(mMonitor,
+                                                LOG_EVENT_ID_SYSTEM_APP_NO_AGENT,
+                                                pkgInfo,
+                                                LOG_EVENT_CATEGORY_AGENT,
+                                                null);
                                     }
                                 } else {
                                     if (DEBUG) Slog.i(TAG, "Restore manifest from "
                                             + info.packageName + " but allowBackup=false");
+                                    mMonitor = monitorEvent(mMonitor,
+                                            LOG_EVENT_ID_FULL_RESTORE_ALLOW_BACKUP_FALSE,
+                                            pkgInfo,
+                                            LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                                            null);
                                 }
                             } catch (NameNotFoundException e) {
                                 // Okay, the target app isn't installed.  We can process
@@ -6352,26 +6561,71 @@
                                 } else {
                                     policy = RestorePolicy.IGNORE;
                                 }
+                                Bundle monitoringExtras = putMonitoringExtra(null,
+                                        EXTRA_LOG_EVENT_PACKAGE_NAME, info.packageName);
+                                monitoringExtras = putMonitoringExtra(monitoringExtras,
+                                        EXTRA_LOG_POLICY_ALLOW_APKS, mAllowApks);
+                                mMonitor = monitorEvent(mMonitor,
+                                        LOG_EVENT_ID_APK_NOT_INSTALLED,
+                                        null,
+                                        LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                                        monitoringExtras);
                             }
 
                             if (policy == RestorePolicy.ACCEPT_IF_APK && !hasApk) {
                                 Slog.i(TAG, "Cannot restore package " + info.packageName
                                         + " without the matching .apk");
+                                mMonitor = monitorEvent(mMonitor,
+                                        LOG_EVENT_ID_CANNOT_RESTORE_WITHOUT_APK,
+                                        null,
+                                        LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                                        putMonitoringExtra(null,
+                                                EXTRA_LOG_EVENT_PACKAGE_NAME, info.packageName));
                             }
                         } else {
                             Slog.i(TAG, "Missing signature on backed-up package "
                                     + info.packageName);
+                            mMonitor = monitorEvent(mMonitor,
+                                    LOG_EVENT_ID_MISSING_SIGNATURE,
+                                    null,
+                                    LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                                    putMonitoringExtra(null,
+                                            EXTRA_LOG_EVENT_PACKAGE_NAME, info.packageName));
                         }
                     } else {
                         Slog.i(TAG, "Expected package " + info.packageName
                                 + " but restore manifest claims " + manifestPackage);
+                        Bundle monitoringExtras = putMonitoringExtra(null,
+                                EXTRA_LOG_EVENT_PACKAGE_NAME, info.packageName);
+                        monitoringExtras = putMonitoringExtra(monitoringExtras,
+                                EXTRA_LOG_MANIFEST_PACKAGE_NAME, manifestPackage);
+                        mMonitor = monitorEvent(mMonitor,
+                                LOG_EVENT_ID_EXPECTED_DIFFERENT_PACKAGE,
+                                null,
+                                LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                                monitoringExtras);
                     }
                 } else {
                     Slog.i(TAG, "Unknown restore manifest version " + version
                             + " for package " + info.packageName);
+                    Bundle monitoringExtras = putMonitoringExtra(null,
+                            EXTRA_LOG_EVENT_PACKAGE_NAME, info.packageName);
+                    monitoringExtras = putMonitoringExtra(monitoringExtras,
+                            EXTRA_LOG_EVENT_PACKAGE_VERSION, version);
+                    mMonitor = monitorEvent(mMonitor,
+                            BackupManagerMonitor.LOG_EVENT_ID_UNKNOWN_VERSION,
+                            null,
+                            LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                            monitoringExtras);
+
                 }
             } catch (NumberFormatException e) {
                 Slog.w(TAG, "Corrupt restore manifest for package " + info.packageName);
+                mMonitor = monitorEvent(mMonitor,
+                        BackupManagerMonitor.LOG_EVENT_ID_CORRUPT_MANIFEST,
+                        null,
+                        LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                        putMonitoringExtra(null, EXTRA_LOG_EVENT_PACKAGE_NAME, info.packageName));
             } catch (IllegalArgumentException e) {
                 Slog.w(TAG, e.getMessage());
             }
@@ -8461,12 +8715,21 @@
                 RestoreDescription desc = mTransport.nextRestorePackage();
                 if (desc == null) {
                     Slog.e(TAG, "No restore metadata available; halting");
+                    mMonitor = monitorEvent(mMonitor,
+                            BackupManagerMonitor.LOG_EVENT_ID_NO_RESTORE_METADATA_AVAILABLE,
+                            mCurrentPackage,
+                            BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null);
                     mStatus = BackupTransport.TRANSPORT_ERROR;
                     executeNextState(UnifiedRestoreState.FINAL);
                     return;
                 }
                 if (!PACKAGE_MANAGER_SENTINEL.equals(desc.getPackageName())) {
-                    Slog.e(TAG, "Required metadata but got " + desc.getPackageName());
+                    Slog.e(TAG, "Required package metadata but got "
+                            + desc.getPackageName());
+                    mMonitor = monitorEvent(mMonitor,
+                            BackupManagerMonitor.LOG_EVENT_ID_NO_PM_METADATA_RECEIVED,
+                            mCurrentPackage,
+                            BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null);
                     mStatus = BackupTransport.TRANSPORT_ERROR;
                     executeNextState(UnifiedRestoreState.FINAL);
                     return;
@@ -8494,7 +8757,11 @@
                 // signature/version verification etc, so we simply do not proceed with
                 // the restore operation.
                 if (!mPmAgent.hasMetadata()) {
-                    Slog.e(TAG, "No restore metadata available, so not restoring");
+                    Slog.e(TAG, "PM agent has no metadata, so not restoring");
+                    mMonitor = monitorEvent(mMonitor,
+                            BackupManagerMonitor.LOG_EVENT_ID_PM_AGENT_HAS_NO_METADATA,
+                            mCurrentPackage,
+                            BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null);
                     EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,
                             PACKAGE_MANAGER_SENTINEL,
                             "Package manager restore metadata missing");
@@ -8510,6 +8777,10 @@
             } catch (Exception e) {
                 // If we lost the transport at any time, halt
                 Slog.e(TAG, "Unable to contact transport for restore: " + e.getMessage());
+                mMonitor = monitorEvent(mMonitor,
+                        BackupManagerMonitor.LOG_EVENT_ID_LOST_TRANSPORT,
+                        null,
+                        BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT, null);
                 mStatus = BackupTransport.TRANSPORT_ERROR;
                 mBackupHandler.removeMessages(MSG_BACKUP_RESTORE_STEP, this);
                 executeNextState(UnifiedRestoreState.FINAL);
@@ -8562,6 +8833,11 @@
                     // Whoops, we thought we could restore this package but it
                     // turns out not to be present.  Skip it.
                     Slog.e(TAG, "Package not present: " + pkgName);
+                    mMonitor = monitorEvent(mMonitor,
+                            BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_NOT_PRESENT,
+                            mCurrentPackage,
+                            BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                            null);
                     EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, pkgName,
                             "Package missing on device");
                     nextState = UnifiedRestoreState.RUNNING_QUEUE;
@@ -8574,17 +8850,37 @@
                     // handle this case, we do not attempt the restore.
                     if ((mCurrentPackage.applicationInfo.flags
                             & ApplicationInfo.FLAG_RESTORE_ANY_VERSION) == 0) {
-                        String message = "Version " + metaInfo.versionCode
+                        String message = "Source version " + metaInfo.versionCode
                                 + " > installed version " + mCurrentPackage.versionCode;
                         Slog.w(TAG, "Package " + pkgName + ": " + message);
+                        Bundle monitoringExtras = putMonitoringExtra(null,
+                                BackupManagerMonitor.EXTRA_LOG_RESTORE_VERSION,
+                                metaInfo.versionCode);
+                        monitoringExtras = putMonitoringExtra(monitoringExtras,
+                                BackupManagerMonitor.EXTRA_LOG_RESTORE_ANYWAY, false);
+                        mMonitor = monitorEvent(mMonitor,
+                                BackupManagerMonitor.LOG_EVENT_ID_RESTORE_VERSION_HIGHER,
+                                mCurrentPackage,
+                                BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                                monitoringExtras);
                         EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,
                                 pkgName, message);
                         nextState = UnifiedRestoreState.RUNNING_QUEUE;
                         return;
                     } else {
-                        if (DEBUG) Slog.v(TAG, "Version " + metaInfo.versionCode
-                                + " > installed " + mCurrentPackage.versionCode
+                        if (DEBUG) Slog.v(TAG, "Source version " + metaInfo.versionCode
+                                + " > installed version " + mCurrentPackage.versionCode
                                 + " but restoreAnyVersion");
+                        Bundle monitoringExtras = putMonitoringExtra(null,
+                                BackupManagerMonitor.EXTRA_LOG_RESTORE_VERSION,
+                                metaInfo.versionCode);
+                        monitoringExtras = putMonitoringExtra(monitoringExtras,
+                                BackupManagerMonitor.EXTRA_LOG_RESTORE_ANYWAY, true);
+                        mMonitor = monitorEvent(mMonitor,
+                                BackupManagerMonitor.LOG_EVENT_ID_RESTORE_VERSION_HIGHER,
+                                mCurrentPackage,
+                                BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                                monitoringExtras);
                     }
                 }
 
@@ -8631,6 +8927,9 @@
                     Slog.i(TAG, "Data exists for package " + packageName
                             + " but app has no agent; skipping");
                 }
+                mMonitor = monitorEvent(mMonitor,
+                        BackupManagerMonitor.LOG_EVENT_ID_APP_HAS_NO_AGENT, mCurrentPackage,
+                        BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT, null);
                 EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, packageName,
                         "Package has no agent");
                 executeNextState(UnifiedRestoreState.RUNNING_QUEUE);
@@ -8640,6 +8939,9 @@
             Metadata metaInfo = mPmAgent.getRestoredMetadata(packageName);
             if (!BackupUtils.signaturesMatch(metaInfo.sigHashes, mCurrentPackage)) {
                 Slog.w(TAG, "Signature mismatch restoring " + packageName);
+                mMonitor = monitorEvent(mMonitor,
+                        BackupManagerMonitor.LOG_EVENT_ID_SIGNATURE_MISMATCH, mCurrentPackage,
+                        BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null);
                 EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, packageName,
                         "Signature mismatch");
                 executeNextState(UnifiedRestoreState.RUNNING_QUEUE);
@@ -8652,6 +8954,9 @@
                     ApplicationThreadConstants.BACKUP_MODE_INCREMENTAL);
             if (mAgent == null) {
                 Slog.w(TAG, "Can't find backup agent for " + packageName);
+                mMonitor = monitorEvent(mMonitor,
+                        BackupManagerMonitor.LOG_EVENT_ID_CANT_FIND_AGENT, mCurrentPackage,
+                        BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null);
                 EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, packageName,
                         "Restore agent missing");
                 executeNextState(UnifiedRestoreState.RUNNING_QUEUE);
@@ -8857,7 +9162,7 @@
                 EventLog.writeEvent(EventLogTags.FULL_RESTORE_PACKAGE,
                         mCurrentPackage.packageName);
 
-                mEngine = new FullRestoreEngine(this, null, mCurrentPackage, false, false, mEphemeralOpToken);
+                mEngine = new FullRestoreEngine(this, null, mMonitor, mCurrentPackage, false, false, mEphemeralOpToken);
                 mEngineThread = new EngineThread(mEngine, mEnginePipes[0]);
 
                 ParcelFileDescriptor eWriteEnd = mEnginePipes[1];
@@ -9001,8 +9306,10 @@
                 if (DEBUG) {
                     Slog.w(TAG, "Full-data restore target timed out; shutting down");
                 }
-                mMonitor = monitorEvent(mMonitor, BackupManagerMonitor.LOG_EVENT_ID_FULL_RESTORE_TIMEOUT,
-                        mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT);
+
+                mMonitor = monitorEvent(mMonitor,
+                        BackupManagerMonitor.LOG_EVENT_ID_FULL_RESTORE_TIMEOUT,
+                        mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT, null);
                 mEngineThread.handleTimeout();
 
                 IoUtils.closeQuietly(mEnginePipes[1]);
@@ -9103,6 +9410,24 @@
 
             // done; we can finally release the wakelock and be legitimately done.
             Slog.i(TAG, "Restore complete.");
+
+            synchronized (mPendingRestores) {
+                if (mPendingRestores.size() > 0) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "Starting next pending restore.");
+                    }
+                    PerformUnifiedRestoreTask task = mPendingRestores.remove();
+                    mBackupHandler.sendMessage(
+                            mBackupHandler.obtainMessage(MSG_BACKUP_RESTORE_STEP, task));
+
+                } else {
+                    mIsRestoreInProgress = false;
+                    if (MORE_DEBUG) {
+                        Slog.d(TAG, "No pending restores.");
+                    }
+                }
+            }
+
             mWakelock.release();
         }
 
@@ -9245,8 +9570,9 @@
         public void handleCancel(boolean cancelAll) {
             removeOperation(mEphemeralOpToken);
             Slog.e(TAG, "Timeout restoring application " + mCurrentPackage.packageName);
-            mMonitor = monitorEvent(mMonitor, BackupManagerMonitor.LOG_EVENT_ID_KEY_VALUE_RESTORE_TIMEOUT,
-                    mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT);
+            mMonitor = monitorEvent(mMonitor,
+                    BackupManagerMonitor.LOG_EVENT_ID_KEY_VALUE_RESTORE_TIMEOUT,
+                    mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT, null);
             EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,
                     mCurrentPackage.packageName, "restore timeout");
             // Handle like an agent that threw on invocation: wipe it and go on to the next
@@ -9567,7 +9893,9 @@
     public void backupNow() {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "backupNow");
 
-        if (mPowerManager.isPowerSaveMode()) {
+        final PowerSaveState result =
+                mPowerManager.getPowerSaveState(ServiceType.KEYVALUE_BACKUP);
+        if (result.batterySaverEnabled) {
             if (DEBUG) Slog.v(TAG, "Not running backup while in battery save mode");
             KeyValueBackupJob.schedule(mContext);   // try again in several hours
         } else {
@@ -10912,19 +11240,55 @@
         }
     }
 
+    private Bundle putMonitoringExtra(Bundle extras, String key, String value) {
+        if (extras == null) {
+            extras = new Bundle();
+        }
+        extras.putString(key, value);
+        return extras;
+    }
+
+    private Bundle putMonitoringExtra(Bundle extras, String key, int value) {
+        if (extras == null) {
+            extras = new Bundle();
+        }
+        extras.putInt(key, value);
+        return extras;
+    }
+
+    private Bundle putMonitoringExtra(Bundle extras, String key, long value) {
+        if (extras == null) {
+            extras = new Bundle();
+        }
+        extras.putLong(key, value);
+        return extras;
+    }
+
+
+    private Bundle putMonitoringExtra(Bundle extras, String key, boolean value) {
+        if (extras == null) {
+            extras = new Bundle();
+        }
+        extras.putBoolean(key, value);
+        return extras;
+    }
+
     private static IBackupManagerMonitor monitorEvent(IBackupManagerMonitor monitor, int id,
-            PackageInfo pkg, int category) {
+            PackageInfo pkg, int category, Bundle extras) {
         if (monitor != null) {
             try {
                 Bundle bundle = new Bundle();
                 bundle.putInt(BackupManagerMonitor.EXTRA_LOG_EVENT_ID, id);
                 bundle.putInt(BackupManagerMonitor.EXTRA_LOG_EVENT_CATEGORY, category);
                 if (pkg != null) {
-                    bundle.putString(BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_NAME,
+                    bundle.putString(EXTRA_LOG_EVENT_PACKAGE_NAME,
                             pkg.packageName);
                     bundle.putInt(BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_VERSION,
                             pkg.versionCode);
                 }
+                if (extras != null) {
+                    bundle.putAll(extras);
+                }
                 monitor.onEvent(bundle);
                 return monitor;
             } catch(RemoteException e) {
diff --git a/services/backup/java/com/android/server/backup/TransportManager.java b/services/backup/java/com/android/server/backup/TransportManager.java
index b9dbe13..619ddb1 100644
--- a/services/backup/java/com/android/server/backup/TransportManager.java
+++ b/services/backup/java/com/android/server/backup/TransportManager.java
@@ -41,6 +41,7 @@
 import com.android.server.EventLogTags;
 
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -103,13 +104,18 @@
         // been removed from mBoundTransports because onServiceDisconnected would already been
         // called on TransportConnection objects.
         synchronized (mTransportLock) {
-            for (ComponentName transport : mValidTransports.keySet()) {
-                if (transport.getPackageName().equals(packageName)) {
-                    TransportConnection removed = mValidTransports.remove(transport);
-                    if (removed != null) {
-                        mContext.unbindService(removed);
-                        log_verbose("Package removed, Removing transport: " +
-                                transport.flattenToShortString());
+            Iterator<Map.Entry<ComponentName, TransportConnection>> iter =
+                    mValidTransports.entrySet().iterator();
+            while (iter.hasNext()) {
+                Map.Entry<ComponentName, TransportConnection> validTransport = iter.next();
+                ComponentName componentName = validTransport.getKey();
+                if (componentName.getPackageName().equals(packageName)) {
+                    TransportConnection transportConnection = validTransport.getValue();
+                    iter.remove();
+                    if (transportConnection != null) {
+                        mContext.unbindService(transportConnection);
+                        log_verbose("Package removed, removing transport: "
+                                + componentName.flattenToShortString());
                     }
                 }
             }
@@ -278,15 +284,16 @@
     }
 
     private void tryBindTransport(ServiceInfo transport) {
-        Slog.d(TAG, "Binding to transport: " + transport.getComponentName().flattenToShortString());
+        final ComponentName transportComponentName = transport.getComponentName();
+        Slog.d(TAG, "Binding to transport: " + transportComponentName.flattenToShortString());
         // TODO: b/22388012 (Multi user backup and restore)
-        TransportConnection connection = new TransportConnection(transport.getComponentName());
-        if (bindToTransport(transport.getComponentName(), connection)) {
+        TransportConnection connection = new TransportConnection(transportComponentName);
+        if (bindToTransport(transportComponentName, connection)) {
             synchronized (mTransportLock) {
-                mValidTransports.put(transport.getComponentName(), connection);
+                mValidTransports.put(transportComponentName, connection);
             }
         } else {
-            Slog.w(TAG, "Couldn't bind to transport " + transport.getComponentName());
+            Slog.w(TAG, "Couldn't bind to transport " + transportComponentName);
         }
     }
 
diff --git a/services/core/Android.mk b/services/core/Android.mk
index cd88b85..1864d34 100644
--- a/services/core/Android.mk
+++ b/services/core/Android.mk
@@ -19,7 +19,6 @@
 
 LOCAL_JAVA_LIBRARIES := \
     services.net \
-    telephony-common \
     android.hardware.light@2.0-java \
     android.hardware.power@1.0-java \
     android.hardware.tv.cec@1.0-java
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index b1560e6..0d438cb 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -99,6 +99,7 @@
     static final boolean DEBUG_VALIDATE = localLOGV || false;
     static final boolean DEBUG_ALARM_CLOCK = localLOGV || false;
     static final boolean DEBUG_LISTENER_CALLBACK = localLOGV || false;
+    static final boolean DEBUG_WAKELOCK = localLOGV || false;
     static final boolean RECORD_ALARMS_IN_HISTORY = true;
     static final boolean RECORD_DEVICE_IDLE_ALARMS = false;
     static final int ALARM_EVENT = 1;
@@ -856,6 +857,19 @@
             mFilterStats = fs;
             mAlarmType = alarmType;
         }
+
+        @Override
+        public String toString() {
+            return "InFlight{"
+                    + "pendingIntent=" + mPendingIntent
+                    + ", workSource=" + mWorkSource
+                    + ", uid=" + mUid
+                    + ", tag=" + mTag
+                    + ", broadcastStats=" + mBroadcastStats
+                    + ", filterStats=" + mFilterStats
+                    + ", alarmType=" + mAlarmType
+                    + "}";
+        }
     }
 
     static final class FilterStats {
@@ -873,6 +887,19 @@
             mBroadcastStats = broadcastStats;
             mTag = tag;
         }
+
+        @Override
+        public String toString() {
+            return "FilterStats{"
+                    + "tag=" + mTag
+                    + ", lastTime=" + lastTime
+                    + ", aggregateTime=" + aggregateTime
+                    + ", count=" + count
+                    + ", numWakeup=" + numWakeup
+                    + ", startTime=" + startTime
+                    + ", nesting=" + nesting
+                    + "}";
+        }
     }
 
     static final class BroadcastStats {
@@ -890,6 +917,19 @@
             mUid = uid;
             mPackageName = packageName;
         }
+
+        @Override
+        public String toString() {
+            return "BroadcastStats{"
+                    + "uid=" + mUid
+                    + ", packageName=" + mPackageName
+                    + ", aggregateTime=" + aggregateTime
+                    + ", count=" + count
+                    + ", numWakeup=" + numWakeup
+                    + ", startTime=" + startTime
+                    + ", nesting=" + nesting
+                    + "}";
+        }
     }
 
     final SparseArray<ArrayMap<String, BroadcastStats>> mBroadcastStats
@@ -2458,9 +2498,9 @@
                         expectedClockTime = lastTimeChangeClockTime
                                 + (nowELAPSED - mLastTimeChangeRealtime);
                     }
-                    if (lastTimeChangeClockTime == 0 || nowRTC < (expectedClockTime-500)
-                            || nowRTC > (expectedClockTime+500)) {
-                        // The change is by at least +/- 500 ms (or this is the first change),
+                    if (lastTimeChangeClockTime == 0 || nowRTC < (expectedClockTime-1000)
+                            || nowRTC > (expectedClockTime+1000)) {
+                        // The change is by at least +/- 1000 ms (or this is the first change),
                         // let's do it!
                         if (DEBUG_BATCH) {
                             Slog.v(TAG, "Time changed notification from kernel; rebatching");
@@ -2477,7 +2517,8 @@
                         }
                         Intent intent = new Intent(Intent.ACTION_TIME_CHANGED);
                         intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
-                                | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+                                | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
+                                | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
                         getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
 
                         // The world has changed on us, so we need to re-evaluate alarms
@@ -2894,6 +2935,9 @@
                 updateStatsLocked(inflight);
             }
             mBroadcastRefCount--;
+            if (DEBUG_WAKELOCK) {
+                Slog.d(TAG, "mBroadcastRefCount -> " + mBroadcastRefCount);
+            }
             if (mBroadcastRefCount == 0) {
                 mHandler.obtainMessage(AlarmHandler.REPORT_ALARMS_ACTIVE, 0).sendToTarget();
                 mWakeLock.release();
@@ -3034,6 +3078,9 @@
             }
 
             // The alarm is now in flight; now arrange wakelock and stats tracking
+            if (DEBUG_WAKELOCK) {
+                Slog.d(TAG, "mBroadcastRefCount -> " + (mBroadcastRefCount + 1));
+            }
             if (mBroadcastRefCount == 0) {
                 setWakelockWorkSource(alarm.operation, alarm.workSource,
                         alarm.type, alarm.statsTag, (alarm.operation == null) ? alarm.uid : -1,
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index dc0e3e1..de11f36 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -167,14 +167,10 @@
         }
     }
 
-    final SparseArray<ArrayList<Callback>> mOpModeWatchers
-            = new SparseArray<ArrayList<Callback>>();
-    final ArrayMap<String, ArrayList<Callback>> mPackageModeWatchers
-            = new ArrayMap<String, ArrayList<Callback>>();
-    final ArrayMap<IBinder, Callback> mModeWatchers
-            = new ArrayMap<IBinder, Callback>();
-    final SparseArray<SparseArray<Restriction>> mAudioRestrictions
-            = new SparseArray<SparseArray<Restriction>>();
+    final SparseArray<ArraySet<Callback>> mOpModeWatchers = new SparseArray<>();
+    final ArrayMap<String, ArraySet<Callback>> mPackageModeWatchers = new ArrayMap<>();
+    final ArrayMap<IBinder, Callback> mModeWatchers = new ArrayMap<>();
+    final SparseArray<SparseArray<Restriction>> mAudioRestrictions = new SparseArray<>();
 
     public final class Callback implements DeathRecipient {
         final IAppOpsCallback mCallback;
@@ -545,11 +541,11 @@
         ArrayMap<Callback, ArraySet<String>> callbackSpecs = null;
 
         synchronized (this) {
-            ArrayList<Callback> callbacks = mOpModeWatchers.get(code);
+            ArraySet<Callback> callbacks = mOpModeWatchers.get(code);
             if (callbacks != null) {
                 final int callbackCount = callbacks.size();
                 for (int i = 0; i < callbackCount; i++) {
-                    Callback callback = callbacks.get(i);
+                    Callback callback = callbacks.valueAt(i);
                     ArraySet<String> changedPackages = new ArraySet<>();
                     Collections.addAll(changedPackages, uidPackageNames);
                     callbackSpecs = new ArrayMap<>();
@@ -565,7 +561,7 @@
                     }
                     final int callbackCount = callbacks.size();
                     for (int i = 0; i < callbackCount; i++) {
-                        Callback callback = callbacks.get(i);
+                        Callback callback = callbacks.valueAt(i);
                         ArraySet<String> changedPackages = callbackSpecs.get(callback);
                         if (changedPackages == null) {
                             changedPackages = new ArraySet<>();
@@ -623,17 +619,17 @@
             if (op != null) {
                 if (op.mode != mode) {
                     op.mode = mode;
-                    ArrayList<Callback> cbs = mOpModeWatchers.get(code);
+                    ArraySet<Callback> cbs = mOpModeWatchers.get(code);
                     if (cbs != null) {
                         if (repCbs == null) {
-                            repCbs = new ArrayList<Callback>();
+                            repCbs = new ArrayList<>();
                         }
                         repCbs.addAll(cbs);
                     }
                     cbs = mPackageModeWatchers.get(packageName);
                     if (cbs != null) {
                         if (repCbs == null) {
-                            repCbs = new ArrayList<Callback>();
+                            repCbs = new ArrayList<>();
                         }
                         repCbs.addAll(cbs);
                     }
@@ -666,7 +662,7 @@
 
     private static HashMap<Callback, ArrayList<ChangeRec>> addCallbacks(
             HashMap<Callback, ArrayList<ChangeRec>> callbacks,
-            int op, int uid, String packageName, ArrayList<Callback> cbs) {
+            int op, int uid, String packageName, ArraySet<Callback> cbs) {
         if (cbs == null) {
             return callbacks;
         }
@@ -674,8 +670,9 @@
             callbacks = new HashMap<>();
         }
         boolean duplicate = false;
-        for (int i=0; i<cbs.size(); i++) {
-            Callback cb = cbs.get(i);
+        final int N = cbs.size();
+        for (int i=0; i<N; i++) {
+            Callback cb = cbs.valueAt(i);
             ArrayList<ChangeRec> reports = callbacks.get(cb);
             if (reports == null) {
                 reports = new ArrayList<>();
@@ -830,17 +827,17 @@
                 mModeWatchers.put(callback.asBinder(), cb);
             }
             if (op != AppOpsManager.OP_NONE) {
-                ArrayList<Callback> cbs = mOpModeWatchers.get(op);
+                ArraySet<Callback> cbs = mOpModeWatchers.get(op);
                 if (cbs == null) {
-                    cbs = new ArrayList<Callback>();
+                    cbs = new ArraySet<>();
                     mOpModeWatchers.put(op, cbs);
                 }
                 cbs.add(cb);
             }
             if (packageName != null) {
-                ArrayList<Callback> cbs = mPackageModeWatchers.get(packageName);
+                ArraySet<Callback> cbs = mPackageModeWatchers.get(packageName);
                 if (cbs == null) {
-                    cbs = new ArrayList<Callback>();
+                    cbs = new ArraySet<>();
                     mPackageModeWatchers.put(packageName, cbs);
                 }
                 cbs.add(cb);
@@ -858,14 +855,14 @@
             if (cb != null) {
                 cb.unlinkToDeath();
                 for (int i=mOpModeWatchers.size()-1; i>=0; i--) {
-                    ArrayList<Callback> cbs = mOpModeWatchers.valueAt(i);
+                    ArraySet<Callback> cbs = mOpModeWatchers.valueAt(i);
                     cbs.remove(cb);
                     if (cbs.size() <= 0) {
                         mOpModeWatchers.removeAt(i);
                     }
                 }
                 for (int i=mPackageModeWatchers.size()-1; i>=0; i--) {
-                    ArrayList<Callback> cbs = mPackageModeWatchers.valueAt(i);
+                    ArraySet<Callback> cbs = mPackageModeWatchers.valueAt(i);
                     cbs.remove(cb);
                     if (cbs.size() <= 0) {
                         mPackageModeWatchers.removeAt(i);
@@ -2066,10 +2063,10 @@
                 for (int i=0; i<mOpModeWatchers.size(); i++) {
                     pw.print("    Op "); pw.print(AppOpsManager.opToName(mOpModeWatchers.keyAt(i)));
                     pw.println(":");
-                    ArrayList<Callback> callbacks = mOpModeWatchers.valueAt(i);
+                    ArraySet<Callback> callbacks = mOpModeWatchers.valueAt(i);
                     for (int j=0; j<callbacks.size(); j++) {
                         pw.print("      #"); pw.print(j); pw.print(": ");
-                        pw.println(callbacks.get(j));
+                        pw.println(callbacks.valueAt(j));
                     }
                 }
             }
@@ -2079,10 +2076,10 @@
                 for (int i=0; i<mPackageModeWatchers.size(); i++) {
                     pw.print("    Pkg "); pw.print(mPackageModeWatchers.keyAt(i));
                     pw.println(":");
-                    ArrayList<Callback> callbacks = mPackageModeWatchers.valueAt(i);
+                    ArraySet<Callback> callbacks = mPackageModeWatchers.valueAt(i);
                     for (int j=0; j<callbacks.size(); j++) {
                         pw.print("      #"); pw.print(j); pw.print(": ");
-                        pw.println(callbacks.get(j));
+                        pw.println(callbacks.valueAt(j));
                     }
                 }
             }
@@ -2310,23 +2307,23 @@
     }
 
     private void notifyWatchersOfChange(int code) {
-        final ArrayList<Callback> clonedCallbacks;
+        final ArraySet<Callback> clonedCallbacks;
         synchronized (this) {
-            ArrayList<Callback> callbacks = mOpModeWatchers.get(code);
+            ArraySet<Callback> callbacks = mOpModeWatchers.get(code);
             if (callbacks == null) {
                 return;
             }
-            clonedCallbacks = new ArrayList<>(callbacks);
+            clonedCallbacks = new ArraySet<>(callbacks);
         }
 
         // There are components watching for mode changes such as window manager
         // and location manager which are in our process. The callbacks in these
-        // components may require permissions our remote caller does not have.s
+        // components may require permissions our remote caller does not have.
         final long identity = Binder.clearCallingIdentity();
         try {
             final int callbackCount = clonedCallbacks.size();
             for (int i = 0; i < callbackCount; i++) {
-                Callback callback = clonedCallbacks.get(i);
+                Callback callback = clonedCallbacks.valueAt(i);
                 try {
                     callback.mCallback.opChanged(code, -1, null);
                 } catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 6248cab..c9dd116 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -130,6 +130,8 @@
     private int mLastMaxChargingVoltage;
     private int mLastChargeCounter;
 
+    private int mSequence = 1;
+
     private int mInvalidCharger;
     private int mLastInvalidCharger;
 
@@ -448,27 +450,29 @@
                 }
             }
 
-            sendIntentLocked();
+            mSequence++;
 
             // Separate broadcast is sent for power connected / not connected
             // since the standard intent will not wake any applications and some
             // applications may want to have smart behavior based on this.
             if (mPlugType != 0 && mLastPlugType == 0) {
+                final Intent statusIntent = new Intent(Intent.ACTION_POWER_CONNECTED);
+                statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+                statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
                 mHandler.post(new Runnable() {
                     @Override
                     public void run() {
-                        Intent statusIntent = new Intent(Intent.ACTION_POWER_CONNECTED);
-                        statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
                         mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
                     }
                 });
             }
             else if (mPlugType == 0 && mLastPlugType != 0) {
+                final Intent statusIntent = new Intent(Intent.ACTION_POWER_DISCONNECTED);
+                statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+                statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
                 mHandler.post(new Runnable() {
                     @Override
                     public void run() {
-                        Intent statusIntent = new Intent(Intent.ACTION_POWER_DISCONNECTED);
-                        statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
                         mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
                     }
                 });
@@ -476,26 +480,33 @@
 
             if (shouldSendBatteryLowLocked()) {
                 mSentLowBatteryBroadcast = true;
+                final Intent statusIntent = new Intent(Intent.ACTION_BATTERY_LOW);
+                statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+                statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
                 mHandler.post(new Runnable() {
                     @Override
                     public void run() {
-                        Intent statusIntent = new Intent(Intent.ACTION_BATTERY_LOW);
-                        statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
                         mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
                     }
                 });
             } else if (mSentLowBatteryBroadcast && mLastBatteryLevel >= mLowBatteryCloseWarningLevel) {
                 mSentLowBatteryBroadcast = false;
+                final Intent statusIntent = new Intent(Intent.ACTION_BATTERY_OKAY);
+                statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+                statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
                 mHandler.post(new Runnable() {
                     @Override
                     public void run() {
-                        Intent statusIntent = new Intent(Intent.ACTION_BATTERY_OKAY);
-                        statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
                         mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
                     }
                 });
             }
 
+            // We are doing this after sending the above broadcasts, so anything processing
+            // them will get the new sequence number at that point.  (See for example how testing
+            // of JobScheduler's BatteryController works.)
+            sendIntentLocked();
+
             // Update the battery LED
             mLed.updateLightsLocked();
 
@@ -527,6 +538,7 @@
 
         int icon = getIconLocked(mBatteryProps.batteryLevel);
 
+        intent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
         intent.putExtra(BatteryManager.EXTRA_STATUS, mBatteryProps.batteryStatus);
         intent.putExtra(BatteryManager.EXTRA_HEALTH, mBatteryProps.batteryHealth);
         intent.putExtra(BatteryManager.EXTRA_PRESENT, mBatteryProps.batteryPresent);
@@ -666,12 +678,28 @@
         pw.println("Battery service (battery) commands:");
         pw.println("  help");
         pw.println("    Print this help text.");
-        pw.println("  set [ac|usb|wireless|status|level|invalid] <value>");
+        pw.println("  set [-f] [ac|usb|wireless|status|level|present|invalid] <value>");
         pw.println("    Force a battery property value, freezing battery state.");
-        pw.println("  unplug");
+        pw.println("    -f: force a battery change broadcast be sent, prints new sequence.");
+        pw.println("  unplug [-f]");
         pw.println("    Force battery unplugged, freezing battery state.");
-        pw.println("  reset");
+        pw.println("    -f: force a battery change broadcast be sent, prints new sequence.");
+        pw.println("  reset [-f]");
         pw.println("    Unfreeze battery state, returning to current hardware values.");
+        pw.println("    -f: force a battery change broadcast be sent, prints new sequence.");
+    }
+
+    static final int OPTION_FORCE_UPDATE = 1<<0;
+
+    int parseOptions(Shell shell) {
+        String opt;
+        int opts = 0;
+        while ((opt = shell.getNextOption()) != null) {
+            if ("-f".equals(opt)) {
+                opts |= OPTION_FORCE_UPDATE;
+            }
+        }
+        return opts;
     }
 
     int onShellCommand(Shell shell, String cmd) {
@@ -681,6 +709,7 @@
         PrintWriter pw = shell.getOutPrintWriter();
         switch (cmd) {
             case "unplug": {
+                int opts = parseOptions(shell);
                 getContext().enforceCallingOrSelfPermission(
                         android.Manifest.permission.DEVICE_POWER, null);
                 if (!mUpdatesStopped) {
@@ -692,12 +721,13 @@
                 long ident = Binder.clearCallingIdentity();
                 try {
                     mUpdatesStopped = true;
-                    processValuesLocked(false);
+                    processValuesFromShellLocked(pw, opts);
                 } finally {
                     Binder.restoreCallingIdentity(ident);
                 }
             } break;
             case "set": {
+                int opts = parseOptions(shell);
                 getContext().enforceCallingOrSelfPermission(
                         android.Manifest.permission.DEVICE_POWER, null);
                 final String key = shell.getNextArg();
@@ -718,6 +748,9 @@
                     }
                     boolean update = true;
                     switch (key) {
+                        case "present":
+                            mBatteryProps.batteryPresent = Integer.parseInt(value) != 0;
+                            break;
                         case "ac":
                             mBatteryProps.chargerAcOnline = Integer.parseInt(value) != 0;
                             break;
@@ -745,7 +778,7 @@
                         long ident = Binder.clearCallingIdentity();
                         try {
                             mUpdatesStopped = true;
-                            processValuesLocked(false);
+                            processValuesFromShellLocked(pw, opts);
                         } finally {
                             Binder.restoreCallingIdentity(ident);
                         }
@@ -756,6 +789,7 @@
                 }
             } break;
             case "reset": {
+                int opts = parseOptions(shell);
                 getContext().enforceCallingOrSelfPermission(
                         android.Manifest.permission.DEVICE_POWER, null);
                 long ident = Binder.clearCallingIdentity();
@@ -763,7 +797,7 @@
                     if (mUpdatesStopped) {
                         mUpdatesStopped = false;
                         mBatteryProps.set(mLastBatteryProps);
-                        processValuesLocked(false);
+                        processValuesFromShellLocked(pw, opts);
                     }
                 } finally {
                     Binder.restoreCallingIdentity(ident);
@@ -775,6 +809,13 @@
         return 0;
     }
 
+    private void processValuesFromShellLocked(PrintWriter pw, int opts) {
+        processValuesLocked((opts & OPTION_FORCE_UPDATE) != 0);
+        if ((opts & OPTION_FORCE_UPDATE) != 0) {
+            pw.println(mSequence);
+        }
+    }
+
     private void dumpInternal(FileDescriptor fd, PrintWriter pw, String[] args) {
         synchronized (mLock) {
             if (args == null || args.length == 0 || "-a".equals(args[0])) {
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index f315553..df6148e 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -82,6 +82,8 @@
     private static final String SECURE_SETTINGS_BLUETOOTH_ADDR_VALID="bluetooth_addr_valid";
     private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS="bluetooth_address";
     private static final String SECURE_SETTINGS_BLUETOOTH_NAME="bluetooth_name";
+    private static final String REASON_AIRPLANE_MODE = "airplane mode";
+    private static final String REASON_SYSTEM_BOOT = "system boot";
     private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind
     private static final int TIMEOUT_SAVE_MS = 500; //Maximum msec to wait for a save
     //Maximum msec to wait for service restart
@@ -167,7 +169,7 @@
         }
 
         public String toString() {
-            return android.text.format.DateFormat.format("MM-dd hh:mm:ss ", mTimestamp) +
+            return android.text.format.DateFormat.format("MM-dd HH:mm:ss ", mTimestamp) +
                     (mEnable ? "  Enabled " : " Disabled ") + " by " + mPackageName;
         }
 
@@ -195,19 +197,6 @@
 
     private final boolean mPermissionReviewRequired;
 
-    private void registerForAirplaneMode(IntentFilter filter) {
-        final ContentResolver resolver = mContext.getContentResolver();
-        final String airplaneModeRadios = Settings.Global.getString(resolver,
-                Settings.Global.AIRPLANE_MODE_RADIOS);
-        final String toggleableRadios = Settings.Global.getString(resolver,
-                Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
-        boolean mIsAirplaneSensitive = airplaneModeRadios == null ? true :
-                airplaneModeRadios.contains(Settings.Global.RADIO_BLUETOOTH);
-        if (mIsAirplaneSensitive) {
-            filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
-        }
-    }
-
     private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() {
         @Override
         public void onBluetoothStateChange(int prevState, int newState) throws RemoteException  {
@@ -240,6 +229,62 @@
         }
     };
 
+    private final ContentObserver mAirplaneModeObserver = new ContentObserver(null) {
+        @Override
+        public void onChange(boolean unused) {
+            synchronized(this) {
+                if (isBluetoothPersistedStateOn()) {
+                    if (isAirplaneModeOn()) {
+                        persistBluetoothSetting(BLUETOOTH_ON_AIRPLANE);
+                    } else {
+                        persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
+                    }
+                }
+
+                int st = BluetoothAdapter.STATE_OFF;
+                try {
+                    mBluetoothLock.readLock().lock();
+                    if (mBluetooth != null) {
+                        st = mBluetooth.getState();
+                    }
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Unable to call getState", e);
+                    return;
+                } finally {
+                    mBluetoothLock.readLock().unlock();
+                }
+
+                Slog.d(TAG, "Airplane Mode change - current state:  " +
+                          BluetoothAdapter.nameForState(st));
+
+                if (isAirplaneModeOn()) {
+                    // Clear registered LE apps to force shut-off
+                    clearBleApps();
+
+                    // If state is BLE_ON make sure we trigger disableBLE
+                    if (st == BluetoothAdapter.STATE_BLE_ON) {
+                        try {
+                            mBluetoothLock.readLock().lock();
+                            if (mBluetooth != null) {
+                                mBluetooth.onBrEdrDown();
+                                mEnable = false;
+                                mEnableExternal = false;
+                            }
+                        } catch (RemoteException e) {
+                            Slog.e(TAG,"Unable to call onBrEdrDown", e);
+                        } finally {
+                            mBluetoothLock.readLock().unlock();
+                        }
+                    } else if (st == BluetoothAdapter.STATE_ON){
+                        sendDisableMsg(REASON_AIRPLANE_MODE);
+                    }
+                } else if (mEnableExternal) {
+                    sendEnableMsg(mQuietEnableExternal, REASON_AIRPLANE_MODE);
+                }
+            }
+        }
+    };
+
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -250,58 +295,6 @@
                 if (newName != null) {
                     storeNameAndAddress(newName, null);
                 }
-            } else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) {
-                synchronized(mReceiver) {
-                    if (isBluetoothPersistedStateOn()) {
-                        if (isAirplaneModeOn()) {
-                            persistBluetoothSetting(BLUETOOTH_ON_AIRPLANE);
-                        } else {
-                            persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
-                        }
-                    }
-
-                    int st = BluetoothAdapter.STATE_OFF;
-                    try {
-                        mBluetoothLock.readLock().lock();
-                        if (mBluetooth != null) {
-                            st = mBluetooth.getState();
-                        }
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "Unable to call getState", e);
-                    } finally {
-                        mBluetoothLock.readLock().unlock();
-                    }
-                    Slog.d(TAG, "Airplane Mode change - current state: " +
-                              BluetoothAdapter.nameForState(st));
-
-                    if (isAirplaneModeOn()) {
-                        // Clear registered LE apps to force shut-off
-                        clearBleApps();
-                        if (st == BluetoothAdapter.STATE_BLE_ON) {
-                            //if state is BLE_ON make sure you trigger disableBLE part
-                            try {
-                                mBluetoothLock.readLock().lock();
-                                if (mBluetooth != null) {
-                                    mBluetooth.onBrEdrDown();
-                                    mEnable = false;
-                                    mEnableExternal = false;
-                                }
-                            } catch (RemoteException e) {
-                                Slog.e(TAG,"Unable to call onBrEdrDown", e);
-                            } finally {
-                                mBluetoothLock.readLock().unlock();
-                            }
-                        } else if (st == BluetoothAdapter.STATE_ON){
-                            // disable without persisting the setting
-                            Slog.d(TAG, "Calling disable");
-                            sendDisableMsg("airplane mode");
-                        }
-                    } else if (mEnableExternal) {
-                        // enable without persisting the setting
-                        Slog.d(TAG, "Calling enable");
-                        sendEnableMsg(mQuietEnableExternal, "airplane mode");
-                    }
-                }
             }
         }
     };
@@ -333,7 +326,6 @@
         mCallbacks = new RemoteCallbackList<IBluetoothManagerCallback>();
         mStateChangeCallbacks = new RemoteCallbackList<IBluetoothStateChangeCallback>();
         IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
-        registerForAirplaneMode(filter);
         filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
         mContext.registerReceiver(mReceiver, filter);
         loadStoredNameAndAddress();
@@ -342,6 +334,15 @@
             mEnableExternal = true;
         }
 
+        String airplaneModeRadios = Settings.Global.getString(mContentResolver,
+            Settings.Global.AIRPLANE_MODE_RADIOS);
+        if (airplaneModeRadios == null ||
+            airplaneModeRadios.contains(Settings.Global.RADIO_BLUETOOTH)) {
+            mContentResolver.registerContentObserver(
+                Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON),
+                true, mAirplaneModeObserver);
+        }
+
         int systemUiUid = -1;
         try {
             systemUiUid = mContext.getPackageManager().getPackageUidAsUser("com.android.systemui",
@@ -640,6 +641,9 @@
         if (appCount == 0 && mEnable) {
             disableBleScanMode();
         }
+        if (appCount == 0 && !mEnableExternal) {
+            sendBrEdrDownCallback();
+        }
         return appCount;
     }
 
@@ -695,7 +699,14 @@
             return;
         }
 
-        if (isBleAppPresent() == false) {
+        if (isBleAppPresent()) {
+            // Need to stay at BLE ON. Disconnect all Gatt connections
+            try {
+                mBluetoothGatt.unregAll();
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Unable to disconnect all apps.", e);
+            }
+        } else {
             try {
                 mBluetoothLock.readLock().lock();
                 if (mBluetooth != null) mBluetooth.onBrEdrDown();
@@ -704,14 +715,8 @@
             } finally {
                 mBluetoothLock.readLock().unlock();
             }
-        } else {
-            // Need to stay at BLE ON. Disconnect all Gatt connections
-            try {
-                mBluetoothGatt.unregAll();
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Unable to disconnect all apps.", e);
-            }
         }
+
     }
 
     public boolean enableNoAutoConnect(String packageName)
@@ -973,7 +978,7 @@
         }
         if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) {
             if (DBG) Slog.d(TAG, "Auto-enabling Bluetooth.");
-            sendEnableMsg(mQuietEnableExternal, "system boot");
+            sendEnableMsg(mQuietEnableExternal, REASON_SYSTEM_BOOT);
         } else if (!isNameAndAddressSet()) {
             if (DBG) Slog.d(TAG, "Getting adapter name and address");
             Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 4bc9bb1..16ed276 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -395,16 +395,6 @@
      */
     private static final int EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT = 31;
 
-    /**
-     * Indicates a caller has requested to have its callback invoked with
-     * the latest LinkProperties or NetworkCapabilities.
-     *
-     * arg1 = UID of caller
-     * obj  = NetworkRequest
-     */
-    private static final int EVENT_REQUEST_LINKPROPERTIES  = 32;
-    private static final int EVENT_REQUEST_NETCAPABILITIES = 33;
-
     /** Handler thread used for both of the handlers below. */
     @VisibleForTesting
     protected final HandlerThread mHandlerThread;
@@ -815,6 +805,8 @@
         intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
         mContext.registerReceiverAsUser(
                 mUserIntentReceiver, UserHandle.ALL, intentFilter, null, null);
+        mContext.registerReceiverAsUser(mUserPresentReceiver, UserHandle.SYSTEM,
+                new IntentFilter(Intent.ACTION_USER_PRESENT), null, null);
 
         try {
             mNetd.registerObserver(mTethering);
@@ -2563,34 +2555,6 @@
         return nri;
     }
 
-    private void handleRequestCallbackUpdate(NetworkRequest request, int callingUid,
-            String description, int callbackType) {
-        final NetworkRequestInfo nri = getNriForAppRequest(request, callingUid, description);
-        if (nri == null) return;
-
-        final NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
-        // The network that is satisfying this request may have changed since
-        // the application requested the update.
-        //
-        // - If the request is no longer satisfied, don't send any updates.
-        // - If the request is satisfied by a different network, it is the
-        //   caller's responsibility to check that the Network object in the
-        //   callback matches the network that was returned in the last
-        //   onAvailable() callback for this request.
-        if (nai == null) return;
-        callCallbackForRequest(nri, nai, callbackType, 0);
-    }
-
-    private void handleRequestLinkProperties(NetworkRequest request, int callingUid) {
-        handleRequestCallbackUpdate(request, callingUid,
-                "request LinkProperties", ConnectivityManager.CALLBACK_IP_CHANGED);
-    }
-
-    private void handleRequestNetworkCapabilities(NetworkRequest request, int callingUid) {
-        handleRequestCallbackUpdate(request, callingUid,
-                "request NetworkCapabilities", ConnectivityManager.CALLBACK_CAP_CHANGED);
-    }
-
     private void handleTimedOutNetworkRequest(final NetworkRequestInfo nri) {
         if (mNetworkRequests.get(nri.request) != null && mNetworkForRequestId.get(
                 nri.request.requestId) == null) {
@@ -2984,12 +2948,6 @@
                     handleMobileDataAlwaysOn();
                     break;
                 }
-                case EVENT_REQUEST_LINKPROPERTIES:
-                    handleRequestLinkProperties((NetworkRequest) msg.obj, msg.arg1);
-                    break;
-                case EVENT_REQUEST_NETCAPABILITIES:
-                    handleRequestNetworkCapabilities((NetworkRequest) msg.obj, msg.arg1);
-                    break;
                 // Sent by KeepaliveTracker to process an app request on the state machine thread.
                 case NetworkAgent.CMD_START_PACKET_KEEPALIVE: {
                     mKeepaliveTracker.handleStartKeepalive(msg);
@@ -4008,6 +3966,16 @@
         }
     };
 
+    private BroadcastReceiver mUserPresentReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            // Try creating lockdown tracker, since user present usually means
+            // unlocked keystore.
+            updateLockdownVpn();
+            mContext.unregisterReceiver(this);
+        }
+    };
+
     private final HashMap<Messenger, NetworkFactoryInfo> mNetworkFactoryInfos =
             new HashMap<Messenger, NetworkFactoryInfo>();
     private final HashMap<NetworkRequest, NetworkRequestInfo> mNetworkRequests =
@@ -4340,22 +4308,6 @@
     }
 
     @Override
-    public void requestLinkProperties(NetworkRequest networkRequest) {
-        ensureNetworkRequestHasType(networkRequest);
-        if (networkRequest.type == NetworkRequest.Type.LISTEN) return;
-        mHandler.sendMessage(mHandler.obtainMessage(
-                EVENT_REQUEST_LINKPROPERTIES, getCallingUid(), 0, networkRequest));
-    }
-
-    @Override
-    public void requestNetworkCapabilities(NetworkRequest networkRequest) {
-        ensureNetworkRequestHasType(networkRequest);
-        if (networkRequest.type == NetworkRequest.Type.LISTEN) return;
-        mHandler.sendMessage(mHandler.obtainMessage(
-                EVENT_REQUEST_NETCAPABILITIES, getCallingUid(), 0, networkRequest));
-    }
-
-    @Override
     public void releaseNetworkRequest(NetworkRequest networkRequest) {
         ensureNetworkRequestHasType(networkRequest);
         mHandler.sendMessage(mHandler.obtainMessage(
@@ -4867,7 +4819,7 @@
             if (!nr.isListen()) continue;
             if (nai.satisfies(nr) && !nai.isSatisfyingRequest(nr.requestId)) {
                 nai.addRequest(nr);
-                notifyNetworkCallback(nai, nri);
+                notifyNetworkAvailable(nai, nri);
             }
         }
     }
@@ -5049,7 +5001,7 @@
 
         // do this after the default net is switched, but
         // before LegacyTypeTracker sends legacy broadcasts
-        for (NetworkRequestInfo nri : addedRequests) notifyNetworkCallback(newNetwork, nri);
+        for (NetworkRequestInfo nri : addedRequests) notifyNetworkAvailable(newNetwork, nri);
 
         // Linger any networks that are no longer needed. This should be done after sending the
         // available callback for newNetwork.
@@ -5212,7 +5164,7 @@
     }
 
     private void updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo newInfo) {
-        NetworkInfo.State state = newInfo.getState();
+        final NetworkInfo.State state = newInfo.getState();
         NetworkInfo oldInfo = null;
         final int oldScore = networkAgent.getCurrentScore();
         synchronized (networkAgent) {
@@ -5339,15 +5291,27 @@
         sendUpdatedScoreToFactories(nai);
     }
 
-    // notify only this one new request of the current state
-    protected void notifyNetworkCallback(NetworkAgentInfo nai, NetworkRequestInfo nri) {
-        int notifyType = ConnectivityManager.CALLBACK_AVAILABLE;
+    // Notify only this one new request of the current state. Transfer all the
+    // current state by calling NetworkCapabilities and LinkProperties callbacks
+    // so that callers can be guaranteed to have as close to atomicity in state
+    // transfer as can be supported by this current API.
+    protected void notifyNetworkAvailable(NetworkAgentInfo nai, NetworkRequestInfo nri) {
         mHandler.removeMessages(EVENT_TIMEOUT_NETWORK_REQUEST, nri);
-        if (nri.mPendingIntent == null) {
-            callCallbackForRequest(nri, nai, notifyType, 0);
-        } else {
-            sendPendingIntentForRequest(nri, nai, notifyType);
+        if (nri.mPendingIntent != null) {
+            sendPendingIntentForRequest(nri, nai, ConnectivityManager.CALLBACK_AVAILABLE);
+            // Attempt no subsequent state pushes where intents are involved.
+            return;
         }
+
+        callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_AVAILABLE, 0);
+        // Whether a network is currently suspended is also an important
+        // element of state to be transferred (it would not otherwise be
+        // delivered by any currently available mechanism).
+        if (nai.networkInfo.getState() == NetworkInfo.State.SUSPENDED) {
+            callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_SUSPENDED, 0);
+        }
+        callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_CAP_CHANGED, 0);
+        callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_IP_CHANGED, 0);
     }
 
     private void sendLegacyNetworkBroadcast(NetworkAgentInfo nai, DetailedState state, int type) {
diff --git a/services/core/java/com/android/server/GraphicsStatsService.java b/services/core/java/com/android/server/GraphicsStatsService.java
index ecbe1ca..14a9a31 100644
--- a/services/core/java/com/android/server/GraphicsStatsService.java
+++ b/services/core/java/com/android/server/GraphicsStatsService.java
@@ -16,67 +16,150 @@
 
 package com.android.server;
 
+import android.app.AlarmManager;
 import android.app.AppOpsManager;
 import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
 import android.os.Binder;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.IBinder;
 import android.os.MemoryFile;
+import android.os.Message;
 import android.os.ParcelFileDescriptor;
+import android.os.Process;
 import android.os.RemoteException;
+import android.os.Trace;
 import android.util.Log;
 import android.view.IGraphicsStats;
-import android.view.ThreadedRenderer;
+import android.view.IGraphicsStatsCallback;
 
+import java.io.File;
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.HashSet;
+import java.util.TimeZone;
 
 /**
  * This service's job is to collect aggregate rendering profile data. It
  * does this by allowing rendering processes to request an ashmem buffer
- * to place their stats into. This buffer will be pre-initialized with historical
- * data for that process if it exists (if the userId & packageName match a buffer
- * in the historical log)
+ * to place their stats into.
  *
- * This service does not itself attempt to understand the data in the buffer,
- * its primary job is merely to manage distributing these buffers. However,
- * it is assumed that this buffer is for ThreadedRenderer and delegates
- * directly to ThreadedRenderer for dumping buffers.
+ * Buffers are rotated on a daily (in UTC) basis and only the 3 most-recent days
+ * are kept.
  *
- * MEMORY USAGE:
+ * The primary consumer of this is incident reports and automated metric checking. It is not
+ * intended for end-developer consumption, for that we have gfxinfo.
  *
- * This class consumes UP TO:
- * 1) [active rendering processes] * (ASHMEM_SIZE * 2)
- * 2) ASHMEM_SIZE (for scratch space used during dumping)
- * 3) ASHMEM_SIZE * HISTORY_SIZE
- *
- * This is currently under 20KiB total memory in the worst case of
- * 20 processes in history + 10 unique active processes.
+ * Buffer rotation process:
+ * 1) Alarm fires
+ * 2) onRotateGraphicsStatsBuffer() is sent to all active processes
+ * 3) Upon receiving the callback, the process will stop using the previous ashmem buffer and
+ *    request a new one.
+ * 4) When that request is received we now know that the ashmem region is no longer in use so
+ *    it gets queued up for saving to disk and a new ashmem region is created and returned
+ *    for the process to use.
  *
  *  @hide */
 public class GraphicsStatsService extends IGraphicsStats.Stub {
     public static final String GRAPHICS_STATS_SERVICE = "graphicsstats";
 
     private static final String TAG = "GraphicsStatsService";
-    private static final int ASHMEM_SIZE = 464;
-    private static final int HISTORY_SIZE = 20;
+
+    private static final int SAVE_BUFFER = 1;
+    private static final int DELETE_OLD = 2;
+
+    // This isn't static because we need this to happen after registerNativeMethods, however
+    // the class is loaded (and thus static ctor happens) before that occurs.
+    private final int ASHMEM_SIZE = nGetAshmemSize();
+    private final byte[] ZERO_DATA = new byte[ASHMEM_SIZE];
 
     private final Context mContext;
     private final AppOpsManager mAppOps;
+    private final AlarmManager mAlarmManager;
     private final Object mLock = new Object();
     private ArrayList<ActiveBuffer> mActive = new ArrayList<>();
-    private HistoricalData[] mHistoricalLog = new HistoricalData[HISTORY_SIZE];
-    private int mNextHistoricalSlot = 0;
-    private byte[] mTempBuffer = new byte[ASHMEM_SIZE];
+    private File mGraphicsStatsDir;
+    private final Object mFileAccessLock = new Object();
+    private Handler mWriteOutHandler;
+    private boolean mRotateIsScheduled = false;
 
     public GraphicsStatsService(Context context) {
         mContext = context;
         mAppOps = context.getSystemService(AppOpsManager.class);
+        mAlarmManager = context.getSystemService(AlarmManager.class);
+        File systemDataDir = new File(Environment.getDataDirectory(), "system");
+        mGraphicsStatsDir = new File(systemDataDir, "graphicsstats");
+        mGraphicsStatsDir.mkdirs();
+        if (!mGraphicsStatsDir.exists()) {
+            throw new IllegalStateException("Graphics stats directory does not exist: "
+                    + mGraphicsStatsDir.getAbsolutePath());
+        }
+        HandlerThread bgthread = new HandlerThread("GraphicsStats-disk", Process.THREAD_PRIORITY_BACKGROUND);
+        bgthread.start();
+
+        mWriteOutHandler = new Handler(bgthread.getLooper(), new Handler.Callback() {
+            @Override
+            public boolean handleMessage(Message msg) {
+                switch (msg.what) {
+                    case SAVE_BUFFER:
+                        saveBuffer((HistoricalBuffer) msg.obj);
+                        break;
+                    case DELETE_OLD:
+                        deleteOldBuffers();
+                        break;
+                }
+                return true;
+            }
+        });
+    }
+
+    /**
+     * Current rotation policy is to rotate at midnight UTC. We don't specify RTC_WAKEUP because
+     * rotation can be delayed if there's otherwise no activity. However exact is used because
+     * we don't want the system to delay it by TOO much.
+     */
+    private void scheduleRotateLocked() {
+        if (mRotateIsScheduled) {
+            return;
+        }
+        mRotateIsScheduled = true;
+        Calendar calendar = normalizeDate(System.currentTimeMillis());
+        calendar.add(Calendar.DATE, 1);
+        mAlarmManager.setExact(AlarmManager.RTC, calendar.getTimeInMillis(), TAG, this::onAlarm,
+                mWriteOutHandler);
+    }
+
+    private void onAlarm() {
+        // We need to make a copy since some of the callbacks won't be proxy and thus
+        // can result in a re-entrant acquisition of mLock that would result in a modification
+        // of mActive during iteration.
+        ActiveBuffer[] activeCopy;
+        synchronized (mLock) {
+            mRotateIsScheduled = false;
+            scheduleRotateLocked();
+            activeCopy = mActive.toArray(new ActiveBuffer[0]);
+        }
+        for (ActiveBuffer active : activeCopy) {
+            try {
+                active.mCallback.onRotateGraphicsStatsBuffer();
+            } catch (RemoteException e) {
+                Log.w(TAG, String.format("Failed to notify '%s' (pid=%d) to rotate buffers",
+                        active.mInfo.packageName, active.mPid), e);
+            }
+        }
+        // Give a few seconds for everyone to rotate before doing the cleanup
+        mWriteOutHandler.sendEmptyMessageDelayed(DELETE_OLD, 10000);
     }
 
     @Override
-    public ParcelFileDescriptor requestBufferForProcess(String packageName, IBinder token)
+    public ParcelFileDescriptor requestBufferForProcess(String packageName, IGraphicsStatsCallback token)
             throws RemoteException {
         int uid = Binder.getCallingUid();
         int pid = Binder.getCallingPid();
@@ -84,9 +167,12 @@
         long callingIdentity = Binder.clearCallingIdentity();
         try {
             mAppOps.checkPackage(uid, packageName);
+            PackageInfo info = mContext.getPackageManager().getPackageInfo(packageName, 0);
             synchronized (mLock) {
-                pfd = requestBufferForProcessLocked(token, uid, pid, packageName);
+                pfd = requestBufferForProcessLocked(token, uid, pid, packageName, info.versionCode);
             }
+        } catch (PackageManager.NameNotFoundException ex) {
+            throw new RemoteException("Unable to find package: '" + packageName + "'");
         } finally {
             Binder.restoreCallingIdentity(callingIdentity);
         }
@@ -95,51 +181,130 @@
 
     private ParcelFileDescriptor getPfd(MemoryFile file) {
         try {
+            if (!file.getFileDescriptor().valid()) {
+                throw new IllegalStateException("Invalid file descriptor");
+            }
             return new ParcelFileDescriptor(file.getFileDescriptor());
         } catch (IOException ex) {
             throw new IllegalStateException("Failed to get PFD from memory file", ex);
         }
     }
 
-    private ParcelFileDescriptor requestBufferForProcessLocked(IBinder token,
-            int uid, int pid, String packageName) throws RemoteException {
-        ActiveBuffer buffer = fetchActiveBuffersLocked(token, uid, pid, packageName);
+    private ParcelFileDescriptor requestBufferForProcessLocked(IGraphicsStatsCallback token,
+            int uid, int pid, String packageName, int versionCode) throws RemoteException {
+        ActiveBuffer buffer = fetchActiveBuffersLocked(token, uid, pid, packageName, versionCode);
+        scheduleRotateLocked();
         return getPfd(buffer.mProcessBuffer);
     }
 
+    private Calendar normalizeDate(long timestamp) {
+        Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
+        calendar.setTimeInMillis(timestamp);
+        calendar.set(Calendar.HOUR_OF_DAY, 0);
+        calendar.set(Calendar.MINUTE, 0);
+        calendar.set(Calendar.SECOND, 0);
+        calendar.set(Calendar.MILLISECOND, 0);
+        return calendar;
+    }
+
+    private File pathForApp(BufferInfo info) {
+        String subPath = String.format("%d/%s/%d/total",
+                normalizeDate(info.startTime).getTimeInMillis(), info.packageName, info.versionCode);
+        return new File(mGraphicsStatsDir, subPath);
+    }
+
+    private void saveBuffer(HistoricalBuffer buffer) {
+        if (Trace.isTagEnabled(Trace.TRACE_TAG_SYSTEM_SERVER)) {
+            Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "saving graphicsstats for " + buffer.mInfo.packageName);
+        }
+        synchronized (mFileAccessLock) {
+            File path = pathForApp(buffer.mInfo);
+            File parent = path.getParentFile();
+            parent.mkdirs();
+            if (!parent.exists()) {
+                Log.w(TAG, "Unable to create path: '" + parent.getAbsolutePath() + "'");
+                return;
+            }
+            nSaveBuffer(path.getAbsolutePath(), buffer.mInfo.packageName, buffer.mInfo.versionCode,
+                    buffer.mInfo.startTime, buffer.mInfo.endTime, buffer.mData);
+        }
+        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+    }
+
+    private void deleteRecursiveLocked(File file) {
+        if (file.isDirectory()) {
+            for (File child : file.listFiles()) {
+                deleteRecursiveLocked(child);
+            }
+        }
+        if (!file.delete()) {
+            Log.w(TAG, "Failed to delete '" + file.getAbsolutePath() + "'!");
+        }
+    }
+
+    private void deleteOldBuffers() {
+        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "deleting old graphicsstats buffers");
+        synchronized (mFileAccessLock) {
+            File[] files = mGraphicsStatsDir.listFiles();
+            if (files == null || files.length <= 3) {
+                return;
+            }
+            long[] sortedDates = new long[files.length];
+            for (int i = 0; i < files.length; i++) {
+                try {
+                    sortedDates[i] = Long.parseLong(files[i].getName());
+                } catch (NumberFormatException ex) {
+                    // Skip unrecognized folders
+                }
+            }
+            if (sortedDates.length <= 3) {
+                return;
+            }
+            Arrays.sort(sortedDates);
+            for (int i = 0; i < sortedDates.length - 3; i++) {
+                deleteRecursiveLocked(new File(mGraphicsStatsDir, Long.toString(sortedDates[i])));
+            }
+        }
+        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+    }
+
+    private void addToSaveQueue(ActiveBuffer buffer) {
+        try {
+            HistoricalBuffer data = new HistoricalBuffer(buffer);
+            Message.obtain(mWriteOutHandler, SAVE_BUFFER, data).sendToTarget();
+        } catch (IOException e) {
+            Log.w(TAG, "Failed to copy graphicsstats from " + buffer.mInfo.packageName, e);
+        }
+        buffer.closeAllBuffers();
+    }
+
     private void processDied(ActiveBuffer buffer) {
         synchronized (mLock) {
             mActive.remove(buffer);
-            Log.d("GraphicsStats", "Buffer count: " + mActive.size());
         }
-        HistoricalData data = buffer.mPreviousData;
-        buffer.mPreviousData = null;
-        if (data == null) {
-            data = mHistoricalLog[mNextHistoricalSlot];
-            if (data == null) {
-                data = new HistoricalData();
-            }
-        }
-        data.update(buffer.mPackageName, buffer.mUid, buffer.mProcessBuffer);
-        buffer.closeAllBuffers();
-
-        mHistoricalLog[mNextHistoricalSlot] = data;
-        mNextHistoricalSlot = (mNextHistoricalSlot + 1) % mHistoricalLog.length;
+        addToSaveQueue(buffer);
     }
 
-    private ActiveBuffer fetchActiveBuffersLocked(IBinder token, int uid, int pid,
-            String packageName) throws RemoteException {
+    private ActiveBuffer fetchActiveBuffersLocked(IGraphicsStatsCallback token, int uid, int pid,
+            String packageName, int versionCode) throws RemoteException {
         int size = mActive.size();
+        long today = normalizeDate(System.currentTimeMillis()).getTimeInMillis();
         for (int i = 0; i < size; i++) {
-            ActiveBuffer buffers = mActive.get(i);
-            if (buffers.mPid == pid
-                    && buffers.mUid == uid) {
-                return buffers;
+            ActiveBuffer buffer = mActive.get(i);
+            if (buffer.mPid == pid
+                    && buffer.mUid == uid) {
+                // If the buffer is too old we remove it and return a new one
+                if (buffer.mInfo.startTime < today) {
+                    buffer.binderDied();
+                    break;
+                } else {
+                    return buffer;
+                }
             }
         }
         // Didn't find one, need to create it
         try {
-            ActiveBuffer buffers = new ActiveBuffer(token, uid, pid, packageName);
+            ActiveBuffer buffers = new ActiveBuffer(token, uid, pid, packageName, versionCode);
             mActive.add(buffers);
             return buffers;
         } catch (IOException ex) {
@@ -147,71 +312,106 @@
         }
     }
 
-    private HistoricalData removeHistoricalDataLocked(int uid, String packageName) {
-        for (int i = 0; i < mHistoricalLog.length; i++) {
-            final HistoricalData data = mHistoricalLog[i];
-            if (data != null && data.mUid == uid
-                    && data.mPackageName.equals(packageName)) {
-                if (i == mNextHistoricalSlot) {
-                    mHistoricalLog[i] = null;
-                } else {
-                    mHistoricalLog[i] = mHistoricalLog[mNextHistoricalSlot];
-                    mHistoricalLog[mNextHistoricalSlot] = null;
+    private HashSet<File> dumpActiveLocked(long dump, ArrayList<HistoricalBuffer> buffers) {
+        HashSet<File> skipFiles = new HashSet<>(buffers.size());
+        for (int i = 0; i < buffers.size(); i++) {
+            HistoricalBuffer buffer = buffers.get(i);
+            File path = pathForApp(buffer.mInfo);
+            skipFiles.add(path);
+            nAddToDump(dump, path.getAbsolutePath(), buffer.mInfo.packageName,
+                    buffer.mInfo.versionCode,  buffer.mInfo.startTime, buffer.mInfo.endTime,
+                    buffer.mData);
+        }
+        return skipFiles;
+    }
+
+    private void dumpHistoricalLocked(long dump, HashSet<File> skipFiles) {
+        for (File date : mGraphicsStatsDir.listFiles()) {
+            for (File pkg : date.listFiles()) {
+                for (File version : pkg.listFiles()) {
+                    File data = new File(version, "total");
+                    if (skipFiles.contains(data)) {
+                        continue;
+                    }
+                    nAddToDump(dump, data.getAbsolutePath());
                 }
-                return data;
             }
         }
-        return null;
     }
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+        boolean dumpProto = false;
+        for (String str : args) {
+            if ("--proto".equals(str)) {
+                dumpProto = true;
+                break;
+            }
+        }
+        ArrayList<HistoricalBuffer> buffers;
         synchronized (mLock) {
+            buffers = new ArrayList<>(mActive.size());
             for (int i = 0; i < mActive.size(); i++) {
-                final ActiveBuffer buffer = mActive.get(i);
-                fout.print("Package: ");
-                fout.print(buffer.mPackageName);
-                fout.flush();
                 try {
-                    buffer.mProcessBuffer.readBytes(mTempBuffer, 0, 0, ASHMEM_SIZE);
-                    ThreadedRenderer.dumpProfileData(mTempBuffer, fd);
-                } catch (IOException e) {
-                    fout.println("Failed to dump");
+                    buffers.add(new HistoricalBuffer(mActive.get(i)));
+                } catch (IOException ex) {
+                    // Ignore
                 }
-                fout.println();
             }
-            for (HistoricalData buffer : mHistoricalLog) {
-                if (buffer == null) continue;
-                fout.print("Package: ");
-                fout.print(buffer.mPackageName);
-                fout.flush();
-                ThreadedRenderer.dumpProfileData(buffer.mBuffer, fd);
-                fout.println();
+        }
+        long dump = nCreateDump(fd.getInt$(), dumpProto);
+        try {
+            synchronized (mFileAccessLock) {
+                HashSet<File> skipList = dumpActiveLocked(dump, buffers);
+                buffers.clear();
+                dumpHistoricalLocked(dump, skipList);
             }
+        } finally {
+            nFinishDump(dump);
+        }
+    }
+
+    private static native int nGetAshmemSize();
+    private static native long nCreateDump(int outFd, boolean isProto);
+    private static native void nAddToDump(long dump, String path, String packageName,
+            int versionCode, long startTime, long endTime, byte[] data);
+    private static native void nAddToDump(long dump, String path);
+    private static native void nFinishDump(long dump);
+    private static native void nSaveBuffer(String path, String packageName, int versionCode,
+            long startTime, long endTime, byte[] data);
+
+    private final class BufferInfo {
+        final String packageName;
+        final int versionCode;
+        long startTime;
+        long endTime;
+
+        BufferInfo(String packageName, int versionCode, long startTime) {
+            this.packageName = packageName;
+            this.versionCode = versionCode;
+            this.startTime = startTime;
         }
     }
 
     private final class ActiveBuffer implements DeathRecipient {
+        final BufferInfo mInfo;
         final int mUid;
         final int mPid;
-        final String mPackageName;
+        final IGraphicsStatsCallback mCallback;
         final IBinder mToken;
         MemoryFile mProcessBuffer;
-        HistoricalData mPreviousData;
 
-        ActiveBuffer(IBinder token, int uid, int pid, String packageName)
+        ActiveBuffer(IGraphicsStatsCallback token, int uid, int pid, String packageName, int versionCode)
                 throws RemoteException, IOException {
+            mInfo = new BufferInfo(packageName, versionCode, System.currentTimeMillis());
             mUid = uid;
             mPid = pid;
-            mPackageName = packageName;
-            mToken = token;
+            mCallback = token;
+            mToken = mCallback.asBinder();
             mToken.linkToDeath(this, 0);
-            mProcessBuffer = new MemoryFile("GFXStats-" + uid, ASHMEM_SIZE);
-            mPreviousData = removeHistoricalDataLocked(mUid, mPackageName);
-            if (mPreviousData != null) {
-                mProcessBuffer.writeBytes(mPreviousData.mBuffer, 0, 0, ASHMEM_SIZE);
-            }
+            mProcessBuffer = new MemoryFile("GFXStats-" + pid, ASHMEM_SIZE);
+            mProcessBuffer.writeBytes(ZERO_DATA, 0, 0, ASHMEM_SIZE);
         }
 
         @Override
@@ -228,17 +428,13 @@
         }
     }
 
-    private final static class HistoricalData {
-        final byte[] mBuffer = new byte[ASHMEM_SIZE];
-        int mUid;
-        String mPackageName;
-
-        void update(String packageName, int uid, MemoryFile file) {
-            mUid = uid;
-            mPackageName = packageName;
-            try {
-                file.readBytes(mBuffer, 0, 0, ASHMEM_SIZE);
-            } catch (IOException e) {}
+    private final class HistoricalBuffer {
+        final BufferInfo mInfo;
+        final byte[] mData = new byte[ASHMEM_SIZE];
+        HistoricalBuffer(ActiveBuffer active) throws IOException {
+            mInfo = active.mInfo;
+            mInfo.endTime = System.currentTimeMillis();
+            active.mProcessBuffer.readBytes(mData, 0, 0, ASHMEM_SIZE);
         }
     }
 }
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 8442c11..69e481f 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -28,6 +28,7 @@
 import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem;
 import com.android.internal.inputmethod.InputMethodUtils;
 import com.android.internal.inputmethod.InputMethodUtils.InputMethodSettings;
+import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.os.HandlerCaller;
 import com.android.internal.os.SomeArgs;
 import com.android.internal.os.TransferPipe;
@@ -881,7 +882,7 @@
 
     final class MyPackageMonitor extends PackageMonitor {
         /**
-         * Set of packages to be monitored.
+         * Package names that are known to contain {@link InputMethodService}.
          *
          * <p>No need to include packages because of direct-boot unaware IMEs since we always rescan
          * all the packages when the user is unlocked, and direct-boot awareness will not be changed
@@ -889,16 +890,36 @@
          * rescanning.</p>
          */
         @GuardedBy("mMethodMap")
-        private ArraySet<String> mPackagesToMonitorComponentChange = new ArraySet<>();
+        final private ArraySet<String> mKnownImePackageNames = new ArraySet<>();
+
+        /**
+         * Packages that are appeared, disappeared, or modified for whatever reason.
+         *
+         * <p>Note: For now we intentionally use {@link ArrayList} instead of {@link ArraySet}
+         * because 1) the number of elements is almost always 1 or so, and 2) we do not care
+         * duplicate elements for our use case.</p>
+         *
+         * <p>This object must be accessed only from callback methods in {@link PackageMonitor},
+         * which should be bound to {@link #getRegisteredHandler()}.</p>
+         */
+        private final ArrayList<String> mChangedPackages = new ArrayList<>();
+
+        /**
+         * {@code true} if one or more packages that contain {@link InputMethodService} appeared.
+         *
+         * <p>This field must be accessed only from callback methods in {@link PackageMonitor},
+         * which should be bound to {@link #getRegisteredHandler()}.</p>
+         */
+        private boolean mImePackageAppeared = false;
 
         @GuardedBy("mMethodMap")
-        void clearPackagesToMonitorComponentChangeLocked() {
-            mPackagesToMonitorComponentChange.clear();
+        void clearKnownImePackageNamesLocked() {
+            mKnownImePackageNames.clear();
         }
 
         @GuardedBy("mMethodMap")
-        final void addPackageToMonitorComponentChangeLocked(@NonNull String packageName) {
-            mPackagesToMonitorComponentChange.add(packageName);
+        final void addKnownImePackageNameLocked(@NonNull String packageName) {
+            mKnownImePackageNames.add(packageName);
         }
 
         @GuardedBy("mMethodMap")
@@ -943,19 +964,97 @@
         }
 
         @Override
-        public boolean onPackageChanged(String packageName, int uid, String[] components) {
-            // If this package is in the watch list, we want to check it.
-            synchronized (mMethodMap) {
-                return mPackagesToMonitorComponentChange.contains(packageName);
+        public void onBeginPackageChanges() {
+            clearPackageChangeState();
+        }
+
+        @Override
+        public void onPackageAppeared(String packageName, int reason) {
+            if (!mImePackageAppeared) {
+                final PackageManager pm = mContext.getPackageManager();
+                final List<ResolveInfo> services = pm.queryIntentServicesAsUser(
+                        new Intent(InputMethod.SERVICE_INTERFACE).setPackage(packageName),
+                        PackageManager.MATCH_DISABLED_COMPONENTS, getChangingUserId());
+                // No need to lock this because we access it only on getRegisteredHandler().
+                if (!services.isEmpty()) {
+                    mImePackageAppeared = true;
+                }
+            }
+            // No need to lock this because we access it only on getRegisteredHandler().
+            mChangedPackages.add(packageName);
+        }
+
+        @Override
+        public void onPackageDisappeared(String packageName, int reason) {
+            // No need to lock this because we access it only on getRegisteredHandler().
+            mChangedPackages.add(packageName);
+        }
+
+        @Override
+        public void onPackageModified(String packageName) {
+            // No need to lock this because we access it only on getRegisteredHandler().
+            mChangedPackages.add(packageName);
+        }
+
+        @Override
+        public void onPackagesSuspended(String[] packages) {
+            // No need to lock this because we access it only on getRegisteredHandler().
+            for (String packageName : packages) {
+                mChangedPackages.add(packageName);
             }
         }
 
         @Override
-        public void onSomePackagesChanged() {
+        public void onPackagesUnsuspended(String[] packages) {
+            // No need to lock this because we access it only on getRegisteredHandler().
+            for (String packageName : packages) {
+                mChangedPackages.add(packageName);
+            }
+        }
+
+        @Override
+        public void onFinishPackageChanges() {
+            onFinishPackageChangesInternal();
+            clearPackageChangeState();
+        }
+
+        private void clearPackageChangeState() {
+            // No need to lock them because we access these fields only on getRegisteredHandler().
+            mChangedPackages.clear();
+            mImePackageAppeared = false;
+        }
+
+        private boolean shouldRebuildInputMethodListLocked() {
+            // This method is guaranteed to be called only by getRegisteredHandler().
+
+            // If there is any new package that contains at least one IME, then rebuilt the list
+            // of IMEs.
+            if (mImePackageAppeared) {
+                return true;
+            }
+
+            // Otherwise, check if mKnownImePackageNames and mChangedPackages have any intersection.
+            // TODO: Consider to create a utility method to do the following test. List.retainAll()
+            // is an option, but it may still do some extra operations that we do not need here.
+            final int N = mChangedPackages.size();
+            for (int i = 0; i < N; ++i) {
+                final String packageName = mChangedPackages.get(i);
+                if (mKnownImePackageNames.contains(packageName)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        private void onFinishPackageChangesInternal() {
             synchronized (mMethodMap) {
                 if (!isChangingPackagesOfCurrentUserLocked()) {
                     return;
                 }
+                if (!shouldRebuildInputMethodListLocked()) {
+                    return;
+                }
+
                 InputMethodInfo curIm = null;
                 String curInputMethodId = mSettings.getSelectedInputMethod();
                 final int N = mMethodList.size();
@@ -1164,13 +1263,14 @@
 
         Bundle extras = new Bundle();
         extras.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, true);
-        mImeSwitcherNotification = new Notification.Builder(mContext)
-            .setSmallIcon(com.android.internal.R.drawable.ic_notification_ime_default)
-            .setWhen(0)
-            .setOngoing(true)
-            .addExtras(extras)
-            .setCategory(Notification.CATEGORY_SYSTEM)
-            .setColor(com.android.internal.R.color.system_notification_accent_color);
+        mImeSwitcherNotification =
+                new Notification.Builder(mContext, SystemNotificationChannels.VIRTUAL_KEYBOARD)
+                        .setSmallIcon(com.android.internal.R.drawable.ic_notification_ime_default)
+                        .setWhen(0)
+                        .setOngoing(true)
+                        .addExtras(extras)
+                        .setCategory(Notification.CATEGORY_SYSTEM)
+                        .setColor(com.android.internal.R.color.system_notification_accent_color);
 
         Intent intent = new Intent(Settings.ACTION_SHOW_INPUT_METHOD_PICKER);
         mImeSwitchPendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
@@ -2046,7 +2146,7 @@
         }
         mWindowManagerInternal.updateInputMethodWindowStatus(token,
                 (vis & InputMethodService.IME_VISIBLE) != 0,
-                token != null ? info.mTargetWindow : null);
+                info != null ? info.mTargetWindow : null);
     }
 
     private void updateSystemUi(IBinder token, int vis, int backDisposition) {
@@ -3283,7 +3383,7 @@
         mMethodList.clear();
         mMethodMap.clear();
         mMethodMapUpdateCount++;
-        mMyPackageMonitor.clearPackagesToMonitorComponentChangeLocked();
+        mMyPackageMonitor.clearKnownImePackageNamesLocked();
 
         // Use for queryIntentServicesAsUser
         final PackageManager pm = mContext.getPackageManager();
@@ -3339,10 +3439,9 @@
             final int N = allInputMethodServices.size();
             for (int i = 0; i < N; ++i) {
                 final ServiceInfo si = allInputMethodServices.get(i).serviceInfo;
-                if (!android.Manifest.permission.BIND_INPUT_METHOD.equals(si.permission)) {
-                    continue;
+                if (android.Manifest.permission.BIND_INPUT_METHOD.equals(si.permission)) {
+                    mMyPackageMonitor.addKnownImePackageNameLocked(si.packageName);
                 }
-                mMyPackageMonitor.addPackageToMonitorComponentChangeLocked(si.packageName);
             }
         }
 
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index ef7780c..979096e 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -19,6 +19,7 @@
 import android.app.ActivityManager;
 import android.annotation.NonNull;
 import android.content.pm.PackageManagerInternal;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.location.ProviderProperties;
@@ -104,6 +105,7 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.NoSuchElementException;
 import java.util.Set;
 
@@ -225,6 +227,12 @@
 
     private final ArraySet<String> mBackgroundThrottlePackageWhitelist = new ArraySet<>();
 
+    private final ArrayMap<IGnssMeasurementsListener, Identity> mGnssMeasurementsListeners =
+            new ArrayMap<>();
+
+    private final ArrayMap<IGnssNavigationMessageListener, Identity>
+            mGnssNavigationMessageListeners = new ArrayMap<>();
+
     // current active user on the device - other users are denied location data
     private int mCurrentUserId = UserHandle.USER_SYSTEM;
     private int[] mCurrentUserProfiles = new int[] { UserHandle.USER_SYSTEM };
@@ -315,17 +323,17 @@
                     boolean foreground = isImportanceForeground(importance);
                     HashSet<String> affectedProviders = new HashSet<>(mRecordsByProvider.size());
                     synchronized (mLock) {
-                        for (Map.Entry<String, ArrayList<UpdateRecord>> entry
+                        for (Entry<String, ArrayList<UpdateRecord>> entry
                                 : mRecordsByProvider.entrySet()) {
                             String provider = entry.getKey();
                             for (UpdateRecord record : entry.getValue()) {
-                                if (record.mReceiver.mUid == uid
+                                if (record.mReceiver.mIdentity.mUid == uid
                                         && record.mIsForegroundUid != foreground) {
                                     if (D) Log.d(TAG, "request from uid " + uid + " is now "
                                             + (foreground ? "foreground" : "background)"));
                                     record.mIsForegroundUid = foreground;
 
-                                    if (!isThrottlingExemptLocked(record.mReceiver)) {
+                                    if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
                                         affectedProviders.add(provider);
                                     }
                                 }
@@ -334,6 +342,33 @@
                         for (String provider : affectedProviders) {
                             applyRequirementsLocked(provider);
                         }
+
+                        for (Entry<IGnssMeasurementsListener, Identity> entry
+                                : mGnssMeasurementsListeners.entrySet()) {
+                            if (entry.getValue().mUid == uid) {
+                                if (D) Log.d(TAG, "gnss measurements listener from uid " + uid
+                                    + " is now " + (foreground ? "foreground" : "background)"));
+                                if (foreground || isThrottlingExemptLocked(entry.getValue())) {
+                                    mGnssMeasurementsProvider.addListener(entry.getKey());
+                                } else {
+                                    mGnssMeasurementsProvider.removeListener(entry.getKey());
+                                }
+                            }
+                        }
+
+                        for (Entry<IGnssNavigationMessageListener, Identity> entry
+                            : mGnssNavigationMessageListeners.entrySet()) {
+                            if (entry.getValue().mUid == uid) {
+                                if (D) Log.d(TAG, "gnss navigation message listener from uid "
+                                    + uid + " is now "
+                                    + (foreground ? "foreground" : "background)"));
+                                if (foreground || isThrottlingExemptLocked(entry.getValue())) {
+                                    mGnssNavigationMessageProvider.addListener(entry.getKey());
+                                } else {
+                                    mGnssNavigationMessageProvider.removeListener(entry.getKey());
+                                }
+                            }
+                        }
                     }
 
                 }
@@ -344,7 +379,7 @@
             mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
             updateUserProfiles(mCurrentUserId);
 
-            updateThrottlingWhitelistLocked();
+            updateBackgroundThrottlingWhitelistLocked();
 
             // prepare providers
             loadProvidersLocked();
@@ -381,7 +416,7 @@
                 @Override
                 public void onChange(boolean selfChange) {
                     synchronized (mLock) {
-                        updateThrottlingWhitelistLocked();
+                        updateBackgroundThrottlingWhitelistLocked();
                         updateProvidersLocked();
                     }
                 }
@@ -721,14 +756,24 @@
         }
     }
 
+    private static final class Identity {
+        final int mUid;
+        final int mPid;
+        final String mPackageName;
+
+        Identity(int uid, int pid, String packageName) {
+            mUid = uid;
+            mPid = pid;
+            mPackageName = packageName;
+        }
+    }
+
     /**
      * A wrapper class holding either an ILocationListener or a PendingIntent to receive
      * location updates.
      */
     private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
-        final int mUid;  // uid of receiver
-        final int mPid;  // pid of receiver
-        final String mPackageName;  // package name of receiver
+        final Identity mIdentity;
         final int mAllowedResolutionLevel;  // resolution level allowed to receiver
 
         final ILocationListener mListener;
@@ -756,9 +801,7 @@
                 mKey = intent;
             }
             mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
-            mUid = uid;
-            mPid = pid;
-            mPackageName = packageName;
+            mIdentity = new Identity(uid, pid, packageName);
             if (workSource != null && workSource.size() <= 0) {
                 workSource = null;
             }
@@ -770,7 +813,7 @@
             // construct/configure wakelock
             mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
             if (workSource == null) {
-                workSource = new WorkSource(mUid, mPackageName);
+                workSource = new WorkSource(mIdentity.mUid, mIdentity.mPackageName);
             }
             mWakeLock.setWorkSource(workSource);
         }
@@ -865,13 +908,14 @@
                 int op) {
             if (!currentlyMonitoring) {
                 if (allowMonitoring) {
-                    return mAppOps.startOpNoThrow(op, mUid, mPackageName)
+                    return mAppOps.startOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
                             == AppOpsManager.MODE_ALLOWED;
                 }
             } else {
-                if (!allowMonitoring || mAppOps.checkOpNoThrow(op, mUid, mPackageName)
+                if (!allowMonitoring
+                        || mAppOps.checkOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
                         != AppOpsManager.MODE_ALLOWED) {
-                    mAppOps.finishOp(op, mUid, mPackageName);
+                    mAppOps.finishOp(op, mIdentity.mUid, mIdentity.mPackageName);
                     return false;
                 }
             }
@@ -1628,7 +1672,7 @@
         ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
         if (records != null) {
             for (UpdateRecord record : records) {
-                if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mUid))) {
+                if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
                     // Sends a notification message to the receiver
                     if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
                         if (deadReceivers == null) {
@@ -1673,16 +1717,16 @@
 
         if (records != null) {
             for (UpdateRecord record : records) {
-                if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mUid))) {
+                if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
                     if (checkLocationAccess(
-                            record.mReceiver.mPid,
-                            record.mReceiver.mUid,
-                            record.mReceiver.mPackageName,
+                            record.mReceiver.mIdentity.mPid,
+                            record.mReceiver.mIdentity.mUid,
+                            record.mReceiver.mIdentity.mPackageName,
                             record.mReceiver.mAllowedResolutionLevel)) {
                         LocationRequest locationRequest = record.mRequest;
                         long interval = locationRequest.getInterval();
 
-                        if (!isThrottlingExemptLocked(record.mReceiver)) {
+                        if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
                             if (!record.mIsForegroundUid) {
                                 interval = Math.max(interval, backgroundThrottleInterval);
                             }
@@ -1709,7 +1753,7 @@
                 // under that threshold.
                 long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2;
                 for (UpdateRecord record : records) {
-                    if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mUid))) {
+                    if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
                         LocationRequest locationRequest = record.mRequest;
 
                         // Don't assign battery blame for update records whose
@@ -1728,8 +1772,8 @@
                             } else {
                                 // Assign blame to caller.
                                 worksource.add(
-                                        record.mReceiver.mUid,
-                                        record.mReceiver.mPackageName);
+                                        record.mReceiver.mIdentity.mUid,
+                                        record.mReceiver.mIdentity.mPackageName);
                             }
                         }
                     }
@@ -1741,7 +1785,15 @@
         p.setRequest(providerRequest, worksource);
     }
 
-    private void updateThrottlingWhitelistLocked() {
+    @Override
+    public String[] getBackgroundThrottlingWhitelist() {
+        synchronized (mLock) {
+            return mBackgroundThrottlePackageWhitelist.toArray(
+                new String[mBackgroundThrottlePackageWhitelist.size()]);
+        }
+    }
+
+    private void updateBackgroundThrottlingWhitelistLocked() {
         String setting = Settings.Global.getString(
             mContext.getContentResolver(),
             Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST);
@@ -1756,17 +1808,17 @@
             Arrays.asList(setting.split(",")));
     }
 
-    private boolean isThrottlingExemptLocked(Receiver receiver) {
-        if (receiver.mUid == Process.SYSTEM_UID) {
+    private boolean isThrottlingExemptLocked(Identity identity) {
+        if (identity.mUid == Process.SYSTEM_UID) {
             return true;
         }
 
-        if (mBackgroundThrottlePackageWhitelist.contains(receiver.mPackageName)) {
+        if (mBackgroundThrottlePackageWhitelist.contains(identity.mPackageName)) {
             return true;
         }
 
         for (LocationProviderProxy provider : mProxyProviders) {
-            if (receiver.mPackageName.equals(provider.getConnectedPackageName())) {
+            if (identity.mPackageName.equals(provider.getConnectedPackageName())) {
                 return true;
             }
         }
@@ -1790,7 +1842,7 @@
             mRequest = request;
             mReceiver = receiver;
             mIsForegroundUid = isImportanceForeground(
-                    mActivityManager.getPackageImportance(mReceiver.mPackageName));
+                    mActivityManager.getPackageImportance(mReceiver.mIdentity.mPackageName));
 
             ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
             if (records == null) {
@@ -1803,14 +1855,14 @@
 
             // Update statistics for historical location requests by package/provider
             mRequestStatistics.startRequesting(
-                    mReceiver.mPackageName, provider, request.getInterval());
+                    mReceiver.mIdentity.mPackageName, provider, request.getInterval());
         }
 
         /**
          * Method to be called when a record will no longer be used.
          */
         void disposeLocked(boolean removeReceiver) {
-            mRequestStatistics.stopRequesting(mReceiver.mPackageName, mProvider);
+            mRequestStatistics.stopRequesting(mReceiver.mIdentity.mPackageName, mProvider);
 
             // remove from mRecordsByProvider
             ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
@@ -1834,8 +1886,8 @@
 
         @Override
         public String toString() {
-            return "UpdateRecord[" + mProvider + " " + mReceiver.mPackageName
-                    + "(" + mReceiver.mUid + (mIsForegroundUid ? " foreground" : " background")
+            return "UpdateRecord[" + mProvider + " " + mReceiver.mIdentity.mPackageName
+                    + "(" + mReceiver.mIdentity.mUid + (mIsForegroundUid ? " foreground" : " background")
                     + ")" + " " + mRequest + "]";
         }
     }
@@ -1994,7 +2046,8 @@
         if (D) Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver))
                 + " " + name + " " + request + " from " + packageName + "(" + uid + " "
                 + (record.mIsForegroundUid ? "foreground" : "background")
-                + (isThrottlingExemptLocked(receiver) ? " [whitelisted]" : "") + ")");
+                + (isThrottlingExemptLocked(receiver.mIdentity)
+                    ? " [whitelisted]" : "") + ")");
 
         UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
         if (oldRecord != null) {
@@ -2227,13 +2280,33 @@
         if (!hasGnssPermissions(packageName) || mGnssMeasurementsProvider == null) {
             return false;
         }
-        return mGnssMeasurementsProvider.addListener(listener);
+
+        synchronized (mLock) {
+            Identity callerIdentity
+                    = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
+            mGnssMeasurementsListeners.put(listener, callerIdentity);
+            long identity = Binder.clearCallingIdentity();
+            try {
+                if (isThrottlingExemptLocked(callerIdentity)
+                        || isImportanceForeground(
+                                mActivityManager.getPackageImportance(packageName))) {
+                    return mGnssMeasurementsProvider.addListener(listener);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+
+            return true;
+        }
     }
 
     @Override
     public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
         if (mGnssMeasurementsProvider != null) {
-            mGnssMeasurementsProvider.removeListener(listener);
+            synchronized (mLock) {
+                mGnssMeasurementsListeners.remove(listener);
+                mGnssMeasurementsProvider.removeListener(listener);
+            }
         }
     }
 
@@ -2244,13 +2317,33 @@
         if (!hasGnssPermissions(packageName) || mGnssNavigationMessageProvider == null) {
             return false;
         }
-        return mGnssNavigationMessageProvider.addListener(listener);
+
+        synchronized (mLock) {
+            Identity callerIdentity
+                = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
+            mGnssNavigationMessageListeners.put(listener, callerIdentity);
+            long identity = Binder.clearCallingIdentity();
+            try {
+                if (isThrottlingExemptLocked(callerIdentity)
+                        || isImportanceForeground(
+                                mActivityManager.getPackageImportance(packageName))) {
+                    return mGnssNavigationMessageProvider.addListener(listener);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+
+            return true;
+        }
     }
 
     @Override
     public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) {
         if (mGnssNavigationMessageProvider != null) {
-            mGnssNavigationMessageProvider.removeListener(listener);
+            synchronized (mLock) {
+                mGnssNavigationMessageListeners.remove(listener);
+                mGnssNavigationMessageProvider.removeListener(listener);
+            }
         }
     }
 
@@ -2529,26 +2622,30 @@
             Receiver receiver = r.mReceiver;
             boolean receiverDead = false;
 
-            int receiverUserId = UserHandle.getUserId(receiver.mUid);
-            if (!isCurrentProfile(receiverUserId) && !isUidALocationProvider(receiver.mUid)) {
+            int receiverUserId = UserHandle.getUserId(receiver.mIdentity.mUid);
+            if (!isCurrentProfile(receiverUserId)
+                    && !isUidALocationProvider(receiver.mIdentity.mUid)) {
                 if (D) {
                     Log.d(TAG, "skipping loc update for background user " + receiverUserId +
                             " (current user: " + mCurrentUserId + ", app: " +
-                            receiver.mPackageName + ")");
+                            receiver.mIdentity.mPackageName + ")");
                 }
                 continue;
             }
 
-            if (mBlacklist.isBlacklisted(receiver.mPackageName)) {
+            if (mBlacklist.isBlacklisted(receiver.mIdentity.mPackageName)) {
                 if (D) Log.d(TAG, "skipping loc update for blacklisted app: " +
-                        receiver.mPackageName);
+                        receiver.mIdentity.mPackageName);
                 continue;
             }
 
-            if (!reportLocationAccessNoThrow(receiver.mPid, receiver.mUid, receiver.mPackageName,
+            if (!reportLocationAccessNoThrow(
+                    receiver.mIdentity.mPid,
+                    receiver.mIdentity.mUid,
+                    receiver.mIdentity.mPackageName,
                     receiver.mAllowedResolutionLevel)) {
                 if (D) Log.d(TAG, "skipping loc update for no op app: " +
-                        receiver.mPackageName);
+                        receiver.mIdentity.mPackageName);
                 continue;
             }
 
@@ -2671,7 +2768,7 @@
                 ArrayList<Receiver> deadReceivers = null;
 
                 for (Receiver receiver : mReceivers.values()) {
-                    if (receiver.mPackageName.equals(packageName)) {
+                    if (receiver.mIdentity.mPackageName.equals(packageName)) {
                         if (deadReceivers == null) {
                             deadReceivers = new ArrayList<>();
                         }
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index 4a44530..bcee2c1b 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -76,6 +76,7 @@
 import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.widget.ICheckCredentialProgressCallback;
 import com.android.internal.widget.ILockSettings;
@@ -442,21 +443,20 @@
         // Suppress all notifications on non-FBE devices for now
         if (!StorageManager.isFileEncryptedNativeOrEmulated()) return;
 
-        Notification notification = new Notification.Builder(mContext)
-                .setSmallIcon(com.android.internal.R.drawable.ic_user_secure)
-                .setWhen(0)
-                .setOngoing(true)
-                .setTicker(title)
-                .setDefaults(0) // please be quiet
-                .setPriority(Notification.PRIORITY_MAX)
-                .setColor(mContext.getColor(
-                        com.android.internal.R.color.system_notification_accent_color))
-                .setContentTitle(title)
-                .setContentText(message)
-                .setSubText(detail)
-                .setVisibility(Notification.VISIBILITY_PUBLIC)
-                .setContentIntent(intent)
-                .build();
+        Notification notification =
+                new Notification.Builder(mContext, SystemNotificationChannels.SECURITY)
+                        .setSmallIcon(com.android.internal.R.drawable.ic_user_secure)
+                        .setWhen(0)
+                        .setOngoing(true)
+                        .setTicker(title)
+                        .setColor(mContext.getColor(
+                                com.android.internal.R.color.system_notification_accent_color))
+                        .setContentTitle(title)
+                        .setContentText(message)
+                        .setSubText(detail)
+                        .setVisibility(Notification.VISIBILITY_PUBLIC)
+                        .setContentIntent(intent)
+                        .build();
         mNotificationManager.notifyAsUser(null, FBE_ENCRYPTED_NOTIFICATION, notification, user);
     }
 
@@ -1064,6 +1064,14 @@
 
     private void setLockCredentialInternal(String credential, int credentialType,
             String savedCredential, int userId) throws RemoteException {
+        // Normalize savedCredential and credential such that empty string is always represented
+        // as null.
+        if (TextUtils.isEmpty(savedCredential)) {
+            savedCredential = null;
+        }
+        if (TextUtils.isEmpty(credential)) {
+            credential = null;
+        }
         synchronized (mSpManager) {
             if (isSyntheticPasswordBasedCredentialLocked(userId)) {
                 spBasedSetLockCredentialInternalLocked(credential, credentialType, savedCredential,
@@ -2190,20 +2198,34 @@
         try {
             // Managed profile should have escrow enabled
             if (mUserManager.getUserInfo(userId).isManagedProfile()) {
+                Slog.i(TAG, "Managed profile can have escrow token");
                 return;
             }
             DevicePolicyManager dpm = (DevicePolicyManager)
                     mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
             // Devices with Device Owner should have escrow enabled on all users.
             if (dpm.getDeviceOwnerComponentOnAnyUser() != null) {
+                Slog.i(TAG, "Corp-owned device can have escrow token");
+                return;
+            }
+            // We could also have a profile owner on the given (non-managed) user for unicorn cases
+            if (dpm.getProfileOwnerAsUser(userId) != null) {
+                Slog.i(TAG, "User with profile owner can have escrow token");
                 return;
             }
             // If the device is yet to be provisioned (still in SUW), there is still
             // a chance that Device Owner will be set on the device later, so postpone
             // disabling escrow token for now.
             if (!dpm.isDeviceProvisioned()) {
+                Slog.i(TAG, "Postpone disabling escrow tokens until device is provisioned");
                 return;
             }
+
+            // Escrow tokens are enabled on automotive builds.
+            if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
+                return;
+            }
+
             // Disable escrow token permanently on all other device/user types.
             Slog.i(TAG, "Disabling escrow token on user " + userId);
             if (isSyntheticPasswordBasedCredentialLocked(userId)) {
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index b33538cb..46c9f25 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -35,8 +35,7 @@
 import android.net.INetworkScoreService;
 import android.net.NetworkKey;
 import android.net.NetworkScoreManager;
-import android.net.NetworkScorerAppManager;
-import android.net.NetworkScorerAppManager.NetworkScorerAppData;
+import android.net.NetworkScorerAppData;
 import android.net.RecommendationRequest;
 import android.net.RecommendationResult;
 import android.net.ScoredNetwork;
@@ -132,10 +131,10 @@
      * manages the service connection.
      */
     private class NetworkScorerPackageMonitor extends PackageMonitor {
-        final List<String> mPackagesToWatch;
+        final String mPackageToWatch;
 
-        private NetworkScorerPackageMonitor(List<String> packagesToWatch) {
-            mPackagesToWatch = packagesToWatch;
+        private NetworkScorerPackageMonitor(String packageToWatch) {
+            mPackageToWatch = packageToWatch;
         }
 
         @Override
@@ -168,37 +167,27 @@
             evaluateBinding(packageName, true /* forceUnbind */);
         }
 
-        private void evaluateBinding(String scorerPackageName, boolean forceUnbind) {
-            if (!mPackagesToWatch.contains(scorerPackageName)) {
+        private void evaluateBinding(String changedPackageName, boolean forceUnbind) {
+            if (!mPackageToWatch.equals(changedPackageName)) {
                 // Early exit when we don't care about the package that has changed.
                 return;
             }
 
             if (DBG) {
-                Log.d(TAG, "Evaluating binding for: " + scorerPackageName
+                Log.d(TAG, "Evaluating binding for: " + changedPackageName
                         + ", forceUnbind=" + forceUnbind);
             }
+
             final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
             if (activeScorer == null) {
                 // Package change has invalidated a scorer, this will also unbind any service
                 // connection.
                 if (DBG) Log.d(TAG, "No active scorers available.");
-                unbindFromScoringServiceIfNeeded();
-            } else if (activeScorer.getRecommendationServicePackageName().equals(scorerPackageName))
-            {
-                // The active scoring service changed in some way.
-                if (DBG) {
-                    Log.d(TAG, "Possible change to the active scorer: "
-                            + activeScorer.getRecommendationServicePackageName());
-                }
+                refreshBinding();
+            } else { // The scoring service changed in some way.
                 if (forceUnbind) {
                     unbindFromScoringServiceIfNeeded();
                 }
-                bindToScoringServiceIfNeeded(activeScorer);
-            } else {
-                // One of the scoring apps on the device has changed and we may no longer be
-                // bound to the correct scoring app. The logic in bindToScoringServiceIfNeeded()
-                // will sort that out to leave us bound to the most recent active scorer.
                 if (DBG) {
                     Log.d(TAG, "Binding to " + activeScorer.getRecommendationServiceComponent()
                             + " if needed.");
@@ -272,60 +261,75 @@
     /** Called when the system is ready to run third-party code but before it actually does so. */
     void systemReady() {
         if (DBG) Log.d(TAG, "systemReady");
-        registerPackageMonitorIfNeeded();
         registerRecommendationSettingsObserver();
-        refreshRecommendationRequestTimeoutMs();
     }
 
     /** Called when the system is ready for us to start third-party code. */
     void systemRunning() {
         if (DBG) Log.d(TAG, "systemRunning");
-        bindToScoringServiceIfNeeded();
     }
 
-    private void onUserUnlocked(int userId) {
+    @VisibleForTesting
+    void onUserUnlocked(int userId) {
+        if (DBG) Log.d(TAG, "onUserUnlocked(" + userId + ")");
+        refreshBinding();
+    }
+
+    private void refreshBinding() {
+        if (DBG) Log.d(TAG, "refreshBinding()");
+        // Make sure the scorer is up-to-date
+        mNetworkScorerAppManager.updateState();
         registerPackageMonitorIfNeeded();
         bindToScoringServiceIfNeeded();
     }
 
     private void registerRecommendationSettingsObserver() {
-        final List<String> providerPackages =
-            mNetworkScorerAppManager.getPotentialRecommendationProviderPackages();
-        if (!providerPackages.isEmpty()) {
-            final Uri enabledUri = Global.getUriFor(Global.NETWORK_RECOMMENDATIONS_ENABLED);
-            mContentObserver.observe(enabledUri,
-                    ServiceHandler.MSG_RECOMMENDATIONS_ENABLED_CHANGED);
-        }
+        final Uri packageNameUri = Global.getUriFor(Global.NETWORK_RECOMMENDATIONS_PACKAGE);
+        mContentObserver.observe(packageNameUri,
+                ServiceHandler.MSG_RECOMMENDATIONS_PACKAGE_CHANGED);
 
         final Uri timeoutUri = Global.getUriFor(Global.NETWORK_RECOMMENDATION_REQUEST_TIMEOUT_MS);
         mContentObserver.observe(timeoutUri,
                 ServiceHandler.MSG_RECOMMENDATION_REQUEST_TIMEOUT_CHANGED);
+
+        final Uri settingUri = Global.getUriFor(Global.NETWORK_RECOMMENDATIONS_ENABLED);
+        mContentObserver.observe(settingUri,
+                ServiceHandler.MSG_RECOMMENDATION_ENABLED_SETTING_CHANGED);
     }
 
+    /**
+     * Ensures the package manager is registered to monitor the current active scorer.
+     * If a discrepancy is found any previous monitor will be cleaned up
+     * and a new monitor will be created.
+     *
+     * This method is idempotent.
+     */
     private void registerPackageMonitorIfNeeded() {
-        if (DBG) Log.d(TAG, "registerPackageMonitorIfNeeded");
-        final List<String> providerPackages =
-            mNetworkScorerAppManager.getPotentialRecommendationProviderPackages();
+        if (DBG) Log.d(TAG, "registerPackageMonitorIfNeeded()");
+        final NetworkScorerAppData appData = mNetworkScorerAppManager.getActiveScorer();
         synchronized (mPackageMonitorLock) {
             // Unregister the current monitor if needed.
-            if (mPackageMonitor != null) {
+            if (mPackageMonitor != null && (appData == null
+                    || !appData.getRecommendationServicePackageName().equals(
+                            mPackageMonitor.mPackageToWatch))) {
                 if (DBG) {
                     Log.d(TAG, "Unregistering package monitor for "
-                            + mPackageMonitor.mPackagesToWatch);
+                            + mPackageMonitor.mPackageToWatch);
                 }
                 mPackageMonitor.unregister();
                 mPackageMonitor = null;
             }
 
-            // Create and register the monitor if there are packages that could be providers.
-            if (!providerPackages.isEmpty()) {
-                mPackageMonitor = new NetworkScorerPackageMonitor(providerPackages);
+            // Create and register the monitor if a scorer is active.
+            if (appData != null && mPackageMonitor == null) {
+                mPackageMonitor = new NetworkScorerPackageMonitor(
+                        appData.getRecommendationServicePackageName());
                 // TODO: Need to update when we support per-user scorers. http://b/23422763
                 mPackageMonitor.register(mContext, null /* thread */, UserHandle.SYSTEM,
                         false /* externalStorage */);
                 if (DBG) {
                     Log.d(TAG, "Registered package monitor for "
-                            + mPackageMonitor.mPackagesToWatch);
+                            + mPackageMonitor.mPackageToWatch);
                 }
             }
         }
@@ -337,6 +341,13 @@
         bindToScoringServiceIfNeeded(scorerData);
     }
 
+    /**
+     * Ensures the service connection is bound to the current active scorer.
+     * If a discrepancy is found any previous connection will be cleaned up
+     * and a new connection will be created.
+     *
+     * This method is idempotent.
+     */
     private void bindToScoringServiceIfNeeded(NetworkScorerAppData appData) {
         if (DBG) Log.d(TAG, "bindToScoringServiceIfNeeded(" + appData + ")");
         if (appData != null) {
@@ -365,6 +376,8 @@
         synchronized (mServiceConnectionLock) {
             if (mServiceConnection != null) {
                 mServiceConnection.disconnect(mContext);
+                if (DBG) Log.d(TAG, "Disconnected from: "
+                        + mServiceConnection.mAppData.getRecommendationServiceComponent());
             }
             mServiceConnection = null;
         }
@@ -653,17 +666,13 @@
 
     @Override
     public boolean setActiveScorer(String packageName) {
-        // TODO: For now, since SCORE_NETWORKS requires an app to be privileged, we allow such apps
-        // to directly set the scorer app rather than having to use the consent dialog. The
-        // assumption is that anyone bundling a scorer app with the system is trusted by the OEM to
-        // do the right thing and not enable this feature without explaining it to the user.
-        // In the future, should this API be opened to 3p apps, we will need to lock this down and
-        // figure out another way to streamline the UX.
+        // Only the system can set the active scorer
+        if (!isCallerSystemProcess(getCallingUid()) || !callerCanRequestScores()) {
+            throw new SecurityException(
+                    "Caller is neither the system process nor a score requester.");
+        }
 
-        mContext.enforceCallingOrSelfPermission(permission.SCORE_NETWORKS, TAG);
-
-        // Scorers (recommendation providers) are selected and no longer set.
-        return false;
+        return mNetworkScorerAppManager.setActiveScorer(packageName);
     }
 
     /**
@@ -700,7 +709,6 @@
         return null;
     }
 
-
     /**
      * Returns metadata about the active scorer or <code>null</code> if there is no active scorer.
      */
@@ -727,18 +735,24 @@
      */
     @Override
     public List<NetworkScorerAppData> getAllValidScorers() {
+        // Only the system can access this data.
+        if (!isCallerSystemProcess(getCallingUid()) || !callerCanRequestScores()) {
+            throw new SecurityException(
+                    "Caller is neither the system process nor a score requester.");
+        }
+
         return mNetworkScorerAppManager.getAllValidScorers();
     }
 
     @Override
     public void disableScoring() {
         // Only the active scorer or the system should be allowed to disable scoring.
-        if (isCallerActiveScorer(getCallingUid()) || callerCanRequestScores()) {
-            // no-op for now but we could write to the setting if needed.
-        } else {
+        if (!isCallerActiveScorer(getCallingUid()) || !callerCanRequestScores()) {
             throw new SecurityException(
                     "Caller is neither the active scorer nor the scorer manager.");
         }
+
+        // no-op for now but we could write to the setting if needed.
     }
 
     /** Clear scores. Callers are responsible for checking permissions as appropriate. */
@@ -1159,8 +1173,9 @@
     @VisibleForTesting
     public final class ServiceHandler extends Handler {
         public static final int MSG_RECOMMENDATION_REQUEST_TIMEOUT = 1;
-        public static final int MSG_RECOMMENDATIONS_ENABLED_CHANGED = 2;
+        public static final int MSG_RECOMMENDATIONS_PACKAGE_CHANGED = 2;
         public static final int MSG_RECOMMENDATION_REQUEST_TIMEOUT_CHANGED = 3;
+        public static final int MSG_RECOMMENDATION_ENABLED_SETTING_CHANGED = 4;
 
         public ServiceHandler(Looper looper) {
             super(looper);
@@ -1181,8 +1196,9 @@
                     sendDefaultRecommendationResponse(request, remoteCallback);
                     break;
 
-                case MSG_RECOMMENDATIONS_ENABLED_CHANGED:
-                    bindToScoringServiceIfNeeded();
+                case MSG_RECOMMENDATIONS_PACKAGE_CHANGED:
+                case MSG_RECOMMENDATION_ENABLED_SETTING_CHANGED:
+                    refreshBinding();
                     break;
 
                 case MSG_RECOMMENDATION_REQUEST_TIMEOUT_CHANGED:
diff --git a/services/core/java/com/android/server/NetworkScorerAppManager.java b/services/core/java/com/android/server/NetworkScorerAppManager.java
new file mode 100644
index 0000000..5b627d9
--- /dev/null
+++ b/services/core/java/com/android/server/NetworkScorerAppManager.java
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server;
+
+import android.Manifest.permission;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.net.NetworkScoreManager;
+import android.net.NetworkScorerAppData;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Internal class for discovering and managing the network scorer/recommendation application.
+ *
+ * @hide
+ */
+@VisibleForTesting
+public class NetworkScorerAppManager {
+    private static final String TAG = "NetworkScorerAppManager";
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+    private final Context mContext;
+    private final SettingsFacade mSettingsFacade;
+
+    public NetworkScorerAppManager(Context context) {
+      this(context, new SettingsFacade());
+    }
+
+    @VisibleForTesting
+    public NetworkScorerAppManager(Context context, SettingsFacade settingsFacade) {
+        mContext = context;
+        mSettingsFacade = settingsFacade;
+    }
+
+    /**
+     * Returns the list of available scorer apps. The list will be empty if there are
+     * no valid scorers.
+     */
+    @VisibleForTesting
+    public List<NetworkScorerAppData> getAllValidScorers() {
+        if (VERBOSE) Log.v(TAG, "getAllValidScorers()");
+        final PackageManager pm = mContext.getPackageManager();
+        final Intent serviceIntent = new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS);
+        final List<ResolveInfo> resolveInfos =
+                pm.queryIntentServices(serviceIntent, PackageManager.GET_META_DATA);
+        if (resolveInfos == null || resolveInfos.isEmpty()) {
+            if (DEBUG) Log.d(TAG, "Found 0 Services able to handle " + serviceIntent);
+            return Collections.emptyList();
+        }
+
+        List<NetworkScorerAppData> appDataList = new ArrayList<>();
+        for (int i = 0; i < resolveInfos.size(); i++) {
+            final ServiceInfo serviceInfo = resolveInfos.get(i).serviceInfo;
+            if (hasPermissions(serviceInfo.packageName)) {
+                if (VERBOSE) {
+                    Log.v(TAG, serviceInfo.packageName + " is a valid scorer/recommender.");
+                }
+                final ComponentName serviceComponentName =
+                        new ComponentName(serviceInfo.packageName, serviceInfo.name);
+                final String serviceLabel = getRecommendationServiceLabel(serviceInfo, pm);
+                final ComponentName useOpenWifiNetworksActivity =
+                        findUseOpenWifiNetworksActivity(serviceInfo);
+                appDataList.add(
+                        new NetworkScorerAppData(serviceInfo.applicationInfo.uid,
+                                serviceComponentName, serviceLabel, useOpenWifiNetworksActivity));
+            } else {
+                if (VERBOSE) Log.v(TAG, serviceInfo.packageName
+                        + " is NOT a valid scorer/recommender.");
+            }
+        }
+
+        return appDataList;
+    }
+
+    @Nullable
+    private String getRecommendationServiceLabel(ServiceInfo serviceInfo, PackageManager pm) {
+        if (serviceInfo.metaData != null) {
+            final String label = serviceInfo.metaData
+                    .getString(NetworkScoreManager.RECOMMENDATION_SERVICE_LABEL_META_DATA);
+            if (!TextUtils.isEmpty(label)) {
+                return label;
+            }
+        }
+        CharSequence label = serviceInfo.loadLabel(pm);
+        return label == null ? null : label.toString();
+    }
+
+    @Nullable
+    private ComponentName findUseOpenWifiNetworksActivity(ServiceInfo serviceInfo) {
+        if (serviceInfo.metaData == null) {
+            if (DEBUG) {
+                Log.d(TAG, "No metadata found on " + serviceInfo.getComponentName());
+            }
+            return null;
+        }
+        final String useOpenWifiPackage = serviceInfo.metaData
+                .getString(NetworkScoreManager.USE_OPEN_WIFI_PACKAGE_META_DATA);
+        if (TextUtils.isEmpty(useOpenWifiPackage)) {
+            if (DEBUG) {
+                Log.d(TAG, "No use_open_wifi_package metadata found on "
+                        + serviceInfo.getComponentName());
+            }
+            return null;
+        }
+        final Intent enableUseOpenWifiIntent = new Intent(NetworkScoreManager.ACTION_CUSTOM_ENABLE)
+                .setPackage(useOpenWifiPackage);
+        final ResolveInfo resolveActivityInfo = mContext.getPackageManager()
+                .resolveActivity(enableUseOpenWifiIntent, 0 /* flags */);
+        if (VERBOSE) {
+            Log.d(TAG, "Resolved " + enableUseOpenWifiIntent + " to " + resolveActivityInfo);
+        }
+
+        if (resolveActivityInfo != null && resolveActivityInfo.activityInfo != null) {
+            return resolveActivityInfo.activityInfo.getComponentName();
+        }
+
+        return null;
+    }
+
+    /**
+     * Get the application to use for scoring networks.
+     *
+     * @return the scorer app info or null if scoring is disabled (including if no scorer was ever
+     *     selected) or if the previously-set scorer is no longer a valid scorer app (e.g. because
+     *     it was disabled or uninstalled).
+     */
+    @Nullable
+    @VisibleForTesting
+    public NetworkScorerAppData getActiveScorer() {
+        final int enabledSetting = getNetworkRecommendationsEnabledSetting();
+        if (enabledSetting == NetworkScoreManager.RECOMMENDATIONS_ENABLED_FORCED_OFF) {
+            return null;
+        }
+
+        return getScorer(getNetworkRecommendationsPackage());
+    }
+
+    private NetworkScorerAppData getScorer(String packageName) {
+        if (TextUtils.isEmpty(packageName)) {
+            return null;
+        }
+
+        // Otherwise return the recommendation provider (which may be null).
+        List<NetworkScorerAppData> apps = getAllValidScorers();
+        for (int i = 0; i < apps.size(); i++) {
+            NetworkScorerAppData app = apps.get(i);
+            if (app.getRecommendationServicePackageName().equals(packageName)) {
+                return app;
+            }
+        }
+
+        return null;
+    }
+
+    private boolean hasPermissions(String packageName) {
+        final PackageManager pm = mContext.getPackageManager();
+        return pm.checkPermission(permission.SCORE_NETWORKS, packageName)
+                == PackageManager.PERMISSION_GRANTED;
+    }
+
+    /**
+     * Set the specified package as the default scorer application.
+     *
+     * <p>The caller must have permission to write to {@link Settings.Global}.
+     *
+     * @param packageName the packageName of the new scorer to use. If null, the scoring app will
+     *                    revert back to the configured default. Otherwise, the scorer will only
+     *                    be set if it is a valid scorer application.
+     * @return true if the scorer was changed, or false if the package is not a valid scorer or
+     *         a valid network recommendation provider exists.
+     */
+    @VisibleForTesting
+    public boolean setActiveScorer(String packageName) {
+        final String oldPackageName = getNetworkRecommendationsPackage();
+
+        if (TextUtils.equals(oldPackageName, packageName)) {
+            // No change.
+            return true;
+        }
+
+        if (packageName == null) {
+            // revert to the default setting.
+            packageName = getDefaultPackageSetting();
+        }
+
+        Log.i(TAG, "Changing network scorer from " + oldPackageName + " to " + packageName);
+
+        // We only make the change if the new package is valid.
+        if (getScorer(packageName) != null) {
+            setNetworkRecommendationsPackage(packageName);
+            return true;
+        } else {
+            Log.w(TAG, "Requested network scorer is not valid: " + packageName);
+            return false;
+        }
+    }
+
+    /**
+     * Ensures the {@link Settings.Global#NETWORK_RECOMMENDATIONS_PACKAGE} setting points to a valid
+     * package and {@link Settings.Global#NETWORK_RECOMMENDATIONS_ENABLED} is consistent.
+     *
+     * If {@link Settings.Global#NETWORK_RECOMMENDATIONS_PACKAGE} doesn't point to a valid package
+     * then it will be reverted to the default package specified by
+     * {@link R.string#config_defaultNetworkRecommendationProviderPackage}. If the default package
+     * is no longer valid then {@link Settings.Global#NETWORK_RECOMMENDATIONS_ENABLED} will be set
+     * to <code>0</code> (disabled).
+     */
+    @VisibleForTesting
+    public void updateState() {
+        final int enabledSetting = getNetworkRecommendationsEnabledSetting();
+        if (enabledSetting == NetworkScoreManager.RECOMMENDATIONS_ENABLED_FORCED_OFF) {
+            // Don't change anything if it's forced off.
+            if (DEBUG) Log.d(TAG, "Recommendations forced off.");
+            return;
+        }
+
+        // First, see if the current package is still valid. If so, then we can exit early.
+        final String currentPackageName = getNetworkRecommendationsPackage();
+        if (getScorer(currentPackageName) != null) {
+            if (VERBOSE) Log.v(TAG, currentPackageName + " is the active scorer.");
+            setNetworkRecommendationsEnabledSetting(NetworkScoreManager.RECOMMENDATIONS_ENABLED_ON);
+            return;
+        }
+
+        // the active scorer isn't valid, revert to the default if it's different
+        final String defaultPackageName = getDefaultPackageSetting();
+        if (!TextUtils.equals(currentPackageName, defaultPackageName)) {
+            setNetworkRecommendationsPackage(defaultPackageName);
+            if (DEBUG) {
+                Log.d(TAG, "Defaulted the network recommendations app to: " + defaultPackageName);
+            }
+            if (getScorer(defaultPackageName) != null) { // the default is valid
+                if (DEBUG) Log.d(TAG, defaultPackageName + " is now the active scorer.");
+                setNetworkRecommendationsEnabledSetting(
+                        NetworkScoreManager.RECOMMENDATIONS_ENABLED_ON);
+            } else { // the default isn't valid either, we're disabled at this point
+                if (DEBUG) Log.d(TAG, defaultPackageName + " is not an active scorer.");
+                setNetworkRecommendationsEnabledSetting(
+                        NetworkScoreManager.RECOMMENDATIONS_ENABLED_OFF);
+            }
+        }
+    }
+
+    private String getDefaultPackageSetting() {
+        return mContext.getResources().getString(
+                R.string.config_defaultNetworkRecommendationProviderPackage);
+    }
+
+    private String getNetworkRecommendationsPackage() {
+        return mSettingsFacade.getString(mContext, Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE);
+    }
+
+    private void setNetworkRecommendationsPackage(String packageName) {
+        mSettingsFacade.putString(mContext,
+                Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, packageName);
+    }
+
+    private int getNetworkRecommendationsEnabledSetting() {
+        return mSettingsFacade.getInt(mContext, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0);
+    }
+
+    private void setNetworkRecommendationsEnabledSetting(int value) {
+        mSettingsFacade.putInt(mContext,
+                Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, value);
+    }
+
+    /**
+     * Wrapper around Settings to make testing easier.
+     */
+    public static class SettingsFacade {
+        public boolean putString(Context context, String name, String value) {
+            return Settings.Global.putString(context.getContentResolver(), name, value);
+        }
+
+        public String getString(Context context, String name) {
+            return Settings.Global.getString(context.getContentResolver(), name);
+        }
+
+        public boolean putInt(Context context, String name, int value) {
+            return Settings.Global.putInt(context.getContentResolver(), name, value);
+        }
+
+        public int getInt(Context context, String name, int defaultValue) {
+            return Settings.Global.getInt(context.getContentResolver(), name, defaultValue);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/RescueParty.java b/services/core/java/com/android/server/RescueParty.java
index c77a407..480b08a 100644
--- a/services/core/java/com/android/server/RescueParty.java
+++ b/services/core/java/com/android/server/RescueParty.java
@@ -19,9 +19,8 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.pm.UserInfo;
-import android.os.BatteryManager;
-import android.os.BatteryManagerInternal;
 import android.os.Build;
+import android.os.FileUtils;
 import android.os.RecoverySystem;
 import android.os.SystemClock;
 import android.os.SystemProperties;
@@ -36,6 +35,8 @@
 
 import com.android.internal.util.ArrayUtils;
 
+import java.io.File;
+
 /**
  * Utilities to help rescue the system from crash loops. Callers are expected to
  * report boot events and persistent app crashes, and if they happen frequently
@@ -66,24 +67,26 @@
 
     private static boolean isDisabled() {
         // We're disabled on all engineering devices
-        if (Build.IS_ENG) return true;
+        if (Build.IS_ENG) {
+            Slog.v(TAG, "Disabled because of eng build");
+            return true;
+        }
 
         // We're disabled on userdebug devices connected over USB, since that's
         // a decent signal that someone is actively trying to debug the device,
         // or that it's in a lab environment.
-        if (Build.IS_USERDEBUG) {
-            try {
-                if (LocalServices.getService(BatteryManagerInternal.class)
-                        .getPlugType() == BatteryManager.BATTERY_PLUGGED_USB) {
-                    return true;
-                } else {
-                }
-            } catch (Throwable ignored) {
-            }
+        if (Build.IS_USERDEBUG && isUsbActive()) {
+            Slog.v(TAG, "Disabled because of active USB connection");
+            return true;
         }
 
         // One last-ditch check
-        return SystemProperties.getBoolean(PROP_DISABLE_RESCUE, false);
+        if (SystemProperties.getBoolean(PROP_DISABLE_RESCUE, false)) {
+            Slog.v(TAG, "Disabled because of manual property");
+            return true;
+        }
+
+        return false;
     }
 
     /**
@@ -185,14 +188,14 @@
         final ContentResolver resolver = context.getContentResolver();
         try {
             Settings.Global.resetToDefaultsAsUser(resolver, null, mode, UserHandle.USER_SYSTEM);
-        } catch (Exception e) {
-            res = new RuntimeException("Failed to reset global settings", e);
+        } catch (Throwable t) {
+            res = new RuntimeException("Failed to reset global settings", t);
         }
         for (int userId : getAllUserIds(context)) {
             try {
                 Settings.Secure.resetToDefaultsAsUser(resolver, null, mode, userId);
-            } catch (Exception e) {
-                res = new RuntimeException("Failed to reset secure settings for " + userId, e);
+            } catch (Throwable t) {
+                res = new RuntimeException("Failed to reset secure settings for " + userId, t);
             }
         }
         if (res != null) {
@@ -314,6 +317,21 @@
         return userIds;
     }
 
+    /**
+     * Hacky test to check if the device has an active USB connection, which is
+     * a good proxy for someone doing local development work.
+     */
+    private static boolean isUsbActive() {
+        try {
+            final String state = FileUtils
+                    .readTextFile(new File("/sys/class/android_usb/android0/state"), 128, "");
+            return "CONFIGURED".equals(state.trim());
+        } catch (Throwable t) {
+            Slog.w(TAG, "Failed to determine if device was on USB", t);
+            return false;
+        }
+    }
+
     private static String levelToString(int level) {
         switch (level) {
             case LEVEL_NONE: return "NONE";
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 0415971..32136bb 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -70,13 +70,13 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.storage.DiskInfo;
-import android.os.storage.IStorageEventListener;
-import android.os.storage.IStorageShutdownObserver;
 import android.os.storage.IObbActionListener;
+import android.os.storage.IStorageEventListener;
 import android.os.storage.IStorageManager;
-import android.os.storage.StorageManagerInternal;
+import android.os.storage.IStorageShutdownObserver;
 import android.os.storage.OnObbStateChangeListener;
 import android.os.storage.StorageManager;
+import android.os.storage.StorageManagerInternal;
 import android.os.storage.StorageResultCode;
 import android.os.storage.StorageVolume;
 import android.os.storage.VolumeInfo;
@@ -109,6 +109,7 @@
 import com.android.server.NativeDaemonConnector.SensitiveArg;
 import com.android.server.pm.PackageManagerService;
 import com.android.server.storage.AppFuseBridge;
+
 import libcore.io.IoUtils;
 import libcore.util.EmptyArray;
 
@@ -3293,14 +3294,69 @@
     }
 
     @Override
-    public long getAllocatableBytes(String path, int flags) {
-        return new File(path).getUsableSpace();
+    public long getAllocatableBytes(String volumeUuid, int flags) {
+        final StorageManager storage = mContext.getSystemService(StorageManager.class);
+        final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
+
+        final boolean aggressive = (flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0;
+        if (aggressive) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.ALLOCATE_AGGRESSIVE, TAG);
+        }
+
+        final long token = Binder.clearCallingIdentity();
+        try {
+            // In general, apps can allocate as much space as they want, except
+            // we never let them eat into either the minimum cache space or into
+            // the low disk warning space.
+            final File path = storage.findPathForUuid(volumeUuid);
+            if (stats.isQuotaSupported(volumeUuid)) {
+                if (aggressive) {
+                    return Math.max(0,
+                            stats.getFreeBytes(volumeUuid) - storage.getStorageFullBytes(path));
+                } else {
+                    return Math.max(0,
+                            stats.getFreeBytes(volumeUuid) - storage.getStorageLowBytes(path)
+                                    - storage.getStorageCacheBytes(path));
+                }
+            } else {
+                // When we don't have fast quota information, we ignore cached
+                // data and only consider unused bytes.
+                if (aggressive) {
+                    return Math.max(0, path.getUsableSpace() - storage.getStorageFullBytes(path));
+                } else {
+                    return Math.max(0, path.getUsableSpace() - storage.getStorageLowBytes(path));
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     @Override
-    public void allocateBytes(String path, long bytes, int flags) {
-        if (bytes > new File(path).getUsableSpace()) {
-            throw new ParcelableException(new IOException("Not enough usable space"));
+    public void allocateBytes(String volumeUuid, long bytes, int flags) {
+        final StorageManager storage = mContext.getSystemService(StorageManager.class);
+
+        // This method call will enforce FLAG_ALLOCATE_AGGRESSIVE permissions so
+        // we don't have to enforce them locally
+        final long allocatableBytes = getAllocatableBytes(volumeUuid, flags);
+        if (bytes > allocatableBytes) {
+            throw new ParcelableException(new IOException("Failed to allocate " + bytes
+                    + " because only " + allocatableBytes + " allocatable"));
+        }
+
+        // Free up enough disk space to satisfy both the requested allocation
+        // and our low disk warning space.
+        final File path = storage.findPathForUuid(volumeUuid);
+        bytes += storage.getStorageLowBytes(path);
+
+        final long token = Binder.clearCallingIdentity();
+        try {
+            mPms.freeStorage(volumeUuid, bytes, flags);
+        } catch (IOException e) {
+            throw new ParcelableException(e);
+        } finally {
+            Binder.restoreCallingIdentity(token);
         }
     }
 
diff --git a/services/core/java/com/android/server/SystemService.java b/services/core/java/com/android/server/SystemService.java
index ce3166d..421d5a6 100644
--- a/services/core/java/com/android/server/SystemService.java
+++ b/services/core/java/com/android/server/SystemService.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.os.IBinder;
 import android.os.ServiceManager;
+import android.os.UserManager;
 
 /**
  * The base class for services running in the system process. Override and implement
@@ -133,9 +134,16 @@
     public void onStartUser(int userHandle) {}
 
     /**
-     * Called when an existing user is unlocked. This means the
-     * credential-encrypted storage for that user is now available, and
-     * encryption-aware component filtering is no longer in effect.
+     * Called when an existing user is in the process of being unlocked. This
+     * means the credential-encrypted storage for that user is now available,
+     * and encryption-aware component filtering is no longer in effect.
+     * <p>
+     * While dispatching this event to services, the user is in the
+     * {@code STATE_RUNNING_UNLOCKING} state, and once dispatching is finished
+     * the user will transition into the {@code STATE_RUNNING_UNLOCKED} state.
+     * Code written inside system services should use
+     * {@link UserManager#isUserUnlockingOrUnlocked(int)} to handle both of
+     * these states.
      *
      * @param userHandle The identifier of the user.
      */
diff --git a/services/core/java/com/android/server/SystemServiceManager.java b/services/core/java/com/android/server/SystemServiceManager.java
index 3f97d4f..cb13a3d 100644
--- a/services/core/java/com/android/server/SystemServiceManager.java
+++ b/services/core/java/com/android/server/SystemServiceManager.java
@@ -16,6 +16,7 @@
 
 package com.android.server;
 
+import android.annotation.NonNull;
 import android.content.Context;
 import android.os.Trace;
 import android.util.Slog;
@@ -105,22 +106,25 @@
                         + ": service constructor threw an exception", ex);
             }
 
-            // Register it.
-            mServices.add(service);
-
-            // Start it.
-            try {
-                service.onStart();
-            } catch (RuntimeException ex) {
-                throw new RuntimeException("Failed to start service " + name
-                        + ": onStart threw an exception", ex);
-            }
+            startService(service);
             return service;
         } finally {
             Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
         }
     }
 
+    public void startService(@NonNull final SystemService service) {
+        // Register it.
+        mServices.add(service);
+        // Start it.
+        try {
+            service.onStart();
+        } catch (RuntimeException ex) {
+            throw new RuntimeException("Failed to start service " + service.getClass().getName()
+                    + ": onStart threw an exception", ex);
+        }
+    }
+
     /**
      * Starts the specified boot phase for all system services that have been started up to
      * this point.
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index ea33906..531df81 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -57,9 +57,8 @@
 import com.android.internal.telephony.IOnSubscriptionsChangedListener;
 import com.android.internal.telephony.ITelephonyRegistry;
 import com.android.internal.telephony.IPhoneStateListener;
-import com.android.internal.telephony.DefaultPhoneNotifier;
+import com.android.internal.telephony.PhoneConstantConversions;
 import com.android.internal.telephony.PhoneConstants;
-import com.android.internal.telephony.ServiceStateTracker;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.server.am.BatteryStatsService;
 
@@ -171,7 +170,7 @@
 
     private int[] mDataConnectionNetworkType;
 
-    private int mOtaspMode = ServiceStateTracker.OTASP_UNKNOWN;
+    private int mOtaspMode = TelephonyManager.OTASP_UNKNOWN;
 
     private ArrayList<List<CellInfo>> mCellInfo = null;
 
@@ -1497,7 +1496,7 @@
 
         Intent intent = new Intent(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
         intent.putExtra(PhoneConstants.STATE_KEY,
-                DefaultPhoneNotifier.convertCallState(state).toString());
+                PhoneConstantConversions.convertCallState(state).toString());
         if (!TextUtils.isEmpty(incomingNumber)) {
             intent.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber);
         }
@@ -1531,7 +1530,7 @@
         // required info.
         Intent intent = new Intent(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
         intent.putExtra(PhoneConstants.STATE_KEY,
-                DefaultPhoneNotifier.convertDataState(state).toString());
+                PhoneConstantConversions.convertDataState(state).toString());
         if (!isDataConnectivityPossible) {
             intent.putExtra(PhoneConstants.NETWORK_UNAVAILABLE_KEY, true);
         }
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index acacb9e..5115fde 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -58,6 +58,7 @@
 
 import com.android.internal.R;
 import com.android.internal.app.DisableCarModeActivity;
+import com.android.internal.notification.SystemNotificationChannels;
 import com.android.server.power.ShutdownThread;
 import com.android.server.twilight.TwilightListener;
 import com.android.server.twilight.TwilightManager;
@@ -739,7 +740,8 @@
             if (mCarModeEnabled) {
                 Intent carModeOffIntent = new Intent(context, DisableCarModeActivity.class);
 
-                Notification.Builder n = new Notification.Builder(context)
+                Notification.Builder n =
+                        new Notification.Builder(context, SystemNotificationChannels.CAR_MODE)
                         .setSmallIcon(R.drawable.stat_notify_car_mode)
                         .setDefaults(Notification.DEFAULT_LIGHTS)
                         .setOngoing(true)
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 8888325..5fe6952 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -25,6 +25,7 @@
 import android.database.ContentObserver;
 import android.hardware.input.InputManager;
 import android.media.AudioManager;
+import android.os.PowerSaveState;
 import android.os.BatteryStats;
 import android.os.Handler;
 import android.os.IVibratorService;
@@ -50,6 +51,7 @@
 
 import com.android.internal.app.IAppOpsService;
 import com.android.internal.app.IBatteryStats;
+import com.android.server.power.BatterySaverPolicy.ServiceType;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -233,10 +235,15 @@
         mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
         mPowerManagerInternal.registerLowPowerModeObserver(
                 new PowerManagerInternal.LowPowerModeListener() {
-            @Override
-            public void onLowPowerModeChanged(boolean enabled) {
-                updateInputDeviceVibrators();
-            }
+                    @Override
+                    public int getServiceType() {
+                        return ServiceType.VIBRATION;
+                    }
+
+                    @Override
+                    public void onLowPowerModeChanged(PowerSaveState result) {
+                        updateInputDeviceVibrators();
+                    }
         });
 
         mContext.getContentResolver().registerContentObserver(
@@ -553,7 +560,8 @@
                 } catch (SettingNotFoundException snfe) {
                 }
 
-                mLowPowerMode = mPowerManagerInternal.getLowPowerModeEnabled();
+                mLowPowerMode = mPowerManagerInternal
+                        .getLowPowerState(ServiceType.VIBRATION).batterySaverEnabled;
 
                 if (mVibrateInputDevicesSetting) {
                     if (!mInputDeviceListenerRegistered) {
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 5b480d0..0d5a3e0 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -92,6 +92,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.content.PackageMonitor;
+import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
@@ -182,7 +183,8 @@
 
     static {
         ACCOUNTS_CHANGED_INTENT = new Intent(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION);
-        ACCOUNTS_CHANGED_INTENT.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+        ACCOUNTS_CHANGED_INTENT.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
+                | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
     }
 
     private final LinkedHashMap<String, Session> mSessions = new LinkedHashMap<String, Session>();
@@ -287,7 +289,7 @@
                      * and then rebuild the cache. All under the cache lock. But that change is too
                      * large at this point.
                      */
-                    final String removedPackageName = intent.getData().toString();
+                    final String removedPackageName = intent.getData().getSchemeSpecificPart();
                     Runnable purgingRunnable = new Runnable() {
                         @Override
                         public void run() {
@@ -501,10 +503,10 @@
                     UserHandle.getUserId(callingUid));
         } catch (NameNotFoundException e) {
             Log.d(TAG, "Package not found " + e.getMessage());
-            return new HashMap<>();
+            return new LinkedHashMap<>();
         }
 
-        Map<Account, Integer> result = new HashMap<>();
+        Map<Account, Integer> result = new LinkedHashMap<>();
         for (String accountType : accountTypes) {
             synchronized (accounts.cacheLock) {
                 final Account[] accountsOfType = accounts.accountCache.get(accountType);
@@ -1038,7 +1040,7 @@
     private static HashMap<String, Integer> getAuthenticatorTypeAndUIDForUser(
             IAccountAuthenticatorCache authCache,
             int userId) {
-        HashMap<String, Integer> knownAuth = new HashMap<>();
+        HashMap<String, Integer> knownAuth = new LinkedHashMap<>();
         for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> service : authCache
                 .getAllServices(userId)) {
             knownAuth.put(service.type.type, service.uid);
@@ -2779,16 +2781,17 @@
         }
         UserHandle user = UserHandle.of(userId);
         Context contextForUser = getContextForUser(user);
-        Notification n = new Notification.Builder(contextForUser)
-                .setSmallIcon(android.R.drawable.stat_sys_warning)
-                .setWhen(0)
-                .setColor(contextForUser.getColor(
-                        com.android.internal.R.color.system_notification_accent_color))
-                .setContentTitle(title)
-                .setContentText(subtitle)
-                .setContentIntent(PendingIntent.getActivityAsUser(mContext, 0, intent,
-                        PendingIntent.FLAG_CANCEL_CURRENT, null, user))
-                .build();
+        Notification n =
+                new Notification.Builder(contextForUser, SystemNotificationChannels.ACCOUNT)
+                    .setSmallIcon(android.R.drawable.stat_sys_warning)
+                    .setWhen(0)
+                    .setColor(contextForUser.getColor(
+                            com.android.internal.R.color.system_notification_accent_color))
+                    .setContentTitle(title)
+                    .setContentText(subtitle)
+                    .setContentIntent(PendingIntent.getActivityAsUser(mContext, 0, intent,
+                            PendingIntent.FLAG_CANCEL_CURRENT, null, user))
+                    .build();
         installNotification(getCredentialPermissionNotificationId(
                 account, authTokenType, uid), n, packageName, user.getIdentifier());
     }
@@ -3924,7 +3927,7 @@
         List<String> visibleAccountTypes = getTypesVisibleToCaller(callingUid, userId,
                 opPackageName);
         if (visibleAccountTypes.isEmpty()) {
-            return new Account[0];
+            return EMPTY_ACCOUNT_ARRAY;
         }
         long identityToken = clearCallingIdentity();
         try {
@@ -4044,7 +4047,7 @@
                 opPackageName);
         if (visibleAccountTypes.isEmpty()
                 || (type != null && !visibleAccountTypes.contains(type))) {
-            return new Account[]{};
+            return EMPTY_ACCOUNT_ARRAY;
         } else if (visibleAccountTypes.contains(type)) {
             // Prune the list down to just the requested type.
             visibleAccountTypes = new ArrayList<>();
@@ -4191,11 +4194,11 @@
             packageUid = mPackageManager.getPackageUidAsUser(packageName, userId);
         } catch (NameNotFoundException re) {
             Slog.e(TAG, "Couldn't determine the packageUid for " + packageName + re);
-            return new Account[0];
+            return EMPTY_ACCOUNT_ARRAY;
         }
         if (!UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
                 && !isAccountManagedByCaller(type, callingUid, userId)) {
-            return new Account[0];
+            return EMPTY_ACCOUNT_ARRAY;
         }
 
         return getAccountsAsUser(type, userId,
@@ -4226,7 +4229,7 @@
         if (!visibleAccountTypes.contains(type)) {
             Bundle result = new Bundle();
             // Need to return just the accounts that are from matching signatures.
-            result.putParcelableArray(AccountManager.KEY_ACCOUNTS, new Account[0]);
+            result.putParcelableArray(AccountManager.KEY_ACCOUNTS, EMPTY_ACCOUNT_ARRAY);
             try {
                 response.onResult(result);
             } catch (RemoteException e) {
@@ -4843,7 +4846,8 @@
 
                 final String notificationTitleFormat =
                         contextForUser.getText(R.string.notification_title).toString();
-                Notification n = new Notification.Builder(contextForUser)
+                Notification n =
+                        new Notification.Builder(contextForUser, SystemNotificationChannels.ACCOUNT)
                         .setWhen(0)
                         .setSmallIcon(android.R.drawable.stat_sys_warning)
                         .setColor(contextForUser.getColor(
@@ -4863,6 +4867,7 @@
 
     private void installNotification(int notificationId, final Notification notification,
             String packageName, int userId) {
+        SystemNotificationChannels.createAccountChannelForPackage(packageName, mContext);
         final long token = clearCallingIdentity();
         try {
             INotificationManager notificationManager = mInjector.getNotificationManager();
@@ -5363,10 +5368,11 @@
         return newAccountsForType[oldLength];
     }
 
+    @NonNull
     private Account[] filterAccounts(UserAccounts accounts, Account[] unfiltered, int callingUid,
             String callingPackage, boolean includeManagedNotVisible) {
         // filter based on visibility.
-        Map<Account, Integer> firstPass = new HashMap<>();
+        Map<Account, Integer> firstPass = new LinkedHashMap<>();
         for (Account account : unfiltered) {
             int visibility = resolveAccountVisibility(account, callingPackage, accounts);
             if ((visibility == AccountManager.VISIBILITY_VISIBLE
@@ -5385,8 +5391,10 @@
         return filtered;
     }
 
+    @NonNull
     private Map<Account, Integer> filterSharedAccounts(UserAccounts userAccounts,
-            Map<Account, Integer> unfiltered, int callingUid, String callingPackage) {
+            @NonNull Map<Account, Integer> unfiltered, int callingUid,
+            String callingPackage) {
         // first part is to filter shared accounts.
         // unfiltered type check is not necessary.
         if (getUserManager() == null || userAccounts == null || userAccounts.userId < 0
@@ -5436,7 +5444,7 @@
             } catch (NameNotFoundException e) {
                 Log.d(TAG, "Package not found " + e.getMessage());
             }
-            Map<Account, Integer> filtered = new HashMap<>();
+            Map<Account, Integer> filtered = new LinkedHashMap<>();
             for (Map.Entry<Account, Integer> entry : unfiltered.entrySet()) {
                 Account account = entry.getKey();
                 if (account.type.equals(requiredAccountType)) {
@@ -5464,6 +5472,7 @@
      * packageName can be null. If not null, it should be used to filter out restricted accounts
      * that the package is not allowed to access.
      */
+    @NonNull
     protected Account[] getAccountsFromCacheLocked(UserAccounts userAccounts, String accountType,
             int callingUid, String callingPackage, boolean includeManagedNotVisible) {
         if (callingPackage == null) {
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index cec5800..b4f8f61 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -703,27 +703,21 @@
         return false;
     }
 
-    public long setServiceForegroundLocked(ComponentName className, IBinder token,
+    public void setServiceForegroundLocked(ComponentName className, IBinder token,
             int id, Notification notification, int flags) {
         final int userId = UserHandle.getCallingUserId();
         final long origId = Binder.clearCallingIdentity();
         try {
             ServiceRecord r = findServiceLocked(className, token, userId);
             if (r != null) {
-                return setServiceForegroundInnerLocked(r, id, notification, flags);
+                setServiceForegroundInnerLocked(r, id, notification, flags);
             }
-            return ActivityThread.INVALID_PROC_STATE_SEQ;
         } finally {
             Binder.restoreCallingIdentity(origId);
         }
     }
 
-    /**
-     * @return current process state sequence number {@link UidRecord#curProcStateSeq} corresponding
-     *         to the ServiceRecord {@param r} if the calling service has to block until the
-     *         network rules are udpated, Otherwise {@link ActivityThread#INVALID_PROC_STATE_SEQ}.
-     */
-    private long setServiceForegroundInnerLocked(ServiceRecord r, int id,
+    private void setServiceForegroundInnerLocked(ServiceRecord r, int id,
             Notification notification, int flags) {
         if (id != 0) {
             if (notification == null) {
@@ -742,7 +736,7 @@
                         Slog.w(TAG, "Instant app " + r.appInfo.packageName
                                 + " does not have permission to create foreground services"
                                 + ", ignoring.");
-                        return ActivityThread.INVALID_PROC_STATE_SEQ;
+                        return;
                     case AppOpsManager.MODE_ERRORED:
                         throw new SecurityException("Instant app " + r.appInfo.packageName
                                 + " does not have permission to create foreground services");
@@ -770,18 +764,12 @@
             r.foregroundNoti = notification;
             r.isForeground = true;
             r.postNotification();
-            long procStateSeqToReturn = ActivityThread.INVALID_PROC_STATE_SEQ;
             if (r.app != null) {
                 updateServiceForegroundLocked(r.app, true);
-                if (r.app.uidRecord != null &&
-                        r.app.uidRecord.blockState == ActivityThread.NETWORK_STATE_BLOCK) {
-                    procStateSeqToReturn = r.app.uidRecord.curProcStateSeq;
-                }
             }
             getServiceMapLocked(r.userId).ensureNotStartingBackgroundLocked(r);
             mAm.notifyPackageUse(r.serviceInfo.packageName,
                                  PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE);
-            return procStateSeqToReturn;
         } else {
             if (r.isForeground) {
                 r.isForeground = false;
@@ -802,7 +790,6 @@
                 }
             }
         }
-        return ActivityThread.INVALID_PROC_STATE_SEQ;
     }
 
     private void cancelForegroudNotificationLocked(ServiceRecord r) {
@@ -2823,14 +2810,13 @@
     }
 
     List<ActivityManager.RunningServiceInfo> getRunningServiceInfoLocked(int maxNum, int flags,
-        int callingUid, boolean allowed) {
+        int callingUid, boolean allowed, boolean canInteractAcrossUsers) {
         ArrayList<ActivityManager.RunningServiceInfo> res
                 = new ArrayList<ActivityManager.RunningServiceInfo>();
 
         final long ident = Binder.clearCallingIdentity();
         try {
-            if (ActivityManager.checkUidPermission(INTERACT_ACROSS_USERS_FULL, callingUid)
-                == PERMISSION_GRANTED) {
+            if (canInteractAcrossUsers) {
                 int[] users = mAm.mUserController.getUsers();
                 for (int ui=0; ui<users.length && res.size() < maxNum; ui++) {
                     ArrayMap<ComponentName, ServiceRecord> alls = getServicesLocked(users[ui]);
diff --git a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
index 8ed95ee..88e0d03 100644
--- a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
+++ b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
@@ -63,7 +63,6 @@
     static final boolean DEBUG_LOCKTASK = DEBUG_ALL || false;
     static final boolean DEBUG_LRU = DEBUG_ALL || false;
     static final boolean DEBUG_MU = DEBUG_ALL || false;
-    static final boolean DEBUG_NETWORK = DEBUG_ALL || false;
     static final boolean DEBUG_OOM_ADJ = DEBUG_ALL || false;
     static final boolean DEBUG_PAUSE = DEBUG_ALL || false;
     static final boolean DEBUG_POWER = DEBUG_ALL || false;
@@ -108,7 +107,6 @@
     static final String POSTFIX_LOCKTASK = (APPEND_CATEGORY_NAME) ? "_LockTask" : "";
     static final String POSTFIX_LRU = (APPEND_CATEGORY_NAME) ? "_LRU" : "";
     static final String POSTFIX_MU = "_MU";
-    static final String POSTFIX_NETWORK = "_Network";
     static final String POSTFIX_OOM_ADJ = (APPEND_CATEGORY_NAME) ? "_OomAdj" : "";
     static final String POSTFIX_PAUSE = (APPEND_CATEGORY_NAME) ? "_Pause" : "";
     static final String POSTFIX_POWER = (APPEND_CATEGORY_NAME) ? "_Power" : "";
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index aaed0e9..0a65cab 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -42,14 +42,13 @@
 import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.content.res.Configuration.UI_MODE_TYPE_TELEVISION;
-import static android.net.NetworkPolicyManager.isProcStateAllowedWhileIdleOrPowerSaveMode;
-import static android.net.NetworkPolicyManager.isProcStateAllowedWhileRestrictBackgroundOn;
-import static android.net.NetworkPolicyManager.UidStateWithSeqObserver;
 import static android.os.Build.VERSION_CODES.N;
 import static android.os.Process.PROC_CHAR;
 import static android.os.Process.PROC_OUT_LONG;
 import static android.os.Process.PROC_PARENS;
 import static android.os.Process.PROC_SPACE_TERM;
+import static android.net.NetworkPolicyManager.isProcStateAllowedWhileIdleOrPowerSaveMode;
+import static android.net.NetworkPolicyManager.isProcStateAllowedWhileOnRestrictBackground;
 import static android.provider.Settings.Global.ALWAYS_FINISH_ACTIVITIES;
 import static android.provider.Settings.Global.DEBUG_APP;
 import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
@@ -79,7 +78,6 @@
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKTASK;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LRU;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_MU;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_NETWORK;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_POWER;
@@ -109,7 +107,6 @@
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_LOCKTASK;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_LRU;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_MU;
-import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_NETWORK;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_OOM_ADJ;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_POWER;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_PROCESSES;
@@ -138,6 +135,8 @@
 import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
 import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
 import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_PINNABLE;
+import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
+import static com.android.server.am.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
 import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_OPEN;
 import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_RELAUNCH;
 import static com.android.server.wm.AppTransition.TRANSIT_NONE;
@@ -147,6 +146,8 @@
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
 import static org.xmlpull.v1.XmlPullParser.START_TAG;
 
+import static java.lang.Integer.MAX_VALUE;
+
 import android.Manifest;
 import android.Manifest.permission;
 import android.annotation.NonNull;
@@ -319,11 +320,13 @@
 import android.view.View;
 import android.view.WindowManager;
 
+import com.android.internal.notification.SystemNotificationChannels;
 import com.google.android.collect.Lists;
 import com.google.android.collect.Maps;
 
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.AssistUtils;
 import com.android.internal.app.DumpHeapActivity;
 import com.android.internal.app.IAppOpsCallback;
@@ -361,7 +364,6 @@
 import com.android.server.Watchdog;
 import com.android.server.am.ActivityStack.ActivityState;
 import com.android.server.firewall.IntentFirewall;
-import com.android.server.net.NetworkPolicyManagerService;
 import com.android.server.pm.Installer;
 import com.android.server.pm.Installer.InstallerException;
 import com.android.server.statusbar.StatusBarManagerInternal;
@@ -418,7 +420,6 @@
     private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
     private static final String TAG_LRU = TAG + POSTFIX_LRU;
     private static final String TAG_MU = TAG + POSTFIX_MU;
-    private static final String TAG_NETWORK = TAG + POSTFIX_NETWORK;
     private static final String TAG_OOM_ADJ = TAG + POSTFIX_OOM_ADJ;
     private static final String TAG_POWER = TAG + POSTFIX_POWER;
     private static final String TAG_PROCESS_OBSERVERS = TAG + POSTFIX_PROCESS_OBSERVERS;
@@ -605,8 +606,6 @@
     BroadcastStats mLastBroadcastStats;
     BroadcastStats mCurBroadcastStats;
 
-    private UidStateWithSeqObserver mUidStateWithSeqObserver;
-
     BroadcastQueue broadcastQueueForIntent(Intent intent) {
         final boolean isFg = (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0;
         if (DEBUG_BROADCAST_BACKGROUND) Slog.i(TAG_BROADCAST,
@@ -1449,6 +1448,17 @@
 
     private final ArraySet<BroadcastQueue> mTmpBroadcastQueue = new ArraySet();
 
+    /**
+     * A global counter for generating sequence numbers.
+     * This value will be used when incrementing sequence numbers in individual uidRecords.
+     *
+     * Having a global counter ensures that seq numbers are monotonically increasing for a
+     * particular uid even when the uidRecord is re-created.
+     */
+    @GuardedBy("this")
+    @VisibleForTesting
+    long mProcStateSeqCounter = 0;
+
     static final class ProcessChangeItem {
         static final int CHANGE_ACTIVITIES = 1<<0;
         int changes;
@@ -1981,7 +1991,8 @@
                     Context context = mContext.createPackageContext(process.info.packageName, 0);
                     String text = mContext.getString(R.string.heavy_weight_notification,
                             context.getApplicationInfo().loadLabel(context.getPackageManager()));
-                    Notification notification = new Notification.Builder(context)
+                    Notification notification =
+                            new Notification.Builder(context, SystemNotificationChannels.DEVELOPER)
                             .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
                             .setWhen(0)
                             .setOngoing(true)
@@ -2231,7 +2242,8 @@
                     intent.putExtra(DumpHeapActivity.KEY_DIRECT_LAUNCH, reportPackage);
                 }
                 int userId = UserHandle.getUserId(uid);
-                Notification notification = new Notification.Builder(mContext)
+                Notification notification =
+                        new Notification.Builder(mContext, SystemNotificationChannels.DEVELOPER)
                         .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
                         .setWhen(0)
                         .setOngoing(true)
@@ -2612,6 +2624,33 @@
         }
     }
 
+    @VisibleForTesting
+    public ActivityManagerService() {
+        GL_ES_VERSION = 0;
+        mActivityStarter = null;
+        mAppErrors = null;
+        mAppOpsService = null;
+        mBatteryStatsService = null;
+        mCompatModePackages = null;
+        mConstants = null;
+        mGrantFile = null;
+        mHandler = null;
+        mHandlerThread = null;
+        mIntentFirewall = null;
+        mKeyguardController = null;
+        mPermissionReviewRequired = false;
+        mProcessCpuThread = null;
+        mProcessStats = null;
+        mProviderMap = null;
+        mRecentTasks = null;
+        mServices = null;
+        mStackSupervisor = null;
+        mSystemThread = null;
+        mTaskChangeNotificationController = null;
+        mUiHandler = null;
+        mUserController = null;
+    }
+
     // Note: This method is invoked on the main thread but may need to attach various
     // handlers to other threads.  So take care to be explicit about the looper.
     public ActivityManagerService(Context systemContext) {
@@ -3032,15 +3071,24 @@
             startRunningVoiceLocked(r.task.voiceSession, r.info.applicationInfo.uid);
         } else {
             finishRunningVoiceLocked();
-            IVoiceInteractionSession session;
-            if (mLastResumedActivity != null
-                    && ((session = mLastResumedActivity.task.voiceSession) != null
-                    || (session = mLastResumedActivity.voiceSession) != null)) {
-                // We had been in a voice interaction session, but now focused has
-                // move to something different.  Just finish the session, we can't
-                // return to it and retain the proper state and synchronization with
-                // the voice interaction service.
-                finishVoiceTask(session);
+
+            if (mLastResumedActivity != null) {
+                final IVoiceInteractionSession session;
+
+                if (mLastResumedActivity.task != null
+                        && mLastResumedActivity.task.voiceSession != null) {
+                    session = mLastResumedActivity.task.voiceSession;
+                } else {
+                    session = mLastResumedActivity.voiceSession;
+                }
+
+                if (session != null) {
+                    // We had been in a voice interaction session, but now focused has
+                    // move to something different.  Just finish the session, we can't
+                    // return to it and retain the proper state and synchronization with
+                    // the voice interaction service.
+                    finishVoiceTask(session);
+                }
             }
         }
 
@@ -4113,13 +4161,9 @@
         synchronized (this) {
             for (int i=mLruProcesses.size()-1; i>=0; i--) {
                 final ProcessRecord proc = mLruProcesses.get(i);
-                if (procState == ActivityManager.PROCESS_STATE_NONEXISTENT
-                        || procState > proc.setProcState) {
-                    if (proc.pkgList.containsKey(packageName)) {
-                        procState = proc.setProcState;
-                        break;
-                    }
-                    if (proc.pkgDeps != null && proc.pkgDeps.contains(packageName)) {
+                if (procState > proc.setProcState) {
+                    if (proc.pkgList.containsKey(packageName) ||
+                            (proc.pkgDeps != null && proc.pkgDeps.contains(packageName))) {
                         procState = proc.setProcState;
                     }
                 }
@@ -4231,25 +4275,6 @@
                     "*** Delivering " + N + " uid changes");
         }
 
-        if (mUidStateWithSeqObserver != null) {
-            final int registeredCallbackCount = mUidObservers.getRegisteredCallbackCount();
-            for (int i = 0; i < N; ++i) {
-                final UidRecord.ChangeItem item = mActiveUidChanges[i];
-                if (item.change == UidRecord.CHANGE_PROCSTATE) {
-                    mUidStateWithSeqObserver.onUidStateChangedWithSeq(
-                            item.uid, item.processState, item.procStateSeq);
-                    if (VALIDATE_UID_STATES && registeredCallbackCount == 0) {
-                        UidRecord validateUid = mValidateUids.get(item.uid);
-                        if (validateUid == null) {
-                            validateUid = new UidRecord(item.uid);
-                            mValidateUids.put(item.uid, validateUid);
-                        }
-                        validateUid.curProcState = validateUid.setProcState = item.processState;
-                    }
-                }
-            }
-        }
-
         int i = mUidObservers.beginBroadcast();
         while (i > 0) {
             i--;
@@ -7722,7 +7747,7 @@
                             aspectRatio);
                     mStackSupervisor.moveActivityToPinnedStackLocked(r, "enterPictureInPictureMode",
                             bounds, true /* moveHomeStackToFront */);
-                    final ActivityStack stack = mStackSupervisor.getStack(PINNED_STACK_ID);
+                    final PinnedActivityStack stack = mStackSupervisor.getStack(PINNED_STACK_ID);
                     stack.setPictureInPictureAspectRatio(aspectRatio);
                     stack.setPictureInPictureActions(actions);
 
@@ -7776,9 +7801,9 @@
 
                 // Only update the saved args from the args that are set
                 r.pictureInPictureArgs.copyOnlySet(args);
-                final ActivityStack stack = r.getStack();
-                if (stack.getStackId() == PINNED_STACK_ID) {
+                if (r.getStack().getStackId() == PINNED_STACK_ID) {
                     // If the activity is already in picture-in-picture, update the pinned stack now
+                    final PinnedActivityStack stack = r.getStack();
                     stack.setPictureInPictureAspectRatio(r.pictureInPictureArgs.getAspectRatio());
                     stack.setPictureInPictureActions(r.pictureInPictureArgs.getActions());
                 }
@@ -9787,14 +9812,19 @@
                 } else if (bounds != null && stackId != FREEFORM_WORKSPACE_STACK_ID ) {
                     stackId = FREEFORM_WORKSPACE_STACK_ID;
                 }
+
+                // Reparent the task to the right stack if necessary
                 boolean preserveWindow = (resizeMode & RESIZE_MODE_PRESERVE_WINDOW) != 0;
                 if (stackId != task.getStackId()) {
-                    mStackSupervisor.moveTaskToStackUncheckedLocked(task, stackId, ON_TOP,
-                            !FORCE_FOCUS, "resizeTask");
+                    // Defer resume until the task is resized below
+                    task.reparent(stackId, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, ANIMATE,
+                            DEFER_RESUME, "resizeTask");
                     preserveWindow = false;
                 }
 
-                task.resize(bounds, resizeMode, preserveWindow, false /* deferResume */);
+                // After reparenting (which only resizes the task to the stack bounds), resize the
+                // task to the actual bounds provided
+                task.resize(bounds, resizeMode, preserveWindow, !DEFER_RESUME);
             }
         } finally {
             Binder.restoreCallingIdentity(ident);
@@ -10058,8 +10088,18 @@
     }
 
     /**
-     * Moves an activity, and all of the other activities within the same task, to the bottom
-     * of the history stack.  The activity's order within the task is unchanged.
+     * Attempts to move a task backwards in z-order (the order of activities within the task is
+     * unchanged).
+     *
+     * There are several possible results of this call:
+     * - if the task is locked, then we will show the lock toast
+     * - if there is a task behind the provided task, then that task is made visible and resumed as
+     *   this task is moved to the back
+     * - otherwise, if there are no other tasks in the stack:
+     *     - if this task is in the pinned stack, then we remove the stack completely, which will
+     *       have the effect of moving the task to the top or bottom of the fullscreen stack
+     *       (depending on whether it is visible)
+     *     - otherwise, we simply return home and hide this task
      *
      * @param token A reference to the activity we wish to move
      * @param nonRoot If false then this only works if the activity is the root
@@ -10075,10 +10115,6 @@
                 int taskId = ActivityRecord.getTaskForActivityLocked(token, !nonRoot);
                 final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
                 if (task != null) {
-                    if (mStackSupervisor.isLockedTask(task)) {
-                        mStackSupervisor.showLockTaskToast();
-                        return false;
-                    }
                     return ActivityRecord.getStackLocked(token).moveTaskToBackLocked(taskId);
                 }
             } finally {
@@ -10173,14 +10209,16 @@
                     throw new IllegalArgumentException(
                             "exitFreeformMode: No activity record matching token=" + token);
                 }
-                final ActivityStack stack = r.getStackLocked(token);
+
+                final ActivityStack stack = r.getStack();
                 if (stack == null || stack.mStackId != FREEFORM_WORKSPACE_STACK_ID) {
                     throw new IllegalStateException(
                             "exitFreeformMode: You can only go fullscreen from freeform.");
                 }
+
                 if (DEBUG_STACK) Slog.d(TAG_STACK, "exitFreeformMode: " + r);
-                mStackSupervisor.moveTaskToStackLocked(r.task.taskId, FULLSCREEN_WORKSPACE_STACK_ID,
-                        ON_TOP, !FORCE_FOCUS, "exitFreeformMode", ANIMATE);
+                r.task.reparent(FULLSCREEN_WORKSPACE_STACK_ID, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT,
+                        ANIMATE, !DEFER_RESUME, "exitFreeformMode");
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -10197,18 +10235,20 @@
         synchronized (this) {
             long ident = Binder.clearCallingIdentity();
             try {
+                final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
+                if (task == null) {
+                    Slog.w(TAG, "moveTaskToStack: No task for id=" + taskId);
+                    return;
+                }
+
                 if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToStack: moving task=" + taskId
                         + " to stackId=" + stackId + " toTop=" + toTop);
                 if (stackId == DOCKED_STACK_ID) {
                     mWindowManager.setDockedStackCreateState(DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT,
                             null /* initialBounds */);
                 }
-                boolean result = mStackSupervisor.moveTaskToStackLocked(taskId, stackId, toTop,
-                        !FORCE_FOCUS, "moveTaskToStack", ANIMATE);
-                if (result && stackId == DOCKED_STACK_ID) {
-                    // If task moved to docked stack - show recents if needed.
-                    mWindowManager.showRecentApps(false /* fromHome */);
-                }
+                task.reparent(stackId, toTop,
+                        REPARENT_KEEP_STACK_AT_FRONT, ANIMATE, !DEFER_RESUME, "moveTaskToStack");
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -10237,22 +10277,23 @@
                 // TODO: App transition
                 mWindowManager.prepareAppTransition(TRANSIT_ACTIVITY_RELAUNCH, false);
 
-                // Defer the resume so resume/pausing while moving stacks is dangerous.
-                mStackSupervisor.moveTaskToStackLocked(topTask.taskId, DOCKED_STACK_ID,
-                        false /* toTop */, !FORCE_FOCUS, "swapDockedAndFullscreenStack",
-                        ANIMATE, true /* deferResume */);
+                // Defer the resume until we move all the docked tasks to the fullscreen stack below
+                topTask.reparent(DOCKED_STACK_ID, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, ANIMATE,
+                        DEFER_RESUME, "swapDockedAndFullscreenStack - DOCKED_STACK");
                 final int size = tasks.size();
                 for (int i = 0; i < size; i++) {
                     final int id = tasks.get(i).taskId;
                     if (id == topTask.taskId) {
                         continue;
                     }
-                    mStackSupervisor.moveTaskToStackLocked(id,
-                            FULLSCREEN_WORKSPACE_STACK_ID, true /* toTop */, !FORCE_FOCUS,
-                            "swapDockedAndFullscreenStack", ANIMATE, true /* deferResume */);
+
+                    // Defer the resume until after all the tasks have been moved
+                    tasks.get(i).reparent(FULLSCREEN_WORKSPACE_STACK_ID, ON_TOP,
+                            REPARENT_KEEP_STACK_AT_FRONT, ANIMATE, DEFER_RESUME,
+                            "swapDockedAndFullscreenStack - FULLSCREEN_STACK");
                 }
 
-                // Because we deferred the resume, to avoid conflicts with stack switches while
+                // Because we deferred the resume to avoid conflicts with stack switches while
                 // resuming, we need to do it after all the tasks are moved.
                 mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
                 mStackSupervisor.resumeFocusedStackTopActivityLocked();
@@ -10280,21 +10321,26 @@
      */
     @Override
     public boolean moveTaskToDockedStack(int taskId, int createMode, boolean toTop, boolean animate,
-            Rect initialBounds, boolean moveHomeStackFront) {
+            Rect initialBounds) {
         enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "moveTaskToDockedStack()");
         synchronized (this) {
             long ident = Binder.clearCallingIdentity();
             try {
+                final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
+                if (task == null) {
+                    Slog.w(TAG, "moveTaskToDockedStack: No task for id=" + taskId);
+                    return false;
+                }
+
                 if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToDockedStack: moving task=" + taskId
                         + " to createMode=" + createMode + " toTop=" + toTop);
                 mWindowManager.setDockedStackCreateState(createMode, initialBounds);
-                final boolean moved = mStackSupervisor.moveTaskToStackLocked(
-                        taskId, DOCKED_STACK_ID, toTop, !FORCE_FOCUS, "moveTaskToDockedStack",
-                        animate, DEFER_RESUME);
+
+                // Defer resuming until we move the home stack to the front below
+                final boolean moved = task.reparent(DOCKED_STACK_ID, toTop,
+                        REPARENT_KEEP_STACK_AT_FRONT, animate, !DEFER_RESUME,
+                        "moveTaskToDockedStack");
                 if (moved) {
-                    if (moveHomeStackFront) {
-                        mStackSupervisor.moveHomeStackToFront("moveTaskToDockedStack");
-                    }
                     mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
                 }
                 return moved;
@@ -10319,7 +10365,7 @@
         synchronized (this) {
             if (!mSupportsPictureInPicture) {
                 throw new IllegalStateException("moveTopActivityToPinnedStack:"
-                        + "Device doesn't support picture-in-pciture mode");
+                        + "Device doesn't support picture-in-picture mode");
             }
 
             long ident = Binder.clearCallingIdentity();
@@ -10340,7 +10386,7 @@
             synchronized (this) {
                 if (animate) {
                     if (stackId == PINNED_STACK_ID) {
-                        final ActivityStack pinnedStack =
+                        final PinnedActivityStack pinnedStack =
                                 mStackSupervisor.getStack(PINNED_STACK_ID);
                         pinnedStack.animateResizePinnedStack(bounds, animationDuration);
                     } else {
@@ -10424,7 +10470,8 @@
                     stack.positionChildAt(task, position);
                 } else {
                     // Reparent to new stack.
-                    task.reparent(stackId, position, "positionTaskInStack");
+                    task.reparent(stackId, position, REPARENT_LEAVE_STACK_IN_PLACE,
+                            !ANIMATE, !DEFER_RESUME, "positionTaskInStack");
                 }
             } finally {
                 Binder.restoreCallingIdentity(ident);
@@ -10664,7 +10711,7 @@
             providers = AppGlobals.getPackageManager()
                     .queryContentProviders(app.processName, app.uid,
                             STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS
-                                    | MATCH_DEBUG_TRIAGED_MISSING)
+                                    | MATCH_DEBUG_TRIAGED_MISSING, /*metadastaKey=*/ null)
                     .getList();
         } catch (RemoteException ex) {
         }
@@ -10730,16 +10777,14 @@
         try {
             cpi = AppGlobals.getPackageManager().resolveContentProvider(authority,
                     STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS
+                            | PackageManager.MATCH_DISABLED_COMPONENTS
                             | PackageManager.MATCH_DIRECT_BOOT_AWARE
                             | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
                     userId);
         } catch (RemoteException ignored) {
         }
         if (cpi == null) {
-            // TODO: make this an outright failure in a future platform release;
-            // until then anonymous content notifications are unprotected
-            //return "Failed to find provider " + authority + " for user " + userId;
-            return null;
+            return "Failed to find provider " + authority + " for user " + userId;
         }
 
         ProcessRecord r = null;
@@ -12064,6 +12109,12 @@
         mRecentTasks.notifyTaskPersisterLocked(task, flush);
     }
 
+    /** Notifies all listeners when the pinned stack animation starts. */
+    @Override
+    public void notifyPinnedStackAnimationStarted() {
+        mTaskChangeNotificationController.notifyPinnedStackAnimationStarted();
+    }
+
     /** Notifies all listeners when the pinned stack animation ends. */
     @Override
     public void notifyPinnedStackAnimationEnded() {
@@ -14416,7 +14467,8 @@
         boolean dumpClient = false;
         boolean dumpCheckin = false;
         boolean dumpCheckinFormat = false;
-        boolean dumpVisibleStacks = false;
+        boolean dumpVisibleStacksOnly = false;
+        boolean dumpFocusedStackOnly = false;
         String dumpPackage = null;
 
         int opti = 0;
@@ -14431,7 +14483,9 @@
             } else if ("-c".equals(opt)) {
                 dumpClient = true;
             } else if ("-v".equals(opt)) {
-                dumpVisibleStacks = true;
+                dumpVisibleStacksOnly = true;
+            } else if ("-f".equals(opt)) {
+                dumpFocusedStackOnly = true;
             } else if ("-p".equals(opt)) {
                 if (opti < args.length) {
                     dumpPackage = args[opti];
@@ -14622,7 +14676,8 @@
                 LockGuard.dump(fd, pw, args);
             } else {
                 // Dumping a single activity?
-                if (!dumpActivity(fd, pw, cmd, args, opti, dumpAll, dumpVisibleStacks)) {
+                if (!dumpActivity(fd, pw, cmd, args, opti, dumpAll, dumpVisibleStacksOnly,
+                        dumpFocusedStackOnly)) {
                     ActivityManagerShellCommand shell = new ActivityManagerShellCommand(this, true);
                     int res = shell.exec(this, null, fd, null, args, null,
                             new ResultReceiver(null));
@@ -15561,13 +15616,17 @@
      *  - the cmd arg isn't the flattened component name of an existing activity:
      *    dump all activity whose component contains the cmd as a substring
      *  - A hex number of the ActivityRecord object instance.
+     *
+     *  @param dumpVisibleStacksOnly dump activity with {@param name} only if in a visible stack
+     *  @param dumpFocusedStackOnly dump activity with {@param name} only if in the focused stack
      */
     protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
-            int opti, boolean dumpAll, boolean dumpVisibleStacks) {
+            int opti, boolean dumpAll, boolean dumpVisibleStacksOnly, boolean dumpFocusedStackOnly) {
         ArrayList<ActivityRecord> activities;
 
         synchronized (this) {
-            activities = mStackSupervisor.getDumpActivitiesLocked(name, dumpVisibleStacks);
+            activities = mStackSupervisor.getDumpActivitiesLocked(name, dumpVisibleStacksOnly,
+                    dumpFocusedStackOnly);
         }
 
         if (activities.size() <= 0) {
@@ -17527,12 +17586,15 @@
     public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
             int flags) {
         enforceNotIsolatedCaller("getServices");
-        synchronized (this) {
-            final int callingUid = Binder.getCallingUid();
-            final boolean allowed = isGetTasksAllowed("getServices", Binder.getCallingPid(),
-                callingUid);
 
-            return mServices.getRunningServiceInfoLocked(maxNum, flags, callingUid, allowed);
+        final int callingUid = Binder.getCallingUid();
+        final boolean canInteractAcrossUsers = (ActivityManager.checkUidPermission(
+            INTERACT_ACROSS_USERS_FULL, callingUid) == PERMISSION_GRANTED);
+        final boolean allowed = isGetTasksAllowed("getServices", Binder.getCallingPid(),
+            callingUid);
+        synchronized (this) {
+            return mServices.getRunningServiceInfoLocked(maxNum, flags, callingUid,
+                allowed, canInteractAcrossUsers);
         }
     }
 
@@ -17626,16 +17688,11 @@
         }
     }
 
-    /**
-     * Returns sequence number associated with the current process state change if the service
-     * coming to the foreground needs to block for network before proceeding, otherwise
-     * {@link ActivityThread#INVALID_PROC_STATE_SEQ}.
-     */
     @Override
-    public long setServiceForeground(ComponentName className, IBinder token,
+    public void setServiceForeground(ComponentName className, IBinder token,
             int id, Notification notification, int flags) {
         synchronized(this) {
-            return mServices.setServiceForegroundLocked(className, token, id, notification, flags);
+            mServices.setServiceForegroundLocked(className, token, id, notification, flags);
         }
     }
 
@@ -18058,15 +18115,18 @@
             } else if (rl.uid != callingUid) {
                 throw new IllegalArgumentException(
                         "Receiver requested to register for uid " + callingUid
-                        + " was previously registered for uid " + rl.uid);
+                        + " was previously registered for uid " + rl.uid
+                        + " callerPackage is " + callerPackage);
             } else if (rl.pid != callingPid) {
                 throw new IllegalArgumentException(
                         "Receiver requested to register for pid " + callingPid
-                        + " was previously registered for pid " + rl.pid);
+                        + " was previously registered for pid " + rl.pid
+                        + " callerPackage is " + callerPackage);
             } else if (rl.userId != userId) {
                 throw new IllegalArgumentException(
                         "Receiver requested to register for user " + userId
-                        + " was previously registered for user " + rl.userId);
+                        + " was previously registered for user " + rl.userId
+                        + " callerPackage is " + callerPackage);
             }
             BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
                     permission, callingUid, userId);
@@ -18803,7 +18863,7 @@
         final boolean replacePending =
                 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
 
-        if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueing broadcast: " + intent.getAction()
+        if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing broadcast: " + intent.getAction()
                 + " replacePending=" + replacePending);
 
         int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
@@ -18821,7 +18881,9 @@
                     appOp, brOptions, registeredReceivers, resultTo, resultCode, resultData,
                     resultExtras, ordered, sticky, false, userId);
             if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing parallel broadcast " + r);
-            final boolean replaced = replacePending && queue.replaceParallelBroadcastLocked(r);
+            final boolean replaced = replacePending
+                    && (queue.replaceParallelBroadcastLocked(r) != null);
+            // Note: We assume resultTo is null for non-ordered broadcasts.
             if (!replaced) {
                 queue.enqueueParallelBroadcastLocked(r);
                 queue.scheduleBroadcastsLocked();
@@ -18920,8 +18982,25 @@
             if (DEBUG_BROADCAST) Slog.i(TAG_BROADCAST,
                     "Enqueueing broadcast " + r.intent.getAction());
 
-            boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r);
-            if (!replaced) {
+            final BroadcastRecord oldRecord =
+                    replacePending ? queue.replaceOrderedBroadcastLocked(r) : null;
+            if (oldRecord != null) {
+                // Replaced, fire the result-to receiver.
+                if (oldRecord.resultTo != null) {
+                    final BroadcastQueue oldQueue = broadcastQueueForIntent(oldRecord.intent);
+                    try {
+                        oldQueue.performReceiveLocked(oldRecord.callerApp, oldRecord.resultTo,
+                                oldRecord.intent,
+                                Activity.RESULT_CANCELED, null, null,
+                                false, false, oldRecord.userId);
+                    } catch (RemoteException e) {
+                        Slog.w(TAG, "Failure ["
+                                + queue.mQueueName + "] sending broadcast result of "
+                                + intent, e);
+
+                    }
+                }
+            } else {
                 queue.enqueueOrderedBroadcastLocked(r);
                 queue.scheduleBroadcastsLocked();
             }
@@ -18938,8 +19017,7 @@
         return ActivityManager.BROADCAST_SUCCESS;
     }
 
-    final void addBroadcastStatLocked(String action, String srcPackage, int receiveCount,
-            int skipCount, long dispatchTime) {
+    final void rotateBroadcastStatsIfNeededLocked() {
         final long now = SystemClock.elapsedRealtime();
         if (mCurBroadcastStats == null ||
                 (mCurBroadcastStats.mStartRealtime +(24*60*60*1000) < now)) {
@@ -18950,9 +19028,19 @@
             }
             mCurBroadcastStats = new BroadcastStats();
         }
+    }
+
+    final void addBroadcastStatLocked(String action, String srcPackage, int receiveCount,
+            int skipCount, long dispatchTime) {
+        rotateBroadcastStatsIfNeededLocked();
         mCurBroadcastStats.addBroadcast(action, srcPackage, receiveCount, skipCount, dispatchTime);
     }
 
+    final void addBackgroundCheckViolationLocked(String action, String targetPackage) {
+        rotateBroadcastStatsIfNeededLocked();
+        mCurBroadcastStats.addBackgroundCheckViolation(action, targetPackage);
+    }
+
     final Intent verifyBroadcastLocked(Intent intent) {
         // Refuse possible leaked file descriptors
         if (intent != null && intent.hasFileDescriptors() == true) {
@@ -19111,14 +19199,7 @@
             }
 
             if (doNext) {
-                if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
-                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
-                      String.format("ProcessBroadcast from %s (%s) %s", r.callerPackage,
-                        r.callerApp == null ? "caller unknown" : r.callerApp.toShortString(),
-                        r.intent == null ? "" : r.intent.toString()));
-                }
                 r.queue.processNextBroadcast(false);
-                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
             }
             trimApplications();
         } finally {
@@ -19756,7 +19837,7 @@
         mStackSupervisor.setDisplayOverrideConfiguration(mTempConfig, displayId);
 
         final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0;
-        if (isDensityChange) {
+        if (isDensityChange && displayId == DEFAULT_DISPLAY) {
             // Reset the unsupported display size dialog.
             mUiHandler.sendEmptyMessage(SHOW_UNSUPPORTED_DISPLAY_SIZE_DIALOG_MSG);
 
@@ -21396,7 +21477,6 @@
         pendingChange.processState = uidRec != null
                 ? uidRec.setProcState : ActivityManager.PROCESS_STATE_NONEXISTENT;
         pendingChange.ephemeral = uidRec.ephemeral;
-        pendingChange.procStateSeq = uidRec.curProcStateSeq;
 
         // Directly update the power manager, since we sit on top of it and it is critical
         // it be kept in sync (so wake locks will be held as soon as appropriate).
@@ -21771,31 +21851,7 @@
         }
 
         for (int i = mActiveUids.size() - 1; i >= 0; --i) {
-            final UidRecord uidRec = mActiveUids.valueAt(i);
-            uidRec.shouldNotifyAppThreads = false;
-            if (uidRec.curProcState == uidRec.setProcState) {
-                continue;
-            }
-            final int newBlockState = getUidRecordBlockState(uidRec);
-            // Sequence no. associated with process state change will only be updated if the
-            // process is coming from background to foreground or vice versa.
-            if (newBlockState != uidRec.blockState) {
-                uidRec.blockState = newBlockState;
-                uidRec.curProcStateSeq++;
-                uidRec.appThreadListeners = null;
-                uidRec.shouldNotifyAppThreads = true;
-            }
-        }
-
-        for (int i = mLruProcesses.size() - 1; i >= 0; --i) {
-            final ProcessRecord app = mLruProcesses.get(i);
-            if (!app.killedByAm && app.thread != null && app.uidRecord.shouldNotifyAppThreads) {
-                try {
-                    app.thread.setBlockForNetworkState(app.uidRecord.blockState,
-                            app.uidRecord.curProcStateSeq);
-                } catch (RemoteException ignored) {
-                }
-            }
+            incrementProcStateSeqIfNeeded(mActiveUids.valueAt(i));
         }
 
         mNumServiceProcs = mNewNumServiceProcs;
@@ -22147,6 +22203,42 @@
         }
     }
 
+    /**
+     * If {@link UidRecord#curProcStateSeq} needs to be updated, then increments the global seq
+     * counter {@link #mProcStateSeqCounter} and uses that value for {@param uidRec}.
+     */
+    @VisibleForTesting
+    void incrementProcStateSeqIfNeeded(UidRecord uidRec) {
+        if (uidRec.curProcState != uidRec.setProcState && shouldIncrementProcStateSeq(uidRec)) {
+            uidRec.curProcStateSeq = ++mProcStateSeqCounter;
+        }
+    }
+
+    /**
+     * Checks if {@link UidRecord#curProcStateSeq} needs to be incremented depending on whether
+     * the uid is coming from background to foreground state or vice versa.
+     *
+     * @return Returns true if the uid is coming from background to foreground state or vice versa,
+     *                 false otherwise.
+     */
+    @VisibleForTesting
+    boolean shouldIncrementProcStateSeq(UidRecord uidRec) {
+        final boolean isAllowedOnRestrictBackground
+                = isProcStateAllowedWhileOnRestrictBackground(uidRec.curProcState);
+        final boolean isAllowedOnDeviceIdleOrPowerSaveMode
+                = isProcStateAllowedWhileIdleOrPowerSaveMode(uidRec.curProcState);
+
+        final boolean wasAllowedOnRestrictBackground
+                = isProcStateAllowedWhileOnRestrictBackground(uidRec.setProcState);
+        final boolean wasAllowedOnDeviceIdleOrPowerSaveMode
+                = isProcStateAllowedWhileIdleOrPowerSaveMode(uidRec.setProcState);
+
+        // If the uid is coming from background to foreground or vice versa,
+        // then return true. Otherwise false.
+        return (wasAllowedOnDeviceIdleOrPowerSaveMode != isAllowedOnDeviceIdleOrPowerSaveMode)
+                || (wasAllowedOnRestrictBackground != isAllowedOnRestrictBackground);
+    }
+
     final void runInBackgroundDisabled(int uid) {
         synchronized (this) {
             UidRecord uidRec = mActiveUids.get(uid);
@@ -22999,131 +23091,6 @@
                 updateOomAdjLocked(pr);
             }
         }
-
-        @Override
-        public void setUidStateWithSeqObserver(UidStateWithSeqObserver observer) {
-            synchronized (ActivityManagerService.this) {
-                mUidStateWithSeqObserver = observer;
-            }
-        }
-
-        @Override
-        public void notifyNetworkPolicyRulesUpdated(int uid, long procStateSeq) {
-            if (DEBUG_NETWORK) {
-                Slog.d(TAG_NETWORK, "Got update from NPMS uid: " + uid + " seq: " + procStateSeq);
-            }
-            synchronized (ActivityManagerService.this) {
-                final UidRecord record = mActiveUids.get(uid);
-                if (record == null) {
-                    if (DEBUG_NETWORK) {
-                        Slog.d(TAG_NETWORK, "No active uidRecord for uid: " + uid
-                                + "seq: " + procStateSeq);
-                    }
-                    return;
-                }
-                record.lastProcStateSeqWithUpdatedNetworkState = procStateSeq;
-                if (record.curProcStateSeq > procStateSeq) {
-                    if (DEBUG_NETWORK) {
-                        Slog.d(TAG_NETWORK, "Since the current procStateSeq is greater, the "
-                                + "listeners would already be notified when it is incremented.");
-                    }
-                    return;
-                }
-
-                if (record.appThreadListeners == null) {
-                    if (DEBUG_NETWORK) {
-                        Slog.d(TAG_NETWORK, "No app thread listeners for uid: " + uid
-                                + "seq: " + procStateSeq);
-                    }
-                    return;
-                }
-                for (int i = record.appThreadListeners.beginBroadcast() - 1; i >= 0; i--) {
-                    final IApplicationThread listener =
-                            record.appThreadListeners.getBroadcastItem(i);
-                    try {
-                        if (listener != null) {
-                            listener.notifyNetworkStateUpdated(procStateSeq);
-                        }
-                    } catch (RemoteException ignored) {
-                    }
-                }
-                record.appThreadListeners.finishBroadcast();
-                record.appThreadListeners = null;
-            }
-        }
-    }
-
-    @Override
-    public boolean registerNetworkRulesUpdateListener(IApplicationThread listener,
-            long procStateSeq) {
-        synchronized (this) {
-            final int uid = Binder.getCallingUid();
-            final UidRecord record = mActiveUids.get(uid);
-            if (record.lastProcStateSeqWithUpdatedNetworkState >= procStateSeq) {
-                if (DEBUG_NETWORK) {
-                    Slog.v(TAG_NETWORK, "Network state is already updated for seq: " + procStateSeq
-                            + ". No need to register listener for uid: " + uid);
-                }
-                return false;
-            }
-            if (record.curProcStateSeq > procStateSeq) {
-                if (DEBUG_NETWORK) {
-                    Slog.v(TAG_NETWORK, "Since the current procState is greater, there is no need "
-                            + " to register listeners for older seq numbers");
-                }
-            }
-            if (record.appThreadListeners == null) {
-                record.appThreadListeners = new RemoteCallbackList<>();
-            }
-            record.appThreadListeners.register(listener);
-            if (DEBUG_NETWORK) {
-                Slog.v(TAG_NETWORK, "Registered listener for uid: " + uid + " seq: " + procStateSeq);
-            }
-            return true;
-        }
-    }
-
-    private int getUidRecordBlockState(UidRecord uidRec) {
-        final boolean curStateAllowedWhileRestrictBackgroundOn
-                = isProcStateAllowedWhileRestrictBackgroundOn(uidRec.curProcState);
-        final boolean curStateAllowedWhileIdleOrPowerSaveMode
-                = isProcStateAllowedWhileIdleOrPowerSaveMode(uidRec.curProcState);
-
-        if (uidRec.setProcState == ActivityManager.PROCESS_STATE_UNKNOWN) {
-            if (uidRec.curProcState != ActivityManager.PROCESS_STATE_UNKNOWN &&
-                    (curStateAllowedWhileIdleOrPowerSaveMode
-                            || curStateAllowedWhileRestrictBackgroundOn)) {
-                return ActivityThread.NETWORK_STATE_BLOCK;
-            }
-            return ActivityThread.NETWORK_STATE_NO_CHANGE;
-        }
-
-        final boolean prevStateAllowedWhileRestrictBackgroundOn
-                = isProcStateAllowedWhileRestrictBackgroundOn(uidRec.setProcState);
-        final boolean prevStateAllowedWhileIdleOrPowerSaveMode
-                = isProcStateAllowedWhileIdleOrPowerSaveMode(uidRec.setProcState);
-
-        if (prevStateAllowedWhileIdleOrPowerSaveMode == curStateAllowedWhileIdleOrPowerSaveMode &&
-                prevStateAllowedWhileRestrictBackgroundOn ==
-                        curStateAllowedWhileRestrictBackgroundOn) {
-            return uidRec.blockState;
-        }
-
-        if (!prevStateAllowedWhileIdleOrPowerSaveMode && curStateAllowedWhileIdleOrPowerSaveMode) {
-            return ActivityThread.NETWORK_STATE_BLOCK;
-        } else if (!prevStateAllowedWhileRestrictBackgroundOn
-                && curStateAllowedWhileRestrictBackgroundOn) {
-            return ActivityThread.NETWORK_STATE_BLOCK;
-        }
-
-        if (prevStateAllowedWhileIdleOrPowerSaveMode && !curStateAllowedWhileIdleOrPowerSaveMode) {
-            return ActivityThread.NETWORK_STATE_UNBLOCK;
-        } else if (prevStateAllowedWhileRestrictBackgroundOn &&
-                !curStateAllowedWhileRestrictBackgroundOn) {
-            return ActivityThread.NETWORK_STATE_UNBLOCK;
-        }
-
-        return uidRec.blockState;
     }
 
     private final class SleepTokenImpl extends SleepToken {
@@ -23352,10 +23319,11 @@
     }
 
     void updateApplicationInfoLocked(@NonNull List<String> packagesToUpdate, int userId) {
+        final PackageManagerInternal packageManager = getPackageManagerInternalLocked();
         final boolean updateFrameworkRes = packagesToUpdate.contains("android");
         for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
             final ProcessRecord app = mLruProcesses.get(i);
-            if (app.thread == null) {
+            if (app.thread == null || app.pid == Process.myPid()) {
                 continue;
             }
 
@@ -23368,7 +23336,7 @@
                 final String packageName = app.pkgList.keyAt(j);
                 if (updateFrameworkRes || packagesToUpdate.contains(packageName)) {
                     try {
-                        final ApplicationInfo ai = mPackageManagerInt.getApplicationInfo(
+                        final ApplicationInfo ai = packageManager.getApplicationInfo(
                                 packageName, app.userId);
                         if (ai != null) {
                             app.thread.scheduleApplicationInfoChanged(ai);
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 80df26b..aaad12c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -240,6 +240,8 @@
                     return runSupportsSplitScreenMultiwindow(pw);
                 case "update-appinfo":
                     return runUpdateApplicationInfo(pw);
+                case "no-home-screen":
+                    return runNoHomeScreen(pw);
                 default:
                     return handleDefaultCommands(cmd);
             }
@@ -2386,6 +2388,15 @@
         return 0;
     }
 
+    int runNoHomeScreen(PrintWriter pw) throws RemoteException {
+        final Resources res = getResources(pw);
+        if (res == null) {
+            return -1;
+        }
+        pw.println(res.getBoolean(com.android.internal.R.bool.config_noHomeScreen));
+        return 0;
+    }
+
     private Resources getResources(PrintWriter pw) throws RemoteException {
         // system resources does not contain all the device configuration, construct it manually.
         Configuration config = mInterface.getConfiguration();
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 78b6611..77564bb 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -797,15 +797,21 @@
                     + " is already the parent of r=" + this);
         }
 
+        // TODO: Ensure that we do not directly reparent activities across stacks, as that may leave
+        //       the stacks in strange states. For now, we should use Task.reparent() to ensure that
+        //       the stack is left in an OK state.
+        if (prevTask != null && newTask != null && prevTask.getStack() != newTask.getStack()) {
+            throw new IllegalArgumentException(reason + ": task=" + newTask
+                    + " is in a different stack (" + newTask.getStackId() + ") than the parent of"
+                    + " r=" + this + " (" + prevTask.getStackId() + ")");
+        }
+
         // Must reparent first in window manager
         mWindowContainerController.reparent(newTask.getWindowContainerController(), position);
 
         // Remove the activity from the old task and add it to the new task
         prevTask.removeActivity(this);
-        // TODO(b/34179495): This should really be set to null in removeActivity() call above,
-        // but really bad things that I can't track down right now happen when I do that.
-        // So, setting it here now and will change later when there is time for investigation.
-        task = null;
+
         newTask.addActivityAtIndex(position, this);
     }
 
@@ -880,8 +886,8 @@
     /**
      * @return Stack value from current task, null if there is no task.
      */
-    ActivityStack getStack() {
-        return task != null ? task.getStack() : null;
+    <T extends ActivityStack> T getStack() {
+        return task != null ? (T) task.getStack() : null;
     }
 
     boolean changeWindowTranslucency(boolean toOpaque) {
@@ -999,25 +1005,26 @@
         boolean hasPinnedStack = mStackSupervisor.getStack(PINNED_STACK_ID) != null;
         // Don't return early if !isNotLocked, since we want to throw an exception if the activity
         // is in an incorrect state
-        boolean isNotLocked = !isKeyguardLocked && !isCurrentAppLocked;
+        boolean isNotLockedOrOnKeyguard = !isKeyguardLocked && !isCurrentAppLocked;
         switch (state) {
             case RESUMED:
-                // When visible, allow entering PiP if not on the lockscreen and if the task is not
-                // locked
-                return isNotLocked;
+                // When visible, allow entering PiP if the app is not locked.  If it is over the
+                // keyguard, then we will prompt to unlock in the caller before entering PiP.
+                return !isCurrentAppLocked;
             case PAUSING:
             case PAUSED:
                 // When pausing, then only allow enter PiP as in the resume state, and in addition,
                 // require that there is not an existing PiP activity and that the current system
                 // state supports entering PiP
-                return isNotLocked && !hasPinnedStack && supportsPictureInPictureWhilePausing
+                return isNotLockedOrOnKeyguard && !hasPinnedStack
+                        && supportsPictureInPictureWhilePausing
                         && checkEnterPictureInPictureOnHideAppOpsState();
             case STOPPING:
                 // When stopping in a valid state, then only allow enter PiP as in the pause state.
                 // Otherwise, fall through to throw an exception if the caller is trying to enter
                 // PiP in an invalid stopping state.
                 if (supportsPictureInPictureWhilePausing) {
-                    return isNotLocked && !hasPinnedStack
+                    return isNotLockedOrOnKeyguard && !hasPinnedStack
                             && checkEnterPictureInPictureOnHideAppOpsState();
                 }
             default:
@@ -2021,6 +2028,12 @@
 
         // Okay we now are going to make this activity have the new config.
         // But then we need to figure out how it needs to deal with that.
+
+        // Find changes between last reported merged configuration and the current one. This is used
+        // to decide whether to relaunch an activity or just report a configuration change.
+        final int changes = getTaskConfigurationChanges(mTmpConfig1);
+
+        // Update last reported values.
         final Configuration newGlobalConfig = service.getGlobalConfiguration();
         final Configuration newTaskMergedOverrideConfig = task.getMergedOverrideConfiguration();
         mTmpConfig1.setTo(mLastReportedConfiguration);
@@ -2028,9 +2041,6 @@
         mLastReportedConfiguration.setTo(newGlobalConfig);
         mLastReportedOverrideConfiguration.setTo(newTaskMergedOverrideConfig);
 
-        int taskChanges = getTaskConfigurationChanges(this, newTaskMergedOverrideConfig,
-                mTmpConfig2);
-        final int changes = mTmpConfig1.diff(newGlobalConfig) | taskChanges;
         if (changes == 0 && !forceNewConfig) {
             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                     "Configuration no differences in " + this);
@@ -2045,8 +2055,7 @@
         }
 
         if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
-                "Configuration changes for " + this + " ; taskChanges="
-                        + Configuration.configurationDiffToString(taskChanges) + ", allChanges="
+                "Configuration changes for " + this + ", allChanges="
                         + Configuration.configurationDiffToString(changes));
 
         // If the activity isn't currently running, just leave the new configuration and it will
@@ -2144,40 +2153,27 @@
         return (changes&(~configChanged)) != 0;
     }
 
-    private static int getTaskConfigurationChanges(ActivityRecord record, Configuration taskConfig,
-            Configuration oldTaskOverride) {
-        // If we went from full-screen to non-full-screen, make sure to use the correct
-        // configuration task diff, so the diff stays as small as possible.
-        if (Configuration.EMPTY.equals(oldTaskOverride)
-                && !Configuration.EMPTY.equals(taskConfig)) {
-            oldTaskOverride = record.task.extractOverrideConfig(record.mLastReportedConfiguration);
-        }
-
-        // Conversely, do the same when going the other direction.
-        if (Configuration.EMPTY.equals(taskConfig)
-                && !Configuration.EMPTY.equals(oldTaskOverride)) {
-            taskConfig = record.task.extractOverrideConfig(record.mLastReportedConfiguration);
-        }
-
+    private int getTaskConfigurationChanges(Configuration lastReportedConfig) {
         // Determine what has changed.  May be nothing, if this is a config that has come back from
         // the app after going idle.  In that case we just want to leave the official config object
         // now in the activity and do nothing else.
-        int taskChanges = oldTaskOverride.diff(taskConfig, true /* skipUndefined */);
+        final Configuration currentConfig = task.getConfiguration();
+        int taskChanges = lastReportedConfig.diff(currentConfig);
         // We don't want to use size changes if they don't cross boundaries that are important to
         // the app.
         if ((taskChanges & CONFIG_SCREEN_SIZE) != 0) {
-            final boolean crosses = record.crossesHorizontalSizeThreshold(
-                    oldTaskOverride.screenWidthDp, taskConfig.screenWidthDp)
-                    || record.crossesVerticalSizeThreshold(
-                    oldTaskOverride.screenHeightDp, taskConfig.screenHeightDp);
+            final boolean crosses = crossesHorizontalSizeThreshold(lastReportedConfig.screenWidthDp,
+                    currentConfig.screenWidthDp)
+                    || crossesVerticalSizeThreshold(lastReportedConfig.screenHeightDp,
+                    currentConfig.screenHeightDp);
             if (!crosses) {
                 taskChanges &= ~CONFIG_SCREEN_SIZE;
             }
         }
         if ((taskChanges & CONFIG_SMALLEST_SCREEN_SIZE) != 0) {
-            final int oldSmallest = oldTaskOverride.smallestScreenWidthDp;
-            final int newSmallest = taskConfig.smallestScreenWidthDp;
-            if (!record.crossesSmallestSizeThreshold(oldSmallest, newSmallest)) {
+            final int oldSmallest = lastReportedConfig.smallestScreenWidthDp;
+            final int newSmallest = currentConfig.smallestScreenWidthDp;
+            if (!crossesSmallestSizeThreshold(oldSmallest, newSmallest)) {
                 taskChanges &= ~CONFIG_SMALLEST_SCREEN_SIZE;
             }
         }
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 6087fb3..15a9efc 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -84,7 +84,6 @@
 import android.app.ActivityOptions;
 import android.app.AppGlobals;
 import android.app.IActivityController;
-import android.app.RemoteAction;
 import android.app.ResultInfo;
 import android.content.ComponentName;
 import android.content.Intent;
@@ -135,7 +134,8 @@
 /**
  * State and management of a single stack of activities.
  */
-final class ActivityStack extends ConfigurationContainer implements StackWindowListener {
+class ActivityStack<T extends StackWindowController> extends ConfigurationContainer
+        implements StackWindowListener {
 
     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStack" : TAG_AM;
     private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
@@ -247,7 +247,7 @@
 
     final ActivityManagerService mService;
     private final WindowManagerService mWindowManager;
-    private StackWindowController mWindowContainerController;
+    T mWindowContainerController;
     private final RecentTasks mRecentTasks;
 
     /**
@@ -462,14 +462,18 @@
                 ? new LaunchingTaskPositioner() : null;
         final ActivityStackSupervisor.ActivityDisplay display = mActivityContainer.mActivityDisplay;
         mTmpRect2.setEmpty();
-        mWindowContainerController = new StackWindowController(mStackId, this,
-                display.mDisplayId, onTop, mTmpRect2);
+        mWindowContainerController = createStackWindowController(display.mDisplayId, onTop,
+                mTmpRect2);
         activityContainer.mStack = this;
         mStackSupervisor.mActivityContainers.put(mStackId, activityContainer);
         postAddToDisplay(display, mTmpRect2.isEmpty() ? null : mTmpRect2, onTop);
     }
 
-    StackWindowController getWindowContainerController() {
+    T createStackWindowController(int displayId, boolean onTop, Rect outBounds) {
+        return (T) new StackWindowController(mStackId, this, displayId, onTop, outBounds);
+    }
+
+    T getWindowContainerController() {
         return mWindowContainerController;
     }
 
@@ -540,18 +544,6 @@
         mActivityContainer.mActivityDisplay.mDisplay.getSize(out);
     }
 
-    void animateResizePinnedStack(Rect bounds, int animationDuration) {
-        mWindowContainerController.animateResizePinnedStack(bounds, animationDuration);
-    }
-
-    void setPictureInPictureAspectRatio(float aspectRatio) {
-        mWindowContainerController.setPictureInPictureAspectRatio(aspectRatio);
-    }
-
-    void setPictureInPictureActions(List<RemoteAction> actions) {
-        mWindowContainerController.setPictureInPictureActions(actions);
-    }
-
     void getStackDockedModeBounds(Rect outBounds, Rect outTempBounds, Rect outTempInsetBounds,
             boolean ignoreVisibility) {
         mWindowContainerController.getStackDockedModeBounds(outBounds, outTempBounds,
@@ -1526,10 +1518,11 @@
                     return false;
                 }
 
-                if (!isHomeOrRecentsStack() && r.frontOfTask
-                        && task.isOverHomeStack() && !StackId.isHomeOrRecentsStack(stackBehindId)) {
+                if (!isHomeOrRecentsStack() && r.frontOfTask && task.isOverHomeStack()
+                        && !StackId.isHomeOrRecentsStack(stackBehindId) && !isAssistantStack()) {
                     // Stack isn't translucent if it's top activity should have the home stack
-                    // behind it and the stack currently behind it isn't the home or recents stack.
+                    // behind it and the stack currently behind it isn't the home or recents stack
+                    // or the assistant stack.
                     return false;
                 }
             }
@@ -1572,15 +1565,33 @@
         }
 
         if (mStackId == DOCKED_STACK_ID) {
-            // Docked stack is always visible, except in the case where the top running activity
-            // task in the focus stack doesn't support any form of resizing but we show it for the
-            // home task even though it's not resizable.
             final ActivityRecord r = topStack.topRunningActivityLocked();
+
+            // If the assistant stack is focused and translucent, then the docked stack is always
+            // visible
+            if (topStack.isAssistantStack()
+                    && topStack.isStackTranslucent(starting, DOCKED_STACK_ID)) {
+                return STACK_VISIBLE;
+            }
+
+            // Otherwise, the docked stack is always visible, except in the case where the top
+            // running activity task in the focus stack doesn't support any form of resizing but we
+            // show it for the home task even though it's not resizable.
             final TaskRecord task = r != null ? r.task : null;
             return task == null || task.supportsSplitScreen() || task.isHomeTask() ? STACK_VISIBLE
                     : STACK_INVISIBLE;
         }
 
+        // Set home stack to invisible when it is below but not immediately below the docked stack
+        // A case would be if recents stack exists but has no tasks and is below the docked stack
+        // and home stack is below recents
+        if (mStackId == HOME_STACK_ID) {
+            int dockedStackIndex = mStacks.indexOf(mStackSupervisor.getStack(DOCKED_STACK_ID));
+            if (dockedStackIndex > stackIndex && stackIndex != dockedStackIndex - 1) {
+                return STACK_INVISIBLE;
+            }
+        }
+
         // Find the first stack behind front stack that actually got something visible.
         int stackBehindTopIndex = mStacks.indexOf(topStack) - 1;
         while (stackBehindTopIndex >= 0 &&
@@ -3826,7 +3837,9 @@
         r.app = null;
         r.removeWindowContainer();
         final TaskRecord task = r.task;
-        if (task != null && task.removeActivity(r)) {
+        final boolean lastActivity = task != null ? task.removeActivity(r) : false;
+
+        if (lastActivity) {
             if (DEBUG_STACK) Slog.i(TAG_STACK,
                     "removeActivityFromHistoryLocked: last activity removed from " + this);
             if (mStackSupervisor.isFocusedStack(this) && task == topTask() &&
@@ -4348,9 +4361,13 @@
             Slog.i(TAG, "moveTaskToBack: bad taskId=" + taskId);
             return false;
         }
-
         Slog.i(TAG, "moveTaskToBack: " + tr);
-        mStackSupervisor.removeLockedTaskLocked(tr);
+
+        // If the task is locked, then show the lock task toast
+        if (mStackSupervisor.isLockedTask(tr)) {
+            mStackSupervisor.showLockTaskToast();
+            return false;
+        }
 
         // If we have a watcher, preflight the move before committing to it.  First check
         // for *other* available tasks, but if none are available, then try again allowing the
@@ -4413,12 +4430,24 @@
                 prevIsHome = true;
             }
         }
-        mTaskHistory.remove(tr);
-        mTaskHistory.add(0, tr);
-        updateTaskMovement(tr, false);
 
-        // There is an assumption that moving a task to the back moves it behind the home activity.
-        // We make sure here that some activity in the stack will launch home.
+        boolean requiresMove = mTaskHistory.indexOf(tr) != 0;
+        if (requiresMove) {
+            mTaskHistory.remove(tr);
+            mTaskHistory.add(0, tr);
+            updateTaskMovement(tr, false);
+
+            mWindowManager.prepareAppTransition(TRANSIT_TASK_TO_BACK, false);
+            mWindowContainerController.positionChildAtBottom(tr.getWindowContainerController());
+        }
+
+        if (mStackId == PINNED_STACK_ID) {
+            mStackSupervisor.removeStackLocked(PINNED_STACK_ID);
+            return true;
+        }
+
+        // Otherwise, there is an assumption that moving a task to the back moves it behind the
+        // home activity. We make sure here that some activity in the stack will launch home.
         int numTasks = mTaskHistory.size();
         for (int taskNdx = numTasks - 1; taskNdx >= 1; --taskNdx) {
             final TaskRecord task = mTaskHistory.get(taskNdx);
@@ -4431,9 +4460,6 @@
             }
         }
 
-        mWindowManager.prepareAppTransition(TRANSIT_TASK_TO_BACK, false);
-        mWindowContainerController.positionChildAtBottom(tr.getWindowContainerController());
-
         final TaskRecord task = mResumedActivity != null ? mResumedActivity.task : null;
         if (prevIsHome || (task == tr && canGoHome) || (numTasks <= 1 && isOnHomeDisplay())) {
             if (!mService.mBooting && !mService.mBooted) {
@@ -4818,7 +4844,7 @@
     }
 
     ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
-        ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
+        ArrayList<ActivityRecord> activities = new ArrayList<>();
 
         if ("all".equals(name)) {
             for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
@@ -5074,45 +5100,6 @@
         moveToFront(reason);
     }
 
-    /**
-     * Moves the input activity from its current stack to this one.
-     * NOTE: The current task of the activity isn't moved to this stack. Instead a new task is
-     * created on this stack which the activity is added to.
-     * */
-    void moveActivityToStack(ActivityRecord r) {
-        final ActivityStack prevStack = r.getStack();
-        if (prevStack.mStackId == mStackId) {
-            // You are already in the right stack silly...
-            return;
-        }
-
-        final boolean wasFocused = mStackSupervisor.isFocusedStack(prevStack)
-                && (mStackSupervisor.topRunningActivityLocked() == r);
-        final boolean wasResumed = wasFocused && (prevStack.mResumedActivity == r);
-        final boolean wasPaused = prevStack.mPausingActivity == r;
-
-        // Create a new task for the activity to be parented in
-        final TaskRecord task = createTaskRecord(
-                mStackSupervisor.getNextTaskIdForUserLocked(r.userId),
-                r.info, r.intent, null, null, true, r.mActivityType);
-        // This is a new task, so reparenting it to position 0 will move it to the top
-        r.reparent(task, 0 /* position */, "moveActivityToStack");
-
-        // Notify the task actiivties if it was moved to/from a pinned stack
-        mStackSupervisor.scheduleReportPictureInPictureModeChangedIfNeeded(task, prevStack);
-
-        // Resume the activity if necessary after it has moved
-        moveToFrontAndResumeStateIfNeeded(r, wasFocused, wasResumed, wasPaused,
-                "moveActivityToStack");
-        if (wasResumed) {
-            prevStack.mResumedActivity = null;
-        }
-        if (wasPaused) {
-            prevStack.mPausingActivity = null;
-            prevStack.removeTimeoutsForActivityLocked(r);
-        }
-    }
-
     public int getStackId() {
         return mStackId;
     }
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 3c109ac..59f58d7 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -33,6 +33,7 @@
 import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
 import static android.app.ActivityManager.StackId.LAST_STATIC_STACK_ID;
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
 import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -89,6 +90,9 @@
 import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
 import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_PINNABLE;
 import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_WHITELISTED;
+import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
+import static com.android.server.am.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
+import static com.android.server.am.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
 import static com.android.server.wm.AppTransition.TRANSIT_DOCK_TASK_FROM_RECENTS;
 import static java.lang.Integer.MAX_VALUE;
 
@@ -120,7 +124,6 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
 import android.content.res.Configuration;
-import android.graphics.Point;
 import android.graphics.Rect;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayManager.DisplayListener;
@@ -153,7 +156,6 @@
 import android.service.voice.IVoiceInteractionSession;
 import android.util.ArrayMap;
 import android.util.ArraySet;
-import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.IntArray;
 import android.util.Slog;
@@ -179,7 +181,6 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
@@ -670,6 +671,13 @@
         mHomeStack.moveToFront(reason);
     }
 
+    void moveRecentsStackToFront(String reason) {
+        final ActivityStack recentsStack = getStack(RECENTS_STACK_ID);
+        if (recentsStack != null) {
+            recentsStack.moveToFront(reason);
+        }
+    }
+
     /** Returns true if the focus activity was adjusted to the home stack top activity. */
     boolean moveHomeStackTaskToTop(String reason) {
         mHomeStack.moveHomeStackTaskToTop();
@@ -1198,13 +1206,11 @@
     }
 
     ResolveInfo resolveIntent(Intent intent, String resolvedType, int userId, int flags) {
-        try {
-            return AppGlobals.getPackageManager().resolveIntent(intent, resolvedType,
+        synchronized (mService) {
+            return mService.getPackageManagerInternalLocked().resolveIntent(intent, resolvedType,
                     PackageManager.MATCH_INSTANT | PackageManager.MATCH_DEFAULT_ONLY | flags
                     | ActivityManagerService.STOCK_PM_FLAGS, userId);
-        } catch (RemoteException e) {
         }
-        return null;
     }
 
     ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
@@ -1997,8 +2003,8 @@
                     stackId = task.getLaunchStackId();
                 }
                 if (stackId != currentStack.mStackId) {
-                    currentStack = moveTaskToStackUncheckedLocked(task, stackId, ON_TOP,
-                            !FORCE_FOCUS, reason);
+                    task.reparent(stackId, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE,
+                            DEFER_RESUME, "findTaskToMoveToFrontLocked");
                     stackId = currentStack.mStackId;
                     // moveTaskToStackUncheckedLocked() should already placed the task on top,
                     // still need moveTaskToFrontLocked() below for any transition settings.
@@ -2037,19 +2043,25 @@
                 || mService.mSupportsFreeformWindowManagement;
     }
 
-    ActivityStack getStack(int stackId) {
+    protected <T extends ActivityStack> T getStack(int stackId) {
         return getStack(stackId, !CREATE_IF_NEEDED, !ON_TOP);
     }
 
-    ActivityStack getStack(int stackId, boolean createStaticStackIfNeeded, boolean createOnTop) {
+    protected <T extends ActivityStack> T getStack(int stackId, boolean createStaticStackIfNeeded,
+            boolean createOnTop) {
         final ActivityContainer activityContainer = mActivityContainers.get(stackId);
         if (activityContainer != null) {
-            return activityContainer.mStack;
+            return (T) activityContainer.mStack;
         }
         if (!createStaticStackIfNeeded || !StackId.isStaticStack(stackId)) {
             return null;
         }
-        return createStackOnDisplay(stackId, DEFAULT_DISPLAY, createOnTop);
+        if (stackId == DOCKED_STACK_ID) {
+            // Make sure recents stack exist when creating a dock stack as it normally need to be on
+            // the other side of the docked stack and we make visibility decisions based on that.
+            getStack(RECENTS_STACK_ID, CREATE_IF_NEEDED, createOnTop);
+        }
+        return (T) createStackOnDisplay(stackId, DEFAULT_DISPLAY, createOnTop);
     }
 
     /**
@@ -2282,6 +2294,7 @@
             if (onTop) {
                 for (int i = 0; i < size; i++) {
                     final TaskRecord task = tasks.get(i);
+                    final boolean isTopTask = i == (size - 1);
                     if (fromStackId == PINNED_STACK_ID) {
                         // Update the return-to to reflect where the pinned stack task was moved
                         // from so that we retain the stack that was previously visible if the
@@ -2291,20 +2304,25 @@
                         MetricsLogger.action(mService.mContext,
                                 MetricsEvent.ACTION_PICTURE_IN_PICTURE_EXPANDED_TO_FULLSCREEN);
                     }
-                    moveTaskToStackLocked(tasks.get(i).taskId,
-                            FULLSCREEN_WORKSPACE_STACK_ID, onTop, onTop /*forceFocus*/,
-                            "moveTasksToFullscreenStack - onTop", ANIMATE, DEFER_RESUME);
+                    // Defer resume until all the tasks have been moved to the fullscreen stack
+                    task.reparent(FULLSCREEN_WORKSPACE_STACK_ID, ON_TOP,
+                            REPARENT_MOVE_STACK_TO_FRONT, isTopTask /* animate */, DEFER_RESUME,
+                            "moveTasksToFullscreenStack - onTop");
                 }
-
-                ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS);
-                resumeFocusedStackTopActivityLocked();
             } else {
                 for (int i = 0; i < size; i++) {
                     final TaskRecord task = tasks.get(i);
-                    task.reparent(FULLSCREEN_WORKSPACE_STACK_ID, MAX_VALUE,
-                            "moveTasksToFullscreenStack - NOT_onTop");
+                    final int position = fullscreenStack != null
+                            ? Math.max(fullscreenStack.getAllTasks().size() - 1, 0) : 0;
+                    // Defer resume until all the tasks have been moved to the fullscreen stack
+                    task.reparent(FULLSCREEN_WORKSPACE_STACK_ID, position,
+                            REPARENT_LEAVE_STACK_IN_PLACE, !ANIMATE,
+                            DEFER_RESUME, "moveTasksToFullscreenStack - NOT_onTop");
                 }
             }
+
+            ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS);
+            resumeFocusedStackTopActivityLocked();
         } finally {
             mAllowDockedStackResize = true;
             mWindowManager.continueSurfaceLayout();
@@ -2393,7 +2411,18 @@
         mWindowManager.deferSurfaceLayout();
         try {
             ActivityRecord r = stack.topRunningActivityLocked();
-            stack.resize(pinnedBounds, tempPinnedTaskBounds, null);
+            Rect insetBounds = null;
+            if (tempPinnedTaskBounds != null) {
+                // We always use 0,0 as the position for the inset rect because
+                // if we are getting insets at all in the pinned stack it must mean
+                // we are headed for fullscreen.
+                insetBounds = tempRect;
+                insetBounds.top = 0;
+                insetBounds.left = 0;
+                insetBounds.right = tempPinnedTaskBounds.width();
+                insetBounds.bottom = tempPinnedTaskBounds.height();
+            }
+            stack.resize(pinnedBounds, tempPinnedTaskBounds, insetBounds);
             stack.ensureVisibleActivitiesConfigurationLocked(r, false);
         } finally {
             mWindowManager.continueSurfaceLayout();
@@ -2436,14 +2465,16 @@
                             ? Math.max(0, fullscreenStack.getChildCount() - 1)
                             : fullscreenStack.getChildCount();
                     final TaskRecord task = tasks.get(i);
-                    task.reparent(FULLSCREEN_WORKSPACE_STACK_ID, insertPosition, "removeStack");
+                    // Defer resume until we remove all the tasks
+                    task.reparent(FULLSCREEN_WORKSPACE_STACK_ID, insertPosition,
+                            REPARENT_LEAVE_STACK_IN_PLACE, !ANIMATE, DEFER_RESUME, "removeStack");
                 }
                 ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
                 resumeFocusedStackTopActivityLocked();
             } else {
                 // If there is no fullscreen stack, then create the stack and move all the tasks
                 // onto the stack
-                moveTasksToFullscreenStackLocked(PINNED_STACK_ID, false /* onTop */);
+                moveTasksToFullscreenStackLocked(PINNED_STACK_ID, !ON_TOP);
             }
         } else {
             for (int i = tasks.size() - 1; i >= 0; i--) {
@@ -2648,168 +2679,52 @@
     }
 
     /**
-     * Moves the specified task record to the input stack id.
-     * WARNING: This method performs an unchecked/raw move of the task and
-     * can leave the system in an unstable state if used incorrectly.
-     * Use {@link #moveTaskToStackLocked} to perform safe task movement to a stack.
-     * @param task Task to move.
-     * @param stackId Id of stack to move task to.
-     * @param toTop True if the task should be placed at the top of the stack.
-     * @param forceFocus if focus should be moved to the new stack
-     * @param reason Reason the task is been moved.
-     * @return The stack the task was moved to.
+     * Returns the reparent target stack, creating the stack if necessary.  This call also enforces
+     * the various checks on tasks that are going to be reparented from one stack to another.
      */
-    ActivityStack moveTaskToStackUncheckedLocked(TaskRecord task, int stackId, boolean toTop,
-            boolean forceFocus, String reason) {
-
-        if (StackId.isMultiWindowStack(stackId) && !mService.mSupportsMultiWindow) {
-            throw new IllegalStateException("moveTaskToStackUncheckedLocked: Device doesn't "
-                    + "support multi-window task=" + task + " to stackId=" + stackId);
-        }
-
-        final ActivityRecord r = task.topRunningActivityLocked();
+    ActivityStack getReparentTargetStack(TaskRecord task, int stackId, boolean toTop) {
         final ActivityStack prevStack = task.getStack();
-        final boolean wasFocused = isFocusedStack(prevStack) && (topRunningActivityLocked() == r);
-        final boolean wasResumed = prevStack.mResumedActivity == r;
-        final boolean wasPaused = prevStack.mPausingActivity == r;
-        // In some cases the focused stack isn't the front stack. E.g. pinned stack.
-        // Whenever we are moving the top activity from the front stack we want to make sure to move
-        // the stack to the front.
-        final boolean wasFront = isFrontStackOnDisplay(prevStack)
-                && (prevStack.topRunningActivityLocked() == r);
 
-        if (stackId == DOCKED_STACK_ID && !task.isResizeable()) {
-            // We don't allow moving a unresizeable task to the docked stack since the docked
-            // stack is used for split-screen mode and will cause things like the docked divider to
-            // show up. We instead leave the task in its current stack or move it to the fullscreen
-            // stack if it isn't currently in a stack.
-            stackId = (prevStack != null) ? prevStack.mStackId : FULLSCREEN_WORKSPACE_STACK_ID;
-            Slog.w(TAG, "Can not move unresizeable task=" + task
-                    + " to docked stack. Moving to stackId=" + stackId + " instead.");
+        // Check that we aren't reparenting to the same stack that the task is already in
+        if (prevStack != null && prevStack.mStackId == stackId) {
+            Slog.w(TAG, "Can not reparent to same stack, task=" + task
+                    + " already in stackId=" + stackId);
+            return prevStack;
         }
 
-        // Temporarily disable resizeablility of task we are moving. We don't want it to be resized
-        // if a docked stack is created below which will lead to the stack we are moving from and
-        // its resizeable tasks being resized.
-        task.mTemporarilyUnresizable = true;
-        final ActivityStack stack = getStack(stackId, CREATE_IF_NEEDED, toTop);
-        task.mTemporarilyUnresizable = false;
-        task.reparent(stack.mStackId, toTop ? MAX_VALUE : 0, reason);
-
-        // Reset the resumed activity on the previous stack
-        if (wasResumed) {
-            prevStack.mResumedActivity = null;
-        }
-        // Reset the paused activity on the previous stack
-        if (wasPaused) {
-            prevStack.mPausingActivity = null;
-            prevStack.removeTimeoutsForActivityLocked(r);
+        // Ensure that we aren't trying to move into a multi-window stack without multi-window
+        // support
+        if (StackId.isMultiWindowStack(stackId) && !mService.mSupportsMultiWindow) {
+            throw new IllegalArgumentException("Device doesn't support multi-window, can not"
+                    + " reparent task=" + task + " to stackId=" + stackId);
         }
 
-        // If the task had focus before (or we're requested to move focus),
-        // move focus to the new stack by moving the stack to the front.
-        stack.moveToFrontAndResumeStateIfNeeded(r, forceFocus || wasFocused || wasFront, wasResumed,
-                wasPaused, reason);
-
-        return stack;
-    }
-
-    boolean moveTaskToStackLocked(int taskId, int stackId, boolean toTop, boolean forceFocus,
-            String reason, boolean animate) {
-        return moveTaskToStackLocked(taskId, stackId, toTop, forceFocus, reason, animate,
-                false /* deferResume */);
-    }
-
-    boolean moveTaskToStackLocked(int taskId, int stackId, boolean toTop, boolean forceFocus,
-            String reason, boolean animate, boolean deferResume) {
-        final TaskRecord task = anyTaskForIdLocked(taskId);
-        if (task == null) {
-            Slog.w(TAG, "moveTaskToStack: no task for id=" + taskId);
-            return false;
-        }
-
-        final ActivityStack currentStack = task.getStack();
-        if (currentStack != null && currentStack.mStackId == stackId) {
-            // You are already in the right stack silly...
-            Slog.i(TAG, "moveTaskToStack: taskId=" + taskId + " already in stackId=" + stackId);
-            return true;
-        }
-
+        // Ensure that we aren't trying to move into a freeform stack without freeform
+        // support
         if (stackId == FREEFORM_WORKSPACE_STACK_ID && !mService.mSupportsFreeformWindowManagement) {
-            throw new IllegalArgumentException("moveTaskToStack:"
-                    + "Attempt to move task " + taskId + " to unsupported freeform stack");
+            throw new IllegalArgumentException("Device doesn't support freeform, can not reparent"
+                    + " task=" + task);
         }
 
-        final ActivityRecord topActivity = task.getTopActivity();
-        final int sourceStackId = task.getStackId();
-        final boolean mightReplaceWindow =
-                StackId.replaceWindowsOnTaskMove(sourceStackId, stackId) && topActivity != null;
-        if (mightReplaceWindow) {
-            // We are about to relaunch the activity because its configuration changed due to
-            // being maximized, i.e. size change. The activity will first remove the old window
-            // and then add a new one. This call will tell window manager about this, so it can
-            // preserve the old window until the new one is drawn. This prevents having a gap
-            // between the removal and addition, in which no window is visible. We also want the
-            // entrance of the new window to be properly animated.
-            // Note here we always set the replacing window first, as the flags might be needed
-            // during the relaunch. If we end up not doing any relaunch, we clear the flags later.
-            mWindowManager.setWillReplaceWindow(topActivity.appToken, animate);
+        // We don't allow moving a unresizeable task to the docked stack since the docked stack is
+        // used for split-screen mode and will cause things like the docked divider to show up. We
+        // instead leave the task in its current stack or move it to the fullscreen stack if it
+        // isn't currently in a stack.
+        if (stackId == DOCKED_STACK_ID && !task.isResizeable()) {
+            stackId = (prevStack != null) ? prevStack.mStackId : FULLSCREEN_WORKSPACE_STACK_ID;
+            Slog.w(TAG, "Can not move unresizeable task=" + task + " to docked stack."
+                    + " Moving to stackId=" + stackId + " instead.");
         }
 
-        mWindowManager.deferSurfaceLayout();
-        final int preferredLaunchStackId = stackId;
-        boolean kept = true;
+        // Temporarily disable resizeablility of the task as we don't want it to be resized if, for
+        // example, a docked stack is created which will lead to the stack we are moving from being
+        // resized and and its resizeable tasks being resized.
         try {
-            final ActivityStack stack = moveTaskToStackUncheckedLocked(
-                    task, stackId, toTop, forceFocus, reason + " moveTaskToStack");
-            stackId = stack.mStackId;
-
-            if (!animate) {
-                stack.mNoAnimActivities.add(topActivity);
-            }
-
-            // We might trigger a configuration change. Save the current task bounds for freezing.
-            // TODO: Should this call be moved inside the resize method in WM?
-            stack.prepareFreezingTaskBounds();
-
-            // Make sure the task has the appropriate bounds/size for the stack it is in.
-            if (stackId == FULLSCREEN_WORKSPACE_STACK_ID
-                    && !Objects.equals(task.mBounds, stack.mBounds)) {
-                kept = task.resize(stack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow,
-                        deferResume);
-            } else if (stackId == FREEFORM_WORKSPACE_STACK_ID) {
-                Rect bounds = task.getLaunchBounds();
-                if (bounds == null) {
-                    stack.layoutTaskInStack(task, null);
-                    bounds = task.mBounds;
-                }
-                kept = task.resize(bounds, RESIZE_MODE_FORCED, !mightReplaceWindow, deferResume);
-            } else if (stackId == DOCKED_STACK_ID || stackId == PINNED_STACK_ID) {
-                kept = task.resize(stack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow,
-                        deferResume);
-            }
+            task.mTemporarilyUnresizable = true;
+            return getStack(stackId, CREATE_IF_NEEDED, toTop);
         } finally {
-            mWindowManager.continueSurfaceLayout();
+            task.mTemporarilyUnresizable = false;
         }
-
-        if (mightReplaceWindow) {
-            // If we didn't actual do a relaunch (indicated by kept==true meaning we kept the old
-            // window), we need to clear the replace window settings. Otherwise, we schedule a
-            // timeout to remove the old window if the replacing window is not coming in time.
-            mWindowManager.scheduleClearWillReplaceWindows(topActivity.appToken, !kept);
-        }
-
-        if (!deferResume) {
-
-            // The task might have already been running and its visibility needs to be synchronized with
-            // the visibility of the stack / windows.
-            ensureActivitiesVisibleLocked(null, 0, !mightReplaceWindow);
-            resumeFocusedStackTopActivityLocked();
-        }
-
-        handleNonResizableTaskIfNeeded(task, preferredLaunchStackId, stackId);
-
-        return (preferredLaunchStackId == stackId);
     }
 
     boolean moveTopStackActivityToPinnedStackLocked(int stackId, Rect bounds) {
@@ -2840,10 +2755,10 @@
 
     void moveActivityToPinnedStackLocked(ActivityRecord r, String reason, Rect bounds,
             boolean moveHomeStackToFront) {
-
         mWindowManager.deferSurfaceLayout();
+
         // Need to make sure the pinned stack exist so we can resize it below...
-        final ActivityStack stack = getStack(PINNED_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
+        final PinnedActivityStack stack = getStack(PINNED_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
 
         try {
             final TaskRecord task = r.task;
@@ -2868,17 +2783,31 @@
                 // while pausing because that changes the focused stack and may prevent the new
                 // starting activity from resuming.
                 if (moveHomeStackToFront && task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE
-                        && !r.supportsPictureInPictureWhilePausing) {
+                        && (r.state == RESUMED || !r.supportsPictureInPictureWhilePausing)) {
                     // Move the home stack forward if the task we just moved to the pinned stack
                     // was launched from home so home should be visible behind it.
                     moveHomeStackToFront(reason);
                 }
-                moveTaskToStackLocked(
-                        task.taskId, PINNED_STACK_ID, ON_TOP, FORCE_FOCUS, reason, !ANIMATE);
+                // Defer resume until below
+                task.reparent(PINNED_STACK_ID, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, !ANIMATE,
+                        DEFER_RESUME, reason);
             } else {
                 // There are multiple activities in the task and moving the top activity should
-                // reveal/leave the other activities in their original task
-                stack.moveActivityToStack(r);
+                // reveal/leave the other activities in their original task.
+
+                // Currently, we don't support reparenting activities across tasks in two different
+                // stacks, so instead, just create a new task in the same stack, reparent the
+                // activity into that task, and then reparent the whole task to the new stack. This
+                // ensures that all the necessary work to migrate states in the old and new stacks
+                // is also done.
+                final TaskRecord newTask = task.getStack().createTaskRecord(
+                        getNextTaskIdForUserLocked(r.userId), r.info, r.intent, null, null, true,
+                        r.mActivityType);
+                r.reparent(newTask, MAX_VALUE, "moveActivityToStack");
+
+                // Defer resume until below
+                newTask.reparent(PINNED_STACK_ID, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, !ANIMATE,
+                        DEFER_RESUME, reason);
             }
 
             // Reset the state that indicates it can enter PiP while pausing after we've moved it
@@ -2893,7 +2822,7 @@
         ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
         resumeFocusedStackTopActivityLocked();
 
-        stack.animateResizePinnedStack(bounds, -1);
+        stack.animateResizePinnedStack(bounds, -1 /* animationDuration */);
         mService.mTaskChangeNotificationController.notifyActivityPinned();
     }
 
@@ -3512,22 +3441,24 @@
      * Dumps the activities matching the given {@param name} in the either the focused stack
      * or all visible stacks if {@param dumpVisibleStacks} is true.
      */
-    ArrayList<ActivityRecord> getDumpActivitiesLocked(String name, boolean dumpVisibleStacks) {
-        if (dumpVisibleStacks) {
+    ArrayList<ActivityRecord> getDumpActivitiesLocked(String name, boolean dumpVisibleStacksOnly,
+            boolean dumpFocusedStackOnly) {
+        if (dumpFocusedStackOnly) {
+            return mFocusedStack.getDumpActivitiesLocked(name);
+        } else {
             ArrayList<ActivityRecord> activities = new ArrayList<>();
             int numDisplays = mActivityDisplays.size();
             for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
                 ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
                 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                     ActivityStack stack = stacks.get(stackNdx);
-                    if (stack.getStackVisibilityLocked(null) == STACK_VISIBLE) {
+                    if (!dumpVisibleStacksOnly ||
+                            stack.getStackVisibilityLocked(null) == STACK_VISIBLE) {
                         activities.addAll(stack.getDumpActivitiesLocked(name));
                     }
                 }
             }
             return activities;
-        } else {
-            return mFocusedStack.getDumpActivitiesLocked(name);
         }
     }
 
@@ -4354,7 +4285,14 @@
             synchronized (mService) {
                 mStackId = stackId;
                 mActivityDisplay = activityDisplay;
-                new ActivityStack(this, mRecentTasks, onTop);
+                switch (mStackId) {
+                    case PINNED_STACK_ID:
+                        new PinnedActivityStack(this, mRecentTasks, onTop);
+                        break;
+                    default:
+                        new ActivityStack(this, mRecentTasks, onTop);
+                        break;
+                }
                 mIdString = "ActivtyContainer{" + mStackId + "}";
                 if (DEBUG_STACK) Slog.d(TAG_STACK, "Creating " + this);
             }
@@ -4862,9 +4800,8 @@
 
         if (launchStackId != INVALID_STACK_ID) {
             if (task.getStackId() != launchStackId) {
-                moveTaskToStackLocked(
-                        taskId, launchStackId, ON_TOP, FORCE_FOCUS, "startActivityFromRecents",
-                        ANIMATE);
+                task.reparent(launchStackId, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, ANIMATE,
+                        DEFER_RESUME, "startActivityFromRecents");
             }
         }
 
@@ -4885,7 +4822,7 @@
                 setResizingDuringAnimation(task);
             }
 
-            mService.mActivityStarter.postStartActivityUncheckedProcessing(task.getTopActivity(),
+            mService.mActivityStarter.postStartActivityProcessing(task.getTopActivity(),
                     ActivityManager.START_TASK_TO_FRONT,
                     sourceRecord != null ? sourceRecord.task.getStackId() : INVALID_STACK_ID,
                     sourceRecord, task.getStack());
@@ -4911,7 +4848,7 @@
     List<IBinder> getTopVisibleActivities() {
         final ArrayList<IBinder> topActivityTokens = new ArrayList<>();
         // Traverse all displays.
-        for (int i = mActivityDisplays.size(); i >= 0; i--) {
+        for (int i = mActivityDisplays.size() - 1; i >= 0; i--) {
             final ActivityDisplay display = mActivityDisplays.valueAt(i);
             // Traverse all stacks on a display.
             for (int j = display.mStacks.size() - 1; j >= 0; j--) {
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 7605a1e..33889ba 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_CANCELED;
 import static android.app.ActivityManager.START_CLASS_NOT_FOUND;
 import static android.app.ActivityManager.START_DELIVERED_TO_TOP;
 import static android.app.ActivityManager.START_FLAG_ONLY_IF_NEEDED;
@@ -76,28 +77,33 @@
 import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
 import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
 import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED;
+import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
 import static com.android.server.am.ActivityStackSupervisor.FORCE_FOCUS;
 import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
 import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
 import static com.android.server.am.ActivityStackSupervisor.TAG_TASKS;
 import static com.android.server.am.EventLogTags.AM_NEW_INTENT;
+import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
+import static com.android.server.am.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
 
+import static java.lang.Integer.MAX_VALUE;
+
+import android.annotation.NonNull;
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.app.AppGlobals;
 import android.app.IActivityContainer;
 import android.app.IApplicationThread;
-import android.app.KeyguardManager;
 import android.app.PendingIntent;
 import android.app.ProfilerInfo;
 import android.app.WaitResult;
 import android.content.ComponentName;
-import android.content.Context;
 import android.content.IIntentSender;
 import android.content.Intent;
 import android.content.IntentSender;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.AuxiliaryResolveInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
@@ -119,7 +125,7 @@
 import com.android.internal.app.HeavyWeightSwitcherActivity;
 import com.android.internal.app.IVoiceInteractor;
 import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
-import com.android.server.pm.EphemeralResolver;
+import com.android.server.pm.InstantAppResolver;
 import com.android.server.wm.WindowManagerService;
 
 import java.util.ArrayList;
@@ -456,22 +462,9 @@
         // Instead, launch the ephemeral installer. Once the installer is finished, it
         // starts either the intent we resolved here [on install error] or the ephemeral
         // app [on install success].
-        if (rInfo != null && rInfo.ephemeralResponse != null) {
-            final String packageName =
-                    rInfo.ephemeralResponse.resolveInfo.getPackageName();
-            final String splitName = rInfo.ephemeralResponse.splitName;
-            final boolean needsPhaseTwo = rInfo.ephemeralResponse.needsPhase2;
-            final String token = rInfo.ephemeralResponse.token;
-            final int versionCode = rInfo.ephemeralResponse.resolveInfo.getVersionCode();
-            if (needsPhaseTwo) {
-                // request phase two resolution
-                mService.getPackageManagerInternalLocked().requestEphemeralResolutionPhaseTwo(
-                        rInfo.ephemeralResponse, ephemeralIntent, resolvedType, intent,
-                        callingPackage, userId);
-            }
-            intent = EphemeralResolver.buildEphemeralInstallerIntent(intent, ephemeralIntent,
-                    callingPackage, resolvedType, userId, packageName, splitName, versionCode,
-                    token, needsPhaseTwo);
+        if (rInfo != null && rInfo.auxiliaryInfo != null) {
+            intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent,
+                    callingPackage, resolvedType, userId);
             resolvedType = null;
             callingUid = realCallingUid;
             callingPid = realCallingPid;
@@ -519,18 +512,27 @@
 
         doPendingActivityLaunchesLocked(false);
 
-        try {
-            mService.mWindowManager.deferSurfaceLayout();
-            err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
-                    true, options, inTask);
-        } finally {
-            mService.mWindowManager.continueSurfaceLayout();
-        }
-        postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
-        return err;
+        return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
+                options, inTask);
     }
 
-    void postStartActivityUncheckedProcessing(
+    /**
+     * Creates a launch intent for the given auxiliary resolution data.
+     */
+    private @NonNull Intent createLaunchIntent(@NonNull AuxiliaryResolveInfo auxiliaryResponse,
+            Intent originalIntent, String callingPackage, String resolvedType, int userId) {
+        if (auxiliaryResponse.needsPhaseTwo) {
+            // request phase two resolution
+            mService.getPackageManagerInternalLocked().requestInstantAppResolutionPhaseTwo(
+                    auxiliaryResponse, originalIntent, resolvedType, callingPackage, userId);
+        }
+        return InstantAppResolver.buildEphemeralInstallerIntent(originalIntent,
+            callingPackage, resolvedType, userId, auxiliaryResponse.packageName,
+            auxiliaryResponse.splitName, auxiliaryResponse.versionCode,
+            auxiliaryResponse.token, auxiliaryResponse.needsPhaseTwo);
+    }
+
+    void postStartActivityProcessing(
             ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord,
             ActivityStack targetStack) {
 
@@ -585,8 +587,7 @@
             // The activity was already running in the pinned stack so it wasn't started, but either
             // brought to the front or the new intent was delivered to it since it was already in
             // front. Notify anyone interested in this piece of information.
-            mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt(
-                    sourceRecord.launchedFromPackage);
+            mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt();
             return;
         }
     }
@@ -932,6 +933,31 @@
         }
     }
 
+    private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
+            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
+            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
+        int result = START_CANCELED;
+        try {
+            mService.mWindowManager.deferSurfaceLayout();
+            result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
+                    startFlags, doResume, options, inTask);
+        } finally {
+            // If we are not able to proceed, disassociate the activity from the task. Leaving an
+            // activity in an incomplete state can lead to issues, such as performing operations
+            // without a window container.
+            if (result != START_SUCCESS && mStartActivity.task != null) {
+                mStartActivity.task.removeActivity(mStartActivity);
+            }
+            mService.mWindowManager.continueSurfaceLayout();
+        }
+
+        postStartActivityProcessing(r, result, mSupervisor.mFocusedStack.mStackId,  mSourceRecord,
+                mTargetStack);
+
+        return result;
+    }
+
+    // Note: This method should only be called from {@link startActivity}.
     private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
             IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
             int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
@@ -977,11 +1003,22 @@
             if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
                     || isDocumentLaunchesIntoExisting(mLaunchFlags)
                     || mLaunchSingleInstance || mLaunchSingleTask) {
+                final TaskRecord task = mReusedActivity.task;
+
                 // In this situation we want to remove all activities from the task up to the one
                 // being started. In most cases this means we are resetting the task to its initial
                 // state.
-                final ActivityRecord top = mReusedActivity.task.performClearTaskForReuseLocked(
-                        mStartActivity, mLaunchFlags);
+                final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
+                        mLaunchFlags);
+
+                // The above code can remove {@code mReusedActivity} from the task, leading to the
+                // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
+                // task reference is needed in the call below to
+                // {@link setTargetStackAndMoveToFrontIfNeeded}.
+                if (mReusedActivity.task == null) {
+                    mReusedActivity.task = task;
+                }
+
                 if (top != null) {
                     if (top.frontOfTask) {
                         // Activity aliases may mean we use different intents for the top activity,
@@ -1456,9 +1493,9 @@
                         if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
                             // If we want to launch adjacent and mTargetStack is not the computed
                             // launch stack - move task to top of computed stack.
-                            mSupervisor.moveTaskToStackLocked(intentActivity.task.taskId,
-                                    launchStack.mStackId, ON_TOP, FORCE_FOCUS, "launchToSide",
-                                    ANIMATE);
+                            intentActivity.task.reparent(launchStack.mStackId, ON_TOP,
+                                    REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
+                                    "launchToSide");
                         } else {
                             // TODO: This should be reevaluated in MW v2.
                             // We choose to move task to front instead of launching it adjacent
@@ -1523,9 +1560,13 @@
                 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
             // The caller has requested to completely replace any existing task with its new
             // activity. Well that should not be too hard...
-            intentActivity.task.performClearTaskLocked();
-            intentActivity.task.setIntent(mStartActivity);
+            // Note: we must persist the {@link TaskRecord} first as intentActivity could be
+            // removed from calling performClearTaskLocked (For example, if it is being brought out
+            // of history or if it is finished immediately), thus disassociating the task.
             mReuseTask = intentActivity.task;
+            mReuseTask.performClearTaskLocked();
+            mReuseTask.setIntent(mStartActivity);
+
             // When we clear the task - focus will be adjusted, which will bring another task
             // to top before we launch the activity we need. This will temporary swap their
             // mTaskToReturnTo values and we don't want to overwrite them accidentally.
@@ -1539,6 +1580,9 @@
                 // running, and the caller has asked to clear the current task to have this
                 // activity at the top.
                 mAddingToTask = true;
+
+                // We are no longer placing the activity in the task we previously thought we were.
+                mStartActivity.task = null;
                 // Now pretend like this activity is being started by the top of its task, so it
                 // is put in the right place.
                 mSourceRecord = intentActivity;
@@ -1670,8 +1714,8 @@
         if (mTargetStack == null) {
             mTargetStack = sourceStack;
         } else if (mTargetStack != sourceStack) {
-            mSupervisor.moveTaskToStackLocked(sourceTask.taskId, mTargetStack.mStackId,
-                    ON_TOP, FORCE_FOCUS, "launchToSide", !ANIMATE);
+            sourceTask.reparent(mTargetStack.mStackId, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT,
+                    !ANIMATE, DEFER_RESUME, "launchToSide");
         }
 
         final TaskRecord topTask = mTargetStack.topTask();
@@ -1737,9 +1781,9 @@
             mInTask.updateOverrideConfiguration(mLaunchBounds);
             int stackId = mInTask.getLaunchStackId();
             if (stackId != mInTask.getStackId()) {
-                final ActivityStack stack = mSupervisor.moveTaskToStackUncheckedLocked(mInTask,
-                        stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront");
-                stackId = stack.mStackId;
+                mInTask.reparent(stackId, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE,
+                        DEFER_RESUME, "inTaskToFront");
+                stackId = mInTask.getStackId();
             }
             if (StackId.resizeStackWithLaunchBounds(stackId)) {
                 mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
@@ -1838,11 +1882,8 @@
             final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
             final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
             try {
-                final int result = startActivityUnchecked(
-                        pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null);
-                postStartActivityUncheckedProcessing(
-                        pal.r, result, mSupervisor.mFocusedStack.mStackId, mSourceRecord,
-                        mTargetStack);
+                startActivity(pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null,
+                        null);
             } catch (Exception e) {
                 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
                 pal.sendErrorResult(e.getMessage());
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 3571302..1712d48 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -24,6 +24,7 @@
 import android.content.pm.PackageManager;
 import android.net.wifi.IWifiManager;
 import android.net.wifi.WifiActivityEnergyInfo;
+import android.os.PowerSaveState;
 import android.os.BatteryStats;
 import android.os.Binder;
 import android.os.Handler;
@@ -60,6 +61,7 @@
 import com.android.internal.os.PowerProfile;
 import com.android.server.LocalServices;
 import com.android.server.ServiceThread;
+import com.android.server.power.BatterySaverPolicy.ServiceType;
 
 import java.io.File;
 import java.io.FileDescriptor;
@@ -232,7 +234,9 @@
     public void initPowerManagement() {
         final PowerManagerInternal powerMgr = LocalServices.getService(PowerManagerInternal.class);
         powerMgr.registerLowPowerModeObserver(this);
-        mStats.notePowerSaveMode(powerMgr.getLowPowerModeEnabled());
+        mStats.notePowerSaveMode(
+                powerMgr.getLowPowerState(ServiceType.BATTERY_STATS)
+                        .batterySaverEnabled);
         (new WakeupReasonThread()).start();
     }
 
@@ -258,9 +262,14 @@
     }
 
     @Override
-    public void onLowPowerModeChanged(boolean enabled) {
+    public int getServiceType() {
+        return ServiceType.BATTERY_STATS;
+    }
+
+    @Override
+    public void onLowPowerModeChanged(PowerSaveState result) {
         synchronized (mStats) {
-            mStats.notePowerSaveMode(enabled);
+            mStats.notePowerSaveMode(result.batterySaverEnabled);
         }
     }
 
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index ee2467a..c9d19cb 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -16,6 +16,7 @@
 
 package com.android.server.am;
 
+import android.os.Trace;
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.text.SimpleDateFormat;
@@ -216,41 +217,59 @@
 
     public void enqueueParallelBroadcastLocked(BroadcastRecord r) {
         mParallelBroadcasts.add(r);
-        r.enqueueClockTime = System.currentTimeMillis();
+        enqueueBroadcastHelper(r);
     }
 
     public void enqueueOrderedBroadcastLocked(BroadcastRecord r) {
         mOrderedBroadcasts.add(r);
+        enqueueBroadcastHelper(r);
+    }
+
+    /**
+     * Don't call this method directly; call enqueueParallelBroadcastLocked or
+     * enqueueOrderedBroadcastLocked.
+     */
+    private void enqueueBroadcastHelper(BroadcastRecord r) {
         r.enqueueClockTime = System.currentTimeMillis();
+
+        if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
+            Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
+                createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_PENDING),
+                System.identityHashCode(r));
+        }
     }
 
-    public final boolean replaceParallelBroadcastLocked(BroadcastRecord r) {
-        final Intent intent = r.intent;
-        for (int i = mParallelBroadcasts.size() - 1; i >= 0; i--) {
-            final Intent curIntent = mParallelBroadcasts.get(i).intent;
-            if (intent.filterEquals(curIntent)) {
-                if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
-                        "***** DROPPING PARALLEL ["
-                + mQueueName + "]: " + intent);
-                mParallelBroadcasts.set(i, r);
-                return true;
-            }
-        }
-        return false;
+    /**
+     * Find the same intent from queued parallel broadcast, replace with a new one and return
+     * the old one.
+     */
+    public final BroadcastRecord replaceParallelBroadcastLocked(BroadcastRecord r) {
+        return replaceBroadcastLocked(mParallelBroadcasts, r, "PARALLEL");
     }
 
-    public final boolean replaceOrderedBroadcastLocked(BroadcastRecord r) {
+    /**
+     * Find the same intent from queued ordered broadcast, replace with a new one and return
+     * the old one.
+     */
+    public final BroadcastRecord replaceOrderedBroadcastLocked(BroadcastRecord r) {
+        return replaceBroadcastLocked(mOrderedBroadcasts, r, "ORDERED");
+    }
+
+    private BroadcastRecord replaceBroadcastLocked(ArrayList<BroadcastRecord> queue,
+            BroadcastRecord r, String typeForLogging) {
         final Intent intent = r.intent;
-        for (int i = mOrderedBroadcasts.size() - 1; i > 0; i--) {
-            if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
-                if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
-                        "***** DROPPING ORDERED ["
-                        + mQueueName + "]: " + intent);
-                mOrderedBroadcasts.set(i, r);
-                return true;
+        for (int i = queue.size() - 1; i > 0; i--) {
+            final BroadcastRecord old = queue.get(i);
+            if (old.userId == r.userId && intent.filterEquals(old.intent)) {
+                if (DEBUG_BROADCAST) {
+                    Slog.v(TAG_BROADCAST, "***** DROPPING "
+                            + typeForLogging + " [" + mQueueName + "]: " + intent);
+                }
+                queue.set(i, r);
+                return old;
             }
         }
-        return false;
+        return null;
     }
 
     private final void processCurBroadcastLocked(BroadcastRecord r,
@@ -751,7 +770,7 @@
 
             if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "processNextBroadcast ["
                     + mQueueName + "]: "
-                    + mParallelBroadcasts.size() + " broadcasts, "
+                    + mParallelBroadcasts.size() + " parallel broadcasts, "
                     + mOrderedBroadcasts.size() + " ordered broadcasts");
 
             mService.updateCpuStats();
@@ -765,6 +784,16 @@
                 r = mParallelBroadcasts.remove(0);
                 r.dispatchTime = SystemClock.uptimeMillis();
                 r.dispatchClockTime = System.currentTimeMillis();
+
+                if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
+                    Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER,
+                        createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_PENDING),
+                        System.identityHashCode(r));
+                    Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
+                        createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_DELIVERED),
+                        System.identityHashCode(r));
+                }
+
                 final int N = r.receivers.size();
                 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing parallel broadcast ["
                         + mQueueName + "] " + r);
@@ -915,6 +944,14 @@
             if (recIdx == 0) {
                 r.dispatchTime = r.receiverTime;
                 r.dispatchClockTime = System.currentTimeMillis();
+                if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
+                    Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER,
+                        createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_PENDING),
+                        System.identityHashCode(r));
+                    Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
+                        createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_DELIVERED),
+                        System.identityHashCode(r));
+                }
                 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing ordered broadcast ["
                         + mQueueName + "] " + r);
             }
@@ -1158,6 +1195,8 @@
                                 && r.intent.getPackage() == null
                                 && ((r.intent.getFlags()
                                         & Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND) == 0))) {
+                        mService.addBackgroundCheckViolationLocked(r.intent.getAction(),
+                                component.getPackageName());
                         Slog.w(TAG, "Background execution not allowed: receiving "
                                 + r.intent + " to "
                                 + component.flattenToShortString());
@@ -1398,6 +1437,12 @@
         }
         r.finishTime = SystemClock.uptimeMillis();
 
+        if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
+            Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER,
+                createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_DELIVERED),
+                System.identityHashCode(r));
+        }
+
         mBroadcastHistory[mHistoryNext] = r;
         mHistoryNext = ringAdvance(mHistoryNext, 1, MAX_BROADCAST_HISTORY);
 
@@ -1456,6 +1501,14 @@
         }
     }
 
+    private String createBroadcastTraceTitle(BroadcastRecord record, int state) {
+        return String.format("Broadcast %s from %s (%s) %s",
+                state == BroadcastRecord.DELIVERY_PENDING ? "in queue" : "dispatched",
+                record.callerPackage == null ? "" : record.callerPackage,
+                record.callerApp == null ? "process unknown" : record.callerApp.toShortString(),
+                record.intent == null ? "" : record.intent.getAction());
+    }
+
     final boolean dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args,
             int opti, boolean dumpAll, String dumpPackage, boolean needSep) {
         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
diff --git a/services/core/java/com/android/server/am/BroadcastStats.java b/services/core/java/com/android/server/am/BroadcastStats.java
index fdbaada..fd24582 100644
--- a/services/core/java/com/android/server/am/BroadcastStats.java
+++ b/services/core/java/com/android/server/am/BroadcastStats.java
@@ -47,6 +47,7 @@
     static final class ActionEntry {
         final String mAction;
         final ArrayMap<String, PackageEntry> mPackages = new ArrayMap<>();
+        final ArrayMap<String, ViolationEntry> mBackgroundCheckViolations = new ArrayMap<>();
         int mReceiveCount;
         int mSkipCount;
         long mTotalDispatchTime;
@@ -61,6 +62,10 @@
         int mSendCount;
     }
 
+    static final class ViolationEntry {
+        int mCount;
+    }
+
     public BroadcastStats() {
         mStartRealtime = SystemClock.elapsedRealtime();
         mStartUptime = SystemClock.uptimeMillis();
@@ -87,6 +92,20 @@
         pe.mSendCount++;
     }
 
+    public void addBackgroundCheckViolation(String action, String targetPackage) {
+        ActionEntry ae = mActions.get(action);
+        if (ae == null) {
+            ae = new ActionEntry(action);
+            mActions.put(action, ae);
+        }
+        ViolationEntry ve = ae.mBackgroundCheckViolations.get(targetPackage);
+        if (ve == null) {
+            ve = new ViolationEntry();
+            ae.mBackgroundCheckViolations.put(targetPackage, ve);
+        }
+        ve.mCount++;
+    }
+
     public boolean dumpStats(PrintWriter pw, String prefix, String dumpPackage) {
         boolean printedSomething = false;
         ArrayList<ActionEntry> actions = new ArrayList<>(mActions.size());
@@ -123,6 +142,15 @@
                 pw.print(pe.mSendCount);
                 pw.println(" times");
             }
+            for (int j=ae.mBackgroundCheckViolations.size()-1; j>=0; j--) {
+                pw.print(prefix);
+                pw.print("  Bg Check Violation ");
+                pw.print(ae.mBackgroundCheckViolations.keyAt(j));
+                pw.print(": ");
+                ViolationEntry ve = ae.mBackgroundCheckViolations.valueAt(j);
+                pw.print(ve.mCount);
+                pw.println(" times");
+            }
         }
         return printedSomething;
     }
@@ -158,6 +186,14 @@
                 pw.print(pe.mSendCount);
                 pw.println();
             }
+            for (int j=ae.mBackgroundCheckViolations.size()-1; j>=0; j--) {
+                pw.print("v,");
+                pw.print(ae.mBackgroundCheckViolations.keyAt(j));
+                ViolationEntry ve = ae.mBackgroundCheckViolations.valueAt(j);
+                pw.print(",");
+                pw.print(ve.mCount);
+                pw.println();
+            }
         }
     }
 }
diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
index 9b459d1..73a17c6 100644
--- a/services/core/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java
@@ -49,7 +49,6 @@
         // add other system settings here...
 
         sGlobalSettingToTypeMap.put(Settings.Global.DEBUG_VIEW_ATTRIBUTES, int.class);
-        sGlobalSettingToTypeMap.put(Settings.Global.WAIT_FOR_NETWORK_TIMEOUT_MS, long.class);
         // add other global settings here...
     }
 
@@ -57,8 +56,6 @@
 
     private final ActivityManagerService mActivityManagerService;
 
-    private static final long WAIT_FOR_NETWORK_TIMEOUT_DEFAULT_MS = 2000; // 2 sec
-
     public CoreSettingsObserver(ActivityManagerService activityManagerService) {
         super(activityManagerService.mHandler);
         mActivityManagerService = activityManagerService;
@@ -146,13 +143,7 @@
                 } else if (map == sSystemSettingToTypeMap) {
                     value = Settings.System.getLong(context.getContentResolver(), setting, 0);
                 } else {
-                    // TODO: remove this conditional and set the default in settings provider.
-                    if (Settings.Global.WAIT_FOR_NETWORK_TIMEOUT_MS.equals(setting)) {
-                        value = Settings.Global.getLong(context.getContentResolver(), setting,
-                                WAIT_FOR_NETWORK_TIMEOUT_DEFAULT_MS);
-                    } else {
-                        value = Settings.Global.getLong(context.getContentResolver(), setting, 0);
-                    }
+                    value = Settings.Global.getLong(context.getContentResolver(), setting, 0);
                 }
                 snapshot.putLong(setting, value);
             }
diff --git a/services/core/java/com/android/server/am/PinnedActivityStack.java b/services/core/java/com/android/server/am/PinnedActivityStack.java
new file mode 100644
index 0000000..aa7ab15
--- /dev/null
+++ b/services/core/java/com/android/server/am/PinnedActivityStack.java
@@ -0,0 +1,55 @@
+/*
+ * 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.am;
+
+import android.app.RemoteAction;
+import android.graphics.Rect;
+
+import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
+import com.android.server.wm.PinnedStackWindowController;
+import com.android.server.wm.StackWindowController;
+
+import java.util.List;
+
+/**
+ * State and management of the pinned stack of activities.
+ */
+class PinnedActivityStack extends ActivityStack<PinnedStackWindowController> {
+
+    PinnedActivityStack(ActivityContainer activityContainer,
+            RecentTasks recentTasks, boolean onTop) {
+        super(activityContainer, recentTasks, onTop);
+    }
+
+    @Override
+    PinnedStackWindowController createStackWindowController(int displayId, boolean onTop,
+            Rect outBounds) {
+        return new PinnedStackWindowController(mStackId, this, displayId, onTop, outBounds);
+    }
+
+    void animateResizePinnedStack(Rect bounds, int animationDuration) {
+        getWindowContainerController().animateResizePinnedStack(bounds, animationDuration);
+    }
+
+    void setPictureInPictureAspectRatio(float aspectRatio) {
+        getWindowContainerController().setPictureInPictureAspectRatio(aspectRatio);
+    }
+
+    void setPictureInPictureActions(List<RemoteAction> actions) {
+        getWindowContainerController().setPictureInPictureActions(actions);
+    }
+}
diff --git a/services/core/java/com/android/server/am/PreBootBroadcaster.java b/services/core/java/com/android/server/am/PreBootBroadcaster.java
index f4f6b66..e0d3abd 100644
--- a/services/core/java/com/android/server/am/PreBootBroadcaster.java
+++ b/services/core/java/com/android/server/am/PreBootBroadcaster.java
@@ -35,6 +35,7 @@
 import android.util.Slog;
 
 import com.android.internal.R;
+import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.util.ProgressReporter;
 import com.android.server.UiThread;
 
@@ -144,13 +145,13 @@
                         contentIntent = null;
                     }
 
-                    final Notification notif = new Notification.Builder(mService.mContext)
+                    final Notification notif =
+                            new Notification.Builder(mService.mContext,
+                                    SystemNotificationChannels.UPDATES)
                             .setSmallIcon(R.drawable.stat_sys_adb)
                             .setWhen(0)
                             .setOngoing(true)
                             .setTicker(title)
-                            .setDefaults(0)
-                            .setPriority(Notification.PRIORITY_MAX)
                             .setColor(context.getColor(
                                     com.android.internal.R.color.system_notification_accent_color))
                             .setContentTitle(title)
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 82b00da..dfbe59f 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -115,7 +115,7 @@
     long destroyTime;       // time at which destory was initiated.
 
     String stringName;      // caching of toString
-    
+
     private int lastStartId;    // identifier of most recent start request.
 
     static class StartItem {
@@ -203,7 +203,7 @@
             }
         }
     }
-    
+
     void dump(PrintWriter pw, String prefix) {
         pw.print(prefix); pw.print("intent={");
                 pw.print(intent.getIntent().toShortString(false, true, false, true));
@@ -413,7 +413,7 @@
         restartDelay = 0;
         restartTime = 0;
     }
-    
+
     public StartItem findDeliveredStart(int id, boolean remove) {
         final int N = deliveredStarts.size();
         for (int i=0; i<N; i++) {
@@ -423,10 +423,10 @@
                 return si;
             }
         }
-        
+
         return null;
     }
-    
+
     public int getLastStartId() {
         return lastStartId;
     }
@@ -478,7 +478,8 @@
                                 ctx = ams.mContext.createPackageContextAsUser(
                                         appInfo.packageName, 0, new UserHandle(userId));
 
-                                Notification.Builder notiBuilder = new Notification.Builder(ctx);
+                                Notification.Builder notiBuilder = new Notification.Builder(ctx,
+                                        localForegroundNoti.getChannel());
 
                                 // it's ugly, but it clearly identifies the app
                                 notiBuilder.setSmallIcon(appInfo.icon);
@@ -486,9 +487,6 @@
                                 // mark as foreground
                                 notiBuilder.setFlag(Notification.FLAG_FOREGROUND_SERVICE, true);
 
-                                // we are doing the app a kindness here
-                                notiBuilder.setPriority(Notification.PRIORITY_MIN);
-
                                 Intent runningIntent = new Intent(
                                         Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                                 runningIntent.setData(Uri.fromParts("package",
@@ -541,7 +539,7 @@
             });
         }
     }
-    
+
     public void cancelNotification() {
         // Do asynchronous communication with notification manager to
         // avoid deadlocks.
@@ -588,7 +586,7 @@
             }
         });
     }
-    
+
     public void clearDeliveredStartsLocked() {
         for (int i=deliveredStarts.size()-1; i>=0; i--) {
             deliveredStarts.get(i).removeUriPermissionsLocked();
diff --git a/services/core/java/com/android/server/am/TaskChangeNotificationController.java b/services/core/java/com/android/server/am/TaskChangeNotificationController.java
index 9dfc7cd..3cec7e4 100644
--- a/services/core/java/com/android/server/am/TaskChangeNotificationController.java
+++ b/services/core/java/com/android/server/am/TaskChangeNotificationController.java
@@ -46,6 +46,7 @@
     static final int NOTIFY_TASK_REMOVAL_STARTED_LISTENERS = 13;
     static final int NOTIFY_TASK_PROFILE_LOCKED_LISTENERS_MSG = 14;
     static final int NOTIFY_TASK_SNAPSHOT_CHANGED_LISTENERS_MSG = 15;
+    static final int NOTIFY_PINNED_STACK_ANIMATION_STARTED_LISTENERS_MSG = 16;
 
     // Delay in notifying task stack change listeners (in millis)
     static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 100;
@@ -97,7 +98,11 @@
     };
 
     private final TaskStackConsumer mNotifyPinnedActivityRestartAttempt = (l, m) -> {
-        l.onPinnedActivityRestartAttempt((String) m.obj);
+        l.onPinnedActivityRestartAttempt();
+    };
+
+    private final TaskStackConsumer mNotifyPinnedStackAnimationStarted = (l, m) -> {
+        l.onPinnedStackAnimationStarted();
     };
 
     private final TaskStackConsumer mNotifyPinnedStackAnimationEnded = (l, m) -> {
@@ -166,6 +171,9 @@
                 case NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG:
                     forAllRemoteListeners(mNotifyPinnedActivityRestartAttempt, msg);
                     break;
+                case NOTIFY_PINNED_STACK_ANIMATION_STARTED_LISTENERS_MSG:
+                    forAllRemoteListeners(mNotifyPinnedStackAnimationStarted, msg);
+                    break;
                 case NOTIFY_PINNED_STACK_ANIMATION_ENDED_LISTENERS_MSG:
                     forAllRemoteListeners(mNotifyPinnedStackAnimationEnded, msg);
                     break;
@@ -267,15 +275,23 @@
      * running in the pinned stack and the activity was not actually started, but the task is
      * either brought to the front or a new Intent is delivered to it.
      */
-    void notifyPinnedActivityRestartAttempt(String launchedFromPackage) {
+    void notifyPinnedActivityRestartAttempt() {
         mHandler.removeMessages(NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG);
         final Message msg =
-                mHandler.obtainMessage(NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG,
-                        launchedFromPackage);
+                mHandler.obtainMessage(NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG);
         forAllLocalListeners(mNotifyPinnedActivityRestartAttempt, msg);
         msg.sendToTarget();
     }
 
+    /** Notifies all listeners when the pinned stack animation starts. */
+    void notifyPinnedStackAnimationStarted() {
+        mHandler.removeMessages(NOTIFY_PINNED_STACK_ANIMATION_STARTED_LISTENERS_MSG);
+        final Message msg =
+                mHandler.obtainMessage(NOTIFY_PINNED_STACK_ANIMATION_STARTED_LISTENERS_MSG);
+        forAllLocalListeners(mNotifyPinnedStackAnimationStarted, msg);
+        msg.sendToTarget();
+    }
+
     /** Notifies all listeners when the pinned stack animation ends. */
     void notifyPinnedStackAnimationEnded() {
         mHandler.removeMessages(NOTIFY_PINNED_STACK_ANIMATION_ENDED_LISTENERS_MSG);
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index f8645d6..c0c433e 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -16,6 +16,7 @@
 
 package com.android.server.am;
 
+import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.app.Activity;
 import android.app.ActivityManager;
@@ -54,6 +55,7 @@
 import com.android.server.wm.StackWindowController;
 import com.android.server.wm.TaskWindowContainerController;
 import com.android.server.wm.TaskWindowContainerListener;
+import com.android.server.wm.WindowManagerService;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -62,10 +64,13 @@
 import java.io.File;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Objects;
 
 import static android.app.ActivityManager.RESIZE_MODE_FORCED;
+import static android.app.ActivityManager.RESIZE_MODE_SYSTEM;
 import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID;
 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
@@ -107,9 +112,10 @@
 import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
 import static com.android.server.am.ActivityRecord.STARTING_WINDOW_SHOWN;
 import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING;
-import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED;
 import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
 
+import static java.lang.Integer.MAX_VALUE;
+
 final class TaskRecord extends ConfigurationContainer implements TaskWindowContainerListener {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskRecord" : TAG_AM;
     private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
@@ -160,6 +166,24 @@
     static final int INVALID_TASK_ID = -1;
     private static final int INVALID_MIN_SIZE = -1;
 
+    /**
+     * The modes to control how the stack is moved to the front when calling
+     * {@link TaskRecord#reparent}.
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+            REPARENT_MOVE_STACK_TO_FRONT,
+            REPARENT_KEEP_STACK_AT_FRONT,
+            REPARENT_LEAVE_STACK_IN_PLACE
+    })
+    public @interface ReparentMoveStackMode {}
+    // Moves the stack to the front if it was not at the front
+    public static final int REPARENT_MOVE_STACK_TO_FRONT = 0;
+    // Only moves the stack to the front if it was focused or front most already
+    public static final int REPARENT_KEEP_STACK_AT_FRONT = 1;
+    // Do not move the stack as a part of reparenting
+    public static final int REPARENT_LEAVE_STACK_IN_PLACE = 2;
+
     final int taskId;       // Unique identifier for this task.
     String affinity;        // The affinity name for this task, or null; may change identity.
     String rootAffinity;    // Initial base affinity, or null; does not change from initial root.
@@ -537,36 +561,169 @@
         mWindowContainerController.getBounds(bounds);
     }
 
-    // TODO: Should we be doing all the stuff in ASS.moveTaskToStackLocked?
-    void reparent(int stackId, int position, String reason) {
-        mService.mWindowManager.deferSurfaceLayout();
+    /**
+     * Convenience method to reparent a task to the top or bottom position of the stack.
+     */
+    boolean reparent(int preferredStackId, boolean toTop, @ReparentMoveStackMode int moveStackMode,
+            boolean animate, boolean deferResume, String reason) {
+        return reparent(preferredStackId, toTop ? MAX_VALUE : 0, moveStackMode, animate,
+                deferResume, reason);
+    }
 
+    /**
+     * Reparents the task into a preferred stack, creating it if necessary.
+     *
+     * @param preferredStackId the stack id of the target stack to move this task
+     * @param position the position to place this task in the new stack
+     * @param animate whether or not we should wait for the new window created as a part of the
+     *                reparenting to be drawn and animated in
+     * @param moveStackMode whether or not to move the stack to the front always, only if it was
+     *                      previously focused & in front, or never
+     * @param deferResume whether or not to update the visibility of other tasks and stacks that may
+     *                    have changed as a result of this reparenting
+     * @param reason the caller of this reparenting
+     * @return
+     */
+    boolean reparent(int preferredStackId, int position, @ReparentMoveStackMode int moveStackMode,
+            boolean animate, boolean deferResume, String reason) {
+        final ActivityStackSupervisor supervisor = mService.mStackSupervisor;
+        final WindowManagerService windowManager = mService.mWindowManager;
+        final ActivityStack sourceStack = getStack();
+        final ActivityStack toStack = supervisor.getReparentTargetStack(this, preferredStackId,
+                position == MAX_VALUE);
+        if (toStack == sourceStack) {
+            return false;
+        }
+
+        final int sourceStackId = getStackId();
+        final int stackId = toStack.getStackId();
+        final ActivityRecord topActivity = getTopActivity();
+
+        final boolean mightReplaceWindow = StackId.replaceWindowsOnTaskMove(sourceStackId, stackId)
+                && topActivity != null;
+        if (mightReplaceWindow) {
+            // We are about to relaunch the activity because its configuration changed due to
+            // being maximized, i.e. size change. The activity will first remove the old window
+            // and then add a new one. This call will tell window manager about this, so it can
+            // preserve the old window until the new one is drawn. This prevents having a gap
+            // between the removal and addition, in which no window is visible. We also want the
+            // entrance of the new window to be properly animated.
+            // Note here we always set the replacing window first, as the flags might be needed
+            // during the relaunch. If we end up not doing any relaunch, we clear the flags later.
+            windowManager.setWillReplaceWindow(topActivity.appToken, animate);
+        }
+
+        windowManager.deferSurfaceLayout();
+        boolean kept = true;
         try {
-            final ActivityStackSupervisor supervisor = mService.mStackSupervisor;
-            final ActivityStack newStack = supervisor.getStack(stackId,
-                    CREATE_IF_NEEDED, false /* toTop */);
+            final ActivityRecord r = topRunningActivityLocked();
+            final boolean wasFocused = supervisor.isFocusedStack(sourceStack)
+                    && (topRunningActivityLocked() == r);
+            final boolean wasResumed = sourceStack.mResumedActivity == r;
+            final boolean wasPaused = sourceStack.mPausingActivity == r;
+
+            // In some cases the focused stack isn't the front stack. E.g. pinned stack.
+            // Whenever we are moving the top activity from the front stack we want to make sure to
+            // move the stack to the front.
+            final boolean wasFront = supervisor.isFrontStackOnDisplay(sourceStack)
+                    && (sourceStack.topRunningActivityLocked() == r);
+
             // Adjust the position for the new parent stack as needed.
-            position = newStack.getAdjustedPositionForTask(this, position, null /* starting */);
+            position = toStack.getAdjustedPositionForTask(this, position, null /* starting */);
 
             // Must reparent first in window manager to avoid a situation where AM can delete the
             // we are coming from in WM before we reparent because it became empty.
-            mWindowContainerController.reparent(newStack.getWindowContainerController(), position);
+            mWindowContainerController.reparent(toStack.getWindowContainerController(), position);
 
-            final ActivityStack prevStack = mStack;
-            prevStack.removeTask(this, reason, REMOVE_TASK_MODE_MOVING);
-            newStack.addTask(this, position, reason);
+            // Reset the resumed activity on the previous stack
+            if (wasResumed) {
+                sourceStack.mResumedActivity = null;
+            }
 
-            supervisor.scheduleReportPictureInPictureModeChangedIfNeeded(this, prevStack);
+            // Reset the paused activity on the previous stack
+            if (wasPaused) {
+                sourceStack.mPausingActivity = null;
+                sourceStack.removeTimeoutsForActivityLocked(r);
+            }
 
+            // Move the task
+            sourceStack.removeTask(this, reason, REMOVE_TASK_MODE_MOVING);
+            toStack.addTask(this, position, reason);
+
+            // TODO: Ensure that this is actually necessary here
+            // Notify of picture-in-picture mode changes
+            supervisor.scheduleReportPictureInPictureModeChangedIfNeeded(this, sourceStack);
+
+            // TODO: Ensure that this is actually necessary here
+            // Notify the voice session if required
             if (voiceSession != null) {
                 try {
                     voiceSession.taskStarted(intent, taskId);
                 } catch (RemoteException e) {
                 }
             }
+
+            // If the task had focus before (or we're requested to move focus), move focus to the
+            // new stack by moving the stack to the front.
+            final boolean moveStackToFront = moveStackMode == REPARENT_MOVE_STACK_TO_FRONT
+                    || (moveStackMode == REPARENT_KEEP_STACK_AT_FRONT && (wasFocused || wasFront));
+            toStack.moveToFrontAndResumeStateIfNeeded(r, moveStackToFront, wasResumed, wasPaused,
+                    reason);
+            if (!animate) {
+                toStack.mNoAnimActivities.add(topActivity);
+            }
+
+            // We might trigger a configuration change. Save the current task bounds for freezing.
+            // TODO: Should this call be moved inside the resize method in WM?
+            toStack.prepareFreezingTaskBounds();
+
+            // Make sure the task has the appropriate bounds/size for the stack it is in.
+            if (stackId == FULLSCREEN_WORKSPACE_STACK_ID
+                    && !Objects.equals(mBounds, toStack.mBounds)) {
+                kept = resize(toStack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow,
+                        deferResume);
+            } else if (stackId == FREEFORM_WORKSPACE_STACK_ID) {
+                Rect bounds = getLaunchBounds();
+                if (bounds == null) {
+                    toStack.layoutTaskInStack(this, null);
+                    bounds = mBounds;
+                }
+                kept = resize(bounds, RESIZE_MODE_FORCED, !mightReplaceWindow, deferResume);
+            } else if (stackId == DOCKED_STACK_ID || stackId == PINNED_STACK_ID) {
+                if (stackId == DOCKED_STACK_ID && moveStackMode == REPARENT_KEEP_STACK_AT_FRONT) {
+                    // Move recents to front so it is not behind home stack when going into docked
+                    // mode
+                    mService.mStackSupervisor.moveRecentsStackToFront(reason);
+                }
+                kept = resize(toStack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow,
+                        deferResume);
+            }
         } finally {
-            mService.mWindowManager.continueSurfaceLayout();
+            windowManager.continueSurfaceLayout();
         }
+
+        if (mightReplaceWindow) {
+            // If we didn't actual do a relaunch (indicated by kept==true meaning we kept the old
+            // window), we need to clear the replace window settings. Otherwise, we schedule a
+            // timeout to remove the old window if the replacing window is not coming in time.
+            windowManager.scheduleClearWillReplaceWindows(topActivity.appToken, !kept);
+        }
+
+        if (!deferResume) {
+            // The task might have already been running and its visibility needs to be synchronized
+            // with the visibility of the stack / windows.
+            supervisor.ensureActivitiesVisibleLocked(null, 0, !mightReplaceWindow);
+            supervisor.resumeFocusedStackTopActivityLocked();
+        }
+
+        supervisor.handleNonResizableTaskIfNeeded(this, preferredStackId, stackId);
+
+        boolean successful = (preferredStackId == stackId);
+        if (successful && stackId == DOCKED_STACK_ID) {
+            // If task moved to docked stack - show recents if needed.
+            mService.mWindowManager.showRecentApps(false /* fromHome */);
+        }
+        return successful;
     }
 
     void cancelWindowTransition() {
@@ -1081,8 +1238,17 @@
         r.onOverrideConfigurationSent();
     }
 
-    /** @return true if this was the last activity in the task */
+    /**
+     * @return true if this was the last activity in the task
+     */
     boolean removeActivity(ActivityRecord r) {
+        if (r.task != this) {
+            throw new IllegalArgumentException(
+                    "Activity=" + r + " does not belong to task=" + this);
+        }
+
+        r.task = null;
+
         if (mActivities.remove(r) && r.fullscreen) {
             // Was previously in list.
             numFullscreen--;
diff --git a/services/core/java/com/android/server/am/UidRecord.java b/services/core/java/com/android/server/am/UidRecord.java
index 1e16bc9..f15543a 100644
--- a/services/core/java/com/android/server/am/UidRecord.java
+++ b/services/core/java/com/android/server/am/UidRecord.java
@@ -17,12 +17,8 @@
 package com.android.server.am;
 
 import android.app.ActivityManager;
-import android.app.ActivityThread;
-import android.app.IApplicationThread;
-import android.os.RemoteCallbackList;
 import android.os.SystemClock;
 import android.os.UserHandle;
-import android.util.DebugUtils;
 import android.util.TimeUtils;
 
 /**
@@ -39,26 +35,11 @@
     boolean idle;
     int numProcs;
     /**
-     * Seq no. associated with the current process state change (from background to foreground or
-     * vice versa).
+     * Sequence number associated with the {@link #curProcState}. This is incremented using
+     * {@link ActivityManagerService#mProcStateSeqCounter}
+     * when {@link #curProcState} changes from background to foreground or vice versa.
      */
     long curProcStateSeq;
-    /**
-     * Latest seq number for which NetworkPolicyManagerService notified ActivityManagerService that
-     * network policy rules are updated.
-     */
-    long lastProcStateSeqWithUpdatedNetworkState;
-    /**
-     * Current block state indicating whether components in the process corresponding to this
-     * uidRecord needs to block for network or unblock or if there is no change.
-     * value will be one of {@link ActivityThread#NETWORK_STATE_BLOCK},
-     * {@link ActivityThread#NETWORK_STATE_UNBLOCK}, {@link ActivityThread#NETWORK_STATE_NO_CHANGE}.
-     */
-    int blockState;
-    /** Indicates whether app threads need be notified of the current blockState change. */
-    boolean shouldNotifyAppThreads;
-    /** Listeners waiting for the network policy rules to get updated. */
-    RemoteCallbackList<IApplicationThread> appThreadListeners;
 
     static final int CHANGE_PROCSTATE = 0;
     static final int CHANGE_GONE = 1;
@@ -72,7 +53,6 @@
         int change;
         int processState;
         boolean ephemeral;
-        long procStateSeq;
     }
 
     ChangeItem pendingChange;
@@ -109,14 +89,8 @@
         }
         sb.append(" procs:");
         sb.append(numProcs);
-        sb.append(" procStateSeq:");
+        sb.append(" curProcStateSeq:");
         sb.append(curProcStateSeq);
-        sb.append(" lastProcStateSeqWithUpdatedNetworkState:");
-        sb.append(lastProcStateSeqWithUpdatedNetworkState);
-        sb.append(" blockState:");
-        sb.append(DebugUtils.valueToString(ActivityThread.class, "NETWORK_STATE_", blockState));
-        sb.append(" shouldNotifyAppThreads:");
-        sb.append(shouldNotifyAppThreads);
         sb.append("}");
         return sb.toString();
     }
diff --git a/services/core/java/com/android/server/am/UserState.java b/services/core/java/com/android/server/am/UserState.java
index 42c31b1..6710bdc 100644
--- a/services/core/java/com/android/server/am/UserState.java
+++ b/services/core/java/com/android/server/am/UserState.java
@@ -16,7 +16,6 @@
 
 package com.android.server.am;
 
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_MU;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 
@@ -80,10 +79,11 @@
     }
 
     public void setState(int newState) {
-        if (DEBUG_MU) {
-            Slog.i(TAG, "User " + mHandle.getIdentifier() + " state changed from "
-                    + stateToString(state) + " to " + stateToString(newState));
+        if (newState == state) {
+            return;
         }
+        Slog.i(TAG, "User " + mHandle.getIdentifier() + " state changed from "
+                + stateToString(state) + " to " + stateToString(newState));
         lastState = state;
         state = newState;
     }
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 5b3495f..79b99a3 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -6518,35 +6518,22 @@
         return mRecordMonitor.getActiveRecordingConfigurations();
     }
 
-    public void disableRingtoneSync() {
+    public void disableRingtoneSync(final int userId) {
         final int callingUserId = UserHandle.getCallingUserId();
+        if (callingUserId != userId) {
+            mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+                    "disable sound settings syncing for another profile");
+        }
         final long token = Binder.clearCallingIdentity();
         try {
-            UserManager userManager = UserManager.get(mContext);
-
-            // Disable the sync setting
-            Settings.Secure.putIntForUser(mContentResolver,
-                    Settings.Secure.SYNC_PARENT_SOUNDS, 0 /* false */, callingUserId);
-
-            UserInfo parentInfo = userManager.getProfileParent(callingUserId);
-            if (parentInfo != null && parentInfo.id != callingUserId) {
-                // This is a managed profile, so we clone the ringtones from the parent profile
-                cloneRingtoneSetting(callingUserId, parentInfo.id, Settings.System.RINGTONE);
-                cloneRingtoneSetting(callingUserId, parentInfo.id,
-                        Settings.System.NOTIFICATION_SOUND);
-                cloneRingtoneSetting(callingUserId, parentInfo.id, Settings.System.ALARM_ALERT);
-            }
+            // Disable the sync setting so the profile uses its own sound settings.
+            Settings.Secure.putIntForUser(mContentResolver, Settings.Secure.SYNC_PARENT_SOUNDS,
+                    0 /* false */, userId);
         } finally {
             Binder.restoreCallingIdentity(token);
         }
     }
 
-    private void cloneRingtoneSetting(int userId, int parentId, String ringtoneSetting) {
-        String parentSetting = Settings.System.getStringForUser(mContentResolver, ringtoneSetting,
-                parentId);
-        Settings.System.putStringForUser(mContentResolver, ringtoneSetting, parentSetting, userId);
-    }
-
     //======================
     // Audio playback notification
     //======================
diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java
index b4feef3..b3f1548 100644
--- a/services/core/java/com/android/server/audio/MediaFocusControl.java
+++ b/services/core/java/com/android/server/audio/MediaFocusControl.java
@@ -46,9 +46,9 @@
 
     /**
      * set to true so the framework enforces ducking itself, without communicating to apps
-     * that they lost focus.
+     * that they lost focus for most use cases.
      */
-    static final boolean ENFORCE_DUCKING = false;
+    static final boolean ENFORCE_DUCKING = true;
     /**
      * set to true so the framework enforces muting media/game itself when the device is ringing
      * or in a call.
@@ -437,7 +437,7 @@
      * @param attr attributes of the sound about to start playing
      * @return time in ms
      */
-    protected int getFocusRampTimeMs(int focusGain, AudioAttributes attr) {
+    protected static int getFocusRampTimeMs(int focusGain, AudioAttributes attr) {
         switch (attr.getUsage()) {
             case AudioAttributes.USAGE_MEDIA:
             case AudioAttributes.USAGE_GAME:
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index a95a627..82a0ff6 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -25,6 +25,7 @@
 import android.media.IPlaybackConfigDispatcher;
 import android.media.MediaRecorder;
 import android.media.PlayerBase;
+import android.media.VolumeShaper;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -46,16 +47,40 @@
         implements AudioPlaybackConfiguration.PlayerDeathMonitor, PlayerFocusEnforcer {
 
     public final static String TAG = "AudioService.PlaybackActivityMonitor";
-    private final static boolean DEBUG = false;
 
-    private ArrayList<PlayMonitorClient> mClients = new ArrayList<PlayMonitorClient>();
+    private final static boolean DEBUG = false;
+    private final static int VOLUME_SHAPER_SYSTEM_DUCK_ID = 1;
+
+    private final VolumeShaper.Configuration DUCK_VSHAPE =
+            new VolumeShaper.Configuration.Builder()
+                .setId(VOLUME_SHAPER_SYSTEM_DUCK_ID)
+                .setCurve(new float[] { 0.f, 1.f } /* times */,
+                    new float[] { 1.f, 0.2f } /* volumes */)
+                .setOptionFlags(VolumeShaper.Configuration.OPTION_FLAG_CLOCK_TIME)
+                .setDurationMs(MediaFocusControl.getFocusRampTimeMs(
+                    AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,
+                    new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION)
+                            .build()))
+                .build();
+    private final VolumeShaper.Configuration DUCK_ID =
+            new VolumeShaper.Configuration(VOLUME_SHAPER_SYSTEM_DUCK_ID);
+    private final VolumeShaper.Operation PLAY_CREATE_IF_NEEDED =
+            new VolumeShaper.Operation.Builder(VolumeShaper.Operation.PLAY)
+                    .createIfNeeded()
+                    .build();
+    private final VolumeShaper.Operation TERMINATE =
+            new VolumeShaper.Operation.Builder()
+                    .terminate()
+                    .build();
+
+    private final ArrayList<PlayMonitorClient> mClients = new ArrayList<PlayMonitorClient>();
     // a public client is one that needs an anonymized version of the playback configurations, we
     // keep track of whether there is at least one to know when we need to create the list of
     // playback configurations that do not contain uid/pid/package name information.
     private boolean mHasPublicClients = false;
 
     private final Object mPlayerLock = new Object();
-    private HashMap<Integer, AudioPlaybackConfiguration> mPlayers =
+    private final HashMap<Integer, AudioPlaybackConfiguration> mPlayers =
             new HashMap<Integer, AudioPlaybackConfiguration>();
 
     PlaybackActivityMonitor() {
@@ -104,7 +129,9 @@
         synchronized(mPlayerLock) {
             final AudioPlaybackConfiguration apc = mPlayers.get(new Integer(piid));
             // FIXME SoundPool not ready for state reporting
-            if (apc.getPlayerType() == AudioPlaybackConfiguration.PLAYER_TYPE_JAM_SOUNDPOOL) {
+            if (apc != null
+                    && apc.getPlayerType() == AudioPlaybackConfiguration.PLAYER_TYPE_JAM_SOUNDPOOL)
+            {
                 return;
             }
             if (checkConfigurationCaller(piid, apc, binderUid)) {
@@ -125,6 +152,11 @@
         synchronized(mPlayerLock) {
             final AudioPlaybackConfiguration apc = mPlayers.get(new Integer(piid));
             if (checkConfigurationCaller(piid, apc, binderUid)) {
+                try {
+                    apc.getPlayerProxy().applyVolumeShaper(
+                            DUCK_ID,
+                            TERMINATE);
+                } catch (Exception e) { /* silent failure, happens with binder failure */ }
                 mPlayers.remove(new Integer(piid));
             } else {
                 Log.e(TAG, "Error releasing player " + piid);
@@ -257,6 +289,9 @@
             while (piidIterator.hasNext()) {
                 final Integer piid = piidIterator.next();
                 final AudioPlaybackConfiguration apc = mPlayers.get(piid);
+                if (apc == null) {
+                    continue;
+                }
                 if (!winner.hasSameUid(apc.getClientUid())
                         && loser.hasSameUid(apc.getClientUid())
                         && apc.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED)
@@ -268,11 +303,16 @@
                         // the player is speaking, ducking will make the speech unintelligible
                         // so let the app handle it instead
                         return false;
+                    } else if (apc.getPlayerType()
+                            == AudioPlaybackConfiguration.PLAYER_TYPE_JAM_SOUNDPOOL) {
+                        // TODO support ducking of SoundPool players
+                        return false;
                     } else {
                         try {
-                            if (DEBUG) { Log.v(TAG, "ducking player " + piid); }
-                            //FIXME just a test before we have VolumeShape
-                            apc.getPlayerProxy().setPan(-1.0f);
+                            Log.v(TAG, "ducking player " + piid);
+                            apc.getPlayerProxy().applyVolumeShaper(
+                                    DUCK_VSHAPE,
+                                    PLAY_CREATE_IF_NEEDED);
                             mDuckedPlayers.add(piid);
                         } catch (Exception e) {
                             Log.e(TAG, "Error ducking player " + piid, e);
@@ -299,10 +339,11 @@
                 if (apc != null
                         && winner.hasSameUid(apc.getClientUid())) {
                     try {
-                        if (DEBUG) { Log.v(TAG, "unducking player" + piid); }
+                        Log.v(TAG, "unducking player" + piid);
                         mDuckedPlayers.remove(new Integer(piid));
-                        //FIXME just a test before we have VolumeShape
-                        apc.getPlayerProxy().setPan(0.0f);
+                        apc.getPlayerProxy().applyVolumeShaper(
+                                DUCK_ID,
+                                VolumeShaper.Operation.REVERSE);
                     } catch (Exception e) {
                         Log.e(TAG, "Error unducking player " + piid, e);
                     }
@@ -327,6 +368,9 @@
             while (piidIterator.hasNext()) {
                 final Integer piid = piidIterator.next();
                 final AudioPlaybackConfiguration apc = mPlayers.get(piid);
+                if (apc == null) {
+                    continue;
+                }
                 final int playerUsage = apc.getAudioAttributes().getUsage();
                 boolean mute = false;
                 for (int usageToMute : usagesToMute) {
@@ -337,11 +381,11 @@
                 }
                 if (mute) {
                     try {
-                        if (DEBUG) { Log.v(TAG, "muting player" + piid); }
+                        Log.v(TAG, "call: muting player" + piid);
                         apc.getPlayerProxy().setVolume(0.0f);
                         mMutedPlayers.add(piid);
                     } catch (Exception e) {
-                        Log.e(TAG, "Error muting player " + piid, e);
+                        Log.e(TAG, "call: error muting player " + piid, e);
                     }
                 }
             }
@@ -361,10 +405,10 @@
                 final AudioPlaybackConfiguration apc = mPlayers.get(piid);
                 if (apc != null) {
                     try {
-                        if (DEBUG) { Log.v(TAG, "unmuting player" + piid); }
+                        Log.v(TAG, "call: unmuting player" + piid);
                         apc.getPlayerProxy().setVolume(1.0f);
                     } catch (Exception e) {
-                        Log.e(TAG, "Error unmuting player " + piid, e);
+                        Log.e(TAG, "call: error unmuting player " + piid, e);
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/camera/CameraService.java b/services/core/java/com/android/server/camera/CameraServiceProxy.java
similarity index 96%
rename from services/core/java/com/android/server/camera/CameraService.java
rename to services/core/java/com/android/server/camera/CameraServiceProxy.java
index 7d9adf2..d155825 100644
--- a/services/core/java/com/android/server/camera/CameraService.java
+++ b/services/core/java/com/android/server/camera/CameraServiceProxy.java
@@ -40,11 +40,11 @@
 import java.util.Set;
 
 /**
- * CameraService is the system_server analog to the camera service running in mediaserver.
+ * CameraServiceProxy is the system_server analog to the camera service running in mediaserver.
  *
  * @hide
  */
-public class CameraService extends SystemService
+public class CameraServiceProxy extends SystemService
         implements Handler.Callback, IBinder.DeathRecipient {
     private static final String TAG = "CameraService_proxy";
     private static final boolean DEBUG = false;
@@ -131,7 +131,7 @@
         }
     };
 
-    public CameraService(Context context) {
+    public CameraServiceProxy(Context context) {
         super(context);
         mContext = context;
         mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_DISPLAY, /*allowTo*/false);
@@ -149,7 +149,7 @@
                 notifySwitchWithRetries(msg.arg1);
             } break;
             default: {
-                Slog.e(TAG, "CameraService error, invalid message: " + msg.what);
+                Slog.e(TAG, "CameraServiceProxy error, invalid message: " + msg.what);
             } break;
         }
         return true;
@@ -160,7 +160,8 @@
         mUserManager = UserManager.get(mContext);
         if (mUserManager == null) {
             // Should never see this unless someone messes up the SystemServer service boot order.
-            throw new IllegalStateException("UserManagerService must start before CameraService!");
+            throw new IllegalStateException("UserManagerService must start before" +
+                    " CameraServiceProxy!");
         }
 
         IntentFilter filter = new IntentFilter();
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index 94417b5..8abde78 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -255,8 +255,8 @@
                         clip.getItemAt(0).getText().toString());
                 }
                 final int callingUid = Binder.getCallingUid();
-                if (mAppOps.noteOp(AppOpsManager.OP_WRITE_CLIPBOARD, callingUid,
-                        callingPackage) != AppOpsManager.MODE_ALLOWED) {
+                if (!clipboardAccessAllowed(AppOpsManager.OP_WRITE_CLIPBOARD, callingPackage,
+                            callingUid)) {
                     return;
                 }
                 checkDataOwnerLocked(clip, callingUid);
@@ -304,8 +304,8 @@
         @Override
         public ClipData getPrimaryClip(String pkg) {
             synchronized (this) {
-                if (mAppOps.noteOp(AppOpsManager.OP_READ_CLIPBOARD, Binder.getCallingUid(),
-                        pkg) != AppOpsManager.MODE_ALLOWED) {
+                if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, pkg,
+                            Binder.getCallingUid())) {
                     return null;
                 }
                 addActiveOwnerLocked(Binder.getCallingUid(), pkg);
@@ -316,8 +316,8 @@
         @Override
         public ClipDescription getPrimaryClipDescription(String callingPackage) {
             synchronized (this) {
-                if (mAppOps.checkOp(AppOpsManager.OP_READ_CLIPBOARD, Binder.getCallingUid(),
-                        callingPackage) != AppOpsManager.MODE_ALLOWED) {
+                if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, callingPackage,
+                            Binder.getCallingUid())) {
                     return null;
                 }
                 PerUserClipboard clipboard = getClipboard();
@@ -328,8 +328,8 @@
         @Override
         public boolean hasPrimaryClip(String callingPackage) {
             synchronized (this) {
-                if (mAppOps.checkOp(AppOpsManager.OP_READ_CLIPBOARD, Binder.getCallingUid(),
-                        callingPackage) != AppOpsManager.MODE_ALLOWED) {
+                if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, callingPackage,
+                            Binder.getCallingUid())) {
                     return false;
                 }
                 return getClipboard().primaryClip != null;
@@ -355,8 +355,8 @@
         @Override
         public boolean hasClipboardText(String callingPackage) {
             synchronized (this) {
-                if (mAppOps.checkOp(AppOpsManager.OP_READ_CLIPBOARD, Binder.getCallingUid(),
-                        callingPackage) != AppOpsManager.MODE_ALLOWED) {
+                if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, callingPackage,
+                            Binder.getCallingUid())) {
                     return false;
                 }
                 PerUserClipboard clipboard = getClipboard();
@@ -417,8 +417,9 @@
                 try {
                     ListenerInfo li = (ListenerInfo)
                             clipboard.primaryClipListeners.getBroadcastCookie(i);
-                    if (mAppOps.checkOpNoThrow(AppOpsManager.OP_READ_CLIPBOARD, li.mUid,
-                            li.mPackageName) == AppOpsManager.MODE_ALLOWED) {
+
+                    if (clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, li.mPackageName,
+                                li.mUid)) {
                         clipboard.primaryClipListeners.getBroadcastItem(i)
                                 .dispatchPrimaryClipChanged();
                     }
@@ -551,4 +552,24 @@
             revokeItemLocked(clipboard.primaryClip.getItemAt(i));
         }
     }
+
+    private boolean clipboardAccessAllowed(int op, String callingPackage, int callingUid) {
+        // Check the AppOp.
+        if (mAppOps.checkOp(op, callingUid, callingPackage) != AppOpsManager.MODE_ALLOWED) {
+            return false;
+        }
+        try {
+            // Installed apps can access the clipboard at any time.
+            if (!AppGlobals.getPackageManager().isInstantApp(callingPackage,
+                        UserHandle.getUserId(callingUid))) {
+                return true;
+            }
+            // Instant apps can only access the clipboard if they are in the foreground.
+            return mAm.isAppForeground(callingUid);
+        } catch (RemoteException e) {
+            Slog.e("clipboard", "Failed to get Instant App status for package " + callingPackage,
+                    e);
+            return false;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index fbda901..cf33313 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -790,6 +790,8 @@
             if (userAgent != null) {
                urlConnection.setRequestProperty("User-Agent", userAgent);
             }
+            // cannot read request header after connection
+            String requestHeader = urlConnection.getRequestProperties().toString();
 
             // Time how long it takes to get a response to our request
             long requestTimestamp = SystemClock.elapsedRealtime();
@@ -803,6 +805,7 @@
             validationLog(ValidationProbeEvent.getProbeName(probeType) + " " + url +
                     " time=" + (responseTimestamp - requestTimestamp) + "ms" +
                     " ret=" + httpResponseCode +
+                    " request=" + requestHeader +
                     " headers=" + urlConnection.getHeaderFields());
             // NOTE: We may want to consider an "HTTP/1.0 204" response to be a captive
             // portal.  The only example of this seen so far was a captive portal.  For
diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
index 68fe505..83751a9 100644
--- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
@@ -32,6 +32,7 @@
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.notification.SystemNotificationChannels;
 
 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
@@ -187,7 +188,9 @@
             return;
         }
 
-        Notification.Builder builder = new Notification.Builder(mContext)
+        final String channelId = highPriority ? SystemNotificationChannels.NETWORK_ALERTS :
+                SystemNotificationChannels.NETWORK_STATUS;
+        Notification.Builder builder = new Notification.Builder(mContext, channelId)
                 .setWhen(System.currentTimeMillis())
                 .setShowWhen(notifyType == NotificationType.NETWORK_SWITCH)
                 .setSmallIcon(icon)
@@ -198,10 +201,6 @@
                 .setContentTitle(title)
                 .setContentIntent(intent)
                 .setLocalOnly(true)
-                .setPriority(highPriority ?
-                        Notification.PRIORITY_HIGH :
-                        Notification.PRIORITY_DEFAULT)
-                .setDefaults(highPriority ? Notification.DEFAULT_ALL : 0)
                 .setOnlyAlertOnce(true);
 
         if (notifyType == NotificationType.NETWORK_SWITCH) {
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 6c608a2..60357c2 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -66,6 +66,7 @@
 import android.util.SparseArray;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.util.IndentingPrintWriter;
@@ -76,6 +77,7 @@
 import com.android.server.connectivity.tethering.IControlsTethering;
 import com.android.server.connectivity.tethering.IPv6TetheringCoordinator;
 import com.android.server.connectivity.tethering.IPv6TetheringInterfaceServices;
+import com.android.server.connectivity.tethering.OffloadController;
 import com.android.server.connectivity.tethering.TetheringConfiguration;
 import com.android.server.connectivity.tethering.TetherInterfaceStateMachine;
 import com.android.server.connectivity.tethering.UpstreamNetworkMonitor;
@@ -145,6 +147,7 @@
             .getSystem().getString(com.android.internal.R.string.config_wifi_tether_enable));
 
     private final StateMachine mTetherMasterSM;
+    private final OffloadController mOffloadController;
     private final UpstreamNetworkMonitor mUpstreamNetworkMonitor;
     private String mCurrentUpstreamIface;
 
@@ -175,6 +178,7 @@
         mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper);
         mTetherMasterSM.start();
 
+        mOffloadController = new OffloadController(mTetherMasterSM.getHandler());
         mUpstreamNetworkMonitor = new UpstreamNetworkMonitor(
                 mContext, mTetherMasterSM, TetherMasterSM.EVENT_UPSTREAM_CALLBACK);
 
@@ -668,7 +672,8 @@
                 tethered_notification_message);
 
         if (mTetheredNotificationBuilder == null) {
-            mTetheredNotificationBuilder = new Notification.Builder(mContext);
+            mTetheredNotificationBuilder =
+                    new Notification.Builder(mContext, SystemNotificationChannels.NETWORK_STATUS);
             mTetheredNotificationBuilder.setWhen(0)
                     .setOngoing(true)
                     .setColor(mContext.getColor(
@@ -950,6 +955,8 @@
         // Events from NetworkCallbacks that we process on the master state
         // machine thread on behalf of the UpstreamNetworkMonitor.
         static final int EVENT_UPSTREAM_CALLBACK                = BASE_MASTER + 5;
+        // we treated the error and want now to clear it
+        static final int CMD_CLEAR_ERROR                        = BASE_MASTER + 6;
 
         private State mInitialState;
         private State mTetherModeAliveState;
@@ -1201,6 +1208,8 @@
 
             protected void handleNewUpstreamNetworkState(NetworkState ns) {
                 mIPv6TetheringCoordinator.updateUpstreamNetworkState(ns);
+                mOffloadController.setUpstreamLinkProperties(
+                        (ns != null) ? ns.linkProperties : null);
             }
         }
 
@@ -1357,12 +1366,14 @@
         class TetherModeAliveState extends TetherMasterUtilState {
             final SimChangeListener simChange = new SimChangeListener(mContext);
             boolean mTryCell = true;
+
             @Override
             public void enter() {
                 // TODO: examine if we should check the return value.
                 turnOnMasterTetherSettings(); // may transition us out
                 simChange.startListening();
                 mUpstreamNetworkMonitor.start();
+                mOffloadController.start();
 
                 // Better try something first pass or crazy tests cases will fail.
                 chooseUpstreamType(true);
@@ -1371,6 +1382,7 @@
 
             @Override
             public void exit() {
+                mOffloadController.stop();
                 unrequestUpstreamMobileConnection();
                 mUpstreamNetworkMonitor.stop();
                 simChange.stopListening();
@@ -1491,6 +1503,10 @@
                         TetherInterfaceStateMachine who = (TetherInterfaceStateMachine)message.obj;
                         who.sendMessage(mErrorNotification);
                         break;
+                    case CMD_CLEAR_ERROR:
+                        mErrorNotification = ConnectivityManager.TETHER_ERROR_NO_ERROR;
+                        transitionTo(mInitialState);
+                        break;
                     default:
                        retValue = false;
                 }
@@ -1635,6 +1651,12 @@
             // Not really very much we can do here.
         }
 
+        // If TetherMasterSM is in ErrorState, TetherMasterSM stays there.
+        // Thus we give a chance for TetherMasterSM to recover to InitialState
+        // by sending CMD_CLEAR_ERROR
+        if (error == ConnectivityManager.TETHER_ERROR_MASTER_ERROR) {
+            mTetherMasterSM.sendMessage(TetherMasterSM.CMD_CLEAR_ERROR, who);
+        }
         switch (state) {
             case IControlsTethering.STATE_UNAVAILABLE:
             case IControlsTethering.STATE_AVAILABLE:
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index b963555..9fc2fc7 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -85,6 +85,7 @@
 import com.android.internal.net.VpnConfig;
 import com.android.internal.net.VpnInfo;
 import com.android.internal.net.VpnProfile;
+import com.android.internal.notification.SystemNotificationChannels;
 import com.android.server.DeviceIdleController;
 import com.android.server.LocalServices;
 import com.android.server.net.BaseNetworkObserver;
@@ -1293,17 +1294,16 @@
                     mContext, /* request */ 0, intent,
                     PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT,
                     null, user);
-            final Notification.Builder builder = new Notification.Builder(mContext)
-                    .setDefaults(0)
-                    .setSmallIcon(R.drawable.vpn_connected)
-                    .setContentTitle(mContext.getString(R.string.vpn_lockdown_disconnected))
-                    .setContentText(mContext.getString(R.string.vpn_lockdown_config))
-                    .setContentIntent(configIntent)
-                    .setCategory(Notification.CATEGORY_SYSTEM)
-                    .setPriority(Notification.PRIORITY_LOW)
-                    .setVisibility(Notification.VISIBILITY_PUBLIC)
-                    .setOngoing(true)
-                    .setColor(mContext.getColor(R.color.system_notification_accent_color));
+            final Notification.Builder builder =
+                    new Notification.Builder(mContext, SystemNotificationChannels.VPN)
+                            .setSmallIcon(R.drawable.vpn_connected)
+                            .setContentTitle(mContext.getString(R.string.vpn_lockdown_disconnected))
+                            .setContentText(mContext.getString(R.string.vpn_lockdown_config))
+                            .setContentIntent(configIntent)
+                            .setCategory(Notification.CATEGORY_SYSTEM)
+                            .setVisibility(Notification.VISIBILITY_PUBLIC)
+                            .setOngoing(true)
+                            .setColor(mContext.getColor(R.color.system_notification_accent_color));
             notificationManager.notifyAsUser(TAG, 0, builder.build(), user);
         } finally {
             Binder.restoreCallingIdentity(token);
diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java b/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
new file mode 100644
index 0000000..220e751
--- /dev/null
+++ b/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
@@ -0,0 +1,53 @@
+/*
+ * 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.connectivity.tethering;
+
+import android.net.LinkProperties;
+import android.os.Handler;
+import android.util.Log;
+
+/**
+ * A wrapper around hardware offload interface.
+ *
+ * @hide
+ */
+public class OffloadController {
+    private static final String TAG = OffloadController.class.getSimpleName();
+
+    private final Handler mHandler;
+    private LinkProperties mUpstreamLinkProperties;
+
+    public OffloadController(Handler h) {
+        mHandler = h;
+    }
+
+    public void start() {
+        // TODO: initOffload() and configure callbacks to be handled on our
+        // preferred Handler.
+        Log.d(TAG, "tethering offload not supported");
+    }
+
+    public void stop() {
+        // TODO: stopOffload().
+        mUpstreamLinkProperties = null;
+    }
+
+    public void setUpstreamLinkProperties(LinkProperties lp) {
+        // TODO: setUpstreamParameters().
+        mUpstreamLinkProperties = 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 5e51579..710ab33 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
@@ -167,7 +167,8 @@
     private void maybeLogMessage(State state, int what) {
         if (DBG) {
             Log.d(TAG, state.getName() + " got " +
-                    sMagicDecoderRing.get(what, Integer.toString(what)));
+                    sMagicDecoderRing.get(what, Integer.toString(what)) + ", Iface = " +
+                    mIfaceName);
         }
     }
 
diff --git a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java b/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
index 017c5fb..6209929 100644
--- a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
@@ -20,6 +20,8 @@
 import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
 
 import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
 import android.net.ConnectivityManager;
 import android.net.ConnectivityManager.NetworkCallback;
 import android.net.LinkProperties;
@@ -72,6 +74,7 @@
 
     private final Context mContext;
     private final StateMachine mTarget;
+    private final Handler mHandler;
     private final int mWhat;
     private final HashMap<Network, NetworkState> mNetworkMap = new HashMap<>();
     private ConnectivityManager mCM;
@@ -84,6 +87,7 @@
     public UpstreamNetworkMonitor(Context ctx, StateMachine tgt, int what) {
         mContext = ctx;
         mTarget = tgt;
+        mHandler = mTarget.getHandler();
         mWhat = what;
     }
 
@@ -99,10 +103,10 @@
         final NetworkRequest listenAllRequest = new NetworkRequest.Builder()
                 .clearCapabilities().build();
         mListenAllCallback = new UpstreamNetworkCallback(CALLBACK_LISTEN_ALL);
-        cm().registerNetworkCallback(listenAllRequest, mListenAllCallback);
+        cm().registerNetworkCallback(listenAllRequest, mListenAllCallback, mHandler);
 
         mDefaultNetworkCallback = new UpstreamNetworkCallback(CALLBACK_TRACK_DEFAULT);
-        cm().registerDefaultNetworkCallback(mDefaultNetworkCallback);
+        cm().registerDefaultNetworkCallback(mDefaultNetworkCallback, mHandler);
     }
 
     public void stop() {
@@ -154,7 +158,7 @@
         // Additionally, we log a message to aid in any subsequent debugging.
         Log.d(TAG, "requesting mobile upstream network: " + mobileUpstreamRequest);
 
-        cm().requestNetwork(mobileUpstreamRequest, mMobileNetworkCallback, 0, legacyType);
+        cm().requestNetwork(mobileUpstreamRequest, mMobileNetworkCallback, 0, legacyType, mHandler);
     }
 
     public void releaseMobileNetworkRequest() {
@@ -182,14 +186,32 @@
         switch (callbackType) {
             case CALLBACK_LISTEN_ALL:
                 break;
+
             case CALLBACK_TRACK_DEFAULT:
-                cm().requestNetworkCapabilities(mDefaultNetworkCallback);
-                cm().requestLinkProperties(mDefaultNetworkCallback);
+                if (mDefaultNetworkCallback == null) {
+                    // The callback was unregistered in the interval between
+                    // ConnectivityService enqueueing onAvailable() and our
+                    // handling of it here on the mHandler thread.
+                    //
+                    // Clean-up of this network entry is deferred to the
+                    // handling of onLost() by other callbacks.
+                    //
+                    // These request*() calls can be deleted post oag/339444.
+                    return;
+                }
                 mCurrentDefault = network;
                 break;
+
             case CALLBACK_MOBILE_REQUEST:
-                cm().requestNetworkCapabilities(mMobileNetworkCallback);
-                cm().requestLinkProperties(mMobileNetworkCallback);
+                if (mMobileNetworkCallback == null) {
+                    // The callback was unregistered in the interval between
+                    // ConnectivityService enqueueing onAvailable() and our
+                    // handling of it here on the mHandler thread.
+                    //
+                    // Clean-up of this network entry is deferred to the
+                    // handling of onLost() by other callbacks.
+                    return;
+                }
                 break;
         }
 
@@ -292,8 +314,9 @@
     }
 
     /**
-     * A NetworkCallback class that relays information of interest to the
-     * tethering master state machine thread for subsequent processing.
+     * A NetworkCallback class that handles information of interest directly
+     * in the thread on which it is invoked. To avoid locking, this MUST be
+     * run on the same thread as the target state machine's handler.
      */
     private class UpstreamNetworkCallback extends NetworkCallback {
         private final int mCallbackType;
@@ -304,22 +327,35 @@
 
         @Override
         public void onAvailable(Network network) {
-            mTarget.getHandler().post(() -> handleAvailable(mCallbackType, network));
+            checkExpectedThread();
+            handleAvailable(mCallbackType, network);
         }
 
         @Override
         public void onCapabilitiesChanged(Network network, NetworkCapabilities newNc) {
-            mTarget.getHandler().post(() -> handleNetCap(network, newNc));
+            checkExpectedThread();
+            handleNetCap(network, newNc);
         }
 
         @Override
         public void onLinkPropertiesChanged(Network network, LinkProperties newLp) {
-            mTarget.getHandler().post(() -> handleLinkProp(network, newLp));
+            checkExpectedThread();
+            handleLinkProp(network, newLp);
         }
 
+        // TODO: Handle onNetworkSuspended();
+        // TODO: Handle onNetworkResumed();
+
         @Override
         public void onLost(Network network) {
-            mTarget.getHandler().post(() -> handleLost(mCallbackType, network));
+            checkExpectedThread();
+            handleLost(mCallbackType, network);
+        }
+
+        private void checkExpectedThread() {
+            if (Looper.myLooper() != mHandler.getLooper()) {
+                Log.wtf(TAG, "Handling callback in unexpected thread.");
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index 886c97f..f47a9079 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -43,6 +43,7 @@
 import android.database.sqlite.SQLiteException;
 import android.net.Uri;
 import android.os.Binder;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.FactoryTest;
 import android.os.IBinder;
@@ -287,7 +288,7 @@
      */
     @Override
     public void registerContentObserver(Uri uri, boolean notifyForDescendants,
-                                        IContentObserver observer, int userHandle) {
+            IContentObserver observer, int userHandle, int targetSdkVersion) {
         if (observer == null || uri == null) {
             throw new IllegalArgumentException("You must pass a valid uri and observer");
         }
@@ -296,13 +297,22 @@
         final int pid = Binder.getCallingPid();
 
         userHandle = handleIncomingUser(uri, pid, uid,
-                Intent.FLAG_GRANT_READ_URI_PERMISSION, userHandle);
+                Intent.FLAG_GRANT_READ_URI_PERMISSION, true, userHandle);
 
         final String msg = LocalServices.getService(ActivityManagerInternal.class)
                 .checkContentProviderAccess(uri.getAuthority(), userHandle);
         if (msg != null) {
-            Log.w(TAG, "Ignoring content changes for " + uri + " from " + uid + ": " + msg);
-            return;
+            if (targetSdkVersion >= Build.VERSION_CODES.O) {
+                throw new SecurityException(msg);
+            } else {
+                if (msg.startsWith("Failed to find provider")) {
+                    // Sigh, we need to quietly let apps targeting older API
+                    // levels notify on non-existent providers.
+                } else {
+                    Log.w(TAG, "Ignoring content changes for " + uri + " from " + uid + ": " + msg);
+                    return;
+                }
+            }
         }
 
         synchronized (mRootNode) {
@@ -316,7 +326,7 @@
     public void registerContentObserver(Uri uri, boolean notifyForDescendants,
                                         IContentObserver observer) {
         registerContentObserver(uri, notifyForDescendants, observer,
-                UserHandle.getCallingUserId());
+                UserHandle.getCallingUserId(), Build.VERSION_CODES.CUR_DEVELOPMENT);
     }
 
     @Override
@@ -340,8 +350,8 @@
      */
     @Override
     public void notifyChange(Uri uri, IContentObserver observer,
-                             boolean observerWantsSelfNotifications, int flags,
-                             int userHandle) {
+            boolean observerWantsSelfNotifications, int flags, int userHandle,
+            int targetSdkVersion) {
         if (DEBUG) Slog.d(TAG, "Notifying update of " + uri + " for user " + userHandle
                 + " from observer " + observer + ", flags " + Integer.toHexString(flags));
 
@@ -354,13 +364,22 @@
         final int callingUserHandle = UserHandle.getCallingUserId();
 
         userHandle = handleIncomingUser(uri, pid, uid,
-                Intent.FLAG_GRANT_WRITE_URI_PERMISSION, userHandle);
+                Intent.FLAG_GRANT_WRITE_URI_PERMISSION, true, userHandle);
 
         final String msg = LocalServices.getService(ActivityManagerInternal.class)
                 .checkContentProviderAccess(uri.getAuthority(), userHandle);
         if (msg != null) {
-            Log.w(TAG, "Ignoring notify for " + uri + " from " + uid + ": " + msg);
-            return;
+            if (targetSdkVersion >= Build.VERSION_CODES.O) {
+                throw new SecurityException(msg);
+            } else {
+                if (msg.startsWith("Failed to find provider")) {
+                    // Sigh, we need to quietly let apps targeting older API
+                    // levels notify on non-existent providers.
+                } else {
+                    Log.w(TAG, "Ignoring notify for " + uri + " from " + uid + ": " + msg);
+                    return;
+                }
+            }
         }
 
         // This makes it so that future permission checks will be in the context of this
@@ -427,7 +446,7 @@
                              boolean observerWantsSelfNotifications, boolean syncToNetwork) {
         notifyChange(uri, observer, observerWantsSelfNotifications,
                 syncToNetwork ? ContentResolver.NOTIFY_SYNC_TO_NETWORK : 0,
-                UserHandle.getCallingUserId());
+                UserHandle.getCallingUserId(), Build.VERSION_CODES.CUR_DEVELOPMENT);
     }
 
     /**
@@ -1125,7 +1144,8 @@
         }
     }
 
-    private int handleIncomingUser(Uri uri, int pid, int uid, int modeFlags, int userId) {
+    private int handleIncomingUser(Uri uri, int pid, int uid, int modeFlags, boolean allowNonFull,
+            int userId) {
         if (userId == UserHandle.USER_CURRENT) {
             userId = ActivityManager.getCurrentUser();
         }
@@ -1138,8 +1158,24 @@
         } else if (userId != UserHandle.getCallingUserId()) {
             if (checkUriPermission(uri, pid, uid, modeFlags,
                     userId) != PackageManager.PERMISSION_GRANTED) {
-                mContext.enforceCallingOrSelfPermission(
-                        Manifest.permission.INTERACT_ACROSS_USERS_FULL, TAG);
+                boolean allow = false;
+                if (mContext.checkCallingOrSelfPermission(
+                        Manifest.permission.INTERACT_ACROSS_USERS_FULL)
+                                == PackageManager.PERMISSION_GRANTED) {
+                    allow = true;
+                } else if (allowNonFull && mContext.checkCallingOrSelfPermission(
+                        Manifest.permission.INTERACT_ACROSS_USERS)
+                                == PackageManager.PERMISSION_GRANTED) {
+                    allow = true;
+                }
+                if (!allow) {
+                    final String permissions = allowNonFull
+                            ? (Manifest.permission.INTERACT_ACROSS_USERS_FULL + " or " +
+                                    Manifest.permission.INTERACT_ACROSS_USERS)
+                            : Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+                    throw new SecurityException(TAG + "Neither user " + uid
+                            + " nor current process has " + permissions);
+                }
             }
         }
 
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 5b539ff..bbad493 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -81,6 +81,7 @@
 import android.util.Pair;
 import android.util.Slog;
 
+import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.util.ArrayUtils;
 import com.android.server.LocalServices;
 import com.android.server.job.JobSchedulerInternal;
@@ -3250,7 +3251,8 @@
                     R.string.contentServiceTooManyDeletesNotificationDesc);
 
             Context contextForUser = getContextForUser(user);
-            Notification notification = new Notification.Builder(contextForUser)
+            Notification notification =
+                    new Notification.Builder(contextForUser, SystemNotificationChannels.ACCOUNT)
                     .setSmallIcon(R.drawable.stat_notify_sync_error)
                     .setTicker(mContext.getString(R.string.contentServiceSync))
                     .setWhen(System.currentTimeMillis())
@@ -3460,4 +3462,4 @@
             return mContext;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index bed269c..0ef0561 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -705,11 +705,14 @@
             mAppliedDimming = false;
         }
 
-        // If low power mode is enabled, cut the brightness level by half
+        // If low power mode is enabled, scale brightness by screenLowPowerBrightnessFactor
         // as long as it is above the minimum threshold.
         if (mPowerRequest.lowPowerMode) {
             if (brightness > mScreenBrightnessRangeMinimum) {
-                brightness = Math.max(brightness / 2, mScreenBrightnessRangeMinimum);
+                final float brightnessFactor =
+                        Math.min(mPowerRequest.screenLowPowerBrightnessFactor, 1);
+                final int lowPowerBrightness = (int) (brightness * brightnessFactor);
+                brightness = Math.max(lowPowerBrightness, mScreenBrightnessRangeMinimum);
             }
             if (!mAppliedLowPower) {
                 slowChange = false;
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index 5f348bf..a947b41 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -261,7 +261,6 @@
 
             mPrimaryDisplayDeviceInfo = deviceInfo;
             mInfo = null;
-            mOverrideDisplayInfo = null;
         }
     }
 
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index 74e025d..5149933 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -149,13 +149,7 @@
     }
 
     private void handleBinderDiedLocked(IBinder appToken) {
-        VirtualDisplayDevice device = mVirtualDisplayDevices.remove(appToken);
-        if (device != null) {
-            Slog.i(TAG, "Virtual display device released because application token died: "
-                    + device.mOwnerPackageName);
-            device.destroyLocked(false);
-            sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_REMOVED);
-        }
+        mVirtualDisplayDevices.remove(appToken);
     }
 
     private void handleMediaProjectionStoppedLocked(IBinder appToken) {
@@ -216,6 +210,10 @@
         public void binderDied() {
             synchronized (getSyncRoot()) {
                 handleBinderDiedLocked(mAppToken);
+                Slog.i(TAG, "Virtual display device released because application token died: "
+                    + mOwnerPackageName);
+                destroyLocked(false);
+                sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_REMOVED);
             }
         }
 
diff --git a/services/core/java/com/android/server/fingerprint/ClientMonitor.java b/services/core/java/com/android/server/fingerprint/ClientMonitor.java
index 5a1e445..43bb21d 100644
--- a/services/core/java/com/android/server/fingerprint/ClientMonitor.java
+++ b/services/core/java/com/android/server/fingerprint/ClientMonitor.java
@@ -68,7 +68,9 @@
         mIsRestricted = restricted;
         mOwner = owner;
         try {
-            token.linkToDeath(this, 0);
+            if (token != null) {
+                token.linkToDeath(this, 0);
+            }
         } catch (RemoteException e) {
             Slog.w(TAG, "caught remote exception in linkToDeath: ", e);
         }
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index e83b228..0f29942 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -1180,7 +1180,7 @@
 
             // Statistics about secure fingerprint transactions (e.g. to unlock password
             // storage, make secure purchases, etc.)
-            final PerformanceStats crypto = mPerformanceMap.get(userId);
+            final PerformanceStats crypto = mCryptoPerformanceMap.get(userId);
             if (crypto != null) {
                 final long countsToken = proto.start(FingerprintUserStatsProto.CRYPTO);
                 proto.write(FingerprintActionStatsProto.ACCEPT, crypto.accept);
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 4c6b832..fc86d68 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -1659,6 +1659,17 @@
         }
 
         @Override
+        public void setStandbyMode(final boolean isStandbyModeOn) {
+            enforceAccessPermission();
+            runOnServiceThread(new Runnable() {
+                @Override
+                public void run() {
+                    HdmiControlService.this.setStandbyMode(isStandbyModeOn);
+                }
+            });
+        }
+
+        @Override
         protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) {
             getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
             final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
@@ -2203,6 +2214,29 @@
         }
     }
 
+    void setStandbyMode(boolean isStandbyModeOn) {
+        assertRunOnServiceThread();
+        if (isPowerOnOrTransient() && isStandbyModeOn) {
+            mPowerManager.goToSleep(SystemClock.uptimeMillis(),
+                    PowerManager.GO_TO_SLEEP_REASON_HDMI, 0);
+            if (playback() != null) {
+                playback().sendStandby(0 /* unused */);
+            }
+        } else if (isPowerStandbyOrTransient() && !isStandbyModeOn) {
+            mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.server.hdmi:WAKE");
+            if (playback() != null) {
+                oneTouchPlay(new IHdmiControlCallback.Stub() {
+                    @Override
+                    public void onComplete(int result) {
+                        if (result != HdmiControlManager.RESULT_SUCCESS) {
+                            Slog.w(TAG, "Failed to complete 'one touch play'. result=" + result);
+                        }
+                    }
+                });
+            }
+        }
+    }
+
     boolean isProhibitMode() {
         synchronized (mLock) {
             return mProhibitMode;
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 3793b91..297d5bd 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -23,6 +23,7 @@
 import android.util.Log;
 import android.view.Display;
 import com.android.internal.inputmethod.InputMethodSubtypeHandle;
+import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.os.SomeArgs;
 import com.android.internal.R;
 import com.android.internal.util.Preconditions;
@@ -973,17 +974,17 @@
                     intent, 0, null, UserHandle.CURRENT);
 
             Resources r = mContext.getResources();
-            Notification notification = new Notification.Builder(mContext)
-                    .setContentTitle(r.getString(
-                            R.string.select_keyboard_layout_notification_title))
-                    .setContentText(r.getString(
-                            R.string.select_keyboard_layout_notification_message))
-                    .setContentIntent(keyboardLayoutIntent)
-                    .setSmallIcon(R.drawable.ic_settings_language)
-                    .setPriority(Notification.PRIORITY_LOW)
-                    .setColor(mContext.getColor(
-                            com.android.internal.R.color.system_notification_accent_color))
-                    .build();
+            Notification notification =
+                    new Notification.Builder(mContext, SystemNotificationChannels.PHYSICAL_KEYBOARD)
+                            .setContentTitle(r.getString(
+                                    R.string.select_keyboard_layout_notification_title))
+                            .setContentText(r.getString(
+                                    R.string.select_keyboard_layout_notification_message))
+                            .setContentIntent(keyboardLayoutIntent)
+                            .setSmallIcon(R.drawable.ic_settings_language)
+                            .setColor(mContext.getColor(
+                                    com.android.internal.R.color.system_notification_accent_color))
+                            .build();
             mNotificationManager.notifyAsUser(null,
                     R.string.select_keyboard_layout_notification_title,
                     notification, UserHandle.ALL);
diff --git a/services/core/java/com/android/server/job/JobPackageTracker.java b/services/core/java/com/android/server/job/JobPackageTracker.java
index 82e2eb4..0a6d8a4 100644
--- a/services/core/java/com/android/server/job/JobPackageTracker.java
+++ b/services/core/java/com/android/server/job/JobPackageTracker.java
@@ -437,7 +437,7 @@
         for (int i=0; i<size; i++) {
             final int index = mEventIndices.indexOf(i);
             final int uid = mEventUids[index];
-            if (filterUid != -1 && filterUid != UserHandle.getAppId(filterUid)) {
+            if (filterUid != -1 && filterUid != UserHandle.getAppId(uid)) {
                 continue;
             }
             final int cmd = mEventCmds[index];
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index a748013..c973911 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -131,6 +131,8 @@
     final List<JobServiceContext> mActiveServices = new ArrayList<>();
     /** List of controllers that will notify this service of updates to jobs. */
     List<StateController> mControllers;
+    /** Need direct access to this for testing. */
+    BatteryController mBatteryController;
     /**
      * Queue of pending jobs. The JobServiceContext class will receive jobs from this list
      * when ready to execute them.
@@ -194,6 +196,7 @@
         // Key names stored in the settings value.
         private static final String KEY_MIN_IDLE_COUNT = "min_idle_count";
         private static final String KEY_MIN_CHARGING_COUNT = "min_charging_count";
+        private static final String KEY_MIN_BATTERY_NOT_LOW_COUNT = "min_battery_not_low_count";
         private static final String KEY_MIN_CONNECTIVITY_COUNT = "min_connectivity_count";
         private static final String KEY_MIN_CONTENT_COUNT = "min_content_count";
         private static final String KEY_MIN_READY_JOBS_COUNT = "min_ready_jobs_count";
@@ -207,6 +210,7 @@
 
         private static final int DEFAULT_MIN_IDLE_COUNT = 1;
         private static final int DEFAULT_MIN_CHARGING_COUNT = 1;
+        private static final int DEFAULT_MIN_BATTERY_NOT_LOW_COUNT = 1;
         private static final int DEFAULT_MIN_CONNECTIVITY_COUNT = 1;
         private static final int DEFAULT_MIN_CONTENT_COUNT = 1;
         private static final int DEFAULT_MIN_READY_JOBS_COUNT = 1;
@@ -229,6 +233,11 @@
          */
         int MIN_CHARGING_COUNT = DEFAULT_MIN_CHARGING_COUNT;
         /**
+         * Minimum # of "battery not low" jobs that must be ready in order to force the JMS to
+         * schedule things early.
+         */
+        int MIN_BATTERY_NOT_LOW_COUNT = DEFAULT_MIN_BATTERY_NOT_LOW_COUNT;
+        /**
          * Minimum # of connectivity jobs that must be ready in order to force the JMS to schedule
          * things early.  1 == Run connectivity jobs as soon as ready.
          */
@@ -312,6 +321,8 @@
                         DEFAULT_MIN_IDLE_COUNT);
                 MIN_CHARGING_COUNT = mParser.getInt(KEY_MIN_CHARGING_COUNT,
                         DEFAULT_MIN_CHARGING_COUNT);
+                MIN_BATTERY_NOT_LOW_COUNT = mParser.getInt(KEY_MIN_BATTERY_NOT_LOW_COUNT,
+                        DEFAULT_MIN_BATTERY_NOT_LOW_COUNT);
                 MIN_CONNECTIVITY_COUNT = mParser.getInt(KEY_MIN_CONNECTIVITY_COUNT,
                         DEFAULT_MIN_CONNECTIVITY_COUNT);
                 MIN_CONTENT_COUNT = mParser.getInt(KEY_MIN_CONTENT_COUNT,
@@ -356,6 +367,9 @@
             pw.print("    "); pw.print(KEY_MIN_CHARGING_COUNT); pw.print("=");
             pw.print(MIN_CHARGING_COUNT); pw.println();
 
+            pw.print("    "); pw.print(KEY_MIN_BATTERY_NOT_LOW_COUNT); pw.print("=");
+            pw.print(MIN_BATTERY_NOT_LOW_COUNT); pw.println();
+
             pw.print("    "); pw.print(KEY_MIN_CONNECTIVITY_COUNT); pw.print("=");
             pw.print(MIN_CONNECTIVITY_COUNT); pw.println();
 
@@ -785,7 +799,8 @@
         mControllers.add(ConnectivityController.get(this));
         mControllers.add(TimeController.get(this));
         mControllers.add(IdleController.get(this));
-        mControllers.add(BatteryController.get(this));
+        mBatteryController = BatteryController.get(this);
+        mControllers.add(mBatteryController);
         mControllers.add(AppIdleController.get(this));
         mControllers.add(ContentObserverController.get(this));
         mControllers.add(DeviceIdleJobsController.get(this));
@@ -1186,6 +1201,7 @@
          */
         class MaybeReadyJobQueueFunctor implements JobStatusFunctor {
             int chargingCount;
+            int batteryNotLowCount;
             int idleCount;
             int backoffCount;
             int connectivityCount;
@@ -1223,6 +1239,9 @@
                     if (job.hasChargingConstraint()) {
                         chargingCount++;
                     }
+                    if (job.hasBatteryNotLowConstraint()) {
+                        batteryNotLowCount++;
+                    }
                     if (job.hasContentTriggerConstraint()) {
                         contentCount++;
                     }
@@ -1241,6 +1260,7 @@
                         idleCount >= mConstants.MIN_IDLE_COUNT ||
                         connectivityCount >= mConstants.MIN_CONNECTIVITY_COUNT ||
                         chargingCount >= mConstants.MIN_CHARGING_COUNT ||
+                        batteryNotLowCount >= mConstants.MIN_BATTERY_NOT_LOW_COUNT ||
                         contentCount >= mConstants.MIN_CONTENT_COUNT ||
                         (runnableJobs != null
                                 && runnableJobs.size() >= mConstants.MIN_READY_JOBS_COUNT)) {
@@ -1264,6 +1284,7 @@
                 idleCount =  0;
                 backoffCount = 0;
                 connectivityCount = 0;
+                batteryNotLowCount = 0;
                 contentCount = 0;
                 runnableJobs = null;
             }
@@ -1764,6 +1785,34 @@
         return 0;
     }
 
+    void setMonitorBattery(boolean enabled) {
+        synchronized (mLock) {
+            if (mBatteryController != null) {
+                mBatteryController.getTracker().setMonitorBatteryLocked(enabled);
+            }
+        }
+    }
+
+    int getBatterySeq() {
+        synchronized (mLock) {
+            return mBatteryController != null ? mBatteryController.getTracker().getSeq() : -1;
+        }
+    }
+
+    boolean getBatteryCharging() {
+        synchronized (mLock) {
+            return mBatteryController != null
+                    ? mBatteryController.getTracker().isOnStablePower() : false;
+        }
+    }
+
+    boolean getBatteryNotLow() {
+        synchronized (mLock) {
+            return mBatteryController != null
+                    ? mBatteryController.getTracker().isBatteryNotLow() : false;
+        }
+    }
+
     private String printContextIdToJobMap(JobStatus[] map, String initial) {
         StringBuilder s = new StringBuilder(initial + ": ");
         for (int i=0; i<map.length; i++) {
diff --git a/services/core/java/com/android/server/job/JobSchedulerShellCommand.java b/services/core/java/com/android/server/job/JobSchedulerShellCommand.java
index 2d62c1c..ec23407 100644
--- a/services/core/java/com/android/server/job/JobSchedulerShellCommand.java
+++ b/services/core/java/com/android/server/job/JobSchedulerShellCommand.java
@@ -43,10 +43,19 @@
     public int onCommand(String cmd) {
         final PrintWriter pw = getOutPrintWriter();
         try {
-            if ("run".equals(cmd)) {
-                return runJob();
-            } else {
-                return handleDefaultCommands(cmd);
+            switch (cmd != null ? cmd : "") {
+                case "run":
+                    return runJob(pw);
+                case "monitor-battery":
+                    return runMonitorBattery(pw);
+                case "get-battery-seq":
+                    return runGetBatterySeq(pw);
+                case "get-battery-charging":
+                    return runGetBatteryCharging(pw);
+                case "get-battery-not-low":
+                    return runGetBatteryNotLow(pw);
+                default:
+                    return handleDefaultCommands(cmd);
             }
         } catch (Exception e) {
             pw.println("Exception: " + e);
@@ -54,20 +63,23 @@
         return -1;
     }
 
-    private int runJob() {
-        try {
-            final int uid = Binder.getCallingUid();
-            final int perm = mPM.checkUidPermission(
-                    "android.permission.CHANGE_APP_IDLE_STATE", uid);
-            if (perm != PackageManager.PERMISSION_GRANTED) {
-                throw new SecurityException("Uid " + uid
-                        + " not permitted to force scheduled jobs");
-            }
-        } catch (RemoteException e) {
-            // Can't happen
+    private void checkPermission(String operation) throws Exception {
+        final int uid = Binder.getCallingUid();
+        if (uid == 0) {
+            // Root can do anything.
+            return;
         }
+        final int perm = mPM.checkUidPermission(
+                "android.permission.CHANGE_APP_IDLE_STATE", uid);
+        if (perm != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("Uid " + uid
+                    + " not permitted to " + operation);
+        }
+    }
 
-        final PrintWriter pw = getOutPrintWriter();
+    private int runJob(PrintWriter pw) throws Exception {
+        checkPermission("force scheduled jobs");
+
         boolean force = false;
         int userId = UserHandle.USER_SYSTEM;
 
@@ -133,6 +145,42 @@
         return ret;
     }
 
+    private int runMonitorBattery(PrintWriter pw) throws Exception {
+        checkPermission("change battery monitoring");
+        String opt = getNextArgRequired();
+        boolean enabled;
+        if ("on".equals(opt)) {
+            enabled = true;
+        } else if ("off".equals(opt)) {
+            enabled = false;
+        } else {
+            getErrPrintWriter().println("Error: unknown option " + opt);
+            return 1;
+        }
+        mInternal.setMonitorBattery(enabled);
+        if (enabled) pw.println("Battery monitoring enabled");
+        else pw.println("Battery monitoring disabled");
+        return 0;
+    }
+
+    private int runGetBatterySeq(PrintWriter pw) {
+        int seq = mInternal.getBatterySeq();
+        pw.println(seq);
+        return 0;
+    }
+
+    private int runGetBatteryCharging(PrintWriter pw) {
+        boolean val = mInternal.getBatteryCharging();
+        pw.println(val);
+        return 0;
+    }
+
+    private int runGetBatteryNotLow(PrintWriter pw) {
+        boolean val = mInternal.getBatteryNotLow();
+        pw.println(val);
+        return 0;
+    }
+
     @Override
     public void onHelp() {
         final PrintWriter pw = getOutPrintWriter();
@@ -140,7 +188,6 @@
         pw.println("Job scheduler (jobscheduler) commands:");
         pw.println("  help");
         pw.println("    Print this help text.");
-        pw.println();
         pw.println("  run [-f | --force] [-u | --user USER_ID] PACKAGE JOB_ID");
         pw.println("    Trigger immediate execution of a specific scheduled job.");
         pw.println("    Options:");
@@ -148,6 +195,15 @@
         pw.println("         connectivity are not currently met");
         pw.println("      -u or --user: specify which user's job is to be run; the default is");
         pw.println("         the primary or system user");
+        pw.println("  monitor-battery [on|off]");
+        pw.println("    Control monitoring of all battery changes.  Off by default.  Turning");
+        pw.println("    on makes get-battery-seq useful.");
+        pw.println("  get-battery-seq");
+        pw.println("    Return the last battery update sequence number that was received.");
+        pw.println("  get-battery-charging");
+        pw.println("    Return whether the battery is currently considered to be charging.");
+        pw.println("  get-battery-not-low");
+        pw.println("    Return whether the battery is currently considered to not be low.");
         pw.println();
     }
 
diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java
index dd3f85f..ccfc287 100644
--- a/services/core/java/com/android/server/job/JobStore.java
+++ b/services/core/java/com/android/server/job/JobStore.java
@@ -381,6 +381,9 @@
             if (jobStatus.hasChargingConstraint()) {
                 out.attribute(null, "charging", Boolean.toString(true));
             }
+            if (jobStatus.hasBatteryNotLowConstraint()) {
+                out.attribute(null, "battery-not-low", Boolean.toString(true));
+            }
             out.endTag(null, XML_TAG_PARAMS_CONSTRAINTS);
         }
 
diff --git a/services/core/java/com/android/server/job/controllers/BatteryController.java b/services/core/java/com/android/server/job/controllers/BatteryController.java
index f6b8ef4..05527be 100644
--- a/services/core/java/com/android/server/job/controllers/BatteryController.java
+++ b/services/core/java/com/android/server/job/controllers/BatteryController.java
@@ -80,32 +80,38 @@
 
     @Override
     public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) {
-        final boolean isOnStablePower = mChargeTracker.isOnStablePower();
-        if (taskStatus.hasChargingConstraint()) {
+        if (taskStatus.hasPowerConstraint()) {
             mTrackedTasks.add(taskStatus);
-            taskStatus.setChargingConstraintSatisfied(isOnStablePower);
+            taskStatus.setChargingConstraintSatisfied(mChargeTracker.isOnStablePower());
+            taskStatus.setBatteryNotLowConstraintSatisfied(mChargeTracker.isBatteryNotLow());
         }
     }
 
     @Override
     public void maybeStopTrackingJobLocked(JobStatus taskStatus, JobStatus incomingJob, boolean forUpdate) {
-        if (taskStatus.hasChargingConstraint()) {
+        if (taskStatus.hasPowerConstraint()) {
             mTrackedTasks.remove(taskStatus);
         }
     }
 
     private void maybeReportNewChargingState() {
         final boolean stablePower = mChargeTracker.isOnStablePower();
+        final boolean batteryNotLow = mChargeTracker.isBatteryNotLow();
         if (DEBUG) {
             Slog.d(TAG, "maybeReportNewChargingState: " + stablePower);
         }
         boolean reportChange = false;
         synchronized (mLock) {
-            for (JobStatus ts : mTrackedTasks) {
+            for (int i = mTrackedTasks.size() - 1; i >= 0; i--) {
+                final JobStatus ts = mTrackedTasks.get(i);
                 boolean previous = ts.setChargingConstraintSatisfied(stablePower);
                 if (previous != stablePower) {
                     reportChange = true;
                 }
+                previous = ts.setBatteryNotLowConstraintSatisfied(batteryNotLow);
+                if (previous != batteryNotLow) {
+                    reportChange = true;
+                }
             }
         }
         // Let the scheduler know that state has changed. This may or may not result in an
@@ -127,6 +133,10 @@
         private boolean mCharging;
         /** Keep track of whether the battery is charged enough that we want to do work. */
         private boolean mBatteryHealthy;
+        /** Sequence number of last broadcast. */
+        private int mLastBatterySeq = -1;
+
+        private BroadcastReceiver mMonitor;
 
         public ChargingTracker() {
         }
@@ -149,10 +159,42 @@
             mCharging = batteryManagerInternal.isPowered(BatteryManager.BATTERY_PLUGGED_ANY);
         }
 
-        boolean isOnStablePower() {
+        public void setMonitorBatteryLocked(boolean enabled) {
+            if (enabled) {
+                if (mMonitor == null) {
+                    mMonitor = new BroadcastReceiver() {
+                        @Override public void onReceive(Context context, Intent intent) {
+                            ChargingTracker.this.onReceive(context, intent);
+                        }
+                    };
+                    IntentFilter filter = new IntentFilter();
+                    filter.addAction(Intent.ACTION_BATTERY_CHANGED);
+                    mContext.registerReceiver(mMonitor, filter);
+                }
+            } else {
+                if (mMonitor != null) {
+                    mContext.unregisterReceiver(mMonitor);
+                    mMonitor = null;
+                }
+            }
+        }
+
+        public boolean isOnStablePower() {
             return mCharging && mBatteryHealthy;
         }
 
+        public boolean isBatteryNotLow() {
+            return mBatteryHealthy;
+        }
+
+        public boolean isMonitoring() {
+            return mMonitor != null;
+        }
+
+        public int getSeq() {
+            return mLastBatterySeq;
+        }
+
         @Override
         public void onReceive(Context context, Intent intent) {
             onReceiveInternal(intent);
@@ -191,13 +233,20 @@
                 mCharging = false;
                 maybeReportNewChargingState();
             }
+            mLastBatterySeq = intent.getIntExtra(BatteryManager.EXTRA_SEQUENCE, mLastBatterySeq);
         }
     }
 
     @Override
     public void dumpControllerStateLocked(PrintWriter pw, int filterUid) {
         pw.print("Battery: stable power = ");
-        pw.println(mChargeTracker.isOnStablePower());
+        pw.print(mChargeTracker.isOnStablePower());
+        pw.print(", not low = ");
+        pw.println(mChargeTracker.isBatteryNotLow());
+        if (mChargeTracker.isMonitoring()) {
+            pw.print("MONITORING: seq=");
+            pw.println(mChargeTracker.getSeq());
+        }
         pw.print("Tracking ");
         pw.print(mTrackedTasks.size());
         pw.println(":");
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 4b39bf9..9a55fed 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -46,16 +46,17 @@
     public static final long NO_LATEST_RUNTIME = Long.MAX_VALUE;
     public static final long NO_EARLIEST_RUNTIME = 0L;
 
-    static final int CONSTRAINT_CHARGING = 1<<0;
-    static final int CONSTRAINT_TIMING_DELAY = 1<<1;
-    static final int CONSTRAINT_DEADLINE = 1<<2;
-    static final int CONSTRAINT_IDLE = 1<<3;
-    static final int CONSTRAINT_UNMETERED = 1<<4;
-    static final int CONSTRAINT_CONNECTIVITY = 1<<5;
-    static final int CONSTRAINT_APP_NOT_IDLE = 1<<6;
-    static final int CONSTRAINT_CONTENT_TRIGGER = 1<<7;
-    static final int CONSTRAINT_DEVICE_NOT_DOZING = 1<<8;
-    static final int CONSTRAINT_NOT_ROAMING = 1<<9;
+    static final int CONSTRAINT_CHARGING = JobInfo.CONSTRAINT_FLAG_CHARGING;
+    static final int CONSTRAINT_IDLE = JobInfo.CONSTRAINT_FLAG_DEVICE_IDLE;
+    static final int CONSTRAINT_BATTERY_NOT_LOW = JobInfo.CONSTRAINT_FLAG_BATTERY_NOT_LOW;
+    static final int CONSTRAINT_TIMING_DELAY = 1<<31;
+    static final int CONSTRAINT_DEADLINE = 1<<30;
+    static final int CONSTRAINT_UNMETERED = 1<<29;
+    static final int CONSTRAINT_CONNECTIVITY = 1<<28;
+    static final int CONSTRAINT_APP_NOT_IDLE = 1<<27;
+    static final int CONSTRAINT_CONTENT_TRIGGER = 1<<26;
+    static final int CONSTRAINT_DEVICE_NOT_DOZING = 1<<25;
+    static final int CONSTRAINT_NOT_ROAMING = 1<<24;
 
     // Soft override: ignore constraints like time that don't affect API availability
     public static final int OVERRIDE_SOFT = 1;
@@ -163,7 +164,7 @@
         this.latestRunTimeElapsedMillis = latestRunTimeElapsedMillis;
         this.numFailures = numFailures;
 
-        int requiredConstraints = 0;
+        int requiredConstraints = job.getConstraintFlags();
         if (job.getNetworkType() == JobInfo.NETWORK_TYPE_ANY) {
             requiredConstraints |= CONSTRAINT_CONNECTIVITY;
         }
@@ -173,18 +174,12 @@
         if (job.getNetworkType() == JobInfo.NETWORK_TYPE_NOT_ROAMING) {
             requiredConstraints |= CONSTRAINT_NOT_ROAMING;
         }
-        if (job.isRequireCharging()) {
-            requiredConstraints |= CONSTRAINT_CHARGING;
-        }
         if (earliestRunTimeElapsedMillis != NO_EARLIEST_RUNTIME) {
             requiredConstraints |= CONSTRAINT_TIMING_DELAY;
         }
         if (latestRunTimeElapsedMillis != NO_LATEST_RUNTIME) {
             requiredConstraints |= CONSTRAINT_DEADLINE;
         }
-        if (job.isRequireDeviceIdle()) {
-            requiredConstraints |= CONSTRAINT_IDLE;
-        }
         if (job.getTriggerContentUris() != null) {
             requiredConstraints |= CONSTRAINT_CONTENT_TRIGGER;
         }
@@ -331,6 +326,14 @@
         return (requiredConstraints&CONSTRAINT_CHARGING) != 0;
     }
 
+    public boolean hasBatteryNotLowConstraint() {
+        return (requiredConstraints&CONSTRAINT_BATTERY_NOT_LOW) != 0;
+    }
+
+    public boolean hasPowerConstraint() {
+        return (requiredConstraints&(CONSTRAINT_CHARGING|CONSTRAINT_BATTERY_NOT_LOW)) != 0;
+    }
+
     public boolean hasTimingDelayConstraint() {
         return (requiredConstraints&CONSTRAINT_TIMING_DELAY) != 0;
     }
@@ -379,6 +382,10 @@
         return setConstraintSatisfied(CONSTRAINT_CHARGING, state);
     }
 
+    boolean setBatteryNotLowConstraintSatisfied(boolean state) {
+        return setConstraintSatisfied(CONSTRAINT_BATTERY_NOT_LOW, state);
+    }
+
     boolean setTimingDelayConstraintSatisfied(boolean state) {
         return setConstraintSatisfied(CONSTRAINT_TIMING_DELAY, state);
     }
@@ -453,13 +460,14 @@
     }
 
     static final int CONSTRAINTS_OF_INTEREST =
-            CONSTRAINT_CHARGING | CONSTRAINT_TIMING_DELAY |
+            CONSTRAINT_CHARGING | CONSTRAINT_BATTERY_NOT_LOW | CONSTRAINT_TIMING_DELAY |
             CONSTRAINT_CONNECTIVITY | CONSTRAINT_UNMETERED | CONSTRAINT_NOT_ROAMING |
             CONSTRAINT_IDLE | CONSTRAINT_CONTENT_TRIGGER;
 
     // Soft override covers all non-"functional" constraints
     static final int SOFT_OVERRIDE_CONSTRAINTS =
-            CONSTRAINT_CHARGING | CONSTRAINT_TIMING_DELAY | CONSTRAINT_IDLE;
+            CONSTRAINT_CHARGING | CONSTRAINT_BATTERY_NOT_LOW
+                    | CONSTRAINT_TIMING_DELAY | CONSTRAINT_IDLE;
 
     /**
      * @return Whether the constraints set on this job are satisfied.
@@ -495,6 +503,7 @@
                 + ",R=(" + formatRunTime(earliestRunTimeElapsedMillis, NO_EARLIEST_RUNTIME)
                 + "," + formatRunTime(latestRunTimeElapsedMillis, NO_LATEST_RUNTIME) + ")"
                 + ",N=" + job.getNetworkType() + ",C=" + job.isRequireCharging()
+                + ",BL=" + job.isRequireBatteryNotLow()
                 + ",I=" + job.isRequireDeviceIdle()
                 + ",U=" + (job.getTriggerContentUris() != null)
                 + ",F=" + numFailures + ",P=" + job.isPersisted()
@@ -550,6 +559,9 @@
         if ((constraints&CONSTRAINT_CHARGING) != 0) {
             pw.print(" CHARGING");
         }
+        if ((constraints& CONSTRAINT_BATTERY_NOT_LOW) != 0) {
+            pw.print(" BATTERY_NOT_LOW");
+        }
         if ((constraints&CONSTRAINT_TIMING_DELAY) != 0) {
             pw.print(" TIMING_DELAY");
         }
@@ -607,7 +619,8 @@
                 pw.println(Integer.toHexString(job.getFlags()));
             }
             pw.print(prefix); pw.print("  Requires: charging=");
-            pw.print(job.isRequireCharging()); pw.print(" deviceIdle=");
+            pw.print(job.isRequireCharging()); pw.print(" batteryNotLow=");
+            pw.print(job.isRequireBatteryNotLow()); pw.print(" deviceIdle=");
             pw.println(job.isRequireDeviceIdle());
             if (job.getTriggerContentUris() != null) {
                 pw.print(prefix); pw.println("  Trigger content URIs:");
diff --git a/services/core/java/com/android/server/location/ContextHubService.java b/services/core/java/com/android/server/location/ContextHubService.java
index a4c0fa8..258fb6d 100644
--- a/services/core/java/com/android/server/location/ContextHubService.java
+++ b/services/core/java/com/android/server/location/ContextHubService.java
@@ -120,36 +120,6 @@
         return mContextHubInfo[contextHubHandle];
     }
 
-    // TODO(b/30808791): Remove this when NanoApp's API is correctly treating
-    // app IDs as 64-bits.
-    private static long parseAppId(NanoApp app) {
-        // NOTE: If this shifting seems odd (since it's actually "ONAN"), note
-        //     that it matches how this is defined in context_hub.h.
-        final int HEADER_MAGIC =
-            (((int)'N' <<  0) |
-             ((int)'A' <<  8) |
-             ((int)'N' << 16) |
-             ((int)'O' << 24));
-        final int HEADER_MAGIC_OFFSET = 4;
-        final int HEADER_APP_ID_OFFSET = 8;
-
-        ByteBuffer header = ByteBuffer.wrap(app.getAppBinary())
-            .order(ByteOrder.LITTLE_ENDIAN);
-
-        try {
-            if (header.getInt(HEADER_MAGIC_OFFSET) == HEADER_MAGIC) {
-                // This is a legitimate nanoapp header.  Let's grab the app ID.
-                return header.getLong(HEADER_APP_ID_OFFSET);
-            }
-        } catch (IndexOutOfBoundsException e) {
-            // The header is undersized.  We'll fall through to our code
-            // path below, which handles being unable to parse the header.
-        }
-        // We failed to parse the header.  Even through it's probably wrong,
-        // let's give NanoApp's idea of our ID.  This is at least consistent.
-        return app.getAppId();
-    }
-
     @Override
     public int loadNanoApp(int contextHubHandle, NanoApp app) throws RemoteException {
         checkPermissions();
@@ -169,15 +139,6 @@
         msgHeader[HEADER_FIELD_MSG_TYPE] = MSG_LOAD_NANO_APP;
 
         long appId = app.getAppId();
-        // TODO(b/30808791): Remove this hack when the NanoApp API is fixed,
-        //     and getAppId() returns a 'long' instead of an 'int'.
-        if ((appId >> 32) != 0) {
-            // We're unlikely to notice this warning, but at least
-            // we can avoid running our hack logic.
-            Log.w(TAG, "Code has not been updated since API fix.");
-        } else {
-            appId = parseAppId(app);
-        }
 
         msgHeader[HEADER_FIELD_LOAD_APP_ID_LO] = (int)(appId & 0xFFFFFFFF);
         msgHeader[HEADER_FIELD_LOAD_APP_ID_HI] = (int)((appId >> 32) & 0xFFFFFFFF);
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index fdaba0b..3a1ddd7 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -16,13 +16,6 @@
 
 package com.android.server.location;
 
-import com.android.internal.app.IAppOpsService;
-import com.android.internal.app.IBatteryStats;
-import com.android.internal.location.GpsNetInitiatedHandler;
-import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
-import com.android.internal.location.ProviderProperties;
-import com.android.internal.location.ProviderRequest;
-
 import android.app.AlarmManager;
 import android.app.AppOpsManager;
 import android.app.PendingIntent;
@@ -55,6 +48,7 @@
 import android.net.NetworkRequest;
 import android.net.Uri;
 import android.os.AsyncTask;
+import android.os.PowerSaveState;
 import android.os.BatteryStats;
 import android.os.Binder;
 import android.os.Bundle;
@@ -81,6 +75,17 @@
 import android.util.Log;
 import android.util.NtpTrustedTime;
 
+import com.android.internal.app.IAppOpsService;
+import com.android.internal.app.IBatteryStats;
+import com.android.internal.location.GpsNetInitiatedHandler;
+import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
+import com.android.internal.location.ProviderProperties;
+import com.android.internal.location.ProviderRequest;
+import com.android.server.power.BatterySaverPolicy;
+import com.android.server.power.BatterySaverPolicy.ServiceType;
+
+import libcore.io.IoUtils;
+
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
@@ -96,7 +101,6 @@
 import java.util.Properties;
 import java.util.Map;
 import java.util.HashMap;
-import libcore.io.IoUtils;
 
 /**
  * A GNSS implementation of LocationProvider used by LocationManager.
@@ -243,14 +247,6 @@
     private static final int TCP_MIN_PORT = 0;
     private static final int TCP_MAX_PORT = 0xffff;
 
-    // Value of batterySaverGpsMode such that GPS isn't affected by battery saver mode.
-    private static final int BATTERY_SAVER_MODE_NO_CHANGE = 0;
-    // Value of batterySaverGpsMode such that GPS is disabled when battery saver mode
-    // is enabled and the screen is off.
-    private static final int BATTERY_SAVER_MODE_DISABLED_WHEN_SCREEN_OFF = 1;
-    // Secure setting for GPS behavior when battery saver mode is on.
-    private static final String BATTERY_SAVER_GPS_MODE = "batterySaverGpsMode";
-
     /** simpler wrapper for ProviderRequest + Worksource */
     private static class GpsRequest {
         public ProviderRequest request;
@@ -548,11 +544,12 @@
     private void updateLowPowerMode() {
         // Disable GPS if we are in device idle mode.
         boolean disableGps = mPowerManager.isDeviceIdleMode();
-        switch (Settings.Secure.getInt(mContext.getContentResolver(), BATTERY_SAVER_GPS_MODE,
-                BATTERY_SAVER_MODE_DISABLED_WHEN_SCREEN_OFF)) {
-            case BATTERY_SAVER_MODE_DISABLED_WHEN_SCREEN_OFF:
+        final PowerSaveState result =
+                mPowerManager.getPowerSaveState(ServiceType.GPS);
+        switch (result.gpsMode) {
+            case BatterySaverPolicy.GPS_MODE_DISABLED_WHEN_SCREEN_OFF:
                 // If we are in battery saver mode and the screen is off, disable GPS.
-                disableGps |= mPowerManager.isPowerSaveMode() && !mPowerManager.isInteractive();
+                disableGps |= result.batterySaverEnabled && !mPowerManager.isInteractive();
                 break;
         }
         if (disableGps != mDisableGps) {
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 407262b..ed558aa 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -37,6 +37,7 @@
 import android.media.IAudioService;
 import android.media.IRemoteVolumeController;
 import android.media.session.IActiveSessionsListener;
+import android.media.session.ICallback;
 import android.media.session.IOnMediaKeyListener;
 import android.media.session.IOnVolumeKeyLongPressListener;
 import android.media.session.ISession;
@@ -64,6 +65,7 @@
 import android.util.Slog;
 import android.util.SparseArray;
 import android.view.KeyEvent;
+import android.view.ViewConfiguration;
 
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
@@ -99,12 +101,14 @@
     private final Object mLock = new Object();
     private final MessageHandler mHandler = new MessageHandler();
     private final PowerManager.WakeLock mMediaEventWakeLock;
+    private final int mLongPressTimeout;
 
     private KeyguardManager mKeyguardManager;
     private IAudioService mAudioService;
     private AudioManagerInternal mAudioManagerInternal;
     private ContentResolver mContentResolver;
     private SettingsObserver mSettingsObserver;
+    private ICallback mCallback;
 
     // List of user IDs running in the foreground.
     // Multiple users can be in the foreground if the work profile is on.
@@ -120,6 +124,7 @@
         mPriorityStack = new MediaSessionStack();
         PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
         mMediaEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleMediaEvent");
+        mLongPressTimeout = ViewConfiguration.getLongPressTimeout();
     }
 
     @Override
@@ -483,6 +488,7 @@
             if (size > 0 && records.get(0).isPlaybackActive(false)) {
                 rememberMediaButtonReceiverLocked(records.get(0));
             }
+            pushAddressedPlayerChangedLocked();
             ArrayList<MediaSession.Token> tokens = new ArrayList<MediaSession.Token>();
             for (int i = 0; i < size; i++) {
                 tokens.add(new MediaSession.Token(records.get(i).getControllerBinder()));
@@ -514,6 +520,52 @@
         }
     }
 
+    private MediaSessionRecord getMediaButtonSessionLocked() {
+        // If we don't have a media button receiver to fall back on
+        // include non-playing sessions for dispatching.
+        boolean useNotPlayingSessions = true;
+        for (int userId : mCurrentUserIdList) {
+            UserRecord ur = mUserRecords.get(userId);
+            if (ur.mLastMediaButtonReceiver != null
+                    || ur.mRestoredMediaButtonReceiver != null) {
+                useNotPlayingSessions = false;
+                break;
+            }
+        }
+        return mPriorityStack.getDefaultMediaButtonSession(
+                mCurrentUserIdList, useNotPlayingSessions);
+    }
+
+    private void pushAddressedPlayerChangedLocked() {
+        if (mCallback == null) {
+            return;
+        }
+        try {
+            MediaSessionRecord mediaButtonSession = getMediaButtonSessionLocked();
+            if (mediaButtonSession != null) {
+                mCallback.onAddressedPlayerChangedToMediaSession(
+                        new MediaSession.Token(mediaButtonSession.getControllerBinder()));
+            } else {
+                for (int userId : mCurrentUserIdList) {
+                    UserRecord user = mUserRecords.get(userId);
+                    if (user.mLastMediaButtonReceiver == null
+                            && user.mRestoredMediaButtonReceiver == null) {
+                        continue;
+                    }
+                    ComponentName componentName = user.mLastMediaButtonReceiver != null
+                            ? user.mLastMediaButtonReceiver.getIntent().getComponent()
+                            : user.mRestoredMediaButtonReceiver;
+                    mCallback.onAddressedPlayerChangedToMediaButtonReceiver(componentName);
+                    return;
+                }
+            }
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to pushAddressedPlayerChangedLocked", e);
+        }
+    }
+
+    // Remember media button receiver and keep it in the persistent storage.
+    // This should be called whenever there's no media session to receive media button event.
     private void rememberMediaButtonReceiverLocked(MediaSessionRecord record) {
         PendingIntent receiver = record.getMediaButtonReceiver();
         UserRecord user = mUserRecords.get(record.getUserId());
@@ -536,6 +588,16 @@
         return "";
     }
 
+    private void dispatchVolumeKeyLongPressLocked(KeyEvent keyEvent) {
+        // Only consider full user.
+        UserRecord user = mUserRecords.get(mCurrentUserIdList.get(0));
+        try {
+            user.mOnVolumeKeyLongPressListener.onVolumeKeyLongPress(keyEvent);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to send " + keyEvent + " to volume key long-press listener");
+        }
+    }
+
     /**
      * Information about a particular user. The contents of this object is
      * guarded by mLock.
@@ -788,19 +850,74 @@
                             + "setup is in progress.");
                     return;
                 }
-                if (isGlobalPriorityActive() && uid != Process.SYSTEM_UID) {
-                    // Prevent dispatching key event through reflection while the global priority
-                    // session is active.
-                    Slog.i(TAG, "Only the system can dispatch media key event "
-                            + "to the global priority session.");
-                    return;
-                }
 
                 synchronized (mLock) {
-                    if (!isGlobalPriorityActive() && isVoiceKey(keyEvent.getKeyCode())) {
+                    boolean isGlobalPriorityActive = mPriorityStack.isGlobalPriorityActive();
+                    if (isGlobalPriorityActive && uid != Process.SYSTEM_UID) {
+                        // Prevent dispatching key event through reflection while the global
+                        // priority session is active.
+                        Slog.i(TAG, "Only the system can dispatch media key event "
+                                + "to the global priority session.");
+                        return;
+                    }
+                    if (!isGlobalPriorityActive) {
+                        // Only consider full user.
+                        UserRecord user = mUserRecords.get(mCurrentUserIdList.get(0));
+                        if (user.mOnMediaKeyListener != null) {
+                            if (DEBUG_KEY_EVENT) {
+                                Log.d(TAG, "Send " + keyEvent + " to media key listener");
+                            }
+                            try {
+                                user.mOnMediaKeyListener.onMediaKey(keyEvent,
+                                        new MediaKeyListenerResultReceiver(keyEvent, needWakeLock));
+                                return;
+                            } catch (RemoteException e) {
+                                Log.w(TAG, "Failed to send " + keyEvent + " to media key listener");
+                            }
+                        }
+                    }
+                    if (!isGlobalPriorityActive && isVoiceKey(keyEvent.getKeyCode())) {
                         handleVoiceKeyEventLocked(keyEvent, needWakeLock);
                     } else {
-                        dispatchMediaKeyEventLocked(keyEvent, needWakeLock, true);
+                        dispatchMediaKeyEventLocked(keyEvent, needWakeLock);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public void setCallback(ICallback callback) {
+            final int pid = Binder.getCallingPid();
+            final int uid = Binder.getCallingUid();
+            final long token = Binder.clearCallingIdentity();
+            try {
+                if (uid != Process.BLUETOOTH_UID) {
+                    throw new SecurityException("Only Bluetooth service processes can set"
+                            + " Callback");
+                }
+                synchronized (mLock) {
+                    Log.d(TAG, "Callback + " + mCallback
+                            + " is set by " + getCallingPackageName(uid));
+                    mCallback = callback;
+                    if (mCallback == null) {
+                        return;
+                    }
+                    try {
+                        mCallback.asBinder().linkToDeath(
+                                new IBinder.DeathRecipient() {
+                                    @Override
+                                    public void binderDied() {
+                                        synchronized (mLock) {
+                                            mCallback = null;
+                                        }
+                                    }
+                                }, 0);
+                        pushAddressedPlayerChangedLocked();
+                    } catch (RemoteException e) {
+                        Log.w(TAG, "Failed to set callback", e);
+                        mCallback = null;
                     }
                 }
             } finally {
@@ -936,7 +1053,7 @@
             final int uid = Binder.getCallingUid();
             final long token = Binder.clearCallingIdentity();
 
-            if (DEBUG) {
+            if (DEBUG_KEY_EVENT) {
                 Log.d(TAG, "dispatchVolumeKeyEvent, pid=" + pid + ", uid=" + uid + ", event="
                         + keyEvent);
             }
@@ -944,7 +1061,8 @@
             try {
                 synchronized (mLock) {
                     // Only consider full user.
-                    UserRecord user = mUserRecords.get(mCurrentUserIdList.get(0));
+                    int userId = mCurrentUserIdList.get(0);
+                    UserRecord user = mUserRecords.get(userId);
 
                     if (mPriorityStack.isGlobalPriorityActive()
                             || user.mOnVolumeKeyLongPressListener == null) {
@@ -954,11 +1072,17 @@
                         //       at the same time.
                         if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
                             if (keyEvent.getRepeatCount() == 0) {
-                                user.mInitialDownVolumeKeyEvent = keyEvent;
+                                // Keeps the copy of the KeyEvent because it can be reused.
+                                user.mInitialDownVolumeKeyEvent = KeyEvent.obtain(keyEvent);
                                 user.mInitialDownVolumeStream = stream;
                                 user.mInitialDownMusicOnly = musicOnly;
+                                mHandler.sendMessageDelayed(
+                                        mHandler.obtainMessage(
+                                                MessageHandler.MSG_VOLUME_INITIAL_DOWN, userId, 0),
+                                        mLongPressTimeout);
                             }
                             if (keyEvent.getRepeatCount() > 0 || keyEvent.isLongPress()) {
+                                mHandler.removeMessages(MessageHandler.MSG_VOLUME_INITIAL_DOWN);
                                 if (user.mInitialDownVolumeKeyEvent != null) {
                                     dispatchVolumeKeyLongPressLocked(
                                             user.mInitialDownVolumeKeyEvent);
@@ -968,6 +1092,7 @@
                                 dispatchVolumeKeyLongPressLocked(keyEvent);
                             }
                         } else { // if up
+                            mHandler.removeMessages(MessageHandler.MSG_VOLUME_INITIAL_DOWN);
                             if (user.mInitialDownVolumeKeyEvent != null
                                     && user.mInitialDownVolumeKeyEvent.getDownTime()
                                             == keyEvent.getDownTime()) {
@@ -988,16 +1113,6 @@
             }
         }
 
-        private void dispatchVolumeKeyLongPressLocked(KeyEvent keyEvent) {
-            // Only consider full user.
-            UserRecord user = mUserRecords.get(mCurrentUserIdList.get(0));
-            try {
-                user.mOnVolumeKeyLongPressListener.onVolumeKeyLongPress(keyEvent);
-            } catch (RemoteException e) {
-                Log.w(TAG, "Failed to send " + keyEvent + " to volume key long-press listener");
-            }
-        }
-
         private void dispatchVolumeKeyEventLocked(
                 KeyEvent keyEvent, int stream, boolean musicOnly) {
             boolean down = keyEvent.getAction() == KeyEvent.ACTION_DOWN;
@@ -1069,7 +1184,9 @@
 
         @Override
         public boolean isGlobalPriorityActive() {
-            return mPriorityStack.isGlobalPriorityActive();
+            synchronized (mLock) {
+                return mPriorityStack.isGlobalPriorityActive();
+            }
         }
 
         @Override
@@ -1125,7 +1242,7 @@
                     && AudioSystem.isStreamActive(suggestedStream, 0)) {
                 preferSuggestedStream = true;
             }
-            if (DEBUG) {
+            if (DEBUG_KEY_EVENT) {
                 Log.d(TAG, "Adjusting " + session + " by " + direction + ". flags="
                         + flags + ", suggestedStream=" + suggestedStream
                         + ", preferSuggestedStream=" + preferSuggestedStream);
@@ -1179,52 +1296,15 @@
                     if (!mVoiceButtonHandled && !keyEvent.isCanceled()) {
                         // Resend the down then send this event through
                         KeyEvent downEvent = KeyEvent.changeAction(keyEvent, KeyEvent.ACTION_DOWN);
-                        dispatchMediaKeyEventLocked(downEvent, needWakeLock, true);
-                        dispatchMediaKeyEventLocked(keyEvent, needWakeLock, true);
+                        dispatchMediaKeyEventLocked(downEvent, needWakeLock);
+                        dispatchMediaKeyEventLocked(keyEvent, needWakeLock);
                     }
                 }
             }
         }
 
-        private void dispatchMediaKeyEventLocked(KeyEvent keyEvent, boolean needWakeLock,
-                boolean checkMediaKeyListener) {
-            // If we don't have a media button receiver to fall back on
-            // include non-playing sessions for dispatching.
-            boolean useNotPlayingSessions = true;
-            for (int userId : mCurrentUserIdList) {
-                UserRecord ur = mUserRecords.get(userId);
-                if (ur.mLastMediaButtonReceiver != null
-                        || ur.mRestoredMediaButtonReceiver != null) {
-                    useNotPlayingSessions = false;
-                    break;
-                }
-            }
-            if (DEBUG) {
-                Log.d(TAG, "dispatchMediaKeyEvent, useNotPlayingSessions="
-                        + useNotPlayingSessions);
-            }
-
-            MediaSessionRecord session = mPriorityStack.getDefaultMediaButtonSession(
-                    mCurrentUserIdList, useNotPlayingSessions);
-
-            if ((session == null
-                    || !session.hasFlag(MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY))
-                    && checkMediaKeyListener) {
-                // Only consider full user.
-                UserRecord user = mUserRecords.get(mCurrentUserIdList.get(0));
-                if (user.mOnMediaKeyListener != null) {
-                    if (DEBUG_KEY_EVENT) {
-                        Log.d(TAG, "Send " + keyEvent + " to media key listener");
-                    }
-                    try {
-                        user.mOnMediaKeyListener.onMediaKey(keyEvent,
-                                new MediaKeyListenerResultReceiver(keyEvent, needWakeLock));
-                        return;
-                    } catch (RemoteException e) {
-                        Log.w(TAG, "Failed to send " + keyEvent + " to media key listener");
-                    }
-                }
-            }
+        private void dispatchMediaKeyEventLocked(KeyEvent keyEvent, boolean needWakeLock) {
+            MediaSessionRecord session = getMediaButtonSessionLocked();
             if (session != null) {
                 if (DEBUG_KEY_EVENT) {
                     Log.d(TAG, "Sending " + keyEvent + " to " + session);
@@ -1237,6 +1317,14 @@
                         needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1,
                         mKeyEventReceiver, Process.SYSTEM_UID,
                         getContext().getPackageName());
+                if (mCallback != null) {
+                    try {
+                        mCallback.onMediaKeyEventDispatchedToMediaSession(keyEvent,
+                                new MediaSession.Token(session.getControllerBinder()));
+                    } catch (RemoteException e) {
+                        Log.w(TAG, "Failed to send callback", e);
+                    }
+                }
             } else {
                 // Launch the last PendingIntent we had with priority
                 for (int userId : mCurrentUserIdList) {
@@ -1253,26 +1341,41 @@
                     mediaButtonIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
                     try {
                         if (user.mLastMediaButtonReceiver != null) {
+                            PendingIntent receiver = user.mLastMediaButtonReceiver;
                             if (DEBUG_KEY_EVENT) {
                                 Log.d(TAG, "Sending " + keyEvent
-                                        + " to the last known pendingIntent "
-                                        + user.mLastMediaButtonReceiver);
+                                        + " to the last known pendingIntent " + receiver);
                             }
-                            user.mLastMediaButtonReceiver.send(getContext(),
+                            receiver.send(getContext(),
                                     needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1,
                                     mediaButtonIntent, mKeyEventReceiver, mHandler);
+                            if (mCallback != null) {
+                                ComponentName componentName =
+                                        user.mLastMediaButtonReceiver.getIntent().getComponent();
+                                if (componentName != null) {
+                                    mCallback.onMediaKeyEventDispatchedToMediaButtonReceiver(
+                                            keyEvent, componentName);
+                                }
+                            }
                         } else {
+                            ComponentName receiver = user.mRestoredMediaButtonReceiver;
                             if (DEBUG_KEY_EVENT) {
                                 Log.d(TAG, "Sending " + keyEvent + " to the restored intent "
-                                        + user.mRestoredMediaButtonReceiver);
+                                        + receiver);
                             }
-                            mediaButtonIntent.setComponent(user.mRestoredMediaButtonReceiver);
+                            mediaButtonIntent.setComponent(receiver);
                             getContext().sendBroadcastAsUser(mediaButtonIntent,
                                     UserHandle.of(userId));
+                            if (mCallback != null) {
+                                mCallback.onMediaKeyEventDispatchedToMediaButtonReceiver(
+                                        keyEvent, receiver);
+                            }
                         }
                     } catch (CanceledException e) {
                         Log.i(TAG, "Error sending key event to media button receiver "
                                 + user.mLastMediaButtonReceiver, e);
+                    } catch (RemoteException e) {
+                        Log.w(TAG, "Failed to send callback", e);
                     }
                     return;
                 }
@@ -1383,7 +1486,12 @@
                 mHandled = true;
                 mHandler.removeCallbacks(this);
                 synchronized (mLock) {
-                    dispatchMediaKeyEventLocked(mKeyEvent, mNeedWakeLock, false);
+                    if (!mPriorityStack.isGlobalPriorityActive()
+                            && isVoiceKey(mKeyEvent.getKeyCode())) {
+                        handleVoiceKeyEventLocked(mKeyEvent, mNeedWakeLock);
+                    } else {
+                        dispatchMediaKeyEventLocked(mKeyEvent, mNeedWakeLock);
+                    }
                 }
             }
         }
@@ -1480,6 +1588,7 @@
 
     final class MessageHandler extends Handler {
         private static final int MSG_SESSIONS_CHANGED = 1;
+        private static final int MSG_VOLUME_INITIAL_DOWN = 2;
 
         @Override
         public void handleMessage(Message msg) {
@@ -1487,6 +1596,16 @@
                 case MSG_SESSIONS_CHANGED:
                     pushSessionsChanged(msg.arg1);
                     break;
+                case MSG_VOLUME_INITIAL_DOWN:
+                    synchronized (mLock) {
+                        UserRecord user = mUserRecords.get((int) msg.arg1);
+                        if (user != null && user.mInitialDownVolumeKeyEvent != null) {
+                            dispatchVolumeKeyLongPressLocked(user.mInitialDownVolumeKeyEvent);
+                            // Mark that the key is already handled.
+                            user.mInitialDownVolumeKeyEvent = null;
+                        }
+                    }
+                    break;
             }
         }
 
diff --git a/services/core/java/com/android/server/net/LockdownVpnTracker.java b/services/core/java/com/android/server/net/LockdownVpnTracker.java
index 4a8539a..a5e7d7c 100644
--- a/services/core/java/com/android/server/net/LockdownVpnTracker.java
+++ b/services/core/java/com/android/server/net/LockdownVpnTracker.java
@@ -47,6 +47,7 @@
 import com.android.internal.R;
 import com.android.internal.net.VpnConfig;
 import com.android.internal.net.VpnProfile;
+import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.util.Preconditions;
 import com.android.server.ConnectivityService;
 import com.android.server.EventLogTags;
@@ -330,18 +331,18 @@
     }
 
     private void showNotification(int titleRes, int iconRes) {
-        final Notification.Builder builder = new Notification.Builder(mContext)
-                .setWhen(0)
-                .setSmallIcon(iconRes)
-                .setContentTitle(mContext.getString(titleRes))
-                .setContentText(mContext.getString(R.string.vpn_lockdown_config))
-                .setContentIntent(mConfigIntent)
-                .setPriority(Notification.PRIORITY_LOW)
-                .setOngoing(true)
-                .addAction(R.drawable.ic_menu_refresh, mContext.getString(R.string.reset),
-                        mResetIntent)
-                .setColor(mContext.getColor(
-                        com.android.internal.R.color.system_notification_accent_color));
+        final Notification.Builder builder =
+                new Notification.Builder(mContext, SystemNotificationChannels.VPN)
+                        .setWhen(0)
+                        .setSmallIcon(iconRes)
+                        .setContentTitle(mContext.getString(titleRes))
+                        .setContentText(mContext.getString(R.string.vpn_lockdown_config))
+                        .setContentIntent(mConfigIntent)
+                        .setOngoing(true)
+                        .addAction(R.drawable.ic_menu_refresh, mContext.getString(R.string.reset),
+                                mResetIntent)
+                        .setColor(mContext.getColor(
+                                com.android.internal.R.color.system_notification_accent_color));
 
         NotificationManager.from(mContext).notify(TAG, 0, builder.build());
     }
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 91c9316..4e9d838 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -23,7 +23,6 @@
 import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
 import static android.Manifest.permission.READ_PHONE_STATE;
 import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE;
-import static android.app.ActivityThread.INVALID_PROC_STATE_SEQ;
 import static android.content.Intent.ACTION_PACKAGE_ADDED;
 import static android.content.Intent.ACTION_UID_REMOVED;
 import static android.content.Intent.ACTION_USER_ADDED;
@@ -54,15 +53,13 @@
 import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
 import static android.net.NetworkPolicyManager.MASK_METERED_NETWORKS;
 import static android.net.NetworkPolicyManager.MASK_ALL_NETWORKS;
-import static android.net.NetworkPolicyManager.RULE_INVALID;
 import static android.net.NetworkPolicyManager.RULE_NONE;
 import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
 import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
 import static android.net.NetworkPolicyManager.RULE_TEMPORARY_ALLOW_METERED;
-import static android.net.NetworkPolicyManager.UidStateWithSeqObserver;
 import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
 import static android.net.NetworkPolicyManager.isProcStateAllowedWhileIdleOrPowerSaveMode;
-import static android.net.NetworkPolicyManager.isProcStateAllowedWhileRestrictBackgroundOn;
+import static android.net.NetworkPolicyManager.isProcStateAllowedWhileOnRestrictBackground;
 import static android.net.NetworkPolicyManager.uidPoliciesToString;
 import static android.net.NetworkPolicyManager.uidRulesToString;
 import static android.net.NetworkTemplate.MATCH_MOBILE_3G_LOWER;
@@ -99,7 +96,6 @@
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
-import android.app.ActivityManagerInternal;
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
 import android.app.IActivityManager;
@@ -129,15 +125,14 @@
 import android.net.NetworkIdentity;
 import android.net.NetworkInfo;
 import android.net.NetworkPolicy;
-import android.net.NetworkPolicyManager;
 import android.net.NetworkQuotaInfo;
 import android.net.NetworkState;
 import android.net.NetworkTemplate;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
+import android.os.PowerSaveState;
 import android.os.Binder;
-import android.os.Debug;
 import android.os.Environment;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -169,16 +164,15 @@
 import android.util.NtpTrustedTime;
 import android.util.Pair;
 import android.util.Slog;
-import android.util.SparseArray;
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
-import android.util.SparseLongArray;
 import android.util.TrustedTime;
 import android.util.Xml;
 
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.IndentingPrintWriter;
@@ -187,6 +181,7 @@
 import com.android.server.LocalServices;
 import com.android.server.SystemConfig;
 
+import com.android.server.power.BatterySaverPolicy.ServiceType;
 import libcore.io.IoUtils;
 
 import com.google.android.collect.Lists;
@@ -220,16 +215,14 @@
  * enforcement.
  *
  * <p>
- * This class uses 4 locks to synchronize state:
+ * This class uses 2-3 locks to synchronize state:
  * <ul>
  * <li>{@code mUidRulesFirstLock}: used to guard state related to individual UIDs (such as firewall
  * rules).
  * <li>{@code mNetworkPoliciesSecondLock}: used to guard state related to network interfaces (such
  * as network policies).
- * <li>{@code mDispatchedThirdLock}: used to guard state related to process state sequence numbers
- * of uids which are currently blocked waiting for network.
- * <li>{@code allLocks}: not a "real" lock, but an indication (through @GuardedBy) that both locks
- * {@code mUidRulesFirstLock} and {@code mNetworkPoliciesSecondLock} must be held.
+ * <li>{@code allLocks}: not a "real" lock, but an indication (through @GuardedBy) that all locks
+ * must be held.
  * </ul>
  *
  * <p>
@@ -237,11 +230,8 @@
  * <ul>
  * <li>{@code UL()}: require the "UID" lock ({@code mUidRulesFirstLock}).
  * <li>{@code NL()}: require the "Network" lock ({@code mNetworkPoliciesSecondLock}).
- * <li>{@code DL()}: require the "Dispatched" lock ({@code mDispatchedThirdLock}).
- * <li>{@code AL()}: require both locks {@code mUidRulesFirstLock} and
- * {@code mNetworkPoliciesSecondLock}.
- * When multiple locks are needed, they must be obtained in order ({@code mUidRulesFirstLock}
- * first, then {@code mNetworkPoliciesSecondLock}, then {@code mDispatchedThirdLock}, etc..
+ * <li>{@code AL()}: require all locks, which must be obtained in order ({@code mUidRulesFirstLock}
+ * first, then {@code mNetworkPoliciesSecondLock}, then {@code mYetAnotherGuardThirdLock}, etc..
  * </ul>
  */
 public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
@@ -328,27 +318,6 @@
     // See main javadoc for instructions on how to use these locks.
     final Object mUidRulesFirstLock = new Object();
     final Object mNetworkPoliciesSecondLock = new Object();
-    final Object mDispatchedThirdLock = new Object();
-
-    @GuardedBy("mDispatchedThirdLock")
-    private final SparseLongArray mLastHandledProcStateSeq = new SparseLongArray();
-
-    /**
-     * Used for tracking whether the updated uid and firewall rules have been dispatched to
-     * ConnectivityService and NetworkManagementService respectively.
-     *
-     * SparseIntArray: uid -> dispatch flags (one or more combinations of {@link #FLAG_NONE},
-     * {@link #FLAG_UID_RULES_DISPATCHED}, {@link #FLAG_FIREWALL_RULES_DISPATCHED} and
-     * {@link #FLAG_ALL_RULES_DISPATCHED}).
-     */
-    @GuardedBy("mDispatchedThirdLock")
-    private final SparseIntArray mDispatchFlagsForCurProcStateSeq = new SparseIntArray();
-
-    private final int FLAG_NONE = 0;
-    private final int FLAG_UID_RULES_DISPATCHED = 1 << 0;
-    private final int FLAG_FIREWALL_RULES_DISPATCHED = 1 << 1;
-    private final int FLAG_ALL_RULES_DISPATCHED =
-            (FLAG_UID_RULES_DISPATCHED | FLAG_FIREWALL_RULES_DISPATCHED);
 
     @GuardedBy("allLocks") volatile boolean mSystemReady;
 
@@ -443,8 +412,6 @@
 
     private final IPackageManager mIPm;
 
-    private ActivityManagerInternal mActivityManagerInternal;
-
 
     // TODO: keep whitelist of system-critical services that should never have
     // rules enforced, such as system, phone, and radio UIDs.
@@ -625,18 +592,26 @@
                     mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
                     mPowerManagerInternal.registerLowPowerModeObserver(
                             new PowerManagerInternal.LowPowerModeListener() {
-                        @Override
-                        public void onLowPowerModeChanged(boolean enabled) {
-                            if (LOGD) Slog.d(TAG, "onLowPowerModeChanged(" + enabled + ")");
-                            synchronized (mUidRulesFirstLock) {
-                                if (mRestrictPower != enabled) {
-                                    mRestrictPower = enabled;
-                                    updateRulesForRestrictPowerUL();
+                                @Override
+                                public int getServiceType() {
+                                    return ServiceType.NETWORK_FIREWALL;
                                 }
-                            }
-                        }
+
+                                @Override
+                                public void onLowPowerModeChanged(PowerSaveState result) {
+                                    final boolean enabled = result.batterySaverEnabled;
+                                    if (LOGD) Slog.d(TAG,
+                                            "onLowPowerModeChanged(" + enabled + ")");
+                                    synchronized (mUidRulesFirstLock) {
+                                        if (mRestrictPower != enabled) {
+                                            mRestrictPower = enabled;
+                                            updateRulesForRestrictPowerUL();
+                                        }
+                                    }
+                                }
                     });
-                    mRestrictPower = mPowerManagerInternal.getLowPowerModeEnabled();
+                    mRestrictPower = mPowerManagerInternal.getLowPowerState(
+                            ServiceType.NETWORK_FIREWALL).batterySaverEnabled;
 
                     mSystemReady = true;
 
@@ -655,16 +630,13 @@
 
             try {
                 mActivityManager.registerUidObserver(mUidObserver,
-                        ActivityManager.UID_OBSERVER_GONE,
+                        ActivityManager.UID_OBSERVER_PROCSTATE|ActivityManager.UID_OBSERVER_GONE,
                         ActivityManager.PROCESS_STATE_UNKNOWN, null);
                 mNetworkManager.registerObserver(mAlertObserver);
             } catch (RemoteException e) {
                 // ignored; both services live in system_server
             }
 
-            mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
-            mActivityManagerInternal.setUidStateWithSeqObserver(mUidStateWithSeqObserver);
-
             // listen for changes to power save whitelist
             final IntentFilter whitelistFilter = new IntentFilter(
                     PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED);
@@ -746,24 +718,17 @@
         }
     }
 
-    final private UidStateWithSeqObserver mUidStateWithSeqObserver = new UidStateWithSeqObserver() {
-        @Override
-        public void onUidStateChangedWithSeq(int uid, int procState, long procStateSeq) {
+    final private IUidObserver mUidObserver = new IUidObserver.Stub() {
+        @Override public void onUidStateChanged(int uid, int procState) throws RemoteException {
             Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "onUidStateChanged");
             try {
-                final long effectiveProcStateSeq = getEffectiveProcStateSeq(uid, procStateSeq);
                 synchronized (mUidRulesFirstLock) {
-                    updateUidStateUL(uid, procState, effectiveProcStateSeq);
+                    updateUidStateUL(uid, procState);
                 }
             } finally {
                 Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
             }
         }
-    };
-
-    final private IUidObserver mUidObserver = new IUidObserver.Stub() {
-        @Override public void onUidStateChanged(int uid, int procState) throws RemoteException {
-        }
 
         @Override public void onUidGone(int uid, boolean disabled) throws RemoteException {
             synchronized (mUidRulesFirstLock) {
@@ -1115,7 +1080,8 @@
      */
     private void enqueueNotification(NetworkPolicy policy, int type, long totalBytes) {
         final String tag = buildNotificationTag(policy, type);
-        final Notification.Builder builder = new Notification.Builder(mContext);
+        final Notification.Builder builder =
+                new Notification.Builder(mContext, SystemNotificationChannels.NETWORK_STATUS);
         builder.setOnlyAlertOnce(true);
         builder.setWhen(0L);
         builder.setColor(mContext.getColor(
@@ -1133,7 +1099,7 @@
                 builder.setContentTitle(title);
                 builder.setContentText(body);
                 builder.setDefaults(Notification.DEFAULT_ALL);
-                builder.setPriority(Notification.PRIORITY_HIGH);
+                builder.setChannel(SystemNotificationChannels.NETWORK_ALERTS);
 
                 final Intent snoozeIntent = buildSnoozeWarningIntent(policy.template);
                 builder.setDeleteIntent(PendingIntent.getBroadcast(
@@ -1890,7 +1856,7 @@
         }
 
         // uid policy changed, recompute rules and persist policy.
-        updateRulesForDataUsageRestrictionsUL(uid, true);
+        updateRulesForDataUsageRestrictionsUL(uid);
         if (persist) {
             synchronized (mNetworkPoliciesSecondLock) {
                 writePolicyAL();
@@ -2489,7 +2455,7 @@
 
     private boolean isUidForegroundOnRestrictBackgroundUL(int uid) {
         final int procState = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
-        return isProcStateAllowedWhileRestrictBackgroundOn(procState);
+        return isProcStateAllowedWhileOnRestrictBackground(procState);
     }
 
     private boolean isUidForegroundOnRestrictPowerUL(int uid) {
@@ -2507,50 +2473,26 @@
      * {@link #updateRulesForDataUsageRestrictionsUL(int)} and
      * {@link #updateRulesForPowerRestrictionsUL(int)}
      */
-    private void updateUidStateUL(int uid, int uidState, long procStateSeq) {
+    private void updateUidStateUL(int uid, int uidState) {
         Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateUidStateUL");
         try {
             final int oldUidState = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
             if (oldUidState != uidState) {
                 // state changed, push updated rules
                 mUidState.put(uid, uidState);
-                if (procStateSeq != INVALID_PROC_STATE_SEQ) {
-                    int updatedUidRules = RULE_INVALID;
-                    ReturnStatus status = updateRestrictBackgroundRulesOnUidStatusChangedUL(
-                            uid, oldUidState, uidState, false);
-                    if (status != null && status.mNeedToNotify) {
-                        updatedUidRules = status.mNewUidRules;
+                updateRestrictBackgroundRulesOnUidStatusChangedUL(uid, oldUidState, uidState);
+                if (isProcStateAllowedWhileIdleOrPowerSaveMode(oldUidState)
+                        != isProcStateAllowedWhileIdleOrPowerSaveMode(uidState) ) {
+                    if (isUidIdle(uid)) {
+                        updateRuleForAppIdleUL(uid);
                     }
-                    final boolean procStateChangedAllowedWhileIdleOrPowerSaveMode =
-                            isProcStateAllowedWhileIdleOrPowerSaveMode(oldUidState)
-                                    != isProcStateAllowedWhileIdleOrPowerSaveMode(uidState);
-                    if (procStateChangedAllowedWhileIdleOrPowerSaveMode) {
-                        status = updateRulesForPowerRestrictionsUL(uid, false);
-                        if (status != null && status.mNeedToNotify) {
-                            updatedUidRules = status.mNewUidRules;
-                        }
+                    if (mDeviceIdleMode) {
+                        updateRuleForDeviceIdleUL(uid);
                     }
-                    // TODO: We can avoid this if the rules are not changed. But since dispatching
-                    // to ConnectivityService is currently asynchronous, we need this to make sure
-                    // any previous the msg_rules_changes have been handled. Optimize this once
-                    // dispatching from NPMS to ConnectivityService is made synchronous.
-                    mHandler.obtainMessage(MSG_RULES_CHANGED, uid, updatedUidRules,
-                            procStateSeq).sendToTarget();
-                    if (procStateChangedAllowedWhileIdleOrPowerSaveMode) {
-                        if (isUidIdle(uid)) {
-                            updateRuleForAppIdleUL(uid);
-                        }
-                        if (mDeviceIdleMode) {
-                            updateRuleForDeviceIdleUL(uid);
-                        }
-                        if (mRestrictPower) {
-                            updateRuleForRestrictPowerUL(uid);
-                        }
+                    if (mRestrictPower) {
+                        updateRuleForRestrictPowerUL(uid);
                     }
-                    synchronized (mDispatchedThirdLock) {
-                        setDispatchedFlagDL(uid, procStateSeq, FLAG_FIREWALL_RULES_DISPATCHED);
-                        checkAndNotifyDL(uid, procStateSeq);
-                    }
+                    updateRulesForPowerRestrictionsUL(uid);
                 }
                 updateNetworkStats(uid, isUidStateForegroundUL(uidState));
             }
@@ -2559,61 +2501,6 @@
         }
     }
 
-    /**
-     * Returns {@link android.app.ActivityThread#INVALID_PROC_STATE_SEQ} if acting on
-     * {@param procStateSeq} leads to an invalid state, otherwise update global state and return
-     * {@param procStateSeq}.
-     */
-    private long getEffectiveProcStateSeq(int uid, long procStateSeq) {
-        synchronized (mDispatchedThirdLock) {
-            final long lastHandledProcStateSeq = mLastHandledProcStateSeq.get(uid);
-            if (procStateSeq < lastHandledProcStateSeq) {
-                Slog.wtf(TAG, "procStateSeq from AMS should never go down, procStateSeq: "
-                        + procStateSeq + " lastHandledProcStateSeq: " + lastHandledProcStateSeq
-                        + " uid: " + uid);
-                return INVALID_PROC_STATE_SEQ;
-            }
-            if (procStateSeq == lastHandledProcStateSeq) {
-                if (LOGD) {
-                    Slog.d(TAG, "procStateSeq: " + procStateSeq + " is not changed, so process is "
-                            + "not jumping from background to foreground or vice versa. "
-                            + "uid: " + uid);
-                }
-                return INVALID_PROC_STATE_SEQ;
-            }
-            mLastHandledProcStateSeq.put(uid, procStateSeq);
-            mDispatchFlagsForCurProcStateSeq.put(uid, 0);
-            return procStateSeq;
-        }
-    }
-
-    /**
-     * Update dispatch flags to include {@param flag}.
-     */
-    private void setDispatchedFlagDL(int uid, long procStateSeq, int flag) {
-        int dispatchedFlag = mDispatchFlagsForCurProcStateSeq.get(uid);
-        dispatchedFlag |= flag;
-        mDispatchFlagsForCurProcStateSeq.put(uid, dispatchedFlag);
-    }
-
-    /**
-     * Check whether uid and firewall rules are dispatched to ConnectivityService and
-     * NetworkManagementService respectively, if so notify ActivityManagerService that network
-     * rules are updated.
-     */
-    private void checkAndNotifyDL(int uid, long procStateSeq) {
-        synchronized (mDispatchedThirdLock) {
-            final int dispatchedFlags = mDispatchFlagsForCurProcStateSeq.get(uid);
-            if (dispatchedFlags == FLAG_ALL_RULES_DISPATCHED) {
-                if (LOGD) {
-                    Slog.d(TAG, "Notifying AMS that network rules are updated for uid: " + uid
-                            + " seq: " + procStateSeq + " callers: " + Debug.getCallers(3));
-                }
-                mActivityManagerInternal.notifyNetworkPolicyRulesUpdated(uid, procStateSeq);
-            }
-        }
-    }
-
     private void removeUidStateUL(int uid) {
         final int index = mUidState.indexOfKey(uid);
         if (index >= 0) {
@@ -2621,21 +2508,17 @@
             mUidState.removeAt(index);
             if (oldUidState != ActivityManager.PROCESS_STATE_CACHED_EMPTY) {
                 updateRestrictBackgroundRulesOnUidStatusChangedUL(uid, oldUidState,
-                        ActivityManager.PROCESS_STATE_CACHED_EMPTY, true);
+                        ActivityManager.PROCESS_STATE_CACHED_EMPTY);
                 if (mDeviceIdleMode) {
                     updateRuleForDeviceIdleUL(uid);
                 }
                 if (mRestrictPower) {
                     updateRuleForRestrictPowerUL(uid);
                 }
-                updateRulesForPowerRestrictionsUL(uid, true);
+                updateRulesForPowerRestrictionsUL(uid);
                 updateNetworkStats(uid, false);
             }
         }
-        synchronized (mDispatchedThirdLock) {
-            mLastHandledProcStateSeq.delete(uid);
-            mDispatchFlagsForCurProcStateSeq.delete(uid);
-        }
     }
 
     // adjust stats accounting based on foreground status
@@ -2647,16 +2530,15 @@
         }
     }
 
-    private ReturnStatus updateRestrictBackgroundRulesOnUidStatusChangedUL(int uid, int oldUidState,
-            int newUidState, boolean notify) {
+    private void updateRestrictBackgroundRulesOnUidStatusChangedUL(int uid, int oldUidState,
+            int newUidState) {
         final boolean oldForeground =
-                isProcStateAllowedWhileRestrictBackgroundOn(oldUidState);
+                isProcStateAllowedWhileOnRestrictBackground(oldUidState);
         final boolean newForeground =
-                isProcStateAllowedWhileRestrictBackgroundOn(newUidState);
+                isProcStateAllowedWhileOnRestrictBackground(newUidState);
         if (oldForeground != newForeground) {
-            return updateRulesForDataUsageRestrictionsUL(uid, notify);
+            updateRulesForDataUsageRestrictionsUL(uid);
         }
-        return null;
     }
 
     void updateRulesForPowerSaveUL() {
@@ -2732,8 +2614,7 @@
     // (mPowerSaveTempWhitelistAppIds) for whitelisting, we can reuse their logic in this method.
     private void updateRulesForWhitelistedPowerSaveUL(int uid, boolean enabled, int chain) {
         if (enabled) {
-            if (isWhitelistedBatterySaverUL(uid)
-                    || isProcStateAllowedWhileIdleOrPowerSaveMode(mUidState.get(uid))) {
+            if (isWhitelistedBatterySaverUL(uid) || isUidForegroundOnRestrictPowerUL(uid)) {
                 setUidFirewallRule(chain, uid, FIREWALL_RULE_ALLOW);
             } else {
                 setUidFirewallRule(chain, uid, FIREWALL_RULE_DEFAULT);
@@ -2805,7 +2686,7 @@
                 // Skip if it had no restrictions to begin with
                 if ((oldRules & MASK_ALL_NETWORKS) == 0) continue;
             }
-            updateRulesForPowerRestrictionsUL(uid, oldRules, paroled, true);
+            updateRulesForPowerRestrictionsUL(uid, oldRules, paroled);
         }
     }
 
@@ -2885,10 +2766,10 @@
                     final int uid = UserHandle.getUid(user.id, app.uid);
                     switch (type) {
                         case TYPE_RESTRICT_BACKGROUND:
-                            updateRulesForDataUsageRestrictionsUL(uid, true);
+                            updateRulesForDataUsageRestrictionsUL(uid);
                             break;
                         case TYPE_RESTRICT_POWER:
-                            updateRulesForPowerRestrictionsUL(uid, true);
+                            updateRulesForPowerRestrictionsUL(uid);
                             break;
                         default:
                             Slog.w(TAG, "Invalid type for updateRulesForAllApps: " + type);
@@ -2914,7 +2795,7 @@
                 updateRuleForDeviceIdleUL(uid);
                 updateRuleForRestrictPowerUL(uid);
                 // Update internal rules.
-                updateRulesForPowerRestrictionsUL(uid, true);
+                updateRulesForPowerRestrictionsUL(uid);
             }
         }
     }
@@ -2978,10 +2859,6 @@
         mPowerSaveWhitelistExceptIdleAppIds.delete(uid);
         mPowerSaveWhitelistAppIds.delete(uid);
         mPowerSaveTempWhitelistAppIds.delete(uid);
-        synchronized (mDispatchedThirdLock) {
-            mLastHandledProcStateSeq.delete(uid);
-            mDispatchFlagsForCurProcStateSeq.delete(uid);
-        }
 
         // ...then update iptables asynchronously.
         mHandler.obtainMessage(MSG_RESET_FIREWALL_RULES_BY_UID, uid, 0).sendToTarget();
@@ -3007,10 +2884,10 @@
         updateRuleForRestrictPowerUL(uid);
 
         // Update internal state for power-related modes.
-        updateRulesForPowerRestrictionsUL(uid, true);
+        updateRulesForPowerRestrictionsUL(uid);
 
         // Update firewall and internal rules for Data Saver Mode.
-        updateRulesForDataUsageRestrictionsUL(uid, true);
+        updateRulesForDataUsageRestrictionsUL(uid);
     }
 
     /**
@@ -3051,16 +2928,11 @@
      *
      * <p>The {@link #mUidRules} map is used to define the transtion of states of an UID.
      *
-     * @param uid The uid for which the rules have to be updated.
-     * @param notify Indicates whether to notify network policy listeners if the rules are updated.
-     *
-     * @return ReturnStatus includes new updated rules and whether network policy listeners
-     *         (INetworkPolicyListener) need to be notified.
      */
-    private ReturnStatus updateRulesForDataUsageRestrictionsUL(int uid, boolean notify) {
+    private void updateRulesForDataUsageRestrictionsUL(int uid) {
         if (!isUidValidForWhitelistRules(uid)) {
             if (LOGD) Slog.d(TAG, "no need to update restrict data rules for uid " + uid);
-            return new ReturnStatus(false, RULE_NONE);
+            return;
         }
 
         final int uidPolicy = mUidPolicy.get(uid, POLICY_NONE);
@@ -3155,12 +3027,9 @@
                         + ", oldRule=" + uidRulesToString(oldUidRules));
             }
 
-            if (notify) {
-                mHandler.obtainMessage(MSG_RULES_CHANGED, uid, newUidRules).sendToTarget();
-            }
-            return new ReturnStatus(true, newUidRules);
+            // Dispatch changed rule to existing listeners.
+            mHandler.obtainMessage(MSG_RULES_CHANGED, uid, newUidRules).sendToTarget();
         }
-        return new ReturnStatus(false, newUidRules);
     }
 
     /**
@@ -3181,18 +3050,16 @@
      * <p>
      * <strong>NOTE: </strong>This method does not update the firewall rules on {@code netd}.
      */
-    private ReturnStatus updateRulesForPowerRestrictionsUL(int uid, boolean notify) {
+    private void updateRulesForPowerRestrictionsUL(int uid) {
         final int oldUidRules = mUidRules.get(uid, RULE_NONE);
 
-        final ReturnStatus status = updateRulesForPowerRestrictionsUL(uid, oldUidRules, false,
-                notify);
+        final int newUidRules = updateRulesForPowerRestrictionsUL(uid, oldUidRules, false);
 
-        if (status.mNewUidRules == RULE_NONE) {
+        if (newUidRules == RULE_NONE) {
             mUidRules.delete(uid);
         } else {
-            mUidRules.put(uid, status.mNewUidRules);
+            mUidRules.put(uid, newUidRules);
         }
-        return status;
     }
 
     /**
@@ -3201,17 +3068,13 @@
      * @param uid the uid of the app to update rules for
      * @param oldUidRules the current rules for the uid, in order to determine if there's a change
      * @param paroled whether to ignore idle state of apps and only look at other restrictions.
-     * @param notify whether to notify network policy listeners (INetworkPolicyListener) if the
-     *               rules are updated.
      *
-     * @return ReturnStatus includes new updated rules and whether network policy listeners
-     *         (INetworkPolicyListener) need to be notified.
+     * @return the new computed rules for the uid
      */
-    private ReturnStatus updateRulesForPowerRestrictionsUL(int uid, int oldUidRules,
-            boolean paroled, boolean notify) {
+    private int updateRulesForPowerRestrictionsUL(int uid, int oldUidRules, boolean paroled) {
         if (!isUidValidForBlacklistRules(uid)) {
             if (LOGD) Slog.d(TAG, "no need to update restrict power rules for uid " + uid);
-            return new ReturnStatus(false, RULE_NONE);
+            return RULE_NONE;
         }
 
         final boolean isIdle = !paroled && isUidIdle(uid);
@@ -3263,23 +3126,10 @@
                         + ", newRule=" + uidRulesToString(newUidRules)
                         + ", oldRule=" + uidRulesToString(oldUidRules));
             }
-            if (notify) {
-                mHandler.obtainMessage(MSG_RULES_CHANGED, uid, newUidRules).sendToTarget();
-            }
-            return new ReturnStatus(true, newUidRules);
+            mHandler.obtainMessage(MSG_RULES_CHANGED, uid, newUidRules).sendToTarget();
         }
 
-        return new ReturnStatus(false, newUidRules);
-    }
-
-    private static final class ReturnStatus {
-        boolean mNeedToNotify;
-        int mNewUidRules;
-
-        ReturnStatus(boolean needToNotify, int newUidRules) {
-            mNeedToNotify = needToNotify;
-            mNewUidRules = newUidRules;
-        }
+        return newUidRules;
     }
 
     private class AppIdleStateChangeListener
@@ -3293,7 +3143,7 @@
                 if (LOGV) Log.v(TAG, "onAppIdleStateChanged(): uid=" + uid + ", idle=" + idle);
                 synchronized (mUidRulesFirstLock) {
                     updateRuleForAppIdleUL(uid);
-                    updateRulesForPowerRestrictionsUL(uid, true);
+                    updateRulesForPowerRestrictionsUL(uid);
                 }
             } catch (NameNotFoundException nnfe) {
             }
@@ -3353,26 +3203,13 @@
                 case MSG_RULES_CHANGED: {
                     final int uid = msg.arg1;
                     final int uidRules = msg.arg2;
-                    if (uidRules != RULE_INVALID) {
-                        dispatchUidRulesChanged(mConnectivityListener, uid, uidRules);
+                    dispatchUidRulesChanged(mConnectivityListener, uid, uidRules);
+                    final int length = mListeners.beginBroadcast();
+                    for (int i = 0; i < length; i++) {
+                        final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
+                        dispatchUidRulesChanged(listener, uid, uidRules);
                     }
-                    final Long procStateSeq = (Long) msg.obj;
-                    if (procStateSeq != null) {
-                        synchronized (mDispatchedThirdLock) {
-                            if (mLastHandledProcStateSeq.get(uid) == procStateSeq) {
-                                setDispatchedFlagDL(uid, procStateSeq, FLAG_UID_RULES_DISPATCHED);
-                                checkAndNotifyDL(uid, procStateSeq);
-                            }
-                        }
-                    }
-                    if (uidRules != RULE_INVALID) {
-                        final int length = mListeners.beginBroadcast();
-                        for (int i = 0; i < length; i++) {
-                            final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
-                            dispatchUidRulesChanged(listener, uid, uidRules);
-                        }
-                        mListeners.finishBroadcast();
-                    }
+                    mListeners.finishBroadcast();
                     return true;
                 }
                 case MSG_METERED_IFACES_CHANGED: {
diff --git a/services/core/java/com/android/server/notification/BadgeExtractor.java b/services/core/java/com/android/server/notification/BadgeExtractor.java
index 4795fbf..e6edaf1 100644
--- a/services/core/java/com/android/server/notification/BadgeExtractor.java
+++ b/services/core/java/com/android/server/notification/BadgeExtractor.java
@@ -46,7 +46,9 @@
         if (!appCanShowBadge) {
             record.setShowBadge(false);
         } else {
-            record.setShowBadge(record.getChannel().canShowBadge() && appCanShowBadge);
+            record.setShowBadge(mConfig.getNotificationChannel(record.sbn.getPackageName(),
+                    record.sbn.getUid(), record.getChannel().getId(), false).canShowBadge()
+                    && appCanShowBadge);
         }
 
         return null;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index ff42527..be8aaf0 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1440,6 +1440,11 @@
                 return ;
             }
 
+            if (isCallerInstantApp(pkg)) {
+                throw new SecurityException("Instant app " + pkg
+                        + " is not allowed to create toasts");
+            }
+
             final boolean isSystemToast = isCallerSystem() || ("android".equals(pkg));
             final boolean isPackageSuspended =
                     isPackageSuspendedForUser(pkg, Binder.getCallingUid());
@@ -2024,11 +2029,11 @@
          */
         @Override
         public void snoozeNotificationUntilFromListener(INotificationListener token, String key,
-                long snoozeUntil) {
+                long duration) {
             long identity = Binder.clearCallingIdentity();
             try {
                 final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
-                snoozeNotificationInt(key, snoozeUntil, null, info);
+                snoozeNotificationInt(key, duration, null, info);
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
@@ -2731,9 +2736,10 @@
                                Notification.EXTRA_BUILDER_APPLICATION_INFO);
                 final Bundle extras = new Bundle();
                 extras.putParcelable(Notification.EXTRA_BUILDER_APPLICATION_INFO, appInfo);
+                final String channelId = notificationRecord.getChannel().getId();
                 final Notification summaryNotification =
-                        new Notification.Builder(getContext()).setSmallIcon(
-                                adjustedSbn.getNotification().getSmallIcon())
+                        new Notification.Builder(getContext(), channelId)
+                                .setSmallIcon(adjustedSbn.getNotification().getSmallIcon())
                                 .setGroupSummary(true)
                                 .setGroup(GroupHelper.AUTOGROUP_KEY)
                                 .setFlag(Notification.FLAG_AUTOGROUP_SUMMARY, true)
@@ -2786,6 +2792,7 @@
             dump.put("bans", mRankingHelper.dumpBansJson(filter));
             dump.put("ranking", mRankingHelper.dumpJson(filter));
             dump.put("stats", mUsageStats.dumpJson(filter));
+            dump.put("channels", mRankingHelper.dumpChannelsJson(filter));
         } catch (JSONException e) {
             e.printStackTrace();
         }
@@ -3044,6 +3051,10 @@
             throw new IllegalArgumentException("null not allowed: pkg=" + pkg
                     + " id=" + id + " notification=" + notification);
         }
+
+        // The system can post notifications for any package, let us resolve that.
+        final int notificationUid = resolveNotificationUid(opPkg, callingUid, userId);
+
         // Fix the notification as best we can.
         try {
             final ApplicationInfo ai = mPackageManagerClient.getApplicationInfoAsUser(
@@ -3063,13 +3074,13 @@
             channelId = (new Notification.TvExtender(notification)).getChannel();
         }
         final NotificationChannel channel =  mRankingHelper.getNotificationChannelWithFallback(pkg,
-                callingUid, channelId, false /* includeDeleted */);
+                notificationUid, channelId, false /* includeDeleted */);
         final StatusBarNotification n = new StatusBarNotification(
-                pkg, opPkg, id, tag, callingUid, callingPid, notification,
+                pkg, opPkg, id, tag, notificationUid, callingPid, notification,
                 user, null, System.currentTimeMillis());
         final NotificationRecord r = new NotificationRecord(getContext(), n, channel);
 
-        if (!checkDisqualifyingFeatures(userId, callingUid, id,tag, r)) {
+        if (!checkDisqualifyingFeatures(userId, notificationUid, id,tag, r)) {
             return;
         }
 
@@ -3095,6 +3106,19 @@
         idOut[0] = id;
     }
 
+    private int resolveNotificationUid(String opPackageName, int callingUid, int userId) {
+        // The system can post notifications on behalf of any package it wants
+        if (isCallerSystem() && opPackageName != null && !"android".equals(opPackageName)) {
+            try {
+                return getContext().getPackageManager()
+                        .getPackageUidAsUser(opPackageName, userId);
+            } catch (NameNotFoundException e) {
+                /* ignore */
+            }
+        }
+        return callingUid;
+    }
+
     /**
      * Checks if a notification can be posted. checks rate limiter, snooze helper, and blocking.
      *
@@ -3123,6 +3147,13 @@
                         }
                         return false;
                     }
+                } else if (isCallerInstantApp(pkg)) {
+                    // Ephemeral apps have some special contraints for notifications.
+                    // They are not allowed to create new notifications however they are allowed to
+                    // update notifications created by the system (e.g. a foreground service
+                    // notification).
+                    throw new SecurityException("Instant app " + pkg
+                            + " cannot create notifications");
                 }
 
                 int count = 0;
@@ -3397,7 +3428,7 @@
 
     @VisibleForTesting
     void scheduleTimeoutLocked(NotificationRecord record) {
-        if (record.getNotification().getTimeout() > System.currentTimeMillis()) {
+        if (record.getNotification().getTimeout() > 0) {
             final PendingIntent pi = PendingIntent.getBroadcast(getContext(),
                     REQUEST_CODE_TIMEOUT,
                     new Intent(ACTION_NOTIFICATION_TIMEOUT)
@@ -3406,8 +3437,8 @@
                             .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
                             .putExtra(EXTRA_KEY, record.getKey()),
                     PendingIntent.FLAG_UPDATE_CURRENT);
-            mAlarmManager.setExactAndAllowWhileIdle(
-                    AlarmManager.RTC_WAKEUP, record.getNotification().getTimeout(), pi);
+            mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+                    SystemClock.elapsedRealtime() + record.getNotification().getTimeout(), pi);
         }
     }
 
@@ -4173,16 +4204,16 @@
         }
     }
 
-    void snoozeNotificationInt(String key, long until, String snoozeCriterionId,
+    void snoozeNotificationInt(String key, long duration, String snoozeCriterionId,
             ManagedServiceInfo listener) {
         String listenerName = listener == null ? null : listener.component.toShortString();
-        if (until < System.currentTimeMillis() && snoozeCriterionId == null) {
+        if (duration <= 0 && snoozeCriterionId == null) {
             return;
         }
 
         if (DBG) {
-            Slog.d(TAG, String.format("snooze event(%s, %d, %s, %s)", key, until, snoozeCriterionId,
-                    listenerName));
+            Slog.d(TAG, String.format("snooze event(%s, %d, %s, %s)", key, duration,
+                    snoozeCriterionId, listenerName));
         }
         // Needs to post so that it can cancel notifications not yet enqueued.
         mHandler.post(new Runnable() {
@@ -4203,7 +4234,7 @@
                                     snoozeCriterionId);
                             mSnoozeHelper.snooze(r);
                         } else {
-                            mSnoozeHelper.snooze(r, until);
+                            mSnoozeHelper.snooze(r, duration);
                         }
                         savePolicyFile();
                     }
@@ -4413,6 +4444,27 @@
         checkCallerIsSameApp(pkg);
     }
 
+    private boolean isCallerInstantApp(String pkg) {
+        // System is always allowed to act for ephemeral apps.
+        if (isCallerSystem()) {
+            return false;
+        }
+
+        mAppOps.checkPackage(Binder.getCallingUid(), pkg);
+
+        try {
+            ApplicationInfo ai = mPackageManager.getApplicationInfo(pkg, 0,
+                    UserHandle.getCallingUserId());
+            if (ai == null) {
+                throw new SecurityException("Unknown package " + pkg);
+            }
+            return ai.isInstantApp();
+        } catch (RemoteException re) {
+            throw new SecurityException("Unknown package " + pkg, re);
+        }
+
+    }
+
     private void checkCallerIsSameApp(String pkg) {
         final int uid = Binder.getCallingUid();
         try {
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 3016b17..d751a22 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -778,9 +778,9 @@
                     .addTaggedData(MetricsEvent.NOTIFICATION_TAG, sbn.getTag());
         }
         return mLogMaker
-                .setCategory(MetricsEvent.VIEW_UNKNOWN)
-                .setType(MetricsEvent.TYPE_UNKNOWN)
-                .setSubtype(0)
+                .clearCategory()
+                .clearType()
+                .clearSubtype()
                 .clearTaggedData(MetricsEvent.NOTIFICATION_SHADE_INDEX)
                 .addTaggedData(MetricsEvent.NOTIFICATION_SINCE_CREATE_MILLIS, getLifespanMs(now))
                 .addTaggedData(MetricsEvent.NOTIFICATION_SINCE_UPDATE_MILLIS, getFreshnessMs(now))
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 76890b1..6097071 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -19,6 +19,8 @@
 
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto;
 import com.android.internal.util.Preconditions;
 
 import android.app.Notification;
@@ -30,8 +32,10 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ParceledListSlice;
+import android.metrics.LogMaker;
 import android.os.Build;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.service.notification.NotificationListenerService.Ranking;
 import android.text.TextUtils;
 import android.util.ArrayMap;
@@ -65,6 +69,7 @@
 
     private static final String ATT_VERSION = "version";
     private static final String ATT_NAME = "name";
+    private static final String ATT_NAME_RES_ID = "name_res_id";
     private static final String ATT_UID = "uid";
     private static final String ATT_ID = "id";
     private static final String ATT_PRIORITY = "priority";
@@ -190,9 +195,14 @@
                             if (TAG_GROUP.equals(tagName)) {
                                 String id = parser.getAttributeValue(null, ATT_ID);
                                 CharSequence groupName = parser.getAttributeValue(null, ATT_NAME);
+                                int groupNameRes = safeInt(parser, ATT_NAME_RES_ID, 0);
                                 if (!TextUtils.isEmpty(id)) {
-                                    final NotificationChannelGroup group =
-                                            new NotificationChannelGroup(id, groupName);
+                                    NotificationChannelGroup group = null;
+                                    if (groupName != null) {
+                                        group = new NotificationChannelGroup(id, groupName);
+                                    } else {
+                                        group = new NotificationChannelGroup(id, groupNameRes);
+                                    }
                                     r.groups.put(id, group);
                                 }
                             }
@@ -200,12 +210,19 @@
                             if (TAG_CHANNEL.equals(tagName)) {
                                 String id = parser.getAttributeValue(null, ATT_ID);
                                 CharSequence channelName = parser.getAttributeValue(null, ATT_NAME);
+                                int channelNameRes = safeInt(parser, ATT_NAME_RES_ID, 0);
                                 int channelImportance =
                                         safeInt(parser, ATT_IMPORTANCE, DEFAULT_IMPORTANCE);
 
                                 if (!TextUtils.isEmpty(id)) {
-                                    final NotificationChannel channel = new NotificationChannel(id,
-                                            channelName, channelImportance);
+                                    NotificationChannel channel;
+                                    if (channelName != null) {
+                                        channel = new NotificationChannel(id, channelName,
+                                                channelImportance);
+                                    } else {
+                                        channel = new NotificationChannel(id, channelNameRes,
+                                                channelImportance);
+                                    }
                                     channel.populateFromXml(parser);
                                     r.channels.put(id, channel);
                                 }
@@ -285,7 +302,7 @@
             NotificationChannel channel;
             channel = new NotificationChannel(
                     NotificationChannel.DEFAULT_CHANNEL_ID,
-                    mContext.getString(R.string.default_notification_channel_label),
+                    R.string.default_notification_channel_label,
                     r.importance);
             channel.setBypassDnd(r.priority == Notification.PRIORITY_MAX);
             channel.setLockscreenVisibility(r.visibility);
@@ -373,8 +390,9 @@
                 final NotificationRecord record = notificationList.get(i);
                 record.setAuthoritativeRank(i);
                 final String groupKey = record.getGroupKey();
-                boolean isGroupSummary = record.getNotification().isGroupSummary();
-                if (isGroupSummary || !mProxyByGroupTmp.containsKey(groupKey)) {
+                NotificationRecord existingProxy = mProxyByGroupTmp.get(groupKey);
+                if (existingProxy == null
+                        || record.getImportance() > existingProxy.getImportance()) {
                     mProxyByGroupTmp.put(groupKey, record);
                 }
             }
@@ -464,11 +482,18 @@
         Preconditions.checkNotNull(pkg);
         Preconditions.checkNotNull(group);
         Preconditions.checkNotNull(group.getId());
-        Preconditions.checkNotNull(group.getName());
+        Preconditions.checkNotNull(!TextUtils.isEmpty(group.getName())
+                || group.getNameResId() != 0);
         Record r = getOrCreateRecord(pkg, uid);
         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);
         r.groups.put(group.getId(), group);
         updateConfig();
     }
@@ -479,7 +504,8 @@
         Preconditions.checkNotNull(pkg);
         Preconditions.checkNotNull(channel);
         Preconditions.checkNotNull(channel.getId());
-        Preconditions.checkNotNull(channel.getName());
+        Preconditions.checkArgument(!TextUtils.isEmpty(channel.getName())
+                || channel.getNameResId() != 0);
         Record r = getOrCreateRecord(pkg, uid);
         if (r == null) {
             throw new IllegalArgumentException("Invalid package");
@@ -490,14 +516,21 @@
         if (channel.getGroup() != null && !r.groups.containsKey(channel.getGroup())) {
             throw new IllegalArgumentException("NotificationChannelGroup doesn't exist");
         }
+        if (NotificationChannel.DEFAULT_CHANNEL_ID.equals(channel.getId())) {
+            throw new IllegalArgumentException("Reserved id");
+        }
 
         NotificationChannel existing = r.channels.get(channel.getId());
-        // Keep existing settings
-        if (existing != null) {
+        // Keep existing settings, except deleted status and name
+        if (existing != null && fromTargetApp) {
             if (existing.isDeleted()) {
                 existing.setDeleted(false);
-                updateConfig();
             }
+
+            existing.setNameResId(channel.getNameResId());
+
+            MetricsLogger.action(getChannelLog(channel, pkg));
+            updateConfig();
             return;
         }
         if (channel.getImportance() < NotificationManager.IMPORTANCE_NONE
@@ -516,7 +549,13 @@
         if (!r.showBadge) {
             channel.setShowBadge(false);
         }
+        if (channel.getSound() == null) {
+            channel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI,
+                    Notification.AUDIO_ATTRIBUTES_DEFAULT);
+        }
         r.channels.put(channel.getId(), channel);
+        MetricsLogger.action(getChannelLog(channel, pkg).setType(
+                MetricsProto.MetricsEvent.TYPE_OPEN));
         updateConfig();
     }
 
@@ -544,6 +583,8 @@
             updatedChannel.setLockscreenVisibility(Ranking.VISIBILITY_NO_OVERRIDE);
         }
         r.channels.put(updatedChannel.getId(), updatedChannel);
+
+        MetricsLogger.action(getChannelLog(updatedChannel, pkg));
         updateConfig();
     }
 
@@ -591,6 +632,7 @@
         }
         // Assistant cannot change the group
 
+        MetricsLogger.action(getChannelLog(channel, pkg));
         r.channels.put(channel.getId(), channel);
         updateConfig();
     }
@@ -640,6 +682,9 @@
         if (channel != null) {
             channel.setDeleted(true);
         }
+        LogMaker lm = getChannelLog(channel, pkg);
+        lm.setType(MetricsProto.MetricsEvent.TYPE_CLOSE);
+        MetricsLogger.action(lm);
     }
 
     @Override
@@ -911,6 +956,49 @@
         return packageBans;
     }
 
+    /**
+     * Dump only the channel information as structured JSON for the stats collector.
+     *
+     * This is intentionally redundant with {#link dumpJson} because the old
+     * scraper will expect this format.
+     *
+     * @param filter
+     * @return
+     */
+    public JSONArray dumpChannelsJson(NotificationManagerService.DumpFilter filter) {
+        JSONArray channels = new JSONArray();
+        Map<String, Integer> packageChannels = getPackageChannels();
+        for(Entry<String, Integer> channelCount : packageChannels.entrySet()) {
+            final String packageName = channelCount.getKey();
+            if (filter == null || filter.matches(packageName)) {
+                JSONObject channelCountJson = new JSONObject();
+                try {
+                    channelCountJson.put("packageName", packageName);
+                    channelCountJson.put("channelCount", channelCount.getValue());
+                } catch (JSONException e) {
+                    e.printStackTrace();
+                }
+                channels.put(channelCountJson);
+            }
+        }
+        return channels;
+    }
+
+    private Map<String, Integer> getPackageChannels() {
+        ArrayMap<String, Integer> packageChannels = new ArrayMap<>();
+        for (int i = 0; i < mRecords.size(); i++) {
+            final Record r = mRecords.valueAt(i);
+            int channelCount = 0;
+            for (int j = 0; j < r.channels.size();j++) {
+                if (!r.channels.valueAt(j).isDeleted()) {
+                    channelCount++;
+                }
+            }
+            packageChannels.put(r.pkg, channelCount);
+        }
+        return packageChannels;
+    }
+
     public void onPackagesChanged(boolean removingPackage, int changeUserId, String[] pkgList,
             int[] uidList) {
         if (pkgList == null || pkgList.length == 0) {
@@ -958,6 +1046,16 @@
         }
     }
 
+    private LogMaker getChannelLog(NotificationChannel channel, String pkg) {
+        return new LogMaker(MetricsProto.MetricsEvent.ACTION_NOTIFICATION_CHANNEL)
+                .setType(MetricsProto.MetricsEvent.TYPE_UPDATE)
+                .setPackageName(pkg)
+                .addTaggedData(MetricsProto.MetricsEvent.FIELD_NOTIFICATION_CHANNEL_ID,
+                        channel.getId())
+                .addTaggedData(MetricsProto.MetricsEvent.FIELD_NOTIFICATION_CHANNEL_IMPORTANCE,
+                        channel.getImportance());
+    }
+
     private static class Record {
         static int UNKNOWN_UID = UserHandle.USER_NULL;
 
diff --git a/services/core/java/com/android/server/notification/SnoozeHelper.java b/services/core/java/com/android/server/notification/SnoozeHelper.java
index 0cd8cea..913f636 100644
--- a/services/core/java/com/android/server/notification/SnoozeHelper.java
+++ b/services/core/java/com/android/server/notification/SnoozeHelper.java
@@ -32,6 +32,7 @@
 import android.content.IntentFilter;
 import android.net.Uri;
 import android.os.Binder;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.service.notification.StatusBarNotification;
 import android.util.ArrayMap;
@@ -125,9 +126,9 @@
     /**
      * Snoozes a notification and schedules an alarm to repost at that time.
      */
-    protected void snooze(NotificationRecord record, long until) {
+    protected void snooze(NotificationRecord record, long duration) {
         snooze(record);
-        scheduleRepost(record.sbn.getPackageName(), record.getKey(), record.getUserId(), until);
+        scheduleRepost(record.sbn.getPackageName(), record.getKey(), record.getUserId(), duration);
     }
 
     /**
@@ -291,13 +292,14 @@
                 PendingIntent.FLAG_UPDATE_CURRENT);
     }
 
-    private void scheduleRepost(String pkg, String key, int userId, long time) {
+    private void scheduleRepost(String pkg, String key, int userId, long duration) {
         long identity = Binder.clearCallingIdentity();
         try {
             final PendingIntent pi = createPendingIntent(pkg, key, userId);
             mAm.cancel(pi);
+            long time = SystemClock.elapsedRealtime() + duration;
             if (DEBUG) Slog.d(TAG, "Scheduling evaluate for " + new Date(time));
-            mAm.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, time, pi);
+            mAm.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, time, pi);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index cc709ce..2026c1b 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -26,7 +26,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
-import android.app.ActivityManagerNative;
 import android.app.IActivityManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -42,19 +41,23 @@
 import android.os.Binder;
 import android.os.Environment;
 import android.os.IBinder;
-import android.os.Process;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ShellCallback;
+import android.os.SystemProperties;
 import android.os.UserHandle;
+import android.text.TextUtils;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.AtomicFile;
 import android.util.Slog;
 import android.util.SparseArray;
 
+import com.android.internal.util.ConcurrentUtils;
 import com.android.server.FgThread;
 import com.android.server.IoThread;
 import com.android.server.LocalServices;
+import com.android.server.SystemServerInitThreadPool;
 import com.android.server.SystemService;
 import com.android.server.pm.Installer;
 import com.android.server.pm.UserManagerService;
@@ -72,6 +75,8 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Future;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
@@ -195,6 +200,14 @@
 
     static final String PERMISSION_DENIED = "Operation not permitted for user shell";
 
+    /**
+     * The system property that specifies the default overlays to apply.
+     * This is a semicolon separated list of package names.
+     *
+     * Ex: com.android.vendor.overlay_one;com.android.vendor.overlay_two
+     */
+    private static final String DEFAULT_OVERLAYS_PROP = "ro.boot.vendor.overlay.theme";
+
     private final Object mLock = new Object();
 
     private final AtomicFile mSettingsFile;
@@ -209,6 +222,8 @@
 
     private final AtomicBoolean mPersistSettingsScheduled = new AtomicBoolean(false);
 
+    private Future<?> mInitCompleteSignal;
+
     public OverlayManagerService(@NonNull final Context context,
             @NonNull final Installer installer) {
         super(context);
@@ -218,29 +233,31 @@
         mUserManager = UserManagerService.getInstance();
         IdmapManager im = new IdmapManager(installer);
         mSettings = new OverlayManagerSettings();
-        mImpl = new OverlayManagerServiceImpl(mPackageManager, im, mSettings);
+        mImpl = new OverlayManagerServiceImpl(mPackageManager, im, mSettings,
+                getDefaultOverlayPackages());
+        mInitCompleteSignal = SystemServerInitThreadPool.get().submit(() -> {
+            final IntentFilter packageFilter = new IntentFilter();
+            packageFilter.addAction(ACTION_PACKAGE_ADDED);
+            packageFilter.addAction(ACTION_PACKAGE_CHANGED);
+            packageFilter.addAction(ACTION_PACKAGE_REMOVED);
+            packageFilter.addDataScheme("package");
+            getContext().registerReceiverAsUser(new PackageReceiver(), UserHandle.ALL,
+                    packageFilter, null, null);
 
-        final IntentFilter packageFilter = new IntentFilter();
-        packageFilter.addAction(ACTION_PACKAGE_ADDED);
-        packageFilter.addAction(ACTION_PACKAGE_CHANGED);
-        packageFilter.addAction(ACTION_PACKAGE_REMOVED);
-        packageFilter.addDataScheme("package");
-        getContext().registerReceiverAsUser(new PackageReceiver(), UserHandle.ALL,
-                packageFilter, null, null);
+            final IntentFilter userFilter = new IntentFilter();
+            userFilter.addAction(ACTION_USER_REMOVED);
+            getContext().registerReceiverAsUser(new UserReceiver(), UserHandle.ALL,
+                    userFilter, null, null);
 
-        final IntentFilter userFilter = new IntentFilter();
-        userFilter.addAction(ACTION_USER_REMOVED);
-        getContext().registerReceiverAsUser(new UserReceiver(), UserHandle.ALL,
-                userFilter, null, null);
+            restoreSettings();
+            onSwitchUser(UserHandle.USER_SYSTEM);
+            schedulePersistSettings();
 
-        restoreSettings();
-        onSwitchUser(UserHandle.USER_SYSTEM);
-        schedulePersistSettings();
+            mSettings.addChangeListener(new OverlayChangeListener());
 
-        mSettings.addChangeListener(new OverlayChangeListener());
-
-        publishBinderService(Context.OVERLAY_SERVICE, mService);
-        publishLocalService(OverlayManagerService.class, this);
+            publishBinderService(Context.OVERLAY_SERVICE, mService);
+            publishLocalService(OverlayManagerService.class, this);
+        }, "Init OverlayManagerService");
     }
 
     @Override
@@ -249,6 +266,15 @@
     }
 
     @Override
+    public void onBootPhase(int phase) {
+        if (phase == PHASE_SYSTEM_SERVICES_READY) {
+            ConcurrentUtils.waitForFutureNoInterrupt(mInitCompleteSignal,
+                    "Wait for OverlayManagerService init");
+            mInitCompleteSignal = null;
+        }
+    }
+
+    @Override
     public void onSwitchUser(final int newUserId) {
         // ensure overlays in the settings are up-to-date, and propagate
         // any asset changes to the rest of the system
@@ -259,6 +285,21 @@
         updateAssets(newUserId, targets);
     }
 
+    private static Set<String> getDefaultOverlayPackages() {
+        final String str = SystemProperties.get(DEFAULT_OVERLAYS_PROP);
+        if (TextUtils.isEmpty(str)) {
+            return Collections.emptySet();
+        }
+
+        final ArraySet<String> defaultPackages = new ArraySet<>();
+        for (String packageName : str.split(";")) {
+            if (!TextUtils.isEmpty(packageName)) {
+                defaultPackages.add(packageName);
+            }
+        }
+        return defaultPackages;
+    }
+
     private final class PackageReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(@NonNull final Context context, @NonNull final Intent intent) {
@@ -463,6 +504,25 @@
         }
 
         @Override
+        public boolean setEnabledExclusive(@Nullable final String packageName, final boolean enable,
+                int userId) throws RemoteException {
+            enforceChangeOverlayPackagesPermission("setEnabled");
+            userId = handleIncomingUser(userId, "setEnabled");
+            if (packageName == null) {
+                return false;
+            }
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    return mImpl.setEnabledExclusive(packageName, enable, userId);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override
         public boolean setPriority(@Nullable final String packageName,
                 @Nullable final String parentPackageName, int userId) throws RemoteException {
             enforceChangeOverlayPackagesPermission("setPriority");
@@ -646,7 +706,7 @@
                     Slog.d(TAG, String.format("send broadcast %s", intent));
                 }
                 try {
-                    ActivityManagerNative.getDefault().broadcastIntent(null, intent, null, null, 0,
+                    ActivityManager.getService().broadcastIntent(null, intent, null, null, 0,
                             null, null, null, android.app.AppOpsManager.OP_NONE, null, false, false,
                             userId);
                 } catch (RemoteException e) {
@@ -664,7 +724,38 @@
     }
 
     private void updateAssets(final int userId, List<String> targetPackageNames) {
-        // TODO: implement when we integrate OMS properly
+        final PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
+        final boolean updateFrameworkRes = targetPackageNames.contains("android");
+        if (updateFrameworkRes) {
+            targetPackageNames = pm.getTargetPackageNames(userId);
+        }
+
+        final Map<String, List<String>> pendingChanges = new ArrayMap<>(targetPackageNames.size());
+        synchronized (mLock) {
+            final int N = targetPackageNames.size();
+            for (int i = 0; i < N; i++) {
+                final String targetPackageName = targetPackageNames.get(i);
+                pendingChanges.put(targetPackageName,
+                        mImpl.getEnabledOverlayPackageNames(targetPackageName, userId));
+            }
+        }
+
+        final int N = targetPackageNames.size();
+        for (int i = 0; i < N; i++) {
+            final String targetPackageName = targetPackageNames.get(i);
+            if (!pm.setEnabledOverlayPackages(
+                        userId, targetPackageName, pendingChanges.get(targetPackageName))) {
+                Slog.e(TAG, String.format("Failed to change enabled overlays for %s user %d",
+                            targetPackageName, userId));
+            }
+        }
+
+        final IActivityManager am = ActivityManager.getService();
+        try {
+            am.scheduleApplicationInfoChanged(targetPackageNames, userId);
+        } catch (RemoteException e) {
+            // Intentionally left empty.
+        }
     }
 
     private void schedulePersistSettings() {
diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
index 0e33409..b085179 100644
--- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
@@ -27,8 +27,8 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.om.OverlayInfo;
-import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
+import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Slog;
@@ -53,13 +53,16 @@
     private final PackageManagerHelper mPackageManager;
     private final IdmapManager mIdmapManager;
     private final OverlayManagerSettings mSettings;
+    private final Set<String> mDefaultOverlays;
 
     OverlayManagerServiceImpl(@NonNull final PackageManagerHelper packageManager,
             @NonNull final IdmapManager idmapManager,
-            @NonNull final OverlayManagerSettings settings) {
+            @NonNull final OverlayManagerSettings settings,
+            @NonNull final Set<String> defaultOverlays) {
         mPackageManager = packageManager;
         mIdmapManager = idmapManager;
         mSettings = settings;
+        mDefaultOverlays = defaultOverlays;
     }
 
     /*
@@ -92,12 +95,22 @@
             final PackageInfo overlayPackage = overlayPackages.get(i);
             final OverlayInfo oi = storedOverlayInfos.get(overlayPackage.packageName);
             if (oi == null || !oi.targetPackageName.equals(overlayPackage.overlayTarget)) {
-                if (oi != null) {
-                    packagesToUpdateAssets.add(oi.targetPackageName);
-                }
+                // Update the overlay if it didn't exist or had the wrong target package.
                 mSettings.init(overlayPackage.packageName, newUserId,
                         overlayPackage.overlayTarget,
                         overlayPackage.applicationInfo.getBaseCodePath());
+
+                if (oi == null) {
+                    // This overlay does not exist in our settings.
+                    if (mDefaultOverlays.contains(overlayPackage.packageName)) {
+                        // Enable this overlay by default.
+                        mSettings.setEnabled(overlayPackage.packageName, newUserId, true);
+                    }
+                } else {
+                    // The targetPackageName we have stored doesn't match the overlay's target.
+                    // Queue the old target for an update as well.
+                    packagesToUpdateAssets.add(oi.targetPackageName);
+                }
             }
 
             try {
@@ -132,7 +145,7 @@
             }
         }
 
-        return new ArrayList<String>(packagesToUpdateAssets);
+        return new ArrayList<>(packagesToUpdateAssets);
     }
 
     void onUserRemoved(final int userId) {
@@ -288,6 +301,38 @@
         }
     }
 
+    boolean setEnabledExclusive(@NonNull final String packageName, final boolean enable,
+            final int userId) {
+        if (DEBUG) {
+            Slog.d(TAG, String.format("setEnabled packageName=%s enable=%s userId=%d",
+                        packageName, enable, userId));
+        }
+
+        final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
+        if (overlayPackage == null) {
+            return false;
+        }
+
+        try {
+            final OverlayInfo oi = mSettings.getOverlayInfo(packageName, userId);
+            List<OverlayInfo> allOverlays = getOverlayInfosForTarget(oi.targetPackageName, userId);
+
+            // Disable all other overlays.
+            allOverlays.remove(oi);
+            for (int i = 0; i < allOverlays.size(); i++) {
+                mSettings.setEnabled(allOverlays.get(i).packageName, userId, false);
+            }
+
+            final PackageInfo targetPackage =
+                    mPackageManager.getPackageInfo(oi.targetPackageName, userId);
+            mSettings.setEnabled(packageName, userId, enable);
+            updateState(targetPackage, overlayPackage, userId);
+            return true;
+        } catch (OverlayManagerSettings.BadKeyException e) {
+            return false;
+        }
+    }
+
     boolean setPriority(@NonNull final String packageName,
             @NonNull final String newParentPackageName, final int userId) {
         return mSettings.setPriority(packageName, newParentPackageName, userId);
@@ -303,6 +348,7 @@
 
     void onDump(@NonNull final PrintWriter pw) {
         mSettings.dump(pw);
+        pw.println("Default overlays: " + TextUtils.join(";", mDefaultOverlays));
     }
 
     List<String> getEnabledOverlayPackageNames(@NonNull final String targetPackageName,
diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java
index 44908a7..2262a2e 100644
--- a/services/core/java/com/android/server/om/OverlayManagerSettings.java
+++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java
@@ -45,7 +45,6 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.ListIterator;
-import java.util.Map;
 
 /**
  * Data structure representing the current state of all overlay packages in the
@@ -361,7 +360,7 @@
         private static final String ATTR_USER_ID = "userId";
         private static final String ATTR_VERSION = "version";
 
-        private static final int CURRENT_VERSION = 1;
+        private static final int CURRENT_VERSION = 2;
 
         public static void restore(@NonNull final ArrayList<SettingsItem> table,
                 @NonNull final InputStream is) throws IOException, XmlPullParserException {
@@ -373,7 +372,7 @@
                 XmlUtils.beginDocument(parser, TAG_OVERLAYS);
                 int version = XmlUtils.readIntAttribute(parser, ATTR_VERSION);
                 if (version != CURRENT_VERSION) {
-                    throw new XmlPullParserException("unrecognized version " + version);
+                    upgrade(version);
                 }
                 int depth = parser.getDepth();
 
@@ -388,6 +387,18 @@
             }
         }
 
+        private static void upgrade(int oldVersion) throws XmlPullParserException {
+            switch (oldVersion) {
+                case 0:
+                case 1:
+                    // Throw an exception which will cause the overlay file to be ignored
+                    // and overwritten.
+                    throw new XmlPullParserException("old version " + oldVersion + "; ignoring");
+                default:
+                    throw new XmlPullParserException("unrecognized version " + oldVersion);
+            }
+        }
+
         private static SettingsItem restoreRow(@NonNull final XmlPullParser parser, final int depth)
                 throws IOException {
             final String packageName = XmlUtils.readStringAttribute(parser, ATTR_PACKAGE_NAME);
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index 06b6f66..6365d15 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -59,6 +59,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -1035,14 +1036,22 @@
         }
     }
 
+    private File[] getDefaultPermissionFiles() {
+        ArrayList<File> ret = new ArrayList<File>();
+        File dir = new File(Environment.getRootDirectory(), "etc/default-permissions");
+        if (dir.isDirectory() && dir.canRead()) {
+            Collections.addAll(ret, dir.listFiles());
+        }
+        dir = new File(Environment.getVendorDirectory(), "etc/default-permissions");
+        if (dir.isDirectory() && dir.canRead()) {
+            Collections.addAll(ret, dir.listFiles());
+        }
+        return ret.isEmpty() ? null : ret.toArray(new File[0]);
+    }
+
     private @NonNull ArrayMap<String, List<DefaultPermissionGrant>>
             readDefaultPermissionExceptionsLPw() {
-        File dir = new File(Environment.getRootDirectory(), "etc/default-permissions");
-        if (!dir.exists() || !dir.isDirectory() || !dir.canRead()) {
-            return new ArrayMap<>(0);
-        }
-
-        File[] files = dir.listFiles();
+        File[] files = getDefaultPermissionFiles();
         if (files == null) {
             return new ArrayMap<>(0);
         }
@@ -1052,7 +1061,7 @@
         // Iterate over the files in the directory and scan .xml files
         for (File file : files) {
             if (!file.getPath().endsWith(".xml")) {
-                Slog.i(TAG, "Non-xml file " + file + " in " + dir + " directory, ignoring");
+                Slog.i(TAG, "Non-xml file " + file + " in " + file.getParent() + " directory, ignoring");
                 continue;
             }
             if (!file.canRead()) {
diff --git a/services/core/java/com/android/server/pm/EphemeralResolver.java b/services/core/java/com/android/server/pm/EphemeralResolver.java
deleted file mode 100644
index d99a1b6..0000000
--- a/services/core/java/com/android/server/pm/EphemeralResolver.java
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.pm;
-
-import android.app.ActivityManager;
-import android.app.ActivityManagerNative;
-import android.app.PendingIntent;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.IIntentSender;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.IntentSender;
-import android.content.pm.ActivityInfo;
-import android.content.pm.EphemeralIntentFilter;
-import android.content.pm.EphemeralRequest;
-import android.content.pm.EphemeralResolveInfo;
-import android.content.pm.EphemeralResponse;
-import android.content.pm.EphemeralResolveInfo.EphemeralDigest;
-import android.os.Binder;
-import android.os.Handler;
-import android.os.RemoteException;
-import android.util.Log;
-import android.util.Slog;
-
-import com.android.server.pm.EphemeralResolverConnection.PhaseTwoCallback;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.UUID;
-
-/** @hide */
-public abstract class EphemeralResolver {
-    public static EphemeralResponse doEphemeralResolutionPhaseOne(Context context,
-            EphemeralResolverConnection connection, EphemeralRequest requestObj) {
-        final Intent intent = requestObj.origIntent;
-        final EphemeralDigest digest =
-                new EphemeralDigest(intent.getData().getHost(), 5 /*maxDigests*/);
-        final int[] shaPrefix = digest.getDigestPrefix();
-        final List<EphemeralResolveInfo> ephemeralResolveInfoList =
-                connection.getEphemeralResolveInfoList(shaPrefix);
-        if (ephemeralResolveInfoList == null || ephemeralResolveInfoList.size() == 0) {
-            // No hash prefix match; there are no ephemeral apps for this domain.
-            return null;
-        }
-
-        final String token = UUID.randomUUID().toString();
-        return EphemeralResolver.filterEphemeralIntent(ephemeralResolveInfoList,
-                intent, requestObj.resolvedType, requestObj.userId,
-                intent.getPackage(), digest, token);
-    }
-
-    public static void doEphemeralResolutionPhaseTwo(Context context,
-            EphemeralResolverConnection connection, EphemeralRequest requestObj,
-            ActivityInfo ephemeralInstaller, Handler callbackHandler) {
-        final Intent intent = requestObj.origIntent;
-        final String hostName = intent.getData().getHost();
-        final EphemeralDigest digest = new EphemeralDigest(hostName, 5 /*maxDigests*/);
-
-        final PhaseTwoCallback callback = new PhaseTwoCallback() {
-            @Override
-            void onPhaseTwoResolved(EphemeralResolveInfo ephemeralResolveInfo,
-                    int sequence) {
-                final String packageName;
-                final String splitName;
-                final int versionCode;
-                if (ephemeralResolveInfo != null) {
-                    final ArrayList<EphemeralResolveInfo> ephemeralResolveInfoList =
-                            new ArrayList<EphemeralResolveInfo>(1);
-                    ephemeralResolveInfoList.add(ephemeralResolveInfo);
-                    final EphemeralResponse ephemeralIntentInfo =
-                            EphemeralResolver.filterEphemeralIntent(
-                                    ephemeralResolveInfoList, intent, null /*resolvedType*/,
-                                    0 /*userId*/, intent.getPackage(), digest,
-                                    requestObj.responseObj.token);
-                    if (ephemeralIntentInfo != null
-                            && ephemeralIntentInfo.resolveInfo != null) {
-                        packageName = ephemeralIntentInfo.resolveInfo.getPackageName();
-                        splitName = ephemeralIntentInfo.splitName;
-                        versionCode = ephemeralIntentInfo.resolveInfo.getVersionCode();
-                    } else {
-                        packageName = null;
-                        splitName = null;
-                        versionCode = -1;
-                    }
-                } else {
-                    packageName = null;
-                    splitName = null;
-                    versionCode = -1;
-                }
-                final Intent installerIntent = buildEphemeralInstallerIntent(
-                        requestObj.launchIntent,
-                        requestObj.origIntent,
-                        requestObj.callingPackage,
-                        requestObj.resolvedType,
-                        requestObj.userId,
-                        packageName,
-                        splitName,
-                        versionCode,
-                        requestObj.responseObj.token,
-                        false /*needsPhaseTwo*/);
-                installerIntent.setComponent(new ComponentName(
-                        ephemeralInstaller.packageName, ephemeralInstaller.name));
-                context.startActivity(installerIntent);
-            }
-        };
-        connection.getEphemeralIntentFilterList(
-                hostName, callback, callbackHandler, 0 /*sequence*/);
-    }
-
-    /**
-     * Builds and returns an intent to launch the ephemeral installer.
-     */
-    public static Intent buildEphemeralInstallerIntent(Intent launchIntent, Intent origIntent,
-            String callingPackage, String resolvedType, int userId, String ephemeralPackageName,
-            String ephemeralSplitName, int versionCode, String token, boolean needsPhaseTwo) {
-        // Construct the intent that launches the ephemeral installer
-        int flags = launchIntent.getFlags();
-        final Intent intent = new Intent();
-        intent.setFlags(flags
-                | Intent.FLAG_ACTIVITY_NEW_TASK
-                | Intent.FLAG_ACTIVITY_CLEAR_TASK
-                | Intent.FLAG_ACTIVITY_NO_HISTORY
-                | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
-        // TODO: Remove when the platform has fully implemented ephemeral apps
-        intent.setData(origIntent.getData().buildUpon().clearQuery().build());
-        intent.putExtra(Intent.EXTRA_EPHEMERAL_TOKEN, token);
-        intent.putExtra(Intent.EXTRA_EPHEMERAL_HOSTNAME, origIntent.getData().getHost());
-
-        if (!needsPhaseTwo) {
-            // We have all of the data we need; just start the installer without a second phase
-            final Intent nonEphemeralIntent = new Intent(origIntent);
-            nonEphemeralIntent.setFlags(
-                    nonEphemeralIntent.getFlags() | Intent.FLAG_IGNORE_EPHEMERAL);
-            // Intent that is launched if the ephemeral package couldn't be installed
-            // for any reason.
-            try {
-                final IIntentSender failureIntentTarget = ActivityManagerNative.getDefault()
-                        .getIntentSender(
-                                ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
-                                null /*token*/, null /*resultWho*/, 1 /*requestCode*/,
-                                new Intent[] { nonEphemeralIntent },
-                                new String[] { resolvedType },
-                                PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
-                                        | PendingIntent.FLAG_IMMUTABLE,
-                                null /*bOptions*/, userId);
-                intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE,
-                        new IntentSender(failureIntentTarget));
-            } catch (RemoteException ignore) { /* ignore; same process */ }
-
-            // Success intent goes back to the installer
-            final Intent ephemeralIntent = new Intent(launchIntent)
-                    .setComponent(null)
-                    .setPackage(ephemeralPackageName);
-            // Intent that is eventually launched if the ephemeral package was
-            // installed successfully. This will actually be launched by a platform
-            // broadcast receiver.
-            try {
-                final IIntentSender successIntentTarget = ActivityManagerNative.getDefault()
-                        .getIntentSender(
-                                ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
-                                null /*token*/, null /*resultWho*/, 0 /*requestCode*/,
-                                new Intent[] { ephemeralIntent },
-                                new String[] { resolvedType },
-                                PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
-                                        | PendingIntent.FLAG_IMMUTABLE,
-                                null /*bOptions*/, userId);
-                intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS,
-                        new IntentSender(successIntentTarget));
-            } catch (RemoteException ignore) { /* ignore; same process */ }
-
-            intent.putExtra(Intent.EXTRA_PACKAGE_NAME, ephemeralPackageName);
-            intent.putExtra(Intent.EXTRA_SPLIT_NAME, ephemeralSplitName);
-            intent.putExtra(Intent.EXTRA_VERSION_CODE, versionCode);
-        }
-
-        return intent;
-    }
-
-    private static EphemeralResponse filterEphemeralIntent(
-            List<EphemeralResolveInfo> ephemeralResolveInfoList,
-            Intent intent, String resolvedType, int userId, String packageName,
-            EphemeralDigest digest, String token) {
-        final int[] shaPrefix = digest.getDigestPrefix();
-        final byte[][] digestBytes = digest.getDigestBytes();
-        // Go in reverse order so we match the narrowest scope first.
-        for (int i = shaPrefix.length - 1; i >= 0 ; --i) {
-            for (EphemeralResolveInfo ephemeralInfo : ephemeralResolveInfoList) {
-                if (!Arrays.equals(digestBytes[i], ephemeralInfo.getDigestBytes())) {
-                    continue;
-                }
-                if (packageName != null
-                        && !packageName.equals(ephemeralInfo.getPackageName())) {
-                    continue;
-                }
-                final List<EphemeralIntentFilter> ephemeralFilters =
-                        ephemeralInfo.getIntentFilters();
-                // No filters; we need to start phase two
-                if (ephemeralFilters == null || ephemeralFilters.isEmpty()) {
-                    return new EphemeralResponse(ephemeralInfo,
-                            new IntentFilter(Intent.ACTION_VIEW) /*intentFilter*/,
-                            null /*splitName*/, token, true /*needsPhase2*/);
-                }
-                // We have a domain match; resolve the filters to see if anything matches.
-                final PackageManagerService.EphemeralIntentResolver ephemeralResolver =
-                        new PackageManagerService.EphemeralIntentResolver();
-                for (int j = ephemeralFilters.size() - 1; j >= 0; --j) {
-                    final EphemeralIntentFilter ephemeralFilter = ephemeralFilters.get(j);
-                    final List<IntentFilter> splitFilters = ephemeralFilter.getFilters();
-                    if (splitFilters == null || splitFilters.isEmpty()) {
-                        continue;
-                    }
-                    for (int k = splitFilters.size() - 1; k >= 0; --k) {
-                        final EphemeralResponse intentInfo =
-                                new EphemeralResponse(ephemeralInfo,
-                                        splitFilters.get(k), ephemeralFilter.getSplitName(),
-                                        token, false /*needsPhase2*/);
-                        ephemeralResolver.addFilter(intentInfo);
-                    }
-                }
-                List<EphemeralResponse> matchedResolveInfoList = ephemeralResolver.queryIntent(
-                        intent, resolvedType, false /*defaultOnly*/, userId);
-                if (!matchedResolveInfoList.isEmpty()) {
-                    return matchedResolveInfoList.get(0);
-                }
-            }
-        }
-        // Hash or filter mis-match; no ephemeral apps for this domain.
-        return null;
-    }
-}
diff --git a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
index 2b6ce10..9c1992c 100644
--- a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
+++ b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
@@ -16,14 +16,13 @@
 
 package com.android.server.pm;
 
-import android.app.EphemeralResolverService;
-import android.app.IEphemeralResolver;
+import android.app.IInstantAppResolver;
+import android.app.InstantAppResolverService;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
-import android.content.pm.EphemeralResolveInfo;
-import android.content.pm.EphemeralResponse;
+import android.content.pm.InstantAppResolveInfo;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
@@ -62,14 +61,14 @@
     private final Intent mIntent;
 
     private volatile boolean mBindRequested;
-    private IEphemeralResolver mRemoteInstance;
+    private IInstantAppResolver mRemoteInstance;
 
     public EphemeralResolverConnection(Context context, ComponentName componentName) {
         mContext = context;
         mIntent = new Intent(Intent.ACTION_RESOLVE_EPHEMERAL_PACKAGE).setComponent(componentName);
     }
 
-    public final List<EphemeralResolveInfo> getEphemeralResolveInfoList(int hashPrefix[]) {
+    public final List<InstantAppResolveInfo> getInstantAppResolveInfoList(int hashPrefix[]) {
         throwIfCalledOnMainThread();
         try {
             return mGetEphemeralResolveInfoCaller.getEphemeralResolveInfoList(
@@ -84,24 +83,25 @@
         return null;
     }
 
-    public final void getEphemeralIntentFilterList(String hostName, PhaseTwoCallback callback,
-            Handler callbackHandler, final int sequence) {
+    public final void getInstantAppIntentFilterList(int hashPrefix[], String hostName,
+            PhaseTwoCallback callback, Handler callbackHandler, final int sequence) {
         final IRemoteCallback remoteCallback = new IRemoteCallback.Stub() {
             @Override
             public void sendResult(Bundle data) throws RemoteException {
-                final EphemeralResolveInfo ephemeralResolveInfo =
-                        data.getParcelable(EphemeralResolverService.EXTRA_RESOLVE_INFO);
+                final ArrayList<InstantAppResolveInfo> resolveList =
+                        data.getParcelableArrayList(
+                                InstantAppResolverService.EXTRA_RESOLVE_INFO);
                 callbackHandler.post(new Runnable() {
                     @Override
                     public void run() {
-                        callback.onPhaseTwoResolved(ephemeralResolveInfo, sequence);
+                        callback.onPhaseTwoResolved(resolveList, sequence);
                     }
                 });
             }
         };
         try {
             getRemoteInstanceLazy()
-                    .getEphemeralIntentFilterList(remoteCallback, hostName, sequence);
+                    .getInstantAppIntentFilterList(hashPrefix, sequence, hostName, remoteCallback);
         } catch (RemoteException re) {
         } catch (TimeoutException te) {
         }
@@ -122,7 +122,7 @@
         }
     }
 
-    private IEphemeralResolver getRemoteInstanceLazy() throws TimeoutException {
+    private IInstantAppResolver getRemoteInstanceLazy() throws TimeoutException {
         synchronized (mLock) {
             if (mRemoteInstance != null) {
                 return mRemoteInstance;
@@ -173,14 +173,15 @@
      * Asynchronous callback when results come back from ephemeral resolution phase two.
      */
     public abstract static class PhaseTwoCallback {
-        abstract void onPhaseTwoResolved(EphemeralResolveInfo ephemeralResolveInfo, int sequence);
+        abstract void onPhaseTwoResolved(
+                List<InstantAppResolveInfo> instantAppResolveInfoList, int sequence);
     }
 
     private final class MyServiceConnection implements ServiceConnection {
         @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
             synchronized (mLock) {
-                mRemoteInstance = IEphemeralResolver.Stub.asInterface(service);
+                mRemoteInstance = IInstantAppResolver.Stub.asInterface(service);
                 mLock.notifyAll();
             }
         }
@@ -194,7 +195,7 @@
     }
 
     private static final class GetEphemeralResolveInfoCaller
-            extends TimedRemoteCaller<List<EphemeralResolveInfo>> {
+            extends TimedRemoteCaller<List<InstantAppResolveInfo>> {
         private final IRemoteCallback mCallback;
 
         public GetEphemeralResolveInfoCaller() {
@@ -202,21 +203,21 @@
             mCallback = new IRemoteCallback.Stub() {
                     @Override
                     public void sendResult(Bundle data) throws RemoteException {
-                        final ArrayList<EphemeralResolveInfo> resolveList =
+                        final ArrayList<InstantAppResolveInfo> resolveList =
                                 data.getParcelableArrayList(
-                                        EphemeralResolverService.EXTRA_RESOLVE_INFO);
+                                        InstantAppResolverService.EXTRA_RESOLVE_INFO);
                         int sequence =
-                                data.getInt(EphemeralResolverService.EXTRA_SEQUENCE, -1);
+                                data.getInt(InstantAppResolverService.EXTRA_SEQUENCE, -1);
                         onRemoteMethodResult(resolveList, sequence);
                     }
             };
         }
 
-        public List<EphemeralResolveInfo> getEphemeralResolveInfoList(
-                IEphemeralResolver target, int hashPrefix[])
+        public List<InstantAppResolveInfo> getEphemeralResolveInfoList(
+                IInstantAppResolver target, int hashPrefix[])
                         throws RemoteException, TimeoutException {
             final int sequence = onBeforeRemoteCall();
-            target.getEphemeralResolveInfoList(mCallback, hashPrefix, sequence);
+            target.getInstantAppResolveInfoList(hashPrefix, sequence, mCallback);
             return getResultTimed(sequence);
         }
     }
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 449d808..5abdb60 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -63,6 +63,9 @@
     public static final int FLAG_CLEAR_CACHE_ONLY = 1 << 8;
     public static final int FLAG_CLEAR_CODE_CACHE_ONLY = 1 << 9;
     public static final int FLAG_USE_QUOTA = 1 << 12;
+    public static final int FLAG_FREE_CACHE_V2 = 1 << 13;
+    public static final int FLAG_FREE_CACHE_V2_DEFY_QUOTA = 1 << 14;
+    public static final int FLAG_FREE_CACHE_NOOP = 1 << 15;
 
     private final boolean mIsolated;
 
@@ -465,6 +468,15 @@
         }
     }
 
+    public boolean isQuotaSupported(String volumeUuid) throws InstallerException {
+        if (!checkBeforeRemote()) return false;
+        try {
+            return mInstalld.isQuotaSupported(volumeUuid);
+        } catch (Exception e) {
+            throw InstallerException.from(e);
+        }
+    }
+
     private static void assertValidInstructionSet(String instructionSet)
             throws InstallerException {
         for (String abi : Build.SUPPORTED_ABIS) {
diff --git a/services/core/java/com/android/server/pm/InstantAppRegistry.java b/services/core/java/com/android/server/pm/InstantAppRegistry.java
index 23925ad..0ae5f31 100644
--- a/services/core/java/com/android/server/pm/InstantAppRegistry.java
+++ b/services/core/java/com/android/server/pm/InstantAppRegistry.java
@@ -42,6 +42,7 @@
 import android.util.Xml;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.os.BackgroundThread;
+import com.android.internal.os.SomeArgs;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.XmlUtils;
 import libcore.io.IoUtils;
@@ -115,8 +116,14 @@
     }
 
     public byte[] getInstantAppCookieLPw(@NonNull String packageName,
-                                         @UserIdInt int userId) {
-        byte[] pendingCookie = mCookiePersistence.getPendingPersistCookie(userId, packageName);
+            @UserIdInt int userId) {
+        // Only installed packages can get their own cookie
+        PackageParser.Package pkg = mService.mPackages.get(packageName);
+        if (pkg == null) {
+            return null;
+        }
+
+        byte[] pendingCookie = mCookiePersistence.getPendingPersistCookieLPr(pkg, userId);
         if (pendingCookie != null) {
             return pendingCookie;
         }
@@ -132,7 +139,7 @@
     }
 
     public boolean setInstantAppCookieLPw(@NonNull String packageName,
-                                          @Nullable byte[] cookie, @UserIdInt int userId) {
+            @Nullable byte[] cookie, @UserIdInt int userId) {
         if (cookie != null && cookie.length > 0) {
             final int maxCookieSize = mService.mContext.getPackageManager()
                     .getInstantAppCookieMaxSize();
@@ -143,25 +150,25 @@
             }
         }
 
-        mCookiePersistence.schedulePersist(userId, packageName, cookie);
+        // Only an installed package can set its own cookie
+        PackageParser.Package pkg = mService.mPackages.get(packageName);
+        if (pkg == null) {
+            return false;
+        }
+
+        mCookiePersistence.schedulePersistLPw(userId, pkg, cookie);
         return true;
     }
 
     private void persistInstantApplicationCookie(@Nullable byte[] cookie,
-            @NonNull String packageName, @UserIdInt int userId) {
+            @NonNull String packageName, @NonNull File cookieFile, @UserIdInt int userId) {
         synchronized (mService.mPackages) {
-            PackageParser.Package pkg = mService.mPackages.get(packageName);
-            if (pkg == null) {
-                return;
-            }
-
             File appDir = getInstantApplicationDir(packageName, userId);
             if (!appDir.exists() && !appDir.mkdirs()) {
                 Slog.e(LOG_TAG, "Cannot create instant app cookie directory");
                 return;
             }
 
-            File cookieFile = computeInstantCookieFile(pkg, userId);
             if (cookieFile.exists() && !cookieFile.delete()) {
                 Slog.e(LOG_TAG, "Cannot delete instant app cookie file");
             }
@@ -170,12 +177,11 @@
             if (cookie == null || cookie.length <= 0) {
                 return;
             }
-
-            try (FileOutputStream fos = new FileOutputStream(cookieFile)) {
-                fos.write(cookie, 0, cookie.length);
-            } catch (IOException e) {
-                Slog.e(LOG_TAG, "Error writing instant app cookie file: " + cookieFile, e);
-            }
+        }
+        try (FileOutputStream fos = new FileOutputStream(cookieFile)) {
+            fos.write(cookie, 0, cookie.length);
+        } catch (IOException e) {
+            Slog.e(LOG_TAG, "Error writing instant app cookie file: " + cookieFile, e);
         }
     }
 
@@ -240,6 +246,8 @@
             if (!currentCookieFile.equals(expectedCookeFile)) {
                 Slog.i(LOG_TAG, "Signature for package " + pkg.packageName
                         + " changed - dropping cookie");
+                // Make sure a pending write for the old signed app is cancelled
+                mCookiePersistence.cancelPendingPersistLPw(pkg, userId);
                 currentCookieFile.delete();
             }
         }
@@ -430,6 +438,7 @@
             bitmap = Bitmap.createBitmap(icon.getIntrinsicWidth(),
                     icon.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
             Canvas canvas = new Canvas(bitmap);
+            icon.setBounds(0, 0, icon.getIntrinsicWidth(), icon.getIntrinsicHeight());
             icon.draw(canvas);
         }
 
@@ -890,71 +899,90 @@
         // In case you wonder why we stash the cookies aside, we use
         // the user id for the message id and the package for the payload.
         // Handler allows removing messages by id and tag where the
-        // tag is is compared using ==. So to allow cancelling the
+        // tag is compared using ==. So to allow cancelling the
         // pending persistence for an app under a given user we use
-        // the fact that package names are interned in the system
-        // process so the == comparison would match and we end up
-        // with a way to cancel persisting the cookie for a user
-        // and package.
-        private final SparseArray<ArrayMap<String, byte[]>> mPendingPersistCookies =
-                new SparseArray<>();
+        // the fact that package are cached by the system so the ==
+        // comparison would match and we end up with a way to cancel
+        // persisting the cookie for a user and package.
+        private final SparseArray<ArrayMap<PackageParser.Package, SomeArgs>> mPendingPersistCookies
+                = new SparseArray<>();
 
         public CookiePersistence(Looper looper) {
             super(looper);
         }
 
-        public void schedulePersist(@UserIdInt int userId,
-                @NonNull String packageName, @NonNull byte[] cookie) {
-            cancelPendingPersist(userId, packageName);
-            addPendingPersistCookie(userId, packageName, cookie);
-            sendMessageDelayed(obtainMessage(userId, packageName),
+        public void schedulePersistLPw(@UserIdInt int userId, @NonNull PackageParser.Package pkg,
+                @NonNull byte[] cookie) {
+            File cookieFile = computeInstantCookieFile(pkg, userId);
+            cancelPendingPersistLPw(pkg, userId);
+            addPendingPersistCookieLPw(userId, pkg, cookie, cookieFile);
+            sendMessageDelayed(obtainMessage(userId, pkg),
                     PERSIST_COOKIE_DELAY_MILLIS);
         }
 
-        public @Nullable byte[] getPendingPersistCookie(@UserIdInt int userId,
-                @NonNull String packageName) {
-            ArrayMap<String, byte[]> pendingWorkForUser = mPendingPersistCookies.get(userId);
+        public @Nullable byte[] getPendingPersistCookieLPr(@NonNull PackageParser.Package pkg,
+                @UserIdInt int userId) {
+            ArrayMap<PackageParser.Package, SomeArgs> pendingWorkForUser =
+                    mPendingPersistCookies.get(userId);
             if (pendingWorkForUser != null) {
-                return pendingWorkForUser.remove(packageName);
+                SomeArgs state = pendingWorkForUser.get(pkg);
+                if (state != null) {
+                    return (byte[]) state.arg1;
+                }
             }
             return null;
         }
 
-        private void cancelPendingPersist(@UserIdInt int userId,
-                @NonNull String packageName) {
-            removePendingPersistCookie(userId, packageName);
-            removeMessages(userId, packageName);
+        public void cancelPendingPersistLPw(@NonNull PackageParser.Package pkg,
+                @UserIdInt int userId) {
+            removeMessages(userId, pkg);
+            SomeArgs state = removePendingPersistCookieLPr(pkg, userId);
+            if (state != null) {
+                state.recycle();
+            }
         }
 
-        private void addPendingPersistCookie(@UserIdInt int userId,
-                @NonNull String packageName, @NonNull byte[] cookie) {
-            ArrayMap<String, byte[]> pendingWorkForUser = mPendingPersistCookies.get(userId);
+        private void addPendingPersistCookieLPw(@UserIdInt int userId,
+                @NonNull PackageParser.Package pkg, @NonNull byte[] cookie,
+                @NonNull File cookieFile) {
+            ArrayMap<PackageParser.Package, SomeArgs> pendingWorkForUser =
+                    mPendingPersistCookies.get(userId);
             if (pendingWorkForUser == null) {
                 pendingWorkForUser = new ArrayMap<>();
                 mPendingPersistCookies.put(userId, pendingWorkForUser);
             }
-            pendingWorkForUser.put(packageName, cookie);
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = cookie;
+            args.arg2 = cookieFile;
+            pendingWorkForUser.put(pkg, args);
         }
 
-        private byte[] removePendingPersistCookie(@UserIdInt int userId,
-                @NonNull String packageName) {
-            ArrayMap<String, byte[]> pendingWorkForUser = mPendingPersistCookies.get(userId);
-            byte[] cookie = null;
+        private SomeArgs removePendingPersistCookieLPr(@NonNull PackageParser.Package pkg,
+                @UserIdInt int userId) {
+            ArrayMap<PackageParser.Package, SomeArgs> pendingWorkForUser =
+                    mPendingPersistCookies.get(userId);
+            SomeArgs state = null;
             if (pendingWorkForUser != null) {
-                cookie = pendingWorkForUser.remove(packageName);
+                state = pendingWorkForUser.remove(pkg);
                 if (pendingWorkForUser.isEmpty()) {
                     mPendingPersistCookies.remove(userId);
                 }
             }
-            return cookie;
+            return state;
         }
 
         @Override
         public void handleMessage(Message message) {
             int userId = message.what;
-            String packageName = (String) message.obj;
-            byte[] cookie = removePendingPersistCookie(userId, packageName);
-            persistInstantApplicationCookie(cookie, packageName, userId);
+            PackageParser.Package pkg = (PackageParser.Package) message.obj;
+            SomeArgs state = removePendingPersistCookieLPr(pkg, userId);
+            if (state == null) {
+                return;
+            }
+            byte[] cookie = (byte[]) state.arg1;
+            File cookieFile = (File) state.arg2;
+            state.recycle();
+            persistInstantApplicationCookie(cookie, pkg.packageName, cookieFile, userId);
         }
     }
 }
diff --git a/services/core/java/com/android/server/pm/InstantAppResolver.java b/services/core/java/com/android/server/pm/InstantAppResolver.java
new file mode 100644
index 0000000..3821418
--- /dev/null
+++ b/services/core/java/com/android/server/pm/InstantAppResolver.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.IIntentSender;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.IntentSender;
+import android.content.pm.ActivityInfo;
+import android.content.pm.InstantAppRequest;
+import android.content.pm.AuxiliaryResolveInfo;
+import android.content.pm.InstantAppIntentFilter;
+import android.content.pm.InstantAppResolveInfo;
+import android.content.pm.InstantAppResolveInfo.InstantAppDigest;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.util.Log;
+import android.util.Slog;
+
+import com.android.server.pm.EphemeralResolverConnection.PhaseTwoCallback;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.UUID;
+
+/** @hide */
+public abstract class InstantAppResolver {
+    public static AuxiliaryResolveInfo doInstantAppResolutionPhaseOne(Context context,
+            EphemeralResolverConnection connection, InstantAppRequest requestObj) {
+        final Intent intent = requestObj.origIntent;
+        final InstantAppDigest digest =
+                new InstantAppDigest(intent.getData().getHost(), 5 /*maxDigests*/);
+        final int[] shaPrefix = digest.getDigestPrefix();
+        final List<InstantAppResolveInfo> instantAppResolveInfoList =
+                connection.getInstantAppResolveInfoList(shaPrefix);
+        if (instantAppResolveInfoList == null || instantAppResolveInfoList.size() == 0) {
+            // No hash prefix match; there are no instant apps for this domain.
+            return null;
+        }
+
+        final String token = UUID.randomUUID().toString();
+        return InstantAppResolver.filterInstantAppIntent(instantAppResolveInfoList,
+                intent, requestObj.resolvedType, requestObj.userId,
+                intent.getPackage(), digest, token);
+    }
+
+    public static void doInstantAppResolutionPhaseTwo(Context context,
+            EphemeralResolverConnection connection, InstantAppRequest requestObj,
+            ActivityInfo instantAppInstaller, Handler callbackHandler) {
+        final Intent intent = requestObj.origIntent;
+        final String hostName = intent.getData().getHost();
+        final InstantAppDigest digest = new InstantAppDigest(hostName, 5 /*maxDigests*/);
+        final int[] shaPrefix = digest.getDigestPrefix();
+
+        final PhaseTwoCallback callback = new PhaseTwoCallback() {
+            @Override
+            void onPhaseTwoResolved(List<InstantAppResolveInfo> instantAppResolveInfoList,
+                    int sequence) {
+                final String packageName;
+                final String splitName;
+                final int versionCode;
+                if (instantAppResolveInfoList != null && instantAppResolveInfoList.size() > 0) {
+                    final AuxiliaryResolveInfo instantAppIntentInfo =
+                            InstantAppResolver.filterInstantAppIntent(
+                                    instantAppResolveInfoList, intent, null /*resolvedType*/,
+                                    0 /*userId*/, intent.getPackage(), digest,
+                                    requestObj.responseObj.token);
+                    if (instantAppIntentInfo != null
+                            && instantAppIntentInfo.resolveInfo != null) {
+                        packageName = instantAppIntentInfo.resolveInfo.getPackageName();
+                        splitName = instantAppIntentInfo.splitName;
+                        versionCode = instantAppIntentInfo.resolveInfo.getVersionCode();
+                    } else {
+                        packageName = null;
+                        splitName = null;
+                        versionCode = -1;
+                    }
+                } else {
+                    packageName = null;
+                    splitName = null;
+                    versionCode = -1;
+                }
+                final Intent installerIntent = buildEphemeralInstallerIntent(
+                        requestObj.origIntent,
+                        requestObj.callingPackage,
+                        requestObj.resolvedType,
+                        requestObj.userId,
+                        packageName,
+                        splitName,
+                        versionCode,
+                        requestObj.responseObj.token,
+                        false /*needsPhaseTwo*/);
+                installerIntent.setComponent(new ComponentName(
+                        instantAppInstaller.packageName, instantAppInstaller.name));
+                context.startActivity(installerIntent);
+            }
+        };
+        connection.getInstantAppIntentFilterList(
+                shaPrefix, hostName, callback, callbackHandler, 0 /*sequence*/);
+    }
+
+    /**
+     * Builds and returns an intent to launch the instant installer.
+     */
+    public static Intent buildEphemeralInstallerIntent(@NonNull Intent origIntent,
+            @NonNull String callingPackage,
+            @NonNull String resolvedType,
+            int userId,
+            @NonNull String instantAppPackageName,
+            @Nullable String instantAppSplitName,
+            int versionCode,
+            @Nullable String token,
+            boolean needsPhaseTwo) {
+        // Construct the intent that launches the instant installer
+        int flags = origIntent.getFlags();
+        final Intent intent = new Intent();
+        intent.setFlags(flags
+                | Intent.FLAG_ACTIVITY_NEW_TASK
+                | Intent.FLAG_ACTIVITY_CLEAR_TASK
+                | Intent.FLAG_ACTIVITY_NO_HISTORY
+                | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+        if (token != null) {
+            intent.putExtra(Intent.EXTRA_EPHEMERAL_TOKEN, token);
+        }
+        if (origIntent.getData() != null) {
+            intent.putExtra(Intent.EXTRA_EPHEMERAL_HOSTNAME, origIntent.getData().getHost());
+        }
+
+        // We have all of the data we need; just start the installer without a second phase
+        if (!needsPhaseTwo) {
+            // Intent that is launched if the package couldn't be installed for any reason.
+            final Intent failureIntent = new Intent(origIntent);
+            failureIntent.setFlags(failureIntent.getFlags() | Intent.FLAG_IGNORE_EPHEMERAL);
+            try {
+                final IIntentSender failureIntentTarget = ActivityManager.getService()
+                        .getIntentSender(
+                                ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
+                                null /*token*/, null /*resultWho*/, 1 /*requestCode*/,
+                                new Intent[] { failureIntent },
+                                new String[] { resolvedType },
+                                PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
+                                        | PendingIntent.FLAG_IMMUTABLE,
+                                null /*bOptions*/, userId);
+                intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE,
+                        new IntentSender(failureIntentTarget));
+            } catch (RemoteException ignore) { /* ignore; same process */ }
+
+            // Intent that is launched if the package was installed successfully.
+            final Intent successIntent = new Intent(origIntent);
+            try {
+                final IIntentSender successIntentTarget = ActivityManager.getService()
+                        .getIntentSender(
+                                ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
+                                null /*token*/, null /*resultWho*/, 0 /*requestCode*/,
+                                new Intent[] { successIntent },
+                                new String[] { resolvedType },
+                                PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
+                                        | PendingIntent.FLAG_IMMUTABLE,
+                                null /*bOptions*/, userId);
+                intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS,
+                        new IntentSender(successIntentTarget));
+            } catch (RemoteException ignore) { /* ignore; same process */ }
+
+            intent.putExtra(Intent.EXTRA_PACKAGE_NAME, instantAppPackageName);
+            intent.putExtra(Intent.EXTRA_SPLIT_NAME, instantAppSplitName);
+            intent.putExtra(Intent.EXTRA_VERSION_CODE, versionCode);
+        }
+
+        return intent;
+    }
+
+    private static AuxiliaryResolveInfo filterInstantAppIntent(
+            List<InstantAppResolveInfo> instantAppResolveInfoList,
+            Intent intent, String resolvedType, int userId, String packageName,
+            InstantAppDigest digest, String token) {
+        final int[] shaPrefix = digest.getDigestPrefix();
+        final byte[][] digestBytes = digest.getDigestBytes();
+        // Go in reverse order so we match the narrowest scope first.
+        for (int i = shaPrefix.length - 1; i >= 0 ; --i) {
+            for (InstantAppResolveInfo instantAppInfo : instantAppResolveInfoList) {
+                if (!Arrays.equals(digestBytes[i], instantAppInfo.getDigestBytes())) {
+                    continue;
+                }
+                if (packageName != null
+                        && !packageName.equals(instantAppInfo.getPackageName())) {
+                    continue;
+                }
+                final List<InstantAppIntentFilter> instantAppFilters =
+                        instantAppInfo.getIntentFilters();
+                // No filters; we need to start phase two
+                if (instantAppFilters == null || instantAppFilters.isEmpty()) {
+                    return new AuxiliaryResolveInfo(instantAppInfo,
+                            new IntentFilter(Intent.ACTION_VIEW) /*intentFilter*/,
+                            null /*splitName*/, token, true /*needsPhase2*/);
+                }
+                // We have a domain match; resolve the filters to see if anything matches.
+                final PackageManagerService.EphemeralIntentResolver instantAppResolver =
+                        new PackageManagerService.EphemeralIntentResolver();
+                for (int j = instantAppFilters.size() - 1; j >= 0; --j) {
+                    final InstantAppIntentFilter instantAppFilter = instantAppFilters.get(j);
+                    final List<IntentFilter> splitFilters = instantAppFilter.getFilters();
+                    if (splitFilters == null || splitFilters.isEmpty()) {
+                        continue;
+                    }
+                    for (int k = splitFilters.size() - 1; k >= 0; --k) {
+                        final AuxiliaryResolveInfo intentInfo =
+                                new AuxiliaryResolveInfo(instantAppInfo,
+                                        splitFilters.get(k), instantAppFilter.getSplitName(),
+                                        token, false /*needsPhase2*/);
+                        instantAppResolver.addFilter(intentInfo);
+                    }
+                }
+                List<AuxiliaryResolveInfo> matchedResolveInfoList = instantAppResolver.queryIntent(
+                        intent, resolvedType, false /*defaultOnly*/, userId);
+                if (!matchedResolveInfoList.isEmpty()) {
+                    return matchedResolveInfoList.get(0);
+                }
+            }
+        }
+        // Hash or filter mis-match; no instant apps for this domain.
+        return null;
+    }
+}
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 96a2577..71bfa64 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -242,6 +242,12 @@
             try {
                 UserInfo callingUserInfo = mUm.getUserInfo(callingUserId);
                 if (callingUserInfo.isManagedProfile()) {
+
+                    // STOPSHIP Remove the whitelist.
+                    if ("com.google.android.talk".equals(callingPackage)
+                            || "com.google.android.quicksearchbox".equals(callingPackage)) {
+                        return false;
+                    }
                     Slog.wtfStack(TAG, message + " by " + callingPackage + " for another profile "
                             + targetUserId + " from " + callingUserId);
 
@@ -436,8 +442,8 @@
 
         @Override
         public ParceledListSlice getShortcuts(String callingPackage, long changedSince,
-                String packageName, List shortcutIds, ComponentName componentName, int flags,
-                UserHandle targetUser) {
+                String packageName, List shortcutIds, ComponentName componentName, Intent intent,
+                int flags, UserHandle targetUser) {
             ensureShortcutPermission(callingPackage);
             if (!canAccessProfile(callingPackage, targetUser, "Cannot get shortcuts")
                     || !isUserEnabled(targetUser)) {
@@ -448,11 +454,17 @@
                         "To query by shortcut ID, package name must also be set");
             }
 
+            if ((flags & ShortcutQuery.FLAG_MATCH_CHOOSER) == 0
+                    && intent != null) {
+                throw new IllegalArgumentException("Supplied an intent in the query, but did "
+                        + "not request chooser targets");
+            }
+
             // TODO(b/29399275): Eclipse compiler requires explicit List<ShortcutInfo> cast below.
             return new ParceledListSlice<>((List<ShortcutInfo>)
                     mShortcutServiceInternal.getShortcuts(getCallingUserId(),
                             callingPackage, changedSince, packageName, shortcutIds,
-                            componentName, flags, targetUser.getIdentifier()));
+                            componentName, intent, flags, targetUser.getIdentifier()));
         }
 
         @Override
@@ -900,6 +912,7 @@
                                         cookie.packageName,
                                         /* changedSince= */ 0, packageName, /* shortcutIds=*/ null,
                                         /* component= */ null,
+                                        /* intent= */ null,
                                         ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY
                                         | ShortcutQuery.FLAG_GET_ALL_KINDS
                                         , userId);
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index bbd227e..aac04da 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -314,7 +314,8 @@
         optimizer.performDexOpt(pkg, libraryDependencies,
                 null /* ISAs */, false /* checkProfiles */,
                 getCompilerFilterForReason(compilationReason),
-                null /* CompilerStats.PackageStats */);
+                null /* CompilerStats.PackageStats */,
+                mPackageManagerService.getDexManager().isUsedByOtherApps(pkg.packageName));
 
         return commands;
     }
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index b589057..d9ea728 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -104,7 +104,7 @@
      */
     int performDexOpt(PackageParser.Package pkg, String[] sharedLibraries,
             String[] instructionSets, boolean checkProfiles, String targetCompilationFilter,
-            CompilerStats.PackageStats packageStats) {
+            CompilerStats.PackageStats packageStats, boolean isUsedByOtherApps) {
         if (!canOptimizePackage(pkg)) {
             return DEX_OPT_SKIPPED;
         }
@@ -119,7 +119,7 @@
             }
             try {
                 return performDexOptLI(pkg, sharedLibraries, instructionSets, checkProfiles,
-                        targetCompilationFilter, packageStats);
+                        targetCompilationFilter, packageStats, isUsedByOtherApps);
             } finally {
                 if (useLock) {
                     mDexoptWakeLock.release();
@@ -135,7 +135,8 @@
     @GuardedBy("mInstallLock")
     private int performDexOptLI(PackageParser.Package pkg, String[] sharedLibraries,
             String[] targetInstructionSets, boolean checkForProfileUpdates,
-            String targetCompilerFilter, CompilerStats.PackageStats packageStats) {
+            String targetCompilerFilter, CompilerStats.PackageStats packageStats,
+            boolean isUsedByOtherApps) {
         final String[] instructionSets = targetInstructionSets != null ?
                 targetInstructionSets : getAppDexInstructionSets(pkg.applicationInfo);
         final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
@@ -143,7 +144,7 @@
         final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
 
         final String compilerFilter = getRealCompilerFilter(pkg.applicationInfo,
-                targetCompilerFilter, isUsedByOtherApps(pkg));
+                targetCompilerFilter, isUsedByOtherApps);
         final boolean profileUpdated = checkForProfileUpdates &&
                 isProfileUpdated(pkg, sharedGid, compilerFilter);
 
@@ -477,40 +478,6 @@
         mSystemReady = true;
     }
 
-    /**
-     * Returns true if the profiling data collected for the given app indicate
-     * that the apps's APK has been loaded by another app.
-     * Note that this returns false for all forward-locked apps and apps without
-     * any collected profiling data.
-     */
-    public static boolean isUsedByOtherApps(PackageParser.Package pkg) {
-        if (pkg.isForwardLocked()) {
-            // Skip the check for forward locked packages since they don't share their code.
-            return false;
-        }
-
-        for (String apkPath : pkg.getAllCodePathsExcludingResourceOnly()) {
-            try {
-                apkPath = PackageManagerServiceUtils.realpath(new File(apkPath));
-            } catch (IOException e) {
-                // Log an error but continue without it.
-                Slog.w(TAG, "Failed to get canonical path", e);
-                continue;
-            }
-            String useMarker = apkPath.replace('/', '@');
-            final int[] currentUserIds = UserManagerService.getInstance().getUserIds();
-            for (int i = 0; i < currentUserIds.length; i++) {
-                File profileDir =
-                        Environment.getDataProfilesDeForeignDexDirectory(currentUserIds[i]);
-                File foreignUseMark = new File(profileDir, useMarker);
-                if (foreignUseMark.exists()) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
     private String printDexoptFlags(int flags) {
         ArrayList<String> flagsList = new ArrayList<>();
 
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 53765f2..37f78b4 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -88,6 +88,7 @@
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.content.PackageHelper;
+import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.ImageUtils;
 import com.android.internal.util.IndentingPrintWriter;
@@ -607,6 +608,12 @@
                     + "to use the PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS flag");
         }
 
+        if ((params.installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0
+                || (params.installFlags & PackageManager.INSTALL_EXTERNAL) != 0) {
+            throw new IllegalArgumentException(
+                    "New installs into ASEC containers no longer supported");
+        }
+
         // Defensively resize giant app icons
         if (params.appIcon != null) {
             final ActivityManager am = (ActivityManager) mContext.getSystemService(
@@ -1097,7 +1104,7 @@
                 context.getResources().getDimensionPixelSize(
                         android.R.dimen.notification_large_icon_height));
         CharSequence packageLabel = packageInfo.applicationInfo.loadLabel(pm);
-        return new Notification.Builder(context)
+        return new Notification.Builder(context, SystemNotificationChannels.DEVICE_ADMIN)
                 .setSmallIcon(R.drawable.ic_check_circle_24px)
                 .setColor(context.getResources().getColor(
                         R.color.system_notification_accent_color))
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 463cfac..fd731c3 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -24,10 +24,12 @@
 import static android.system.OsConstants.O_CREAT;
 import static android.system.OsConstants.O_RDONLY;
 import static android.system.OsConstants.O_WRONLY;
+
 import static com.android.server.pm.PackageInstallerService.prepareExternalStageCid;
 import static com.android.server.pm.PackageInstallerService.prepareStageDir;
 
 import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
@@ -44,6 +46,7 @@
 import android.content.pm.PackageParser.PackageLite;
 import android.content.pm.PackageParser.PackageParserException;
 import android.content.pm.Signature;
+import android.content.pm.UserInfo;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.FileBridge;
@@ -54,8 +57,8 @@
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.os.RemoteException;
-import android.os.SELinux;
 import android.os.UserHandle;
+import android.os.storage.StorageManager;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.system.OsConstants;
@@ -66,9 +69,6 @@
 import android.util.MathUtils;
 import android.util.Slog;
 
-import libcore.io.IoUtils;
-import libcore.io.Libcore;
-
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.content.NativeLibraryHelper;
 import com.android.internal.content.PackageHelper;
@@ -78,6 +78,9 @@
 import com.android.server.pm.Installer.InstallerException;
 import com.android.server.pm.PackageInstallerService.PackageInstallObserverAdapter;
 
+import libcore.io.IoUtils;
+import libcore.io.Libcore;
+
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileFilter;
@@ -294,6 +297,7 @@
             info.active = mActiveCount.get() > 0;
 
             info.mode = params.mode;
+            info.installReason = params.installReason;
             info.sizeBytes = params.sizeBytes;
             info.appPackageName = params.appPackageName;
             info.appIcon = params.appIcon;
@@ -455,14 +459,9 @@
 
             // If caller specified a total length, allocate it for them. Free up
             // cache space to grow, if needed.
-            if (lengthBytes > 0) {
-                final StructStat stat = Libcore.os.fstat(targetFd);
-                final long deltaBytes = lengthBytes - stat.st_size;
-                // Only need to free up space when writing to internal stage
-                if (stageDir != null && deltaBytes > 0) {
-                    mPm.freeStorage(params.volumeUuid, deltaBytes);
-                }
-                Libcore.os.posix_fallocate(targetFd, 0, lengthBytes);
+            if (stageDir != null && lengthBytes > 0) {
+                mContext.getSystemService(StorageManager.class).allocateBytes(targetFd,
+                        lengthBytes, 0);
             }
 
             if (offsetBytes > 0) {
@@ -1143,6 +1142,25 @@
         }
 
         final boolean success = (returnCode == PackageManager.INSTALL_SUCCEEDED);
+
+        // Send broadcast to default launcher only if it's a new install
+        final boolean isNewInstall = extras == null || !extras.getBoolean(Intent.EXTRA_REPLACING);
+        if (success && isNewInstall) {
+            UserManagerService ums = UserManagerService.getInstance();
+            if (ums != null) {
+                final UserInfo parent = ums.getProfileParent(userId);
+                final int launcherUid = (parent != null) ? parent.id : userId;
+                final ComponentName launcherComponent = mPm.getDefaultHomeActivity(launcherUid);
+                if (launcherComponent != null) {
+                    Intent launcherIntent = new Intent(PackageInstaller.ACTION_SESSION_COMMITTED)
+                            .putExtra(PackageInstaller.EXTRA_SESSION, generateInfo())
+                            .putExtra(Intent.EXTRA_USER, UserHandle.of(userId))
+                            .setPackage(launcherComponent.getPackageName());
+                    mContext.sendBroadcastAsUser(launcherIntent, UserHandle.of(launcherUid));
+                }
+            }
+        }
+
         mCallback.onSessionFinished(this, success);
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 4b294b9..e2358c2 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -128,10 +128,8 @@
 import android.content.pm.AppsQueryHelper;
 import android.content.pm.ChangedPackages;
 import android.content.pm.ComponentInfo;
-import android.content.pm.InstantAppInfo;
-import android.content.pm.EphemeralRequest;
-import android.content.pm.EphemeralResolveInfo;
-import android.content.pm.EphemeralResponse;
+import android.content.pm.InstantAppRequest;
+import android.content.pm.AuxiliaryResolveInfo;
 import android.content.pm.FallbackCategoryProvider;
 import android.content.pm.FeatureInfo;
 import android.content.pm.IOnPermissionsChangeListener;
@@ -143,6 +141,8 @@
 import android.content.pm.IPackageManager;
 import android.content.pm.IPackageMoveObserver;
 import android.content.pm.IPackageStatsObserver;
+import android.content.pm.InstantAppInfo;
+import android.content.pm.InstantAppResolveInfo;
 import android.content.pm.InstrumentationInfo;
 import android.content.pm.IntentFilterVerificationInfo;
 import android.content.pm.KeySet;
@@ -204,15 +204,16 @@
 import android.os.UserManager;
 import android.os.UserManagerInternal;
 import android.os.storage.IStorageManager;
-import android.os.storage.StorageManagerInternal;
 import android.os.storage.StorageEventListener;
 import android.os.storage.StorageManager;
+import android.os.storage.StorageManagerInternal;
 import android.os.storage.VolumeInfo;
 import android.os.storage.VolumeRecord;
 import android.provider.Settings.Global;
 import android.provider.Settings.Secure;
 import android.security.KeyStore;
 import android.security.SystemKeyStore;
+import android.service.pm.PackageServiceDumpProto;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.text.TextUtils;
@@ -235,6 +236,7 @@
 import android.util.SparseIntArray;
 import android.util.Xml;
 import android.util.jar.StrictJarFile;
+import android.util.proto.ProtoOutputStream;
 import android.view.Display;
 
 import com.android.internal.R;
@@ -251,6 +253,7 @@
 import com.android.internal.os.Zygote;
 import com.android.internal.telephony.CarrierAppUtils;
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.ConcurrentUtils;
 import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.IndentingPrintWriter;
@@ -265,6 +268,7 @@
 import com.android.server.LocalServices;
 import com.android.server.ServiceThread;
 import com.android.server.SystemConfig;
+import com.android.server.SystemServerInitThreadPool;
 import com.android.server.Watchdog;
 import com.android.server.net.NetworkPolicyManagerInternal;
 import com.android.server.pm.Installer.InstallerException;
@@ -314,14 +318,15 @@
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Date;
-import java.util.HashSet;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -392,8 +397,8 @@
     private static final boolean DISABLE_EPHEMERAL_APPS = false;
     private static final boolean HIDE_EPHEMERAL_APIS = false;
 
-    private static final boolean ENABLE_QUOTA =
-            SystemProperties.getBoolean("persist.fw.quota", false);
+    private static final boolean ENABLE_FREE_CACHE_V2 =
+            SystemProperties.getBoolean("fw.free_cache_v2", false);
 
     private static final int RADIO_UID = Process.PHONE_UID;
     private static final int LOG_UID = Process.LOG_UID;
@@ -491,18 +496,6 @@
     private static final String PACKAGE_SCHEME = "package";
 
     private static final String VENDOR_OVERLAY_DIR = "/vendor/overlay";
-    /**
-     * If VENDOR_OVERLAY_THEME_PROPERTY is set, search for runtime resource overlay APKs also in
-     * VENDOR_OVERLAY_DIR/<value of VENDOR_OVERLAY_THEME_PROPERTY> in addition to
-     * VENDOR_OVERLAY_DIR.
-     */
-    private static final String VENDOR_OVERLAY_THEME_PROPERTY = "ro.boot.vendor.overlay.theme";
-    /**
-     * Same as VENDOR_OVERLAY_THEME_PROPERTY, except persistent. If set will override whatever
-     * is in VENDOR_OVERLAY_THEME_PROPERTY.
-     */
-    private static final String VENDOR_OVERLAY_THEME_PERSIST_PROPERTY
-            = "persist.vendor.overlay.theme";
 
     /** Permission grant: not grant the permission. */
     private static final int GRANT_DENIED = 1;
@@ -577,7 +570,8 @@
             Manifest.permission.RECEIVE_MMS,
             Manifest.permission.READ_EXTERNAL_STORAGE,
             Manifest.permission.WRITE_EXTERNAL_STORAGE,
-            Manifest.permission.READ_PHONE_NUMBER);
+            Manifest.permission.READ_PHONE_NUMBER,
+            Manifest.permission.ANSWER_PHONE_CALLS);
 
 
     /**
@@ -658,9 +652,12 @@
     final ArrayMap<String, Set<String>> mKnownCodebase =
             new ArrayMap<String, Set<String>>();
 
-    // Tracks available target package names -> overlay package paths.
-    final ArrayMap<String, ArrayMap<String, PackageParser.Package>> mOverlays =
-        new ArrayMap<String, ArrayMap<String, PackageParser.Package>>();
+    // List of APK paths to load for each user and package. This data is never
+    // persisted by the package manager. Instead, the overlay manager will
+    // ensure the data is up-to-date in runtime.
+    @GuardedBy("mPackages")
+    final SparseArray<ArrayMap<String, ArrayList<String>>> mEnabledOverlayPaths =
+        new SparseArray<ArrayMap<String, ArrayList<String>>>();
 
     /**
      * Tracks new system packages [received in an OTA] that we expect to
@@ -737,6 +734,12 @@
     @GuardedBy("mPackages")
     final SparseArray<Map<String, Integer>> mChangedPackagesSequenceNumbers = new SparseArray<>();
 
+    final PackageParser.Callback mPackageParserCallback = new PackageParser.Callback() {
+        @Override public boolean hasFeature(String feature) {
+            return PackageManagerService.this.hasSystemFeature(feature, 0);
+        }
+    };
+
     public static final class SharedLibraryEntry {
         public final String path;
         public final String apk;
@@ -834,12 +837,12 @@
     private int mIntentFilterVerificationToken = 0;
 
     /** The service connection to the ephemeral resolver */
-    final EphemeralResolverConnection mEphemeralResolverConnection;
+    final EphemeralResolverConnection mInstantAppResolverConnection;
 
     /** Component used to install ephemeral applications */
-    ComponentName mEphemeralInstallerComponent;
-    final ActivityInfo mEphemeralInstallerActivity = new ActivityInfo();
-    final ResolveInfo mEphemeralInstallerInfo = new ResolveInfo();
+    ComponentName mInstantAppInstallerComponent;
+    final ActivityInfo mInstantAppInstallerActivity = new ActivityInfo();
+    final ResolveInfo mInstantAppInstallerInfo = new ResolveInfo();
 
     final SparseArray<IntentFilterVerificationState> mIntentFilterVerificationStates
             = new SparseArray<IntentFilterVerificationState>();
@@ -857,6 +860,8 @@
 
     private ArraySet<String> mPrivappPermissionsViolations;
 
+    private Future<?> mPrepareAppDataFuture;
+
     private static class IFVerificationParams {
         PackageParser.Package pkg;
         boolean replacing;
@@ -1159,7 +1164,7 @@
     static final int START_INTENT_FILTER_VERIFICATIONS = 17;
     static final int INTENT_FILTER_VERIFIED = 18;
     static final int WRITE_PACKAGE_LIST = 19;
-    static final int EPHEMERAL_RESOLUTION_PHASE_TWO = 20;
+    static final int INSTANT_APP_RESOLUTION_PHASE_TWO = 20;
 
     static final int WRITE_SETTINGS_DELAY = 10*1000;  // 10 seconds
 
@@ -1730,11 +1735,11 @@
 
                     break;
                 }
-                case EPHEMERAL_RESOLUTION_PHASE_TWO: {
-                    EphemeralResolver.doEphemeralResolutionPhaseTwo(mContext,
-                            mEphemeralResolverConnection,
-                            (EphemeralRequest) msg.obj,
-                            mEphemeralInstallerActivity,
+                case INSTANT_APP_RESOLUTION_PHASE_TWO: {
+                    InstantAppResolver.doInstantAppResolutionPhaseTwo(mContext,
+                            mInstantAppResolverConnection,
+                            (InstantAppRequest) msg.obj,
+                            mInstantAppInstallerActivity,
                             mHandler);
                 }
             }
@@ -2459,16 +2464,6 @@
             // Collect vendor overlay packages. (Do this before scanning any apps.)
             // For security and version matching reason, only consider
             // overlay packages if they reside in the right directory.
-            String overlayThemeDir = SystemProperties.get(VENDOR_OVERLAY_THEME_PERSIST_PROPERTY);
-            if (overlayThemeDir.isEmpty()) {
-                overlayThemeDir = SystemProperties.get(VENDOR_OVERLAY_THEME_PROPERTY);
-            }
-            if (!overlayThemeDir.isEmpty()) {
-                scanDirTracedLI(new File(VENDOR_OVERLAY_DIR, overlayThemeDir), mDefParseFlags
-                        | PackageParser.PARSE_IS_SYSTEM
-                        | PackageParser.PARSE_IS_SYSTEM_DIR
-                        | PackageParser.PARSE_TRUSTED_OVERLAY, scanFlags | SCAN_TRUSTED_OVERLAY, 0);
-            }
             scanDirTracedLI(new File(VENDOR_OVERLAY_DIR), mDefParseFlags
                     | PackageParser.PARSE_IS_SYSTEM
                     | PackageParser.PARSE_IS_SYSTEM_DIR
@@ -2757,8 +2752,32 @@
             } else {
                 storageFlags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
             }
-            reconcileAppsDataLI(StorageManager.UUID_PRIVATE_INTERNAL, UserHandle.USER_SYSTEM,
-                    storageFlags, true /* migrateAppData */);
+            List<String> deferPackages = reconcileAppsDataLI(StorageManager.UUID_PRIVATE_INTERNAL,
+                    UserHandle.USER_SYSTEM, storageFlags, true /* migrateAppData */,
+                    true /* onlyCoreApps */);
+            mPrepareAppDataFuture = SystemServerInitThreadPool.get().submit(() -> {
+                if (deferPackages == null || deferPackages.isEmpty()) {
+                    return;
+                }
+                int count = 0;
+                for (String pkgName : deferPackages) {
+                    PackageParser.Package pkg = null;
+                    synchronized (mPackages) {
+                        PackageSetting ps = mSettings.getPackageLPr(pkgName);
+                        if (ps != null && ps.getInstalled(UserHandle.USER_SYSTEM)) {
+                            pkg = ps.pkg;
+                        }
+                    }
+                    if (pkg != null) {
+                        synchronized (mInstallLock) {
+                            prepareAppDataAndMigrateLIF(pkg, UserHandle.USER_SYSTEM, storageFlags,
+                                    true /* maybeMigrateAppData */);
+                        }
+                        count++;
+                    }
+                }
+                Slog.i(TAG, "Deferred reconcileAppsData finished " + count + " packages");
+            }, "prepareAppData");
 
             // If this is first boot after an OTA, and a normal boot, then
             // we need to clear code cache directories.
@@ -2861,17 +2880,17 @@
                 if (DEBUG_EPHEMERAL) {
                     Slog.i(TAG, "Ephemeral resolver: " + ephemeralResolverComponent);
                 }
-                mEphemeralResolverConnection =
+                mInstantAppResolverConnection =
                         new EphemeralResolverConnection(mContext, ephemeralResolverComponent);
             } else {
-                mEphemeralResolverConnection = null;
+                mInstantAppResolverConnection = null;
             }
-            mEphemeralInstallerComponent = getEphemeralInstallerLPr();
-            if (mEphemeralInstallerComponent != null) {
+            mInstantAppInstallerComponent = getEphemeralInstallerLPr();
+            if (mInstantAppInstallerComponent != null) {
                 if (DEBUG_EPHEMERAL) {
-                    Slog.i(TAG, "Ephemeral installer: " + mEphemeralInstallerComponent);
+                    Slog.i(TAG, "Ephemeral installer: " + mInstantAppInstallerComponent);
                 }
-                setUpEphemeralInstallerActivityLP(mEphemeralInstallerComponent);
+                setUpInstantAppInstallerActivityLP(mInstantAppInstallerComponent);
             }
 
             // Read and update the usage of dex files.
@@ -3374,6 +3393,8 @@
             return null;
         }
 
+        rebaseEnabledOverlays(packageInfo.applicationInfo, userId);
+
         packageInfo.packageName = packageInfo.applicationInfo.packageName =
                 resolveExternalPackageNameLPr(p);
 
@@ -3705,6 +3726,7 @@
             ApplicationInfo ai = PackageParser.generateApplicationInfo(ps.pkg, flags,
                     ps.readUserState(userId), userId);
             if (ai != null) {
+                rebaseEnabledOverlays(ai, userId);
                 ai.packageName = resolveExternalPackageNameLPr(ps.pkg);
             }
             return ai;
@@ -3739,6 +3761,7 @@
                 ApplicationInfo ai = PackageParser.generateApplicationInfo(
                         p, flags, ps.readUserState(userId), userId);
                 if (ai != null) {
+                    rebaseEnabledOverlays(ai, userId);
                     ai.packageName = resolveExternalPackageNameLPr(p);
                 }
                 return ai;
@@ -3755,6 +3778,26 @@
         return null;
     }
 
+    private void rebaseEnabledOverlays(@NonNull ApplicationInfo ai, int userId) {
+        List<String> paths = new ArrayList<>();
+        ArrayMap<String, ArrayList<String>> userSpecificOverlays =
+            mEnabledOverlayPaths.get(userId);
+        if (userSpecificOverlays != null) {
+            if (!"android".equals(ai.packageName)) {
+                ArrayList<String> frameworkOverlays = userSpecificOverlays.get("android");
+                if (frameworkOverlays != null) {
+                    paths.addAll(frameworkOverlays);
+                }
+            }
+
+            ArrayList<String> appOverlays = userSpecificOverlays.get(ai.packageName);
+            if (appOverlays != null) {
+                paths.addAll(appOverlays);
+            }
+        }
+        ai.resourceDirs = paths.size() > 0 ? paths.toArray(new String[paths.size()]) : null;
+    }
+
     private String normalizePackageNameLPr(String packageName) {
         String normalizedPackageName = mSettings.getRenamedPackageLPr(packageName);
         return normalizedPackageName != null ? normalizedPackageName : packageName;
@@ -3765,25 +3808,19 @@
             final IPackageDataObserver observer) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.CLEAR_APP_CACHE, null);
-        // Queue up an async operation since clearing cache may take a little while.
-        mHandler.post(new Runnable() {
-            public void run() {
-                mHandler.removeCallbacks(this);
-                boolean success = true;
-                synchronized (mInstallLock) {
-                    try {
-                        mInstaller.freeCache(volumeUuid, freeStorageSize, 0);
-                    } catch (InstallerException e) {
-                        Slog.w(TAG, "Couldn't clear application caches: " + e);
-                        success = false;
-                    }
-                }
-                if (observer != null) {
-                    try {
-                        observer.onRemoveCompleted(null, success);
-                    } catch (RemoteException e) {
-                        Slog.w(TAG, "RemoveException when invoking call back");
-                    }
+        mHandler.post(() -> {
+            boolean success = false;
+            try {
+                freeStorage(volumeUuid, freeStorageSize, 0);
+                success = true;
+            } catch (IOException e) {
+                Slog.w(TAG, e);
+            }
+            if (observer != null) {
+                try {
+                    observer.onRemoveCompleted(null, success);
+                } catch (RemoteException e) {
+                    Slog.w(TAG, e);
                 }
             }
         });
@@ -3793,42 +3830,77 @@
     public void freeStorage(final String volumeUuid, final long freeStorageSize,
             final IntentSender pi) {
         mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.CLEAR_APP_CACHE, null);
-        // Queue up an async operation since clearing cache may take a little while.
-        mHandler.post(new Runnable() {
-            public void run() {
-                mHandler.removeCallbacks(this);
-                boolean success = true;
-                synchronized (mInstallLock) {
-                    try {
-                        mInstaller.freeCache(volumeUuid, freeStorageSize, 0);
-                    } catch (InstallerException e) {
-                        Slog.w(TAG, "Couldn't clear application caches: " + e);
-                        success = false;
-                    }
-                }
-                if(pi != null) {
-                    try {
-                        // Callback via pending intent
-                        int code = success ? 1 : 0;
-                        pi.sendIntent(null, code, null,
-                                null, null);
-                    } catch (SendIntentException e1) {
-                        Slog.i(TAG, "Failed to send pending intent");
-                    }
+                android.Manifest.permission.CLEAR_APP_CACHE, TAG);
+        mHandler.post(() -> {
+            boolean success = false;
+            try {
+                freeStorage(volumeUuid, freeStorageSize, 0);
+                success = true;
+            } catch (IOException e) {
+                Slog.w(TAG, e);
+            }
+            if (pi != null) {
+                try {
+                    pi.sendIntent(null, success ? 1 : 0, null, null, null);
+                } catch (SendIntentException e) {
+                    Slog.w(TAG, e);
                 }
             }
         });
     }
 
-    void freeStorage(String volumeUuid, long freeStorageSize) throws IOException {
-        synchronized (mInstallLock) {
-            try {
-                mInstaller.freeCache(volumeUuid, freeStorageSize, 0);
-            } catch (InstallerException e) {
-                throw new IOException("Failed to free enough space", e);
+    /**
+     * Blocking call to clear various types of cached data across the system
+     * until the requested bytes are available.
+     */
+    public void freeStorage(String volumeUuid, long bytes, int storageFlags) throws IOException {
+        final StorageManager storage = mContext.getSystemService(StorageManager.class);
+        final File file = storage.findPathForUuid(volumeUuid);
+
+        if (ENABLE_FREE_CACHE_V2) {
+            final boolean aggressive = (storageFlags
+                    & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0;
+
+            // 1. Pre-flight to determine if we have any chance to succeed
+            // 2. Consider preloaded data (after 1w honeymoon, unless aggressive)
+
+            // 3. Consider parsed APK data (aggressive only)
+            if (aggressive) {
+                FileUtils.deleteContents(mCacheDir);
             }
+            if (file.getUsableSpace() >= bytes) return;
+
+            // 4. Consider cached app data (above quotas)
+            try {
+                mInstaller.freeCache(volumeUuid, bytes, Installer.FLAG_FREE_CACHE_V2);
+            } catch (InstallerException ignored) {
+            }
+            if (file.getUsableSpace() >= bytes) return;
+
+            // 5. Consider shared libraries with refcount=0 and age>2h
+            // 6. Consider dexopt output (aggressive only)
+            // 7. Consider ephemeral apps not used in last week
+
+            // 8. Consider cached app data (below quotas)
+            try {
+                mInstaller.freeCache(volumeUuid, bytes, Installer.FLAG_FREE_CACHE_V2
+                        | Installer.FLAG_FREE_CACHE_V2_DEFY_QUOTA);
+            } catch (InstallerException ignored) {
+            }
+            if (file.getUsableSpace() >= bytes) return;
+
+            // 9. Consider DropBox entries
+            // 10. Consider ephemeral cookies
+
+        } else {
+            try {
+                mInstaller.freeCache(volumeUuid, bytes, 0);
+            } catch (InstallerException ignored) {
+            }
+            if (file.getUsableSpace() >= bytes) return;
         }
+
+        throw new IOException("Failed to free " + bytes + " on storage device at " + file);
     }
 
     /**
@@ -3954,8 +4026,17 @@
 
     /**
      * Update given flags when being used to request {@link ResolveInfo}.
+     * <p>Instant apps are resolved specially, depending upon context. Minimally,
+     * {@code}flags{@code} must have the {@link PackageManager#MATCH_INSTANT}
+     * flag set. However, this flag is only honoured in three circumstances:
+     * <ul>
+     * <li>when called from a system process</li>
+     * <li>when the caller holds the permission {@code android.permission.ACCESS_INSTANT_APPS}</li>
+     * <li>when resolution occurs to start an activity with a {@code android.intent.action.VIEW}
+     * action and a {@code android.intent.category.BROWSABLE} category</li>
+     * </ul>
      */
-    int updateFlagsForResolve(int flags, int userId, Object cookie) {
+    int updateFlagsForResolve(int flags, int userId, Intent intent, boolean includeInstantApp) {
         // Safe mode means we shouldn't match any third-party components
         if (mSafeMode) {
             flags |= PackageManager.MATCH_SYSTEM_ONLY;
@@ -3967,13 +4048,24 @@
             flags |= PackageManager.MATCH_INSTANT;
         } else {
             // Otherwise, prevent leaking ephemeral components
+            final boolean isSpecialProcess =
+                    callingUid == Process.SYSTEM_UID
+                    || callingUid == Process.SHELL_UID
+                    || callingUid == 0;
+            final boolean allowMatchInstant =
+                    (includeInstantApp
+                            && Intent.ACTION_VIEW.equals(intent.getAction())
+                            && intent.hasCategory(Intent.CATEGORY_BROWSABLE)
+                            && hasWebURI(intent))
+                    || isSpecialProcess
+                    || mContext.checkCallingOrSelfPermission(
+                            android.Manifest.permission.ACCESS_INSTANT_APPS) == PERMISSION_GRANTED;
             flags &= ~PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY;
-            if (callingUid != Process.SYSTEM_UID && callingUid != 0) {
-                // Unless called from the system process
+            if (!allowMatchInstant) {
                 flags &= ~PackageManager.MATCH_INSTANT;
             }
         }
-        return updateFlagsForComponent(flags, userId, cookie);
+        return updateFlagsForComponent(flags, userId, intent /*cookie*/);
     }
 
     @Override
@@ -4035,8 +4127,12 @@
             if (a != null && mSettings.isEnabledAndMatchLPr(a.info, flags, userId)) {
                 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
                 if (ps == null) return null;
-                return PackageParser.generateActivityInfo(a, flags, ps.readUserState(userId),
-                        userId);
+                ActivityInfo ri = PackageParser.generateActivityInfo(a, flags,
+                        ps.readUserState(userId), userId);
+                if (ri != null) {
+                    rebaseEnabledOverlays(ri.applicationInfo, userId);
+                }
+                return ri;
             }
         }
         return null;
@@ -4162,8 +4258,12 @@
             if (s != null && mSettings.isEnabledAndMatchLPr(s.info, flags, userId)) {
                 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
                 if (ps == null) return null;
-                return PackageParser.generateServiceInfo(s, flags, ps.readUserState(userId),
-                        userId);
+                ServiceInfo si = PackageParser.generateServiceInfo(s, flags,
+                        ps.readUserState(userId), userId);
+                if (si != null) {
+                    rebaseEnabledOverlays(si.applicationInfo, userId);
+                }
+                return si;
             }
         }
         return null;
@@ -4182,8 +4282,12 @@
             if (p != null && mSettings.isEnabledAndMatchLPr(p.info, flags, userId)) {
                 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
                 if (ps == null) return null;
-                return PackageParser.generateProviderInfo(p, flags, ps.readUserState(userId),
-                        userId);
+                ProviderInfo pi = PackageParser.generateProviderInfo(p, flags,
+                        ps.readUserState(userId), userId);
+                if (pi != null) {
+                    rebaseEnabledOverlays(pi.applicationInfo, userId);
+                }
+                return pi;
             }
         }
         return null;
@@ -5498,17 +5602,23 @@
     @Override
     public ResolveInfo resolveIntent(Intent intent, String resolvedType,
             int flags, int userId) {
+        return resolveIntentInternal(
+                intent, resolvedType, flags, userId, false /*includeInstantApp*/);
+    }
+
+    private ResolveInfo resolveIntentInternal(Intent intent, String resolvedType,
+            int flags, int userId, boolean includeInstantApp) {
         try {
             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveIntent");
 
             if (!sUserManager.exists(userId)) return null;
-            flags = updateFlagsForResolve(flags, userId, intent);
+            flags = updateFlagsForResolve(flags, userId, intent, includeInstantApp);
             enforceCrossUserPermission(Binder.getCallingUid(), userId,
                     false /*requireFullPermission*/, false /*checkShell*/, "resolve intent");
 
             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities");
             final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType,
-                    flags, userId);
+                    flags, userId, includeInstantApp);
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
 
             final ResolveInfo bestChoice =
@@ -5530,7 +5640,7 @@
         }
         intent = updateIntentForResolve(intent);
         final String resolvedType = intent.resolveTypeIfNeeded(mContext.getContentResolver());
-        final int flags = updateFlagsForResolve(0, userId, intent);
+        final int flags = updateFlagsForResolve(0, userId, intent, false);
         final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType, flags,
                 userId);
         synchronized (mPackages) {
@@ -5573,6 +5683,11 @@
                 false, false, false, userId);
     }
 
+    /**
+     * Returns whether or not instant apps have been disabled remotely.
+     * <p><em>IMPORTANT</em> This should not be called with the package manager lock
+     * held. Otherwise we run the risk of deadlock.
+     */
     private boolean isEphemeralDisabled() {
         // ephemeral apps have been disabled across the board
         if (DISABLE_EPHEMERAL_APPS) {
@@ -5593,18 +5708,14 @@
     private boolean isEphemeralAllowed(
             Intent intent, List<ResolveInfo> resolvedActivities, int userId,
             boolean skipPackageCheck) {
-        // Short circuit and return early if possible.
-        if (isEphemeralDisabled()) {
-            return false;
-        }
         final int callingUser = UserHandle.getCallingUserId();
         if (callingUser != UserHandle.USER_SYSTEM) {
             return false;
         }
-        if (mEphemeralResolverConnection == null) {
+        if (mInstantAppResolverConnection == null) {
             return false;
         }
-        if (mEphemeralInstallerComponent == null) {
+        if (mInstantAppInstallerComponent == null) {
             return false;
         }
         if (intent.getComponent() != null) {
@@ -5621,6 +5732,7 @@
             return false;
         }
         // Deny ephemeral apps if the user chose _ALWAYS or _ALWAYS_ASK for intent resolution.
+        // Or if there's already an ephemeral app installed that handles the action
         synchronized (mPackages) {
             final int count = (resolvedActivities == null ? 0 : resolvedActivities.size());
             for (int n = 0; n < count; n++) {
@@ -5639,6 +5751,9 @@
                         }
                         return false;
                     }
+                    if (ps.getInstantApp(userId)) {
+                        return false;
+                    }
                 }
             }
         }
@@ -5646,11 +5761,11 @@
         return true;
     }
 
-    private void requestEphemeralResolutionPhaseTwo(EphemeralResponse responseObj,
-            Intent origIntent, String resolvedType, Intent launchIntent, String callingPackage,
+    private void requestInstantAppResolutionPhaseTwo(AuxiliaryResolveInfo responseObj,
+            Intent origIntent, String resolvedType, String callingPackage,
             int userId) {
-        final Message msg = mHandler.obtainMessage(EPHEMERAL_RESOLUTION_PHASE_TWO,
-                new EphemeralRequest(responseObj, origIntent, resolvedType, launchIntent,
+        final Message msg = mHandler.obtainMessage(INSTANT_APP_RESOLUTION_PHASE_TWO,
+                new InstantAppRequest(responseObj, origIntent, resolvedType,
                         callingPackage, userId));
         mHandler.sendMessage(msg);
     }
@@ -5685,6 +5800,13 @@
                 if (ri != null) {
                     return ri;
                 }
+                // If we have an ephemeral app, use it
+                for (int i = 0; i < N; i++) {
+                    ri = query.get(i);
+                    if (ri.activityInfo.applicationInfo.isInstantApp()) {
+                        return ri;
+                    }
+                }
                 ri = new ResolveInfo(mResolveInfo);
                 ri.activityInfo = new ActivityInfo(ri.activityInfo);
                 ri.activityInfo.labelRes = ResolverActivity.getLabelRes(intent.getAction());
@@ -5803,7 +5925,7 @@
             List<ResolveInfo> query, int priority, boolean always,
             boolean removeMatches, boolean debug, int userId) {
         if (!sUserManager.exists(userId)) return null;
-        flags = updateFlagsForResolve(flags, userId, intent);
+        flags = updateFlagsForResolve(flags, userId, intent, false);
         intent = updateIntentForResolve(intent);
         // writer
         synchronized (mPackages) {
@@ -5971,7 +6093,7 @@
             // cross-profile app linking works only towards the parent.
             final UserInfo parent = getProfileParent(sourceUserId);
             synchronized(mPackages) {
-                int flags = updateFlagsForResolve(0, parent.id, intent);
+                int flags = updateFlagsForResolve(0, parent.id, intent, false);
                 CrossProfileDomainInfo xpDomainInfo = getCrossProfileDomainPreferredLpr(
                         intent, resolvedType, flags, sourceUserId, parent.id);
                 return xpDomainInfo != null;
@@ -6030,9 +6152,14 @@
 
     private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
             String resolvedType, int flags, int userId) {
+        return queryIntentActivitiesInternal(intent, resolvedType, flags, userId, false);
+    }
+
+    private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
+            String resolvedType, int flags, int userId, boolean includeInstantApp) {
         if (!sUserManager.exists(userId)) return Collections.emptyList();
         final String instantAppPkgName = getInstantAppPackageName(Binder.getCallingUid());
-        flags = updateFlagsForResolve(flags, userId, intent);
+        flags = updateFlagsForResolve(flags, userId, intent, includeInstantApp);
         enforceCrossUserPermission(Binder.getCallingUid(), userId,
                 false /* requireFullPermission */, false /* checkShell */,
                 "query intent activities");
@@ -6052,23 +6179,31 @@
                 // used when either 1) the calling package is normal and the activity is within
                 // an ephemeral application or 2) the calling package is ephemeral and the
                 // activity is not visible to ephemeral applications.
-                boolean matchEphemeral =
+                final boolean matchInstantApp =
                         (flags & PackageManager.MATCH_INSTANT) != 0;
-                boolean ephemeralVisibleOnly =
+                final boolean matchVisibleToInstantAppOnly =
                         (flags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
-                boolean blockResolution =
-                        (!matchEphemeral && instantAppPkgName == null
-                                && (ai.applicationInfo.privateFlags
-                                        & ApplicationInfo.PRIVATE_FLAG_INSTANT) != 0)
-                        || (ephemeralVisibleOnly && instantAppPkgName != null
-                                && (ai.flags & ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL) == 0);
+                final boolean isCallerInstantApp =
+                        instantAppPkgName != null;
+                final boolean isTargetSameInstantApp =
+                        comp.getPackageName().equals(instantAppPkgName);
+                final boolean isTargetInstantApp =
+                        (ai.applicationInfo.privateFlags
+                                & ApplicationInfo.PRIVATE_FLAG_INSTANT) != 0;
+                final boolean isTargetHiddenFromInstantApp =
+                        (ai.flags & ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL) == 0;
+                final boolean blockResolution =
+                        !isTargetSameInstantApp
+                        && ((!matchInstantApp && !isCallerInstantApp && isTargetInstantApp)
+                                || (matchVisibleToInstantAppOnly && isCallerInstantApp
+                                        && isTargetHiddenFromInstantApp));
                 if (!blockResolution) {
                     final ResolveInfo ri = new ResolveInfo();
                     ri.activityInfo = ai;
                     list.add(ri);
                 }
             }
-            return list;
+            return applyPostResolutionFilter(list, instantAppPkgName);
         }
 
         // reader
@@ -6076,6 +6211,7 @@
         boolean addEphemeral = false;
         List<ResolveInfo> result;
         final String pkgName = intent.getPackage();
+        final boolean ephemeralDisabled = isEphemeralDisabled();
         synchronized (mPackages) {
             if (pkgName == null) {
                 List<CrossProfileIntentFilter> matchingFilters =
@@ -6086,15 +6222,15 @@
                 if (xpResolveInfo != null) {
                     List<ResolveInfo> xpResult = new ArrayList<ResolveInfo>(1);
                     xpResult.add(xpResolveInfo);
-                    return filterForEphemeral(
+                    return applyPostResolutionFilter(
                             filterIfNotSystemUser(xpResult, userId), instantAppPkgName);
                 }
 
                 // Check for results in the current profile.
                 result = filterIfNotSystemUser(mActivities.queryIntent(
                         intent, resolvedType, flags, userId), userId);
-                addEphemeral =
-                        isEphemeralAllowed(intent, result, userId, false /*skipPackageCheck*/);
+                addEphemeral = !ephemeralDisabled
+                        && isEphemeralAllowed(intent, result, userId, false /*skipPackageCheck*/);
 
                 // Check for cross profile results.
                 boolean hasNonNegativePriorityResult = hasNonNegativePriority(result);
@@ -6127,13 +6263,13 @@
                             // And we are not going to add emphemeral app, so we can return the
                             // result straight away.
                             result.add(xpDomainInfo.resolveInfo);
-                            return filterForEphemeral(result, instantAppPkgName);
+                            return applyPostResolutionFilter(result, instantAppPkgName);
                         }
                     } else if (result.size() <= 1 && !addEphemeral) {
                         // No result in parent user and <= 1 result in current profile, and we
                         // are not going to add emphemeral app, so we can return the result without
                         // further processing.
-                        return filterForEphemeral(result, instantAppPkgName);
+                        return applyPostResolutionFilter(result, instantAppPkgName);
                     }
                     // We have more than one candidate (combining results from current and parent
                     // profile), so we need filtering and sorting.
@@ -6144,32 +6280,34 @@
             } else {
                 final PackageParser.Package pkg = mPackages.get(pkgName);
                 if (pkg != null) {
-                    result = filterForEphemeral(filterIfNotSystemUser(
+                    result = applyPostResolutionFilter(filterIfNotSystemUser(
                             mActivities.queryIntentForPackage(
                                     intent, resolvedType, flags, pkg.activities, userId),
                             userId), instantAppPkgName);
                 } else {
                     // the caller wants to resolve for a particular package; however, there
                     // were no installed results, so, try to find an ephemeral result
-                    addEphemeral = isEphemeralAllowed(
-                            intent, null /*result*/, userId, true /*skipPackageCheck*/);
+                    addEphemeral =  !ephemeralDisabled
+                            && isEphemeralAllowed(
+                                    intent, null /*result*/, userId, true /*skipPackageCheck*/);
                     result = new ArrayList<ResolveInfo>();
                 }
             }
         }
         if (addEphemeral) {
             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveEphemeral");
-            final EphemeralRequest requestObject = new EphemeralRequest(
+            final InstantAppRequest requestObject = new InstantAppRequest(
                     null /*responseObj*/, intent /*origIntent*/, resolvedType,
-                    null /*launchIntent*/, null /*callingPackage*/, userId);
-            final EphemeralResponse intentInfo = EphemeralResolver.doEphemeralResolutionPhaseOne(
-                    mContext, mEphemeralResolverConnection, requestObject);
-            if (intentInfo != null) {
+                    null /*callingPackage*/, userId);
+            final AuxiliaryResolveInfo auxiliaryResponse =
+                    InstantAppResolver.doInstantAppResolutionPhaseOne(
+                            mContext, mInstantAppResolverConnection, requestObject);
+            if (auxiliaryResponse != null) {
                 if (DEBUG_EPHEMERAL) {
                     Slog.v(TAG, "Adding ephemeral installer to the ResolveInfo list");
                 }
-                final ResolveInfo ephemeralInstaller = new ResolveInfo(mEphemeralInstallerInfo);
-                ephemeralInstaller.ephemeralResponse = intentInfo;
+                final ResolveInfo ephemeralInstaller = new ResolveInfo(mInstantAppInstallerInfo);
+                ephemeralInstaller.auxiliaryInfo = auxiliaryResponse;
                 // make sure this resolver is the default
                 ephemeralInstaller.isDefault = true;
                 ephemeralInstaller.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART
@@ -6178,6 +6316,7 @@
                 ephemeralInstaller.filter = new IntentFilter(intent.getAction());
                 ephemeralInstaller.filter.addDataPath(
                         intent.getData().getPath(), PatternMatcher.PATTERN_LITERAL);
+                ephemeralInstaller.instantAppAvailable = true;
                 result.add(ephemeralInstaller);
             }
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
@@ -6185,7 +6324,7 @@
         if (sortResult) {
             Collections.sort(result, mResolvePrioritySorter);
         }
-        return filterForEphemeral(result, instantAppPkgName);
+        return applyPostResolutionFilter(result, instantAppPkgName);
     }
 
     private static class CrossProfileDomainInfo {
@@ -6293,16 +6432,40 @@
      *          is performed.
      * @return A filtered list of resolved activities.
      */
-    private List<ResolveInfo> filterForEphemeral(List<ResolveInfo> resolveInfos,
+    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--) {
-            ResolveInfo info = resolveInfos.get(i);
+            final ResolveInfo info = resolveInfos.get(i);
             final boolean isEphemeralApp = info.activityInfo.applicationInfo.isInstantApp();
             // allow activities that are defined in the provided package
             if (isEphemeralApp && ephemeralPkgName.equals(info.activityInfo.packageName)) {
+                if (info.activityInfo.splitName != null
+                        && !ArrayUtils.contains(info.activityInfo.applicationInfo.splitNames,
+                                info.activityInfo.splitName)) {
+                    // requested activity is defined in a split that hasn't been installed yet.
+                    // add the installer to the resolve list
+                    if (DEBUG_EPHEMERAL) {
+                        Slog.v(TAG, "Adding ephemeral installer to the ResolveInfo list");
+                    }
+                    final ResolveInfo installerInfo = new ResolveInfo(mInstantAppInstallerInfo);
+                    installerInfo.auxiliaryInfo = new AuxiliaryResolveInfo(
+                            info.activityInfo.packageName, info.activityInfo.splitName,
+                            info.activityInfo.applicationInfo.versionCode);
+                    // make sure this resolver is the default
+                    installerInfo.isDefault = true;
+                    installerInfo.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART
+                            | IntentFilter.MATCH_ADJUSTMENT_NORMAL;
+                    // add a non-generic filter
+                    installerInfo.filter = new IntentFilter();
+                    // load resources from the correct package
+                    installerInfo.resolvePackageName = info.getComponentInfo().packageName;
+                    resolveInfos.set(i, installerInfo);
+                }
                 continue;
             }
             // allow activities that have been explicitly exposed to ephemeral apps
@@ -6626,7 +6789,7 @@
             Intent[] specifics, String[] specificTypes, Intent intent,
             String resolvedType, int flags, int userId) {
         if (!sUserManager.exists(userId)) return Collections.emptyList();
-        flags = updateFlagsForResolve(flags, userId, intent);
+        flags = updateFlagsForResolve(flags, userId, intent, false);
         enforceCrossUserPermission(Binder.getCallingUid(), userId,
                 false /* requireFullPermission */, false /* checkShell */,
                 "query intent activity options");
@@ -6806,7 +6969,7 @@
     private @NonNull List<ResolveInfo> queryIntentReceiversInternal(Intent intent,
             String resolvedType, int flags, int userId) {
         if (!sUserManager.exists(userId)) return Collections.emptyList();
-        flags = updateFlagsForResolve(flags, userId, intent);
+        flags = updateFlagsForResolve(flags, userId, intent, false);
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
@@ -6843,7 +7006,7 @@
     @Override
     public ResolveInfo resolveService(Intent intent, String resolvedType, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
-        flags = updateFlagsForResolve(flags, userId, intent);
+        flags = updateFlagsForResolve(flags, userId, intent, false);
         List<ResolveInfo> query = queryIntentServicesInternal(intent, resolvedType, flags, userId);
         if (query != null) {
             if (query.size() >= 1) {
@@ -6865,7 +7028,7 @@
     private @NonNull List<ResolveInfo> queryIntentServicesInternal(Intent intent,
             String resolvedType, int flags, int userId) {
         if (!sUserManager.exists(userId)) return Collections.emptyList();
-        flags = updateFlagsForResolve(flags, userId, intent);
+        flags = updateFlagsForResolve(flags, userId, intent, false);
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
@@ -6909,7 +7072,7 @@
     private @NonNull List<ResolveInfo> queryIntentContentProvidersInternal(
             Intent intent, String resolvedType, int flags, int userId) {
         if (!sUserManager.exists(userId)) return Collections.emptyList();
-        flags = updateFlagsForResolve(flags, userId, intent);
+        flags = updateFlagsForResolve(flags, userId, intent, false);
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
@@ -7081,6 +7244,7 @@
                         ai = PackageParser.generateApplicationInfo(ps.pkg, effectiveFlags,
                                 ps.readUserState(userId), userId);
                         if (ai != null) {
+                            rebaseEnabledOverlays(ai, userId);
                             ai.packageName = resolveExternalPackageNameLPr(ps.pkg);
                         }
                     } else {
@@ -7104,6 +7268,7 @@
                         ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
                                 ps.readUserState(userId), userId);
                         if (ai != null) {
+                            rebaseEnabledOverlays(ai, userId);
                             ai.packageName = resolveExternalPackageNameLPr(p);
                             list.add(ai);
                         }
@@ -7145,12 +7310,17 @@
             return false;
         }
 
-        if (!isCallerSameApp(packageName)) {
-            return false;
-        }
         synchronized (mPackages) {
             final PackageSetting ps = mSettings.mPackages.get(packageName);
-            if (ps != null) {
+            final boolean returnAllowed =
+                    ps != null
+                    && (isCallerSameApp(packageName)
+                            || mContext.checkCallingOrSelfPermission(
+                                    android.Manifest.permission.ACCESS_INSTANT_APPS)
+                                            == PERMISSION_GRANTED
+                            || mInstantAppRegistry.isInstantAccessGranted(
+                                    userId, UserHandle.getAppId(Binder.getCallingUid()), ps.appId));
+            if (returnAllowed) {
                 return ps.getInstantApp(userId);
             }
         }
@@ -7247,6 +7417,7 @@
                         ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
                                 ps.readUserState(userId), userId);
                         if (ai != null) {
+                            rebaseEnabledOverlays(ai, userId);
                             finalList.add(ai);
                         }
                     }
@@ -7306,7 +7477,7 @@
 
     @Override
     public @NonNull ParceledListSlice<ProviderInfo> queryContentProviders(String processName,
-            int uid, int flags) {
+            int uid, int flags, String metaDataKey) {
         final int userId = processName != null ? UserHandle.getUserId(uid)
                 : UserHandle.getCallingUserId();
         if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList();
@@ -7324,6 +7495,14 @@
                                 || (p.info.processName.equals(processName)
                                         && UserHandle.isSameApp(p.info.applicationInfo.uid, uid)))
                         && mSettings.isEnabledAndMatchLPr(p.info, flags, userId)) {
+
+                    // See PM.queryContentProviders()'s javadoc for why we have the metaData
+                    // parameter.
+                    if (metaDataKey != null
+                            && (p.metaData == null || !p.metaData.containsKey(metaDataKey))) {
+                        continue;
+                    }
+
                     if (finalList == null) {
                         finalList = new ArrayList<ProviderInfo>(3);
                     }
@@ -7382,60 +7561,6 @@
         return finalList;
     }
 
-    private void createIdmapsForPackageLI(PackageParser.Package pkg) {
-        ArrayMap<String, PackageParser.Package> overlays = mOverlays.get(pkg.packageName);
-        if (overlays == null) {
-            Slog.w(TAG, "Unable to create idmap for " + pkg.packageName + ": no overlay packages");
-            return;
-        }
-        for (PackageParser.Package opkg : overlays.values()) {
-            // Not much to do if idmap fails: we already logged the error
-            // and we certainly don't want to abort installation of pkg simply
-            // because an overlay didn't fit properly. For these reasons,
-            // ignore the return value of createIdmapForPackagePairLI.
-            createIdmapForPackagePairLI(pkg, opkg);
-        }
-    }
-
-    private boolean createIdmapForPackagePairLI(PackageParser.Package pkg,
-            PackageParser.Package opkg) {
-        if (!opkg.mTrustedOverlay) {
-            Slog.w(TAG, "Skipping target and overlay pair " + pkg.baseCodePath + " and " +
-                    opkg.baseCodePath + ": overlay not trusted");
-            return false;
-        }
-        ArrayMap<String, PackageParser.Package> overlaySet = mOverlays.get(pkg.packageName);
-        if (overlaySet == null) {
-            Slog.e(TAG, "was about to create idmap for " + pkg.baseCodePath + " and " +
-                    opkg.baseCodePath + " but target package has no known overlays");
-            return false;
-        }
-        final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
-        // TODO: generate idmap for split APKs
-        try {
-            mInstaller.idmap(pkg.baseCodePath, opkg.baseCodePath, sharedGid);
-        } catch (InstallerException e) {
-            Slog.e(TAG, "Failed to generate idmap for " + pkg.baseCodePath + " and "
-                    + opkg.baseCodePath);
-            return false;
-        }
-        PackageParser.Package[] overlayArray =
-            overlaySet.values().toArray(new PackageParser.Package[0]);
-        Comparator<PackageParser.Package> cmp = new Comparator<PackageParser.Package>() {
-            public int compare(PackageParser.Package p1, PackageParser.Package p2) {
-                return p1.mOverlayPriority - p2.mOverlayPriority;
-            }
-        };
-        Arrays.sort(overlayArray, cmp);
-
-        pkg.applicationInfo.resourceDirs = new String[overlayArray.length];
-        int i = 0;
-        for (PackageParser.Package p : overlayArray) {
-            pkg.applicationInfo.resourceDirs[i++] = p.baseCodePath;
-        }
-        return true;
-    }
-
     private void scanDirTracedLI(File dir, final int parseFlags, int scanFlags, long currentTime) {
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanDir [" + dir.getAbsolutePath() + "]");
         try {
@@ -7457,7 +7582,7 @@
                     + " flags=0x" + Integer.toHexString(parseFlags));
         }
         ParallelPackageParser parallelPackageParser = new ParallelPackageParser(
-                mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir);
+                mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir, mPackageParserCallback);
 
         // Submit files for parsing in parallel
         int fileCount = 0;
@@ -7626,6 +7751,7 @@
         pp.setSeparateProcesses(mSeparateProcesses);
         pp.setOnlyCoreApps(mOnlyCore);
         pp.setDisplayMetrics(mMetrics);
+        pp.setCallback(mPackageParserCallback);
 
         if ((scanFlags & SCAN_TRUSTED_OVERLAY) != 0) {
             parseFlags |= PackageParser.PARSE_TRUSTED_OVERLAY;
@@ -8307,11 +8433,13 @@
                 pdo.performDexOpt(depPackage, null /* sharedLibraries */, instructionSets,
                         false /* checkProfiles */,
                         getCompilerFilterForReason(REASON_NON_SYSTEM_LIBRARY),
-                        getOrCreateCompilerPackageStats(depPackage));
+                        getOrCreateCompilerPackageStats(depPackage),
+                        mDexManager.isUsedByOtherApps(p.packageName));
             }
         }
         return pdo.performDexOpt(p, p.usesLibraryFiles, instructionSets, checkProfiles,
-                targetCompilerFilter, getOrCreateCompilerPackageStats(p));
+                targetCompilerFilter, getOrCreateCompilerPackageStats(p),
+                mDexManager.isUsedByOtherApps(p.packageName));
     }
 
     // Performs dexopt on the used secondary dex files belonging to the given package.
@@ -8583,6 +8711,7 @@
             } catch (InstallerException e) {
                 Slog.w(TAG, String.valueOf(e));
             }
+            mDexManager.notifyPackageDataDestroyed(pkg.packageName, userId);
         }
     }
 
@@ -8592,60 +8721,9 @@
             return;
         }
         destroyAppProfilesLeafLIF(pkg);
-        destroyAppReferenceProfileLeafLIF(pkg, userId, true /* removeBaseMarker */);
         final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
         for (int i = 0; i < childCount; i++) {
             destroyAppProfilesLeafLIF(pkg.childPackages.get(i));
-            destroyAppReferenceProfileLeafLIF(pkg.childPackages.get(i), userId,
-                    true /* removeBaseMarker */);
-        }
-    }
-
-    private void destroyAppReferenceProfileLeafLIF(PackageParser.Package pkg, int userId,
-            boolean removeBaseMarker) {
-        if (pkg.isForwardLocked()) {
-            return;
-        }
-
-        for (String path : pkg.getAllCodePathsExcludingResourceOnly()) {
-            try {
-                path = PackageManagerServiceUtils.realpath(new File(path));
-            } catch (IOException e) {
-                // TODO: Should we return early here ?
-                Slog.w(TAG, "Failed to get canonical path", e);
-                continue;
-            }
-
-            final String useMarker = path.replace('/', '@');
-            for (int realUserId : resolveUserIds(userId)) {
-                File profileDir = Environment.getDataProfilesDeForeignDexDirectory(realUserId);
-                if (removeBaseMarker) {
-                    File foreignUseMark = new File(profileDir, useMarker);
-                    if (foreignUseMark.exists()) {
-                        if (!foreignUseMark.delete()) {
-                            Slog.w(TAG, "Unable to delete foreign user mark for package: "
-                                    + pkg.packageName);
-                        }
-                    }
-                }
-
-                File[] markers = profileDir.listFiles();
-                if (markers != null) {
-                    final String searchString = "@" + pkg.packageName + "@";
-                    // We also delete all markers that contain the package name we're
-                    // uninstalling. These are associated with secondary dex-files belonging
-                    // to the package. Reconstructing the path of these dex files is messy
-                    // in general.
-                    for (File marker : markers) {
-                        if (marker.getName().indexOf(searchString) > 0) {
-                            if (!marker.delete()) {
-                                Slog.w(TAG, "Unable to delete foreign user mark for package: "
-                                    + pkg.packageName);
-                            }
-                        }
-                    }
-                }
-            }
         }
     }
 
@@ -8663,10 +8741,6 @@
             return;
         }
         clearAppProfilesLeafLIF(pkg);
-        // We don't remove the base foreign use marker when clearing profiles because
-        // we will rename it when the app is updated. Unlike the actual profile contents,
-        // the foreign use marker is good across installs.
-        destroyAppReferenceProfileLeafLIF(pkg, userId, false /* removeBaseMarker */);
         final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
         for (int i = 0; i < childCount; i++) {
             clearAppProfilesLeafLIF(pkg.childPackages.get(i));
@@ -9489,7 +9563,7 @@
 
     /**
      * Asserts the parsed package is valid according to the given policy. If the
-     * package is invalid, for whatever reason, throws {@link PackgeManagerException}.
+     * package is invalid, for whatever reason, throws {@link PackageManagerException}.
      * <p>
      * Implementation detail: This method must NOT have any side effects. It would
      * ideally be static, but, it requires locks to read system state.
@@ -9924,19 +9998,9 @@
         // writer
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "updateSettings");
 
-        boolean createIdmapFailed = false;
         synchronized (mPackages) {
             // We don't expect installation to fail beyond this point
 
-            if (pkgSetting.pkg != null) {
-                // Note that |user| might be null during the initial boot scan. If a codePath
-                // for an app has changed during a boot scan, it's due to an app update that's
-                // part of the system partition and marker changes must be applied to all users.
-                final int userId = ((user != null) ? user : UserHandle.ALL).getIdentifier();
-                final int[] userIds = resolveUserIds(userId);
-                maybeRenameForeignDexMarkers(pkgSetting.pkg, pkg, userIds);
-            }
-
             // Add the new setting to mSettings
             mSettings.insertPackageSettingLPw(pkgSetting, pkg);
             // Add the new setting to mPackages
@@ -10265,104 +10329,9 @@
                     mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
                 }
             }
-
-            // Create idmap files for pairs of (packages, overlay packages).
-            // Note: "android", ie framework-res.apk, is handled by native layers.
-            if (pkg.mOverlayTarget != null) {
-                // This is an overlay package.
-                if (pkg.mOverlayTarget != null && !pkg.mOverlayTarget.equals("android")) {
-                    if (!mOverlays.containsKey(pkg.mOverlayTarget)) {
-                        mOverlays.put(pkg.mOverlayTarget,
-                                new ArrayMap<String, PackageParser.Package>());
-                    }
-                    ArrayMap<String, PackageParser.Package> map = mOverlays.get(pkg.mOverlayTarget);
-                    map.put(pkg.packageName, pkg);
-                    PackageParser.Package orig = mPackages.get(pkg.mOverlayTarget);
-                    if (orig != null && !createIdmapForPackagePairLI(orig, pkg)) {
-                        createIdmapFailed = true;
-                    }
-                }
-            } else if (mOverlays.containsKey(pkg.packageName) &&
-                    !pkg.packageName.equals("android")) {
-                // This is a regular package, with one or more known overlay packages.
-                createIdmapsForPackageLI(pkg);
-            }
         }
 
         Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
-
-        if (createIdmapFailed) {
-            throw new PackageManagerException(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
-                    "scanPackageLI failed to createIdmap");
-        }
-    }
-
-    private static void maybeRenameForeignDexMarkers(PackageParser.Package existing,
-            PackageParser.Package update, int[] userIds) {
-        if (existing.applicationInfo == null || update.applicationInfo == null) {
-            // This isn't due to an app installation.
-            return;
-        }
-
-        final File oldCodePath = new File(existing.applicationInfo.getCodePath());
-        final File newCodePath = new File(update.applicationInfo.getCodePath());
-
-        // The codePath hasn't changed, so there's nothing for us to do.
-        if (Objects.equals(oldCodePath, newCodePath)) {
-            return;
-        }
-
-        File canonicalNewCodePath;
-        try {
-            canonicalNewCodePath = new File(PackageManagerServiceUtils.realpath(newCodePath));
-        } catch (IOException e) {
-            Slog.w(TAG, "Failed to get canonical path.", e);
-            return;
-        }
-
-        // This is a bit of a hack. The oldCodePath doesn't exist at this point (because
-        // we've already renamed / deleted it) so we cannot call realpath on it. Here we assume
-        // that the last component of the path (i.e, the name) doesn't need canonicalization
-        // (i.e, that it isn't ".", ".." or a symbolic link). This is a valid assumption for now
-        // but may change in the future. Hopefully this function won't exist at that point.
-        final File canonicalOldCodePath = new File(canonicalNewCodePath.getParentFile(),
-                oldCodePath.getName());
-
-        // Calculate the prefixes of the markers. These are just the paths with "/" replaced
-        // with "@".
-        String oldMarkerPrefix = canonicalOldCodePath.getAbsolutePath().replace('/', '@');
-        if (!oldMarkerPrefix.endsWith("@")) {
-            oldMarkerPrefix += "@";
-        }
-        String newMarkerPrefix = canonicalNewCodePath.getAbsolutePath().replace('/', '@');
-        if (!newMarkerPrefix.endsWith("@")) {
-            newMarkerPrefix += "@";
-        }
-
-        List<String> updatedPaths = update.getAllCodePathsExcludingResourceOnly();
-        List<String> markerSuffixes = new ArrayList<String>(updatedPaths.size());
-        for (String updatedPath : updatedPaths) {
-            String updatedPathName = new File(updatedPath).getName();
-            markerSuffixes.add(updatedPathName.replace('/', '@'));
-        }
-
-        for (int userId : userIds) {
-            File profileDir = Environment.getDataProfilesDeForeignDexDirectory(userId);
-
-            for (String markerSuffix : markerSuffixes) {
-                File oldForeignUseMark = new File(profileDir, oldMarkerPrefix + markerSuffix);
-                File newForeignUseMark = new File(profileDir, newMarkerPrefix + markerSuffix);
-                if (oldForeignUseMark.exists()) {
-                    try {
-                        Os.rename(oldForeignUseMark.getAbsolutePath(),
-                                newForeignUseMark.getAbsolutePath());
-                    } catch (ErrnoException e) {
-                        Slog.w(TAG, "Failed to rename foreign use marker", e);
-                        oldForeignUseMark.delete();
-                    }
-                }
-            }
-        }
     }
 
     /**
@@ -10633,12 +10602,12 @@
         }
     }
 
-    private void setUpEphemeralInstallerActivityLP(ComponentName installerComponent) {
+    private void setUpInstantAppInstallerActivityLP(ComponentName installerComponent) {
         if (installerComponent == null) {
             if (DEBUG_EPHEMERAL) {
                 Slog.d(TAG, "Clear ephemeral installer activity");
             }
-            mEphemeralInstallerActivity.applicationInfo = null;
+            mInstantAppInstallerActivity.applicationInfo = null;
             return;
         }
 
@@ -10647,21 +10616,21 @@
         }
         final PackageParser.Package pkg = mPackages.get(installerComponent.getPackageName());
         // Set up information for ephemeral installer activity
-        mEphemeralInstallerActivity.applicationInfo = pkg.applicationInfo;
-        mEphemeralInstallerActivity.name = installerComponent.getClassName();
-        mEphemeralInstallerActivity.packageName = pkg.applicationInfo.packageName;
-        mEphemeralInstallerActivity.processName = pkg.applicationInfo.packageName;
-        mEphemeralInstallerActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
-        mEphemeralInstallerActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS
+        mInstantAppInstallerActivity.applicationInfo = pkg.applicationInfo;
+        mInstantAppInstallerActivity.name = installerComponent.getClassName();
+        mInstantAppInstallerActivity.packageName = pkg.applicationInfo.packageName;
+        mInstantAppInstallerActivity.processName = pkg.applicationInfo.packageName;
+        mInstantAppInstallerActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
+        mInstantAppInstallerActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS
                 | ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
-        mEphemeralInstallerActivity.theme = 0;
-        mEphemeralInstallerActivity.exported = true;
-        mEphemeralInstallerActivity.enabled = true;
-        mEphemeralInstallerInfo.activityInfo = mEphemeralInstallerActivity;
-        mEphemeralInstallerInfo.priority = 0;
-        mEphemeralInstallerInfo.preferredOrder = 1;
-        mEphemeralInstallerInfo.isDefault = true;
-        mEphemeralInstallerInfo.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART
+        mInstantAppInstallerActivity.theme = 0;
+        mInstantAppInstallerActivity.exported = true;
+        mInstantAppInstallerActivity.enabled = true;
+        mInstantAppInstallerInfo.activityInfo = mInstantAppInstallerActivity;
+        mInstantAppInstallerInfo.priority = 0;
+        mInstantAppInstallerInfo.preferredOrder = 1;
+        mInstantAppInstallerInfo.isDefault = true;
+        mInstantAppInstallerInfo.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART
                 | IntentFilter.MATCH_ADJUSTMENT_NORMAL;
     }
 
@@ -11619,7 +11588,8 @@
             if (!whitelisted) {
                 Slog.w(TAG, "Privileged permission " + perm + " for package "
                         + pkg.packageName + " - not in privapp-permissions whitelist");
-                if (!mSystemReady) {
+                // Only report violations for apps on system image
+                if (!mSystemReady && !pkg.isUpdatedSystemApp()) {
                     if (mPrivappPermissionsViolations == null) {
                         mPrivappPermissionsViolations = new ArraySet<>();
                     }
@@ -12241,6 +12211,7 @@
             }
             res.iconResourceId = info.icon;
             res.system = res.activityInfo.applicationInfo.isSystemApp();
+            res.instantAppAvailable = userState.instantApp;
             return res;
         }
 
@@ -12703,7 +12674,7 @@
     }
 
     static final class EphemeralIntentResolver
-            extends IntentResolver<EphemeralResponse, EphemeralResponse> {
+            extends IntentResolver<AuxiliaryResolveInfo, AuxiliaryResolveInfo> {
         /**
          * The result that has the highest defined order. Ordering applies on a
          * per-package basis. Mapping is from package name to Pair of order and
@@ -12713,35 +12684,35 @@
          * By having a field variable, we're able to track filter ordering as soon as
          * a non-zero order is defined. Otherwise, multiple loops across the result set
          * would be needed to apply ordering. If the intent resolver becomes re-entrant,
-         * this needs to be contained entirely within {@link #filterResults()}.
+         * this needs to be contained entirely within {@link #filterResults}.
          */
-        final ArrayMap<String, Pair<Integer, EphemeralResolveInfo>> mOrderResult = new ArrayMap<>();
+        final ArrayMap<String, Pair<Integer, InstantAppResolveInfo>> mOrderResult = new ArrayMap<>();
 
         @Override
-        protected EphemeralResponse[] newArray(int size) {
-            return new EphemeralResponse[size];
+        protected AuxiliaryResolveInfo[] newArray(int size) {
+            return new AuxiliaryResolveInfo[size];
         }
 
         @Override
-        protected boolean isPackageForFilter(String packageName, EphemeralResponse responseObj) {
+        protected boolean isPackageForFilter(String packageName, AuxiliaryResolveInfo responseObj) {
             return true;
         }
 
         @Override
-        protected EphemeralResponse newResult(EphemeralResponse responseObj, int match,
+        protected AuxiliaryResolveInfo newResult(AuxiliaryResolveInfo responseObj, int match,
                 int userId) {
             if (!sUserManager.exists(userId)) {
                 return null;
             }
             final String packageName = responseObj.resolveInfo.getPackageName();
             final Integer order = responseObj.getOrder();
-            final Pair<Integer, EphemeralResolveInfo> lastOrderResult =
+            final Pair<Integer, InstantAppResolveInfo> lastOrderResult =
                     mOrderResult.get(packageName);
             // ordering is enabled and this item's order isn't high enough
             if (lastOrderResult != null && lastOrderResult.first >= order) {
                 return null;
             }
-            final EphemeralResolveInfo res = responseObj.resolveInfo;
+            final InstantAppResolveInfo res = responseObj.resolveInfo;
             if (order > 0) {
                 // non-zero order, enable ordering
                 mOrderResult.put(packageName, new Pair<>(order, res));
@@ -12750,16 +12721,16 @@
         }
 
         @Override
-        protected void filterResults(List<EphemeralResponse> results) {
+        protected void filterResults(List<AuxiliaryResolveInfo> results) {
             // only do work if ordering is enabled [most of the time it won't be]
             if (mOrderResult.size() == 0) {
                 return;
             }
             int resultSize = results.size();
             for (int i = 0; i < resultSize; i++) {
-                final EphemeralResolveInfo info = results.get(i).resolveInfo;
+                final InstantAppResolveInfo info = results.get(i).resolveInfo;
                 final String packageName = info.getPackageName();
-                final Pair<Integer, EphemeralResolveInfo> savedInfo = mOrderResult.get(packageName);
+                final Pair<Integer, InstantAppResolveInfo> savedInfo = mOrderResult.get(packageName);
                 if (savedInfo == null) {
                     // package doesn't having ordering
                     continue;
@@ -12989,6 +12960,12 @@
                     + "to use the PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS flag");
         }
 
+        if ((installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0
+                || (installFlags & PackageManager.INSTALL_EXTERNAL) != 0) {
+            throw new IllegalArgumentException(
+                    "New installs into ASEC containers no longer supported");
+        }
+
         final File originFile = new File(originPath);
         final OriginInfo origin = OriginInfo.fromUntrustedFile(originFile);
 
@@ -13731,13 +13708,6 @@
         if (!DEFAULT_VERIFY_ENABLE) {
             return false;
         }
-        // Ephemeral apps don't get the full verification treatment
-        if ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0) {
-            if (DEBUG_EPHEMERAL) {
-                Slog.d(TAG, "INSTALL_EPHEMERAL so skipping verification");
-            }
-            return false;
-        }
 
         boolean ensureVerifyAppsEnabled = isUserRestricted(userId, UserManager.ENSURE_VERIFY_APPS);
 
@@ -14165,88 +14135,6 @@
         abstract void handleReturnCode();
     }
 
-    class MeasureParams extends HandlerParams {
-        private final PackageStats mStats;
-        private boolean mSuccess;
-
-        private final IPackageStatsObserver mObserver;
-
-        public MeasureParams(PackageStats stats, IPackageStatsObserver observer) {
-            super(new UserHandle(stats.userHandle));
-            mObserver = observer;
-            mStats = stats;
-        }
-
-        @Override
-        public String toString() {
-            return "MeasureParams{"
-                + Integer.toHexString(System.identityHashCode(this))
-                + " " + mStats.packageName + "}";
-        }
-
-        @Override
-        void handleStartCopy() throws RemoteException {
-            synchronized (mInstallLock) {
-                mSuccess = getPackageSizeInfoLI(mStats.packageName, mStats.userHandle, mStats);
-            }
-
-            if (mSuccess) {
-                boolean mounted = false;
-                try {
-                    final String status = Environment.getExternalStorageState();
-                    mounted = (Environment.MEDIA_MOUNTED.equals(status)
-                            || Environment.MEDIA_MOUNTED_READ_ONLY.equals(status));
-                } catch (Exception e) {
-                }
-
-                if (mounted) {
-                    final UserEnvironment userEnv = new UserEnvironment(mStats.userHandle);
-
-                    mStats.externalCacheSize = calculateDirectorySize(mContainerService,
-                            userEnv.buildExternalStorageAppCacheDirs(mStats.packageName));
-
-                    mStats.externalDataSize = calculateDirectorySize(mContainerService,
-                            userEnv.buildExternalStorageAppDataDirs(mStats.packageName));
-
-                    // Always subtract cache size, since it's a subdirectory
-                    mStats.externalDataSize -= mStats.externalCacheSize;
-
-                    mStats.externalMediaSize = calculateDirectorySize(mContainerService,
-                            userEnv.buildExternalStorageAppMediaDirs(mStats.packageName));
-
-                    mStats.externalObbSize = calculateDirectorySize(mContainerService,
-                            userEnv.buildExternalStorageAppObbDirs(mStats.packageName));
-                }
-            }
-        }
-
-        @Override
-        void handleReturnCode() {
-            if (mObserver != null) {
-                try {
-                    mObserver.onGetStatsCompleted(mStats, mSuccess);
-                } catch (RemoteException e) {
-                    Slog.i(TAG, "Observer no longer exists.");
-                }
-            }
-        }
-
-        @Override
-        void handleServiceError() {
-            Slog.e(TAG, "Could not measure application " + mStats.packageName
-                            + " external storage");
-        }
-    }
-
-    private static long calculateDirectorySize(IMediaContainerService mcs, File[] paths)
-            throws RemoteException {
-        long result = 0;
-        for (File path : paths) {
-            result += mcs.calculateDirectorySize(path.getAbsolutePath());
-        }
-        return result;
-    }
-
     private static void clearDirectory(IMediaContainerService mcs, File[] paths) {
         for (File path : paths) {
             try {
@@ -14740,7 +14628,7 @@
                          */
                         verification.setComponent(requiredVerifierComponent);
                         idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
-                                requiredVerifierComponent.getPackageName(), idleDuration,
+                                mRequiredVerifierPackage, idleDuration,
                                 verifierUser.getIdentifier(), false, "package verifier");
                         mContext.sendOrderedBroadcastAsUser(verification, verifierUser,
                                 android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
@@ -15884,14 +15772,6 @@
 
             final PackageSetting ps = mSettings.mPackages.get(pkgName);
 
-            // don't allow an upgrade from full to ephemeral
-            if (isInstantApp && !ps.getInstantApp(user.getIdentifier())) {
-                // can't downgrade from full to instant
-                Slog.w(TAG, "Can't replace app with instant app: " + pkgName);
-                res.setReturnCode(PackageManager.INSTALL_FAILED_INSTANT_APP_INVALID);
-                return;
-            }
-
             // verify signatures are valid
             if (shouldCheckUpgradeKeySetLP(ps, scanFlags)) {
                 if (!checkUpgradeKeySetLP(ps, pkg)) {
@@ -15949,6 +15829,27 @@
             // In case of rollback, remember per-user/profile install state
             allUsers = sUserManager.getUserIds();
             installedUsers = ps.queryInstalledUsers(allUsers, true);
+
+            // don't allow an upgrade from full to ephemeral
+            if (isInstantApp) {
+                if (user == null || user.getIdentifier() == UserHandle.USER_ALL) {
+                    for (int currentUser : allUsers) {
+                        if (!ps.getInstantApp(currentUser)) {
+                            // can't downgrade from full to instant
+                            Slog.w(TAG, "Can't replace full app with instant app: " + pkgName
+                                    + " for user: " + currentUser);
+                            res.setReturnCode(PackageManager.INSTALL_FAILED_INSTANT_APP_INVALID);
+                            return;
+                        }
+                    }
+                } else if (!ps.getInstantApp(user.getIdentifier())) {
+                    // can't downgrade from full to instant
+                    Slog.w(TAG, "Can't replace full app with instant app: " + pkgName
+                            + " for user: " + user.getIdentifier());
+                    res.setReturnCode(PackageManager.INSTALL_FAILED_INSTANT_APP_INVALID);
+                    return;
+                }
+            }
         }
 
         // Update what is removed
@@ -16100,6 +16001,8 @@
                 setInstantAppForUser(ps, user.getIdentifier(), instantApp, fullApp);
                 prepareAppDataAfterInstallLIF(newPackage);
                 addedPkg = true;
+                mDexManager.notifyPackageUpdated(newPackage.packageName,
+                        newPackage.baseCodePath, newPackage.splitCodePaths);
             } catch (PackageManagerException e) {
                 res.setError("Package couldn't be installed in " + pkg.codePath, e);
             }
@@ -16249,6 +16152,9 @@
                 updateSettingsLI(newPackage, installerPackageName, allUsers, res, user,
                         installReason);
                 prepareAppDataAfterInstallLIF(newPackage);
+
+                mDexManager.notifyPackageUpdated(newPackage.packageName,
+                            newPackage.baseCodePath, newPackage.splitCodePaths);
             }
         } catch (PackageManagerException e) {
             res.setReturnCode(INSTALL_FAILED_INTERNAL_ERROR);
@@ -16611,6 +16517,7 @@
         PackageParser pp = new PackageParser();
         pp.setSeparateProcesses(mSeparateProcesses);
         pp.setDisplayMetrics(mMetrics);
+        pp.setCallback(mPackageParserCallback);
 
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
         final PackageParser.Package pkg;
@@ -16623,13 +16530,19 @@
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
         }
 
-//        // Ephemeral apps must have target SDK >= O.
-//        // TODO: Update conditional and error message when O gets locked down
-//        if (instantApp && pkg.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.N_MR1) {
-//            res.setError(PackageManager.INSTALL_FAILED_EPHEMERAL_INVALID,
-//                    "Ephemeral apps must have target SDK version of at least O");
-//            return;
-//        }
+        // Instant apps must have target SDK >= O and have targetSanboxVersion >= 2
+        if (instantApp && pkg.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.N_MR1) {
+            Slog.w(TAG, "Instant app package " + pkg.packageName
+                    + " does not target O, this will be a fatal error.");
+            // STOPSHIP: Make this a fatal error
+            pkg.applicationInfo.targetSdkVersion = Build.VERSION_CODES.O;
+        }
+        if (instantApp && pkg.applicationInfo.targetSandboxVersion != 2) {
+            Slog.w(TAG, "Instant app package " + pkg.packageName
+                    + " does not target targetSandboxVersion 2, this will be a fatal error.");
+            // STOPSHIP: Make this a fatal error
+            pkg.applicationInfo.targetSandboxVersion = 2;
+        }
 
         if (pkg.applicationInfo.isStaticSharedLibrary()) {
             // Static shared libraries have synthetic package names
@@ -16807,11 +16720,20 @@
                 res.origUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
             }
 
-            // Check whether the newly-scanned package wants to define an already-defined perm
             int N = pkg.permissions.size();
             for (int i = N-1; i >= 0; i--) {
                 PackageParser.Permission perm = pkg.permissions.get(i);
                 BasePermission bp = mSettings.mPermissions.get(perm.info.name);
+
+                // Don't allow anyone but the platform to define ephemeral permissions.
+                if ((perm.info.protectionLevel & PermissionInfo.PROTECTION_FLAG_EPHEMERAL) != 0
+                        && !PLATFORM_PACKAGE_NAME.equals(pkg.packageName)) {
+                    Slog.w(TAG, "Package " + pkg.packageName
+                            + " attempting to delcare ephemeral permission "
+                            + perm.info.name + "; Removing ephemeral.");
+                    perm.info.protectionLevel &= ~PermissionInfo.PROTECTION_FLAG_EPHEMERAL;
+                }
+                // Check whether the newly-scanned package wants to define an already-defined perm
                 if (bp != null) {
                     // If the defining package is signed with our cert, it's okay.  This
                     // also includes the "updating the same package" case, of course.
@@ -16917,7 +16839,8 @@
             mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles,
                     null /* instructionSets */, false /* checkProfiles */,
                     getCompilerFilterForReason(REASON_INSTALL),
-                    getOrCreateCompilerPackageStats(pkg));
+                    getOrCreateCompilerPackageStats(pkg),
+                    mDexManager.isUsedByOtherApps(pkg.packageName));
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
 
             // Notify BackgroundDexOptJobService that the package has been changed.
@@ -17486,6 +17409,7 @@
         }
 
         PackageSetting uninstalledPs = null;
+        PackageParser.Package pkg = null;
 
         // for the uninstall-updates case and restricted profiles, remember the per-
         // user handle installed state
@@ -17506,7 +17430,7 @@
 
             // Static shared libs can be declared by any package, so let us not
             // allow removing a package if it provides a lib others depend on.
-            PackageParser.Package pkg = mPackages.get(packageName);
+            pkg = mPackages.get(packageName);
             if (pkg != null && pkg.staticSharedLibName != null) {
                 SharedLibraryEntry libEntry = getSharedLibraryEntryLPr(pkg.staticSharedLibName,
                         pkg.staticSharedLibVersion);
@@ -17545,8 +17469,9 @@
             }
             synchronized (mPackages) {
                 if (res) {
-                    mInstantAppRegistry.onPackageUninstalledLPw(uninstalledPs.pkg,
-                            info.removedUsers);
+                    if (pkg != null) {
+                        mInstantAppRegistry.onPackageUninstalledLPw(pkg, info.removedUsers);
+                    }
                     updateSequenceNumberLP(packageName, info.removedUsers);
                 }
             }
@@ -18393,8 +18318,6 @@
         try (PackageFreezer freezer = freezePackage(packageName, "clearApplicationProfileData")) {
             synchronized (mInstallLock) {
                 clearAppProfilesLIF(pkg, UserHandle.USER_ALL);
-                destroyAppReferenceProfileLeafLIF(pkg, UserHandle.USER_ALL,
-                        true /* removeBaseMarker */);
             }
         }
     }
@@ -18702,21 +18625,8 @@
     @Override
     public void getPackageSizeInfo(final String packageName, int userHandle,
             final IPackageStatsObserver observer) {
-        mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.GET_PACKAGE_SIZE, null);
-        if (packageName == null) {
-            throw new IllegalArgumentException("Attempt to get size of null packageName");
-        }
-
-        PackageStats stats = new PackageStats(packageName, userHandle);
-
-        /*
-         * Queue up an async operation since the package measurement may take a
-         * little while.
-         */
-        Message msg = mHandler.obtainMessage(INIT_COPY);
-        msg.obj = new MeasureParams(stats, observer);
-        mHandler.sendMessage(msg);
+        throw new UnsupportedOperationException(
+                "Shame on you for calling a hidden API. Shame!");
     }
 
     private boolean getPackageSizeInfoLI(String packageName, int userId, PackageStats stats) {
@@ -19629,6 +19539,35 @@
         return getHomeActivitiesAsUser(allHomeCandidates, UserHandle.getCallingUserId());
     }
 
+    /**
+     * Report the 'Home' activity which is currently set as "always use this one". If non is set
+     * then reports the most likely home activity or null if there are more than one.
+     */
+    public ComponentName getDefaultHomeActivity(int userId) {
+        List<ResolveInfo> allHomeCandidates = new ArrayList<>();
+        ComponentName cn = getHomeActivitiesAsUser(allHomeCandidates, userId);
+        if (cn != null) {
+            return cn;
+        }
+
+        // Find the launcher with the highest priority and return that component if there are no
+        // other home activity with the same priority.
+        int lastPriority = Integer.MIN_VALUE;
+        ComponentName lastComponent = null;
+        final int size = allHomeCandidates.size();
+        for (int i = 0; i < size; i++) {
+            final ResolveInfo ri = allHomeCandidates.get(i);
+            if (ri.priority > lastPriority) {
+                lastComponent = ri.activityInfo.getComponentName();
+                lastPriority = ri.priority;
+            } else if (ri.priority == lastPriority) {
+                // Two components found with same priority.
+                lastComponent = null;
+            }
+        }
+        return lastComponent;
+    }
+
     private Intent getHomeIntent() {
         Intent intent = new Intent(Intent.ACTION_MAIN);
         intent.addCategory(Intent.CATEGORY_HOME);
@@ -20131,6 +20070,14 @@
         }
     }
 
+    public void waitForAppDataPrepared() {
+        if (mPrepareAppDataFuture == null) {
+            return;
+        }
+        ConcurrentUtils.waitForFutureNoInterrupt(mPrepareAppDataFuture, "wait for prepareAppData");
+        mPrepareAppDataFuture = null;
+    }
+
     @Override
     public boolean isSafeMode() {
         return mSafeMode;
@@ -20177,6 +20124,7 @@
         public static final int DUMP_FROZEN = 1 << 19;
         public static final int DUMP_DEXOPT = 1 << 20;
         public static final int DUMP_COMPILER_STATS = 1 << 21;
+        public static final int DUMP_ENABLED_OVERLAYS = 1 << 22;
 
         public static final int OPTION_SHOW_FILTERS = 1 << 0;
 
@@ -20296,12 +20244,16 @@
                 pw.println("    check-permission <permission> <package> [<user>]: does pkg hold perm?");
                 pw.println("    dexopt: dump dexopt state");
                 pw.println("    compiler-stats: dump compiler statistics");
+                pw.println("    enabled-overlays: dump list of enabled overlay packages");
                 pw.println("    <package.name>: info about given package");
                 return;
             } else if ("--checkin".equals(opt)) {
                 checkin = true;
             } else if ("-f".equals(opt)) {
                 dumpState.setOptionEnabled(DumpState.OPTION_SHOW_FILTERS);
+            } else if ("--proto".equals(opt)) {
+                dumpProto(fd);
+                return;
             } else {
                 pw.println("Unknown argument: " + opt + "; use -h for help");
             }
@@ -20424,6 +20376,8 @@
                 dumpState.setDump(DumpState.DUMP_DEXOPT);
             } else if ("compiler-stats".equals(cmd)) {
                 dumpState.setDump(DumpState.DUMP_COMPILER_STATS);
+            } else if ("enabled-overlays".equals(cmd)) {
+                dumpState.setDump(DumpState.DUMP_ENABLED_OVERLAYS);
             } else if ("write".equals(cmd)) {
                 synchronized (mPackages) {
                     mSettings.writeLPr();
@@ -20794,6 +20748,11 @@
                 dumpCompilerStatsLPr(pw, packageName);
             }
 
+            if (!checkin && dumpState.isDumping(DumpState.DUMP_ENABLED_OVERLAYS)) {
+                if (dumpState.onTitlePrinted()) pw.println();
+                dumpEnabledOverlaysLPr(pw);
+            }
+
             if (!checkin && dumpState.isDumping(DumpState.DUMP_MESSAGES) && packageName == null) {
                 if (dumpState.onTitlePrinted()) pw.println();
                 mSettings.dumpReadMessagesLPr(pw, dumpState);
@@ -20832,6 +20791,98 @@
         }
     }
 
+    private void dumpProto(FileDescriptor fd) {
+        final ProtoOutputStream proto = new ProtoOutputStream(fd);
+
+        synchronized (mPackages) {
+            final long requiredVerifierPackageToken =
+                    proto.start(PackageServiceDumpProto.REQUIRED_VERIFIER_PACKAGE);
+            proto.write(PackageServiceDumpProto.PackageShortProto.NAME, mRequiredVerifierPackage);
+            proto.write(
+                    PackageServiceDumpProto.PackageShortProto.UID,
+                    getPackageUid(
+                            mRequiredVerifierPackage,
+                            MATCH_DEBUG_TRIAGED_MISSING,
+                            UserHandle.USER_SYSTEM));
+            proto.end(requiredVerifierPackageToken);
+
+            if (mIntentFilterVerifierComponent != null) {
+                String verifierPackageName = mIntentFilterVerifierComponent.getPackageName();
+                final long verifierPackageToken =
+                        proto.start(PackageServiceDumpProto.VERIFIER_PACKAGE);
+                proto.write(PackageServiceDumpProto.PackageShortProto.NAME, verifierPackageName);
+                proto.write(
+                        PackageServiceDumpProto.PackageShortProto.UID,
+                        getPackageUid(
+                                verifierPackageName,
+                                MATCH_DEBUG_TRIAGED_MISSING,
+                                UserHandle.USER_SYSTEM));
+                proto.end(verifierPackageToken);
+            }
+
+            dumpSharedLibrariesProto(proto);
+            dumpFeaturesProto(proto);
+            mSettings.dumpPackagesProto(proto);
+            mSettings.dumpSharedUsersProto(proto);
+            dumpMessagesProto(proto);
+        }
+        proto.flush();
+    }
+
+    private void dumpMessagesProto(ProtoOutputStream proto) {
+        BufferedReader in = null;
+        String line = null;
+        try {
+            in = new BufferedReader(new FileReader(getSettingsProblemFile()));
+            while ((line = in.readLine()) != null) {
+                if (line.contains("ignored: updated version")) continue;
+                proto.write(PackageServiceDumpProto.MESSAGES, line);
+            }
+        } catch (IOException ignored) {
+        } finally {
+            IoUtils.closeQuietly(in);
+        }
+    }
+
+    private void dumpFeaturesProto(ProtoOutputStream proto) {
+        synchronized (mAvailableFeatures) {
+            final int count = mAvailableFeatures.size();
+            for (int i = 0; i < count; i++) {
+                final FeatureInfo feat = mAvailableFeatures.valueAt(i);
+                final long featureToken = proto.start(PackageServiceDumpProto.FEATURES);
+                proto.write(PackageServiceDumpProto.FeatureProto.NAME, feat.name);
+                proto.write(PackageServiceDumpProto.FeatureProto.VERSION, feat.version);
+                proto.end(featureToken);
+            }
+        }
+    }
+
+    private void dumpSharedLibrariesProto(ProtoOutputStream proto) {
+        final int count = mSharedLibraries.size();
+        for (int i = 0; i < count; i++) {
+            final String libName = mSharedLibraries.keyAt(i);
+            SparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.get(libName);
+            if (versionedLib == null) {
+                continue;
+            }
+            final int versionCount = versionedLib.size();
+            for (int j = 0; j < versionCount; j++) {
+                final SharedLibraryEntry libEntry = versionedLib.valueAt(j);
+                final long sharedLibraryToken =
+                        proto.start(PackageServiceDumpProto.SHARED_LIBRARIES);
+                proto.write(PackageServiceDumpProto.SharedLibraryProto.NAME, libEntry.info.getName());
+                final boolean isJar = (libEntry.path != null);
+                proto.write(PackageServiceDumpProto.SharedLibraryProto.IS_JAR, isJar);
+                if (isJar) {
+                    proto.write(PackageServiceDumpProto.SharedLibraryProto.PATH, libEntry.path);
+                } else {
+                    proto.write(PackageServiceDumpProto.SharedLibraryProto.APK, libEntry.apk);
+                }
+                proto.end(sharedLibraryToken);
+            }
+        }
+    }
+
     private void dumpDexoptStateLPr(PrintWriter pw, String packageName) {
         final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ", 120);
         ipw.println();
@@ -20890,6 +20941,23 @@
         }
     }
 
+    private void dumpEnabledOverlaysLPr(PrintWriter pw) {
+        pw.println("Enabled overlay paths:");
+        final int N = mEnabledOverlayPaths.size();
+        for (int i = 0; i < N; i++) {
+            final int userId = mEnabledOverlayPaths.keyAt(i);
+            pw.println(String.format("    User %d:", userId));
+            final ArrayMap<String, ArrayList<String>> userSpecificOverlays =
+                mEnabledOverlayPaths.valueAt(i);
+            final int M = userSpecificOverlays.size();
+            for (int j = 0; j < M; j++) {
+                final String targetPackageName = userSpecificOverlays.keyAt(j);
+                final ArrayList<String> overlayPackagePaths = userSpecificOverlays.valueAt(j);
+                pw.println(String.format("        %s: %s", targetPackageName, overlayPackagePaths));
+            }
+        }
+    }
+
     private String dumpDomainString(String packageName) {
         List<IntentFilterVerificationInfo> iviList = getIntentFilterVerifications(packageName)
                 .getList();
@@ -21581,6 +21649,11 @@
         }
     }
 
+    private void reconcileAppsDataLI(String volumeUuid, int userId, int flags,
+            boolean migrateAppData) {
+        reconcileAppsDataLI(volumeUuid, userId, flags, migrateAppData, false /* onlyCoreApps */);
+    }
+
     /**
      * Reconcile all app data on given mounted volume.
      * <p>
@@ -21589,11 +21662,13 @@
      * <p>
      * Verifies that directories exist and that ownership and labeling is
      * correct for all installed apps.
+     * @returns list of skipped non-core packages (if {@code onlyCoreApps} is true)
      */
-    private void reconcileAppsDataLI(String volumeUuid, int userId, int flags,
-            boolean migrateAppData) {
+    private List<String> reconcileAppsDataLI(String volumeUuid, int userId, int flags,
+            boolean migrateAppData, boolean onlyCoreApps) {
         Slog.v(TAG, "reconcileAppsData for " + volumeUuid + " u" + userId + " 0x"
                 + Integer.toHexString(flags) + " migrateAppData=" + migrateAppData);
+        List<String> result = onlyCoreApps ? new ArrayList<>() : null;
 
         final File ceDir = Environment.getDataUserCeDirectory(volumeUuid, userId);
         final File deDir = Environment.getDataUserDeDirectory(volumeUuid, userId);
@@ -21657,21 +21732,20 @@
                 // and reconcile again once they're scanned
                 continue;
             }
+            // Skip non-core apps if requested
+            if (onlyCoreApps && !ps.pkg.coreApp) {
+                result.add(packageName);
+                continue;
+            }
 
             if (ps.getInstalled(userId)) {
-                prepareAppDataLIF(ps.pkg, userId, flags);
-
-                if (migrateAppData && maybeMigrateAppDataLIF(ps.pkg, userId)) {
-                    // We may have just shuffled around app data directories, so
-                    // prepare them one more time
-                    prepareAppDataLIF(ps.pkg, userId, flags);
-                }
-
+                prepareAppDataAndMigrateLIF(ps.pkg, userId, flags, migrateAppData);
                 preparedCount++;
             }
         }
 
         Slog.v(TAG, "reconcileAppsData finished " + preparedCount + " packages");
+        return result;
     }
 
     /**
@@ -21732,6 +21806,17 @@
         }
     }
 
+    private void prepareAppDataAndMigrateLIF(PackageParser.Package pkg, int userId, int flags,
+            boolean maybeMigrateAppData) {
+        prepareAppDataLIF(pkg, userId, flags);
+
+        if (maybeMigrateAppData && maybeMigrateAppDataLIF(pkg, userId)) {
+            // We may have just shuffled around app data directories, so
+            // prepare them one more time
+            prepareAppDataLIF(pkg, userId, flags);
+        }
+    }
+
     private void prepareAppDataLeafLIF(PackageParser.Package pkg, int userId, int flags) {
         if (DEBUG_APP_DATA) {
             Slog.v(TAG, "prepareAppData for " + pkg.packageName + " u" + userId + " 0x"
@@ -22899,11 +22984,10 @@
         }
 
         @Override
-        public void requestEphemeralResolutionPhaseTwo(EphemeralResponse responseObj,
-                Intent origIntent, String resolvedType, Intent launchIntent,
-                String callingPackage, int userId) {
-            PackageManagerService.this.requestEphemeralResolutionPhaseTwo(
-                    responseObj, origIntent, resolvedType, launchIntent, callingPackage, userId);
+        public void requestInstantAppResolutionPhaseTwo(AuxiliaryResolveInfo responseObj,
+                Intent origIntent, String resolvedType, String callingPackage, int userId) {
+            PackageManagerService.this.requestInstantAppResolutionPhaseTwo(
+                    responseObj, origIntent, resolvedType, callingPackage, userId);
         }
 
         @Override
@@ -22974,12 +23058,50 @@
             return targetPackages;
         }
 
-
         @Override
-        public boolean setEnabledOverlayPackages(int userId, String targetPackageName,
-                List<String> overlayPackageNames) {
-            // TODO: implement when we integrate OMS properly
-            return false;
+        public boolean setEnabledOverlayPackages(int userId, @NonNull String targetPackageName,
+                @Nullable List<String> overlayPackageNames) {
+            synchronized (mPackages) {
+                if (targetPackageName == null || mPackages.get(targetPackageName) == null) {
+                    Slog.e(TAG, "failed to find package " + targetPackageName);
+                    return false;
+                }
+
+                ArrayList<String> paths = null;
+                if (overlayPackageNames != null) {
+                    final int N = overlayPackageNames.size();
+                    paths = new ArrayList<>(N);
+                    for (int i = 0; i < N; i++) {
+                        final String packageName = overlayPackageNames.get(i);
+                        final PackageParser.Package pkg = mPackages.get(packageName);
+                        if (pkg == null) {
+                            Slog.e(TAG, "failed to find package " + packageName);
+                            return false;
+                        }
+                        paths.add(pkg.baseCodePath);
+                    }
+                }
+
+                ArrayMap<String, ArrayList<String>> userSpecificOverlays =
+                    mEnabledOverlayPaths.get(userId);
+                if (userSpecificOverlays == null) {
+                    userSpecificOverlays = new ArrayMap<>();
+                    mEnabledOverlayPaths.put(userId, userSpecificOverlays);
+                }
+
+                if (paths != null && paths.size() > 0) {
+                    userSpecificOverlays.put(targetPackageName, paths);
+                } else {
+                    userSpecificOverlays.remove(targetPackageName);
+                }
+                return true;
+            }
+        }
+
+        public ResolveInfo resolveIntent(Intent intent, String resolvedType,
+                int flags, int userId) {
+            return resolveIntentInternal(
+                    intent, resolvedType, flags, userId, true /*includeInstantApp*/);
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java b/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
index 9c9a671..0634dac 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
@@ -80,9 +80,7 @@
             try {
                 // Check that the system property name is legal.
                 String sysPropName = getSystemPropertyName(reason);
-                if (sysPropName == null ||
-                        sysPropName.isEmpty() ||
-                        sysPropName.length() > SystemProperties.PROP_NAME_MAX) {
+                if (sysPropName == null || sysPropName.isEmpty()) {
                     throw new IllegalStateException("Reason system property name \"" +
                             sysPropName +"\" for reason " + REASON_STRINGS[reason]);
                 }
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index 45887e1..9feee8c 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -133,7 +133,8 @@
                 sortTemp, packageManagerService);
 
         // Give priority to apps used by other apps.
-        applyPackageFilter((pkg) -> PackageDexOptimizer.isUsedByOtherApps(pkg), result,
+        applyPackageFilter((pkg) ->
+                packageManagerService.getDexManager().isUsedByOtherApps(pkg.packageName), result,
                 remainingPkgs, sortTemp, packageManagerService);
 
         // Filter out packages that aren't recently used, add all remaining apps.
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 5f348ab..b4bba88 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -19,6 +19,9 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageParser;
+import android.content.pm.UserInfo;
+import android.service.pm.PackageProto;
+import android.util.proto.ProtoOutputStream;
 
 import java.io.File;
 import java.util.List;
@@ -128,4 +131,32 @@
         }
         return true;
     }
+
+    public void writeToProto(ProtoOutputStream proto, long fieldId, List<UserInfo> users) {
+        final long packageToken = proto.start(fieldId);
+        proto.write(PackageProto.NAME, (realName != null ? realName : name));
+        proto.write(PackageProto.UID, appId);
+        proto.write(PackageProto.VERSION_CODE, versionCode);
+        proto.write(PackageProto.VERSION_STRING, pkg.mVersionName);
+        proto.write(PackageProto.INSTALL_TIME_MS, firstInstallTime);
+        proto.write(PackageProto.UPDATE_TIME_MS, lastUpdateTime);
+        proto.write(PackageProto.INSTALLER_NAME, installerPackageName);
+
+        if (pkg != null) {
+            long splitToken = proto.start(PackageProto.SPLITS);
+            proto.write(PackageProto.SplitProto.NAME, "base");
+            proto.write(PackageProto.SplitProto.REVISION_CODE, pkg.baseRevisionCode);
+            proto.end(splitToken);
+            if (pkg.splitNames != null) {
+                for (int i = 0; i < pkg.splitNames.length; i++) {
+                    splitToken = proto.start(PackageProto.SPLITS);
+                    proto.write(PackageProto.SplitProto.NAME, pkg.splitNames[i]);
+                    proto.write(PackageProto.SplitProto.REVISION_CODE, pkg.splitRevisionCodes[i]);
+                    proto.end(splitToken);
+                }
+            }
+        }
+        writeUsersInfoToProto(proto, PackageProto.USERS);
+        proto.end(packageToken);
+    }
 }
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index 601377d6..b9c43da 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -25,8 +25,10 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageUserState;
 import android.os.storage.VolumeInfo;
+import android.service.pm.PackageProto;
 import android.util.ArraySet;
 import android.util.SparseArray;
+import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.annotations.VisibleForTesting;
 
@@ -564,4 +566,32 @@
         modifyUserState(userId).domainVerificationStatus =
                 PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
     }
+
+    protected void writeUsersInfoToProto(ProtoOutputStream proto, long fieldId) {
+        int count = userState.size();
+        for (int i = 0; i < count; i++) {
+            final long userToken = proto.start(fieldId);
+            final int userId = userState.keyAt(i);
+            final PackageUserState state = userState.valueAt(i);
+            proto.write(PackageProto.UserInfoProto.ID, userId);
+            final int installType;
+            if (state.instantApp) {
+                installType = PackageProto.UserInfoProto.INSTANT_APP_INSTALL;
+            } else if (state.installed) {
+                installType = PackageProto.UserInfoProto.FULL_APP_INSTALL;
+            } else {
+                installType = PackageProto.UserInfoProto.NOT_INSTALLED_FOR_USER;
+            }
+            proto.write(PackageProto.UserInfoProto.INSTALL_TYPE, installType);
+            proto.write(PackageProto.UserInfoProto.IS_HIDDEN, state.hidden);
+            proto.write(PackageProto.UserInfoProto.IS_SUSPENDED, state.suspended);
+            proto.write(PackageProto.UserInfoProto.IS_STOPPED, state.stopped);
+            proto.write(PackageProto.UserInfoProto.IS_LAUNCHED, !state.notLaunched);
+            proto.write(PackageProto.UserInfoProto.ENABLED_STATE, state.enabled);
+            proto.write(
+                    PackageProto.UserInfoProto.LAST_DISABLED_APP_CALLER,
+                    state.lastDisableAppCaller);
+            proto.end(userToken);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/pm/ParallelPackageParser.java b/services/core/java/com/android/server/pm/ParallelPackageParser.java
index 6033855..4ff3e12 100644
--- a/services/core/java/com/android/server/pm/ParallelPackageParser.java
+++ b/services/core/java/com/android/server/pm/ParallelPackageParser.java
@@ -46,6 +46,7 @@
     private final boolean mOnlyCore;
     private final DisplayMetrics mMetrics;
     private final File mCacheDir;
+    private final PackageParser.Callback mPackageParserCallback;
     private volatile String mInterruptedInThread;
 
     private final BlockingQueue<ParseResult> mQueue = new ArrayBlockingQueue<>(QUEUE_CAPACITY);
@@ -54,11 +55,12 @@
             "package-parsing-thread", Process.THREAD_PRIORITY_FOREGROUND);
 
     ParallelPackageParser(String[] separateProcesses, boolean onlyCoreApps,
-            DisplayMetrics metrics, File cacheDir) {
+            DisplayMetrics metrics, File cacheDir, PackageParser.Callback callback) {
         mSeparateProcesses = separateProcesses;
         mOnlyCore = onlyCoreApps;
         mMetrics = metrics;
         mCacheDir = cacheDir;
+        mPackageParserCallback = callback;
     }
 
     static class ParseResult {
@@ -110,6 +112,7 @@
                 pp.setOnlyCoreApps(mOnlyCore);
                 pp.setDisplayMetrics(mMetrics);
                 pp.setCacheDir(mCacheDir);
+                pp.setCallback(mPackageParserCallback);
                 pr.scanFile = scanFile;
                 pr.pkg = parsePackage(pp, scanFile, parseFlags);
             } catch (Throwable e) {
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index a8a5ff0..570b31f 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -65,6 +65,7 @@
 import android.os.UserManager;
 import android.os.storage.StorageManager;
 import android.os.storage.VolumeInfo;
+import android.service.pm.PackageServiceDumpProto;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -77,6 +78,7 @@
 import android.util.SparseIntArray;
 import android.util.SparseLongArray;
 import android.util.Xml;
+import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.os.BackgroundThread;
@@ -887,9 +889,9 @@
         }
         if (p.appId < 0) {
             PackageManagerService.reportSettingsProblem(Log.WARN,
-                    "Package " + p.name + " could not be assigned a valid uid");
+                    "Package " + p.name + " could not be assigned a valid UID");
             throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
-                    "Creating application package " + p.name + " failed");
+                    "Package " + p.name + " could not be assigned a valid UID");
         }
     }
 
@@ -3370,7 +3372,7 @@
     private void applyDefaultPreferredActivityLPw(PackageManagerService service,
             Intent intent, int flags, ComponentName cn, String scheme, PatternMatcher ssp,
             IntentFilter.AuthorityEntry auth, PatternMatcher path, int userId) {
-        flags = service.updateFlagsForResolve(flags, userId, intent);
+        flags = service.updateFlagsForResolve(flags, userId, intent, false);
         List<ResolveInfo> ri = service.mActivities.queryIntent(intent,
                 intent.getType(), flags, 0);
         if (PackageManagerService.DEBUG_PREFERRED) Log.d(TAG, "Queried " + intent
@@ -4876,6 +4878,16 @@
         }
     }
 
+    void dumpPackagesProto(ProtoOutputStream proto) {
+        List<UserInfo> users = getAllUsers(UserManagerService.getInstance());
+
+        final int count = mPackages.size();
+        for (int i = 0; i < count; i++) {
+            final PackageSetting ps = mPackages.valueAt(i);
+            ps.writeToProto(proto, PackageServiceDumpProto.PACKAGES, users);
+        }
+    }
+
     void dumpPermissionsLPr(PrintWriter pw, String packageName, ArraySet<String> permissionNames,
             DumpState dumpState) {
         boolean printedSomething = false;
@@ -4966,6 +4978,17 @@
         }
     }
 
+    void dumpSharedUsersProto(ProtoOutputStream proto) {
+        final int count = mSharedUsers.size();
+        for (int i = 0; i < count; i++) {
+            final SharedUserSetting su = mSharedUsers.valueAt(i);
+            final long sharedUserToken = proto.start(PackageServiceDumpProto.SHARED_USERS);
+            proto.write(PackageServiceDumpProto.SharedUserProto.USER_ID, su.userId);
+            proto.write(PackageServiceDumpProto.SharedUserProto.NAME, su.name);
+            proto.end(sharedUserToken);
+        }
+    }
+
     void dumpReadMessagesLPr(PrintWriter pw, DumpState dumpState) {
         pw.println("Settings parse messages:");
         pw.print(mReadMessages.toString());
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 570259b..7885748 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -20,6 +20,7 @@
 import android.annotation.UserIdInt;
 import android.content.ComponentName;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.PackageInfo;
 import android.content.pm.ShortcutInfo;
 import android.content.res.Resources;
@@ -31,6 +32,7 @@
 import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.XmlUtils;
 import com.android.server.pm.ShortcutService.ShortcutOperation;
@@ -68,6 +70,9 @@
     private static final String TAG_EXTRAS = "extras";
     private static final String TAG_SHORTCUT = "shortcut";
     private static final String TAG_CATEGORIES = "categories";
+    private static final String TAG_CHOOSER_EXTRAS = "chooser-extras";
+    private static final String TAG_CHOOSER_INTENT_FILTERS = "chooser-intent-filters";
+    private static final String TAG_CHOOSER_COMPONENT_NAMES = "chooser-component-names";
 
     private static final String ATTR_NAME = "name";
     private static final String ATTR_CALL_COUNT = "call-count";
@@ -91,6 +96,7 @@
     private static final String ATTR_ICON_RES_ID = "icon-res";
     private static final String ATTR_ICON_RES_NAME = "icon-resname";
     private static final String ATTR_BITMAP_PATH = "bitmap-path";
+    private static final String ATTR_COMPONENT_NAMES = "component-names";
 
     private static final String NAME_CATEGORIES = "categories";
 
@@ -200,7 +206,7 @@
         if (shortcut != null) {
             mShortcutUser.mService.removeIcon(getPackageUserId(), shortcut);
             shortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_PINNED
-                    | ShortcutInfo.FLAG_MANIFEST);
+                    | ShortcutInfo.FLAG_MANIFEST | ShortcutInfo.FLAG_CHOOSER);
         }
         return shortcut;
     }
@@ -226,7 +232,7 @@
         Preconditions.checkArgument(newShortcut.isEnabled(),
                 "add/setDynamicShortcuts() cannot publish disabled shortcuts");
 
-        newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
+        addCorrectDynamicFlags(newShortcut);
 
         final ShortcutInfo oldShortcut = mShortcuts.get(newShortcut.getId());
 
@@ -250,6 +256,17 @@
         addShortcutInner(newShortcut);
     }
 
+    // TODO: Sample code & JavaDoc for ShortcutManager needs updating to reflect the fact that
+    //       Chooser shortcuts are not always dynamic.
+    public void addCorrectDynamicFlags(@NonNull ShortcutInfo shortcut) {
+        if (shortcut.getIntent() != null) {
+            shortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
+        }
+        if (!ArrayUtils.isEmpty(shortcut.getChooserIntentFilters())) {
+            shortcut.addFlags(ShortcutInfo.FLAG_CHOOSER);
+        }
+    }
+
     /**
      * Remove all shortcuts that aren't pinned nor dynamic.
      */
@@ -282,11 +299,11 @@
         boolean changed = false;
         for (int i = mShortcuts.size() - 1; i >= 0; i--) {
             final ShortcutInfo si = mShortcuts.valueAt(i);
-            if (si.isDynamic()) {
+            if (si.isDynamic() || si.isChooser()) {
                 changed = true;
 
                 si.setTimestamp(now);
-                si.clearFlags(ShortcutInfo.FLAG_DYNAMIC);
+                si.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_CHOOSER);
                 si.setRank(0); // It may still be pinned, so clear the rank.
             }
         }
@@ -355,7 +372,8 @@
         if (oldShortcut.isPinned()) {
 
             oldShortcut.setRank(0);
-            oldShortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_MANIFEST);
+            oldShortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_MANIFEST
+                    | ShortcutInfo.FLAG_CHOOSER);
             if (disable) {
                 oldShortcut.addFlags(ShortcutInfo.FLAG_DISABLED);
             }
@@ -1116,8 +1134,8 @@
                     // Don't adjust ranks for manifest shortcuts.
                     continue;
                 }
-                // At this point, it must be dynamic.
-                if (!si.isDynamic()) {
+                // At this point, it must be dynamic or a chooser.
+                if (!si.isDynamicOrChooser()) {
                     s.wtf("Non-dynamic shortcut found.");
                     continue;
                 }
@@ -1294,7 +1312,7 @@
             ShortcutService.writeAttr(out, ATTR_FLAGS,
                     si.getFlags() &
                             ~(ShortcutInfo.FLAG_HAS_ICON_FILE | ShortcutInfo.FLAG_HAS_ICON_RES
-                            | ShortcutInfo.FLAG_DYNAMIC));
+                            | ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_CHOOSER));
         } else {
             // When writing for backup, ranks shouldn't be saved, since shortcuts won't be restored
             // as dynamic.
@@ -1317,15 +1335,36 @@
         }
         final Intent[] intentsNoExtras = si.getIntentsNoExtras();
         final PersistableBundle[] intentsExtras = si.getIntentPersistableExtrases();
-        final int numIntents = intentsNoExtras.length;
-        for (int i = 0; i < numIntents; i++) {
-            out.startTag(null, TAG_INTENT);
-            ShortcutService.writeAttr(out, ATTR_INTENT_NO_EXTRA, intentsNoExtras[i]);
-            ShortcutService.writeTagExtra(out, TAG_EXTRAS, intentsExtras[i]);
-            out.endTag(null, TAG_INTENT);
+        if (intentsNoExtras != null) {
+            final int numIntents = intentsNoExtras.length;
+            for (int i = 0; i < numIntents; i++) {
+                out.startTag(null, TAG_INTENT);
+                ShortcutService.writeAttr(out, ATTR_INTENT_NO_EXTRA, intentsNoExtras[i]);
+                ShortcutService.writeTagExtra(out, TAG_EXTRAS, intentsExtras[i]);
+                out.endTag(null, TAG_INTENT);
+            }
+        }
+        ShortcutService.writeTagExtra(out, TAG_EXTRAS, si.getExtras());
+
+        ShortcutService.writeTagExtra(out, TAG_CHOOSER_EXTRAS, si.getChooserExtras());
+
+        final IntentFilter[] intentFilters = si.getChooserIntentFilters();
+        if (intentFilters != null) {
+            for (int i = 0; i < intentFilters.length; i++) {
+                out.startTag(null, TAG_CHOOSER_INTENT_FILTERS);
+                intentFilters[i].writeToXml(out);
+                out.endTag(null, TAG_CHOOSER_INTENT_FILTERS);
+            }
         }
 
-        ShortcutService.writeTagExtra(out, TAG_EXTRAS, si.getExtras());
+        final ComponentName[] componentNames = si.getChooserComponentNames();
+        if (componentNames != null) {
+            for (int i = 0; i < componentNames.length; i++) {
+                out.startTag(null, TAG_CHOOSER_COMPONENT_NAMES);
+                ShortcutService.writeAttr(out, ATTR_COMPONENT_NAMES, componentNames[i]);
+                out.endTag(null, TAG_CHOOSER_COMPONENT_NAMES);
+            }
+        }
 
         out.endTag(null, TAG_SHORTCUT);
     }
@@ -1398,6 +1437,9 @@
         String iconResName;
         String bitmapPath;
         ArraySet<String> categories = null;
+        PersistableBundle chooserExtras;
+        List<IntentFilter> chooserIntentFilters = new ArrayList<>();
+        List<ComponentName> chooserComponentNames = new ArrayList<>();
 
         id = ShortcutService.parseStringAttribute(parser, ATTR_ID);
         activityComponent = ShortcutService.parseComponentNameAttribute(parser,
@@ -1458,6 +1500,18 @@
                         }
                     }
                     continue;
+                case TAG_CHOOSER_EXTRAS:
+                    chooserExtras = PersistableBundle.restoreFromXml(parser);
+                    continue;
+                case TAG_CHOOSER_COMPONENT_NAMES:
+                    chooserComponentNames.add(ShortcutService.parseComponentNameAttribute(parser,
+                            ATTR_ACTIVITY));
+                    continue;
+                case TAG_CHOOSER_INTENT_FILTERS:
+                    IntentFilter toAdd = new IntentFilter();
+                    toAdd.readFromXml(parser);
+                    chooserIntentFilters.add(toAdd);
+                    continue;
             }
             throw ShortcutService.throwForInvalidTag(depth, tag);
         }
@@ -1551,10 +1605,10 @@
         // Verify each shortcut's status.
         for (int i = mShortcuts.size() - 1; i >= 0; i--) {
             final ShortcutInfo si = mShortcuts.valueAt(i);
-            if (!(si.isDeclaredInManifest() || si.isDynamic() || si.isPinned())) {
+            if (!(si.isDeclaredInManifest() || si.isDynamicOrChooser() || si.isPinned())) {
                 failed = true;
                 Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
-                        + " is not manifest, dynamic or pinned.");
+                        + " is not manifest, dynamic, chooser or pinned.");
             }
             if (si.isDeclaredInManifest() && si.isDynamic()) {
                 failed = true;
@@ -1581,10 +1635,10 @@
                 Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
                         + " still has an icon");
             }
-            if (si.hasMaskableBitmap() && !si.hasIconFile()) {
+            if (si.hasAdaptiveBitmap() && !si.hasIconFile()) {
                 failed = true;
                 Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
-                    + " has maskable bitmap but was not saved to a file.");
+                    + " has adaptive bitmap but was not saved to a file.");
             }
             if (si.hasIconFile() && si.hasIconResource()) {
                 failed = true;
@@ -1596,6 +1650,11 @@
                 Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
                         + " has a dummy target activity");
             }
+            if (si.getIntent() == null && !si.isChooser()) {
+                failed = true;
+                Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
+                        + " has a null intent, but is not a chooser");
+            }
         }
 
         if (failed) {
diff --git a/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java b/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java
index 6eac5e3..8a8128d 100644
--- a/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java
+++ b/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java
@@ -26,6 +26,7 @@
 import android.content.pm.LauncherApps.PinItemRequest;
 import android.content.pm.ShortcutInfo;
 import android.os.Bundle;
+import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.Log;
 import android.util.Pair;
@@ -48,7 +49,7 @@
     /**
      * Internal for {@link android.content.pm.LauncherApps.PinItemRequest} which receives callbacks.
      */
-    private static class PinItemRequestInner extends IPinItemRequest.Stub {
+    private abstract static class PinItemRequestInner extends IPinItemRequest.Stub {
         protected final ShortcutRequestPinProcessor mProcessor;
         private final IntentSender mResultIntent;
         private final int mLauncherUid;
@@ -63,6 +64,21 @@
             mLauncherUid = launcherUid;
         }
 
+        @Override
+        public ShortcutInfo getShortcutInfo() {
+            return null;
+        }
+
+        @Override
+        public AppWidgetProviderInfo getAppWidgetProviderInfo() {
+            return null;
+        }
+
+        @Override
+        public Bundle getExtras() {
+            return null;
+        }
+
         /**
          * Returns true if the caller is same as the default launcher app when this request
          * object was created.
@@ -126,6 +142,33 @@
     /**
      * Internal for {@link android.content.pm.LauncherApps.PinItemRequest} which receives callbacks.
      */
+    private static class PinAppWidgetRequestInner extends PinItemRequestInner {
+        final AppWidgetProviderInfo mAppWidgetProviderInfo;
+        final Bundle mExtras;
+
+        private PinAppWidgetRequestInner(ShortcutRequestPinProcessor processor,
+                IntentSender resultIntent, int launcherUid,
+                AppWidgetProviderInfo appWidgetProviderInfo, Bundle extras) {
+            super(processor, resultIntent, launcherUid);
+
+            mAppWidgetProviderInfo = appWidgetProviderInfo;
+            mExtras = extras;
+        }
+
+        @Override
+        public AppWidgetProviderInfo getAppWidgetProviderInfo() {
+            return mAppWidgetProviderInfo;
+        }
+
+        @Override
+        public Bundle getExtras() {
+            return mExtras;
+        }
+    }
+
+    /**
+     * Internal for {@link android.content.pm.LauncherApps.PinItemRequest} which receives callbacks.
+     */
     private static class PinShortcutRequestInner extends PinItemRequestInner {
         /** Original shortcut passed by the app. */
         public final ShortcutInfo shortcutOriginal;
@@ -153,6 +196,11 @@
         }
 
         @Override
+        public ShortcutInfo getShortcutInfo() {
+            return shortcutForLauncher;
+        }
+
+        @Override
         protected boolean tryAccept() {
             if (DEBUG) {
                 Slog.d(TAG, "Launcher accepted shortcut. ID=" + shortcutOriginal.getId()
@@ -179,7 +227,7 @@
      * always null.
      */
     public boolean requestPinItemLocked(ShortcutInfo inShortcut, AppWidgetProviderInfo inAppWidget,
-        int userId, IntentSender resultIntent) {
+        Bundle extras, int userId, IntentSender resultIntent) {
 
         // First, make sure the launcher supports it.
 
@@ -208,8 +256,10 @@
         } else {
             int launcherUid = mService.injectGetPackageUid(
                     confirmActivity.first.getPackageName(), launcherUserId);
-            request = new PinItemRequest(inAppWidget,
-                    new PinItemRequestInner(this, resultIntent, launcherUid));
+            request = new PinItemRequest(
+                    new PinAppWidgetRequestInner(this, resultIntent, launcherUid, inAppWidget,
+                            extras),
+                    PinItemRequest.REQUEST_TYPE_APPWIDGET);
         }
         return startRequestConfirmActivity(confirmActivity.first, launcherUserId, request,
                 requestType);
@@ -319,7 +369,7 @@
                         mService.injectGetPackageUid(launcherPackage, launcherUserId),
                         existsAlready);
 
-        return new PinItemRequest(shortcutForLauncher, inner);
+        return new PinItemRequest(inner, PinItemRequest.REQUEST_TYPE_SHORTCUT);
     }
 
     private void validateExistingShortcut(ShortcutInfo shortcutInfo) {
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 057e781..1aaec1a 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -27,6 +27,7 @@
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -45,7 +46,6 @@
 import android.content.pm.ParceledListSlice;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ShortcutInfo;
-import android.content.pm.ShortcutManager;
 import android.content.pm.ShortcutServiceInternal;
 import android.content.pm.ShortcutServiceInternal.ShortcutChangeListener;
 import android.content.pm.UserInfo;
@@ -59,11 +59,13 @@
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Build;
+import android.os.Bundle;
 import android.os.Environment;
 import android.os.FileUtils;
 import android.os.Handler;
 import android.os.LocaleList;
 import android.os.Looper;
+import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
 import android.os.PersistableBundle;
 import android.os.Process;
@@ -1217,7 +1219,7 @@
         shortcut.setIconResourceId(0);
         shortcut.setIconResName(null);
         shortcut.clearFlags(ShortcutInfo.FLAG_HAS_ICON_FILE |
-            ShortcutInfo.FLAG_MASKABLE_BITMAP | ShortcutInfo.FLAG_HAS_ICON_RES);
+            ShortcutInfo.FLAG_ADAPTIVE_BITMAP | ShortcutInfo.FLAG_HAS_ICON_RES);
     }
 
     public void cleanupBitmapsForPackage(@UserIdInt int userId, String packageName) {
@@ -1353,7 +1355,7 @@
                         return;
                     }
                     case Icon.TYPE_BITMAP:
-                    case Icon.TYPE_BITMAP_MASKABLE: {
+                    case Icon.TYPE_ADAPTIVE_BITMAP: {
                         bitmap = icon.getBitmap(); // Don't recycle in this case.
                         break;
                     }
@@ -1384,8 +1386,8 @@
 
                         shortcut.setBitmapPath(out.getFile().getAbsolutePath());
                         shortcut.addFlags(ShortcutInfo.FLAG_HAS_ICON_FILE);
-                        if (icon.getType() == Icon.TYPE_BITMAP_MASKABLE) {
-                            shortcut.addFlags(ShortcutInfo.FLAG_MASKABLE_BITMAP);
+                        if (icon.getType() == Icon.TYPE_ADAPTIVE_BITMAP) {
+                            shortcut.addFlags(ShortcutInfo.FLAG_ADAPTIVE_BITMAP);
                         }
                     } finally {
                         IoUtils.closeQuietly(out);
@@ -1750,6 +1752,7 @@
             ps.clearAllImplicitRanks();
             assignImplicitRanks(newShortcuts);
 
+            // TODO: Consider removing Chooser fields. If so, the FLAG_CHOOSER should be removed
             for (int i = 0; i < size; i++) {
                 final ShortcutInfo source = newShortcuts.get(i);
                 fixUpIncomingShortcutInfo(source, /* forUpdate= */ true);
@@ -1789,6 +1792,13 @@
                 if (replacingIcon || source.hasStringResources()) {
                     fixUpShortcutResourceNamesAndValues(target);
                 }
+
+                // While updating, we keep the dynamic flag as it previously was, but refresh the
+                // chooser flag.
+                // TODO: If we support clearing Chooser fields, we should also remove the flag.
+                if (target.getChooserIntentFilters() != null) {
+                    target.addFlags(ShortcutInfo.FLAG_CHOOSER);
+                }
             }
 
             // Lastly, adjust the ranks.
@@ -1852,12 +1862,13 @@
         return true;
     }
 
+    // TODO: Ensure non-launchable shortcuts can not be pinned
     @Override
     public boolean requestPinShortcut(String packageName, ShortcutInfo shortcut,
             IntentSender resultIntent, int userId) {
         Preconditions.checkNotNull(shortcut);
         Preconditions.checkArgument(shortcut.isEnabled(), "Shortcut must be enabled");
-        return requestPinItem(packageName, userId, shortcut, null, resultIntent);
+        return requestPinItem(packageName, userId, shortcut, null, null, resultIntent);
     }
 
     @Override
@@ -1884,8 +1895,8 @@
      * After validating the caller, it passes the request to {@link #mShortcutRequestPinProcessor}.
      * Either {@param shortcut} or {@param appWidget} should be non-null.
      */
-    private boolean requestPinItem(String packageName, int userId,
-            ShortcutInfo shortcut, AppWidgetProviderInfo appWidget, IntentSender resultIntent) {
+    private boolean requestPinItem(String packageName, int userId, ShortcutInfo shortcut,
+            AppWidgetProviderInfo appWidget, Bundle extras, IntentSender resultIntent) {
         verifyCaller(packageName, userId);
 
         final boolean ret;
@@ -1896,8 +1907,8 @@
                     "Calling application must have a foreground activity or a foreground service");
 
             // Send request to the launcher, if supported.
-            ret = mShortcutRequestPinProcessor.requestPinItemLocked(shortcut, appWidget, userId,
-                    resultIntent);
+            ret = mShortcutRequestPinProcessor.requestPinItemLocked(shortcut, appWidget, extras,
+                    userId, resultIntent);
         }
 
         verifyStates();
@@ -2007,7 +2018,7 @@
 
             return getShortcutsWithQueryLocked(
                     packageName, userId, ShortcutInfo.CLONE_REMOVE_FOR_CREATOR,
-                    ShortcutInfo::isDynamic);
+                    ShortcutInfo::isDynamicOrChooser);
         }
     }
 
@@ -2200,6 +2211,14 @@
         synchronized (mLock) {
             throwIfUserLockedL(userId);
 
+            // For the chooser, we just check is the system is calling.
+            // STOPSHIP: We need to implement a new permission here rather than this terrible check.
+            //           The packageName check is to try to distinguish between when an actual
+            //           launcher is making the call, and when it's the system.
+            if (isCallerSystem() && packageName.equals("android")) {
+                return true;
+            }
+
             final ShortcutUser user = getUserShortcutsLocked(userId);
 
             // Always trust the cached component.
@@ -2372,7 +2391,7 @@
         public List<ShortcutInfo> getShortcuts(int launcherUserId,
                 @NonNull String callingPackage, long changedSince,
                 @Nullable String packageName, @Nullable List<String> shortcutIds,
-                @Nullable ComponentName componentName,
+                @Nullable ComponentName componentName, @Nullable Intent intent,
                 int queryFlags, int userId) {
             final ArrayList<ShortcutInfo> ret = new ArrayList<>();
 
@@ -2394,13 +2413,13 @@
                 if (packageName != null) {
                     getShortcutsInnerLocked(launcherUserId,
                             callingPackage, packageName, shortcutIds, changedSince,
-                            componentName, queryFlags, userId, ret, cloneFlag);
+                            componentName, intent, queryFlags, userId, ret, cloneFlag);
                 } else {
                     final List<String> shortcutIdsF = shortcutIds;
                     getUserShortcutsLocked(userId).forAllPackages(p -> {
                         getShortcutsInnerLocked(launcherUserId,
                                 callingPackage, p.getPackageName(), shortcutIdsF, changedSince,
-                                componentName, queryFlags, userId, ret, cloneFlag);
+                                componentName, intent, queryFlags, userId, ret, cloneFlag);
                     });
                 }
             }
@@ -2409,7 +2428,7 @@
 
         private void getShortcutsInnerLocked(int launcherUserId, @NonNull String callingPackage,
                 @Nullable String packageName, @Nullable List<String> shortcutIds, long changedSince,
-                @Nullable ComponentName componentName, int queryFlags,
+                @Nullable ComponentName componentName, Intent intent, int queryFlags,
                 int userId, ArrayList<ShortcutInfo> ret, int cloneFlag) {
             final ArraySet<String> ids = shortcutIds == null ? null
                     : new ArraySet<>(shortcutIds);
@@ -2434,6 +2453,15 @@
                                 return false;
                             }
                         }
+                        if (intent != null
+                                && !si.hasMatchingFilter(mContext.getContentResolver(), intent)) {
+                            return false;
+                        }
+
+                        if (((queryFlags & ShortcutQuery.FLAG_MATCH_CHOOSER) != 0)
+                                && si.isChooser()) {
+                            return true;
+                        }
                         if (((queryFlags & ShortcutQuery.FLAG_GET_DYNAMIC) != 0)
                                 && si.isDynamic()) {
                             return true;
@@ -2622,10 +2650,10 @@
 
         @Override
         public boolean requestPinAppWidget(@NonNull String callingPackage,
-                @NonNull AppWidgetProviderInfo appWidget, @Nullable IntentSender resultIntent,
-                int userId) {
+                @NonNull AppWidgetProviderInfo appWidget, @Nullable Bundle extras,
+                @Nullable IntentSender resultIntent, int userId) {
             Preconditions.checkNotNull(appWidget);
-            return requestPinItem(callingPackage, userId, null, appWidget, resultIntent);
+            return requestPinItem(callingPackage, userId, null, appWidget, extras, resultIntent);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index fb8429d..36eba8e 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -414,13 +414,6 @@
         final long id = Binder.clearCallingIdentity();
         try {
             switch (key) {
-                case UserManager.DISALLOW_CONFIG_WIFI:
-                    if (newValue) {
-                        android.provider.Settings.Secure.putIntForUser(cr,
-                                android.provider.Settings.Global
-                                        .WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0, userId);
-                    }
-                    break;
                 case UserManager.DISALLOW_DATA_ROAMING:
                     if (newValue) {
                         // DISALLOW_DATA_ROAMING user restriction is set.
diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java
index 00f3711..755c486 100644
--- a/services/core/java/com/android/server/pm/dex/DexManager.java
+++ b/services/core/java/com/android/server/pm/dex/DexManager.java
@@ -22,6 +22,7 @@
 import android.content.pm.PackageParser;
 import android.os.RemoteException;
 import android.os.storage.StorageManager;
+import android.os.UserHandle;
 
 import android.util.Slog;
 
@@ -179,17 +180,64 @@
         }
     }
 
-    public void notifyPackageInstalled(PackageInfo info, int userId) {
-        cachePackageCodeLocation(info, userId);
+    /**
+     * Notifies that a new package was installed for {@code userId}.
+     * {@code userId} must not be {@code UserHandle.USER_ALL}.
+     *
+     * @throws IllegalArgumentException if {@code userId} is {@code UserHandle.USER_ALL}.
+     */
+    public void notifyPackageInstalled(PackageInfo pi, int userId) {
+        if (userId == UserHandle.USER_ALL) {
+            throw new IllegalArgumentException(
+                "notifyPackageInstalled called with USER_ALL");
+        }
+        cachePackageCodeLocation(pi.packageName, pi.applicationInfo.sourceDir,
+                pi.applicationInfo.splitSourceDirs, pi.applicationInfo.dataDir, userId);
     }
 
-    private void cachePackageCodeLocation(PackageInfo info, int userId) {
-        PackageCodeLocations pcl = mPackageCodeLocationsCache.get(info.packageName);
-        if (pcl != null) {
-            pcl.mergeAppDataDirs(info.applicationInfo, userId);
-        } else {
-            mPackageCodeLocationsCache.put(info.packageName,
-                new PackageCodeLocations(info.applicationInfo, userId));
+    /**
+     * Notifies that package {@code packageName} was updated.
+     * This will clear the UsedByOtherApps mark if it exists.
+     */
+    public void notifyPackageUpdated(String packageName, String baseCodePath,
+            String[] splitCodePaths) {
+        cachePackageCodeLocation(packageName, baseCodePath, splitCodePaths, null, /*userId*/ -1);
+        // In case there was an update, write the package use info to disk async.
+        // Note that we do the writing here and not in PackageDexUsage in order to be
+        // consistent with other methods in DexManager (e.g. reconcileSecondaryDexFiles performs
+        // multiple updates in PackaeDexUsage before writing it).
+        if (mPackageDexUsage.clearUsedByOtherApps(packageName)) {
+            mPackageDexUsage.maybeWriteAsync();
+        }
+    }
+
+    /**
+     * Notifies that the user {@code userId} data for package {@code packageName}
+     * was destroyed. This will remove all usage info associated with the package
+     * for the given user.
+     * {@code userId} is allowed to be {@code UserHandle.USER_ALL} in which case
+     * all usage information for the package will be removed.
+     */
+    public void notifyPackageDataDestroyed(String packageName, int userId) {
+        boolean updated = userId == UserHandle.USER_ALL
+            ? mPackageDexUsage.removePackage(packageName)
+            : mPackageDexUsage.removeUserPackage(packageName, userId);
+        // In case there was an update, write the package use info to disk async.
+        // Note that we do the writing here and not in PackageDexUsage in order to be
+        // consistent with other methods in DexManager (e.g. reconcileSecondaryDexFiles performs
+        // multiple updates in PackaeDexUsage before writing it).
+        if (updated) {
+            mPackageDexUsage.maybeWriteAsync();
+        }
+    }
+
+    public void cachePackageCodeLocation(String packageName, String baseCodePath,
+            String[] splitCodePaths, String dataDir, int userId) {
+        PackageCodeLocations pcl = putIfAbsent(mPackageCodeLocationsCache, packageName,
+                new PackageCodeLocations(packageName, baseCodePath, splitCodePaths));
+        pcl.updateCodeLocation(baseCodePath, splitCodePaths);
+        if (dataDir != null) {
+            pcl.mergeAppDataDirs(dataDir, userId);
         }
     }
 
@@ -202,7 +250,8 @@
             int userId = entry.getKey();
             for (PackageInfo pi : packageInfoList) {
                 // Cache the code locations.
-                cachePackageCodeLocation(pi, userId);
+                cachePackageCodeLocation(pi.packageName, pi.applicationInfo.sourceDir,
+                        pi.applicationInfo.splitSourceDirs, pi.applicationInfo.dataDir, userId);
 
                 // Cache a map from package name to the set of user ids who installed the package.
                 // We will use it to sync the data and remove obsolete entries from
@@ -359,6 +408,23 @@
     }
 
     /**
+     * Return true if the profiling data collected for the given app indicate
+     * that the apps's APK has been loaded by another app.
+     * Note that this returns false for all apps without any collected profiling data.
+    */
+    public boolean isUsedByOtherApps(String packageName) {
+        PackageUseInfo useInfo = getPackageUseInfo(packageName);
+        if (useInfo == null) {
+            // No use info, means the package was not used or it was used but not by other apps.
+            // Note that right now we might prune packages which are not used by other apps.
+            // TODO(calin): maybe we should not (prune) so we can have an accurate view when we try
+            // to access the package use.
+            return false;
+        }
+        return useInfo.isUsedByOtherApps();
+    }
+
+    /**
      * Retrieves the package which owns the given dexPath.
      */
     private DexSearchResult getDexPackage(
@@ -408,27 +474,36 @@
      */
     private static class PackageCodeLocations {
         private final String mPackageName;
-        private final String mBaseCodePath;
+        private String mBaseCodePath;
         private final Set<String> mSplitCodePaths;
         // Maps user id to the application private directory.
         private final Map<Integer, Set<String>> mAppDataDirs;
 
         public PackageCodeLocations(ApplicationInfo ai, int userId) {
-            mPackageName = ai.packageName;
-            mBaseCodePath = ai.sourceDir;
+            this(ai.packageName, ai.sourceDir, ai.splitSourceDirs);
+            mergeAppDataDirs(ai.dataDir, userId);
+        }
+        public PackageCodeLocations(String packageName, String baseCodePath,
+                String[] splitCodePaths) {
+            mPackageName = packageName;
             mSplitCodePaths = new HashSet<>();
-            if (ai.splitSourceDirs != null) {
-                for (String split : ai.splitSourceDirs) {
+            mAppDataDirs = new HashMap<>();
+            updateCodeLocation(baseCodePath, splitCodePaths);
+        }
+
+        public void updateCodeLocation(String baseCodePath, String[] splitCodePaths) {
+            mBaseCodePath = baseCodePath;
+            mSplitCodePaths.clear();
+            if (splitCodePaths != null) {
+                for (String split : splitCodePaths) {
                     mSplitCodePaths.add(split);
                 }
             }
-            mAppDataDirs = new HashMap<>();
-            mergeAppDataDirs(ai, userId);
         }
 
-        public void mergeAppDataDirs(ApplicationInfo ai, int userId) {
+        public void mergeAppDataDirs(String dataDir, int userId) {
             Set<String> dataDirs = putIfAbsent(mAppDataDirs, userId, new HashSet<>());
-            dataDirs.add(ai.dataDir);
+            dataDirs.add(dataDir);
         }
 
         public int searchDex(String dexPath, int userId) {
diff --git a/services/core/java/com/android/server/pm/dex/PackageDexUsage.java b/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
index 3693bce0..8a66f12 100644
--- a/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
+++ b/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
@@ -377,7 +377,34 @@
     }
 
     /**
+     * Clears the {@code usesByOtherApps} marker for the package {@code packageName}.
+     * @return true if the package usage info was updated.
+     */
+    public boolean clearUsedByOtherApps(String packageName) {
+        synchronized (mPackageUseInfoMap) {
+            PackageUseInfo packageUseInfo = mPackageUseInfoMap.get(packageName);
+            if (packageUseInfo == null || !packageUseInfo.mIsUsedByOtherApps) {
+                return false;
+            }
+            packageUseInfo.mIsUsedByOtherApps = false;
+            return true;
+        }
+    }
+
+    /**
+     * Remove the usage data associated with package {@code packageName}.
+     * @return true if the package usage was found and removed successfully.
+     */
+    public boolean removePackage(String packageName) {
+        synchronized (mPackageUseInfoMap) {
+            return mPackageUseInfoMap.remove(packageName) != null;
+        }
+    }
+
+    /**
      * Remove all the records about package {@code packageName} belonging to user {@code userId}.
+     * If the package is left with no records of secondary dex usage and is not used by other
+     * apps it will be removed as well.
      * @return true if the record was found and actually deleted,
      *         false if the record doesn't exist
      */
@@ -397,6 +424,12 @@
                     updated = true;
                 }
             }
+            // If no secondary dex info is left and the package is not used by other apps
+            // remove the data since it is now useless.
+            if (packageUseInfo.mDexUseInfoMap.isEmpty() && !packageUseInfo.mIsUsedByOtherApps) {
+                mPackageUseInfoMap.remove(packageName);
+                updated = true;
+            }
             return updated;
         }
     }
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 0d6cd80..4f1754a 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -2398,8 +2398,8 @@
              * permission to add alert windows that aren't
              * {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY}.
              */
-            return (mContext.checkCallingPermission(INTERNAL_SYSTEM_WINDOW) == PERMISSION_GRANTED)
-                    ? ADD_OKAY : ADD_PERMISSION_DENIED;
+            return (mContext.checkCallingOrSelfPermission(INTERNAL_SYSTEM_WINDOW)
+                    == PERMISSION_GRANTED) ? ADD_OKAY : ADD_PERMISSION_DENIED;
         }
 
         // check if user has enabled this operation. SecurityException will be thrown if this app
@@ -2420,8 +2420,8 @@
             default:
                 // in the default mode, we will make a decision here based on
                 // checkCallingPermission()
-                return (mContext.checkCallingPermission(SYSTEM_ALERT_WINDOW) == PERMISSION_GRANTED)
-                        ? ADD_OKAY : ADD_PERMISSION_DENIED;
+                return (mContext.checkCallingOrSelfPermission(SYSTEM_ALERT_WINDOW)
+                        == PERMISSION_GRANTED) ? ADD_OKAY : ADD_PERMISSION_DENIED;
         }
     }
 
diff --git a/services/core/java/com/android/server/power/BatterySaverPolicy.java b/services/core/java/com/android/server/power/BatterySaverPolicy.java
new file mode 100644
index 0000000..8d20531
--- /dev/null
+++ b/services/core/java/com/android/server/power/BatterySaverPolicy.java
@@ -0,0 +1,270 @@
+/*
+ * 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.power;
+
+import android.annotation.IntDef;
+import android.content.ContentResolver;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.provider.Settings;
+import android.util.KeyValueListParser;
+import android.util.Slog;
+import android.os.PowerSaveState;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Class to decide whether to turn on battery saver mode for specific service
+ */
+public class BatterySaverPolicy extends ContentObserver {
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({ServiceType.GPS,
+            ServiceType.VIBRATION,
+            ServiceType.ANIMATION,
+            ServiceType.FULL_BACKUP,
+            ServiceType.KEYVALUE_BACKUP,
+            ServiceType.NETWORK_FIREWALL,
+            ServiceType.SCREEN_BRIGHTNESS,
+            ServiceType.SOUND,
+            ServiceType.BATTERY_STATS})
+    public @interface ServiceType {
+        int NULL = 0;
+        int GPS = 1;
+        int VIBRATION = 2;
+        int ANIMATION = 3;
+        int FULL_BACKUP = 4;
+        int KEYVALUE_BACKUP = 5;
+        int NETWORK_FIREWALL = 6;
+        int SCREEN_BRIGHTNESS = 7;
+        int SOUND = 8;
+        int BATTERY_STATS = 9;
+    }
+
+    private static final String TAG = "BatterySaverPolicy";
+
+    // Value of batterySaverGpsMode such that GPS isn't affected by battery saver mode.
+    public static final int GPS_MODE_NO_CHANGE = 0;
+    // Value of batterySaverGpsMode such that GPS is disabled when battery saver mode
+    // is enabled and the screen is off.
+    public static final int GPS_MODE_DISABLED_WHEN_SCREEN_OFF = 1;
+    // Secure setting for GPS behavior when battery saver mode is on.
+    public static final String SECURE_KEY_GPS_MODE = "batterySaverGpsMode";
+
+    private static final String KEY_GPS_MODE = "gps_mode";
+    private static final String KEY_VIBRATION_DISABLED = "vibration_disabled";
+    private static final String KEY_ANIMATION_DISABLED = "animation_disabled";
+    private static final String KEY_SOUNDTRIGGER_DISABLED = "soundtrigger_disabled";
+    private static final String KEY_FIREWALL_DISABLED = "firewall_disabled";
+    private static final String KEY_ADJUST_BRIGHTNESS_DISABLED = "adjust_brightness_disabled";
+    private static final String KEY_ADJUST_BRIGHTNESS_FACTOR = "adjust_brightness_factor";
+    private static final String KEY_FULLBACKUP_DEFERRED = "fullbackup_deferred";
+    private static final String KEY_KEYVALUE_DEFERRED = "keyvaluebackup_deferred";
+
+    private final KeyValueListParser mParser = new KeyValueListParser(',');
+
+    /**
+     * {@code true} if vibration is disabled in battery saver mode.
+     *
+     * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+     * @see #KEY_VIBRATION_DISABLED
+     */
+    private boolean mVibrationDisabled;
+
+    /**
+     * {@code true} if animation is disabled in battery saver mode.
+     *
+     * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+     * @see #KEY_ANIMATION_DISABLED
+     */
+    private boolean mAnimationDisabled;
+
+    /**
+     * {@code true} if sound trigger is disabled in battery saver mode
+     * in battery saver mode.
+     *
+     * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+     * @see #KEY_SOUNDTRIGGER_DISABLED
+     */
+    private boolean mSoundTriggerDisabled;
+
+    /**
+     * {@code true} if full backup is deferred in battery saver mode.
+     *
+     * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+     * @see #KEY_FULLBACKUP_DEFERRED
+     */
+    private boolean mFullBackupDeferred;
+
+    /**
+     * {@code true} if key value backup is deferred in battery saver mode.
+     *
+     * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+     * @see #KEY_KEYVALUE_DEFERRED
+     */
+    private boolean mKeyValueBackupDeferred;
+
+    /**
+     * {@code true} if network policy firewall is disabled in battery saver mode.
+     *
+     * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+     * @see #KEY_FIREWALL_DISABLED
+     */
+    private boolean mFireWallDisabled;
+
+    /**
+     * {@code true} if adjust brightness is disabled in battery saver mode.
+     *
+     * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+     * @see #KEY_ADJUST_BRIGHTNESS_DISABLED
+     */
+    private boolean mAdjustBrightnessDisabled;
+
+    /**
+     * This is the flag to decide the gps mode in battery saver mode.
+     *
+     * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+     * @see #KEY_GPS_MODE
+     */
+    private int mGpsMode;
+
+    /**
+     * This is the flag to decide the how much to adjust the screen brightness. This is
+     * the float value from 0 to 1 where 1 means don't change brightness.
+     *
+     * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+     * @see #KEY_ADJUST_BRIGHTNESS_FACTOR
+     */
+    private float mAdjustBrightnessFactor;
+
+    private ContentResolver mContentResolver;
+
+    public BatterySaverPolicy(Handler handler) {
+        super(handler);
+    }
+
+    public void start(ContentResolver contentResolver) {
+        mContentResolver = contentResolver;
+
+        mContentResolver.registerContentObserver(Settings.Global.getUriFor(
+                Settings.Global.BATTERY_SAVER_CONSTANTS), false, this);
+        onChange(true, null);
+    }
+
+    @Override
+    public void onChange(boolean selfChange, Uri uri) {
+        final String value = Settings.Global.getString(mContentResolver,
+                Settings.Global.BATTERY_SAVER_CONSTANTS);
+        updateConstants(value);
+    }
+
+    @VisibleForTesting
+    void updateConstants(final String value) {
+        synchronized (BatterySaverPolicy.this) {
+            try {
+                mParser.setString(value);
+            } catch (IllegalArgumentException e) {
+                Slog.e(TAG, "Bad battery saver constants");
+            }
+
+            mVibrationDisabled = mParser.getBoolean(KEY_VIBRATION_DISABLED, true);
+            mAnimationDisabled = mParser.getBoolean(KEY_ANIMATION_DISABLED, true);
+            mSoundTriggerDisabled = mParser.getBoolean(KEY_SOUNDTRIGGER_DISABLED, true);
+            mFullBackupDeferred = mParser.getBoolean(KEY_FULLBACKUP_DEFERRED, true);
+            mKeyValueBackupDeferred = mParser.getBoolean(KEY_KEYVALUE_DEFERRED, true);
+            mFireWallDisabled = mParser.getBoolean(KEY_FIREWALL_DISABLED, false);
+            mAdjustBrightnessDisabled = mParser.getBoolean(KEY_ADJUST_BRIGHTNESS_DISABLED, false);
+            mAdjustBrightnessFactor = mParser.getFloat(KEY_ADJUST_BRIGHTNESS_FACTOR, 0.5f);
+
+            // Get default value from Settings.Secure
+            final int defaultGpsMode = Settings.Secure.getInt(mContentResolver, SECURE_KEY_GPS_MODE,
+                    GPS_MODE_DISABLED_WHEN_SCREEN_OFF);
+            mGpsMode = mParser.getInt(KEY_GPS_MODE, defaultGpsMode);
+        }
+    }
+
+    /**
+     * Get the {@link PowerSaveState} based on {@paramref type} and {@paramref realMode}.
+     * The result will have {@link PowerSaveState#batterySaverEnabled} and some other
+     * parameters when necessary.
+     *
+     * @param type     type of the service, one of {@link ServiceType}
+     * @param realMode whether the battery saver is on by default
+     * @return State data that contains battery saver data
+     */
+    public PowerSaveState getBatterySaverPolicy(@ServiceType int type, boolean realMode) {
+        synchronized (BatterySaverPolicy.this) {
+            final PowerSaveState.Builder builder = new PowerSaveState.Builder();
+            if (!realMode) {
+                return builder.setBatterySaverEnabled(realMode)
+                        .build();
+            }
+            switch (type) {
+                case ServiceType.GPS:
+                    return builder.setBatterySaverEnabled(realMode)
+                            .setGpsMode(mGpsMode)
+                            .build();
+                case ServiceType.ANIMATION:
+                    return builder.setBatterySaverEnabled(mAnimationDisabled)
+                            .build();
+                case ServiceType.FULL_BACKUP:
+                    return builder.setBatterySaverEnabled(mFullBackupDeferred)
+                            .build();
+                case ServiceType.KEYVALUE_BACKUP:
+                    return builder.setBatterySaverEnabled(mKeyValueBackupDeferred)
+                            .build();
+                case ServiceType.NETWORK_FIREWALL:
+                    return builder.setBatterySaverEnabled(!mFireWallDisabled)
+                            .build();
+                case ServiceType.SCREEN_BRIGHTNESS:
+                    return builder.setBatterySaverEnabled(!mAdjustBrightnessDisabled)
+                            .setBrightnessFactor(mAdjustBrightnessFactor)
+                            .build();
+                case ServiceType.SOUND:
+                    return builder.setBatterySaverEnabled(mSoundTriggerDisabled)
+                            .build();
+                case ServiceType.VIBRATION:
+                    return builder.setBatterySaverEnabled(mVibrationDisabled)
+                            .build();
+                default:
+                    return builder.setBatterySaverEnabled(realMode)
+                            .build();
+            }
+        }
+    }
+
+    public void dump(PrintWriter pw) {
+        pw.println();
+        pw.println("Battery saver policy");
+        pw.println("  Settings " + Settings.Global.BATTERY_SAVER_CONSTANTS);
+        pw.println("  value: " + Settings.Global.getString(mContentResolver,
+                Settings.Global.BATTERY_SAVER_CONSTANTS));
+
+        pw.println();
+        pw.println("  " + KEY_VIBRATION_DISABLED + "=" + mVibrationDisabled);
+        pw.println("  " + KEY_ANIMATION_DISABLED + "=" + mAnimationDisabled);
+        pw.println("  " + KEY_FULLBACKUP_DEFERRED + "=" + mFullBackupDeferred);
+        pw.println("  " + KEY_KEYVALUE_DEFERRED + "=" + mKeyValueBackupDeferred);
+        pw.println("  " + KEY_FIREWALL_DISABLED + "=" + mFireWallDisabled);
+        pw.println("  " + KEY_ADJUST_BRIGHTNESS_DISABLED + "=" + mAdjustBrightnessDisabled);
+        pw.println("  " + KEY_ADJUST_BRIGHTNESS_FACTOR + "=" + mAdjustBrightnessFactor);
+        pw.println("  " + KEY_GPS_MODE + "=" + mGpsMode);
+
+    }
+}
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index ffbb428..c58b527 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -43,6 +43,7 @@
 import android.os.Message;
 import android.os.PowerManager;
 import android.os.PowerManagerInternal;
+import android.os.PowerSaveState;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
@@ -51,21 +52,24 @@
 import android.os.UserHandle;
 import android.os.WorkSource;
 import android.provider.Settings;
-import android.provider.Settings.Secure;
 import android.provider.Settings.SettingNotFoundException;
 import android.service.dreams.DreamManagerInternal;
+import android.service.power.PowerServiceDumpProto;
+import android.service.power.PowerServiceSettingsAndConfigurationDumpProto;
+import android.service.power.SuspendBlockerProto;
+import android.service.power.WakeLockProto;
 import android.service.vr.IVrManager;
 import android.service.vr.IVrStateCallbacks;
 import android.util.EventLog;
 import android.util.KeyValueListParser;
-import android.util.Log;
 import android.util.PrintWriterPrinter;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
 import android.view.Display;
 import android.view.WindowManagerPolicy;
-
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IAppOpsService;
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.os.BackgroundThread;
@@ -78,7 +82,7 @@
 import com.android.server.am.BatteryStatsService;
 import com.android.server.lights.Light;
 import com.android.server.lights.LightsManager;
-import com.android.server.vr.VrManagerService;
+import com.android.server.power.BatterySaverPolicy.ServiceType;
 import libcore.util.Objects;
 
 import java.io.FileDescriptor;
@@ -190,6 +194,7 @@
     private final Context mContext;
     private final ServiceThread mHandlerThread;
     private final PowerManagerHandler mHandler;
+    private final BatterySaverPolicy mBatterySaverPolicy;
 
     private LightsManager mLightsManager;
     private BatteryManagerInternal mBatteryManagerInternal;
@@ -575,6 +580,13 @@
             pw.print("    "); pw.print(KEY_NO_CACHED_WAKE_LOCKS); pw.print("=");
             pw.println(NO_CACHED_WAKE_LOCKS);
         }
+
+        void dumpProto(ProtoOutputStream proto) {
+            final long constantsToken = proto.start(PowerServiceDumpProto.CONSTANTS);
+            proto.write(PowerServiceDumpProto.ConstantsProto.IS_NO_CACHED_WAKE_LOCKS,
+                    NO_CACHED_WAKE_LOCKS);
+            proto.end(constantsToken);
+        }
     }
 
     final Constants mConstants;
@@ -596,6 +608,7 @@
         mHandlerThread.start();
         mHandler = new PowerManagerHandler(mHandlerThread.getLooper());
         mConstants = new Constants(mHandler);
+        mBatterySaverPolicy = new BatterySaverPolicy(mHandler);
 
         synchronized (mLock) {
             mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");
@@ -616,6 +629,21 @@
         }
     }
 
+    @VisibleForTesting
+    PowerManagerService(Context context, BatterySaverPolicy batterySaverPolicy) {
+        super(context);
+
+        mBatterySaverPolicy = batterySaverPolicy;
+        mContext = context;
+        mHandlerThread = new ServiceThread(TAG,
+                Process.THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
+        mHandlerThread.start();
+        mHandler = new PowerManagerHandler(mHandlerThread.getLooper());
+        mConstants = new Constants(mHandler);
+        mDisplaySuspendBlocker = null;
+        mWakeLockSuspendBlocker = null;
+    }
+
     @Override
     public void onStart() {
         publishBinderService(Context.POWER_SERVICE, new BinderService());
@@ -674,9 +702,6 @@
                     mAppOps, createSuspendBlockerLocked("PowerManagerService.Broadcasts"),
                     mPolicy);
 
-            final ContentResolver resolver = mContext.getContentResolver();
-            mConstants.start(resolver);
-
             mWirelessChargerDetector = new WirelessChargerDetector(sensorManager,
                     createSuspendBlockerLocked("PowerManagerService.WirelessChargerDetector"),
                     mHandler);
@@ -689,57 +714,6 @@
             mDisplayManagerInternal.initPowerManagement(
                     mDisplayPowerCallbacks, mHandler, sensorManager);
 
-            // Register for settings changes.
-            resolver.registerContentObserver(Settings.Secure.getUriFor(
-                    Settings.Secure.SCREENSAVER_ENABLED),
-                    false, mSettingsObserver, UserHandle.USER_ALL);
-            resolver.registerContentObserver(Settings.Secure.getUriFor(
-                    Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP),
-                    false, mSettingsObserver, UserHandle.USER_ALL);
-            resolver.registerContentObserver(Settings.Secure.getUriFor(
-                    Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK),
-                    false, mSettingsObserver, UserHandle.USER_ALL);
-            resolver.registerContentObserver(Settings.System.getUriFor(
-                    Settings.System.SCREEN_OFF_TIMEOUT),
-                    false, mSettingsObserver, UserHandle.USER_ALL);
-            resolver.registerContentObserver(Settings.Secure.getUriFor(
-                    Settings.Secure.SLEEP_TIMEOUT),
-                    false, mSettingsObserver, UserHandle.USER_ALL);
-            resolver.registerContentObserver(Settings.Global.getUriFor(
-                    Settings.Global.STAY_ON_WHILE_PLUGGED_IN),
-                    false, mSettingsObserver, UserHandle.USER_ALL);
-            resolver.registerContentObserver(Settings.System.getUriFor(
-                    Settings.System.SCREEN_BRIGHTNESS),
-                    false, mSettingsObserver, UserHandle.USER_ALL);
-            resolver.registerContentObserver(Settings.System.getUriFor(
-                    Settings.System.SCREEN_BRIGHTNESS_FOR_VR),
-                    false, mSettingsObserver, UserHandle.USER_ALL);
-            resolver.registerContentObserver(Settings.System.getUriFor(
-                    Settings.System.SCREEN_BRIGHTNESS_MODE),
-                    false, mSettingsObserver, UserHandle.USER_ALL);
-            resolver.registerContentObserver(Settings.System.getUriFor(
-                    Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ),
-                    false, mSettingsObserver, UserHandle.USER_ALL);
-            resolver.registerContentObserver(Settings.Global.getUriFor(
-                    Settings.Global.LOW_POWER_MODE),
-                    false, mSettingsObserver, UserHandle.USER_ALL);
-            resolver.registerContentObserver(Settings.Global.getUriFor(
-                    Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL),
-                    false, mSettingsObserver, UserHandle.USER_ALL);
-            resolver.registerContentObserver(Settings.Global.getUriFor(
-                    Settings.Global.THEATER_MODE_ON),
-                    false, mSettingsObserver, UserHandle.USER_ALL);
-            resolver.registerContentObserver(Settings.Secure.getUriFor(
-                    Settings.Secure.DOUBLE_TAP_TO_WAKE),
-                    false, mSettingsObserver, UserHandle.USER_ALL);
-            IVrManager vrManager = (IVrManager) getBinderService(Context.VR_SERVICE);
-            if (vrManager != null) {
-                try {
-                    vrManager.registerListener(mVrStateCallbacks);
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Failed to register VR mode state listener: " + e);
-                }
-            }
             // Go.
             readConfigurationLocked();
             updateSettingsLocked();
@@ -747,6 +721,62 @@
             updatePowerStateLocked();
         }
 
+        final ContentResolver resolver = mContext.getContentResolver();
+        mConstants.start(resolver);
+        mBatterySaverPolicy.start(resolver);
+
+        // Register for settings changes.
+        resolver.registerContentObserver(Settings.Secure.getUriFor(
+                Settings.Secure.SCREENSAVER_ENABLED),
+                false, mSettingsObserver, UserHandle.USER_ALL);
+        resolver.registerContentObserver(Settings.Secure.getUriFor(
+                Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP),
+                false, mSettingsObserver, UserHandle.USER_ALL);
+        resolver.registerContentObserver(Settings.Secure.getUriFor(
+                Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK),
+                false, mSettingsObserver, UserHandle.USER_ALL);
+        resolver.registerContentObserver(Settings.System.getUriFor(
+                Settings.System.SCREEN_OFF_TIMEOUT),
+                false, mSettingsObserver, UserHandle.USER_ALL);
+        resolver.registerContentObserver(Settings.Secure.getUriFor(
+                Settings.Secure.SLEEP_TIMEOUT),
+                false, mSettingsObserver, UserHandle.USER_ALL);
+        resolver.registerContentObserver(Settings.Global.getUriFor(
+                Settings.Global.STAY_ON_WHILE_PLUGGED_IN),
+                false, mSettingsObserver, UserHandle.USER_ALL);
+        resolver.registerContentObserver(Settings.System.getUriFor(
+                Settings.System.SCREEN_BRIGHTNESS),
+                false, mSettingsObserver, UserHandle.USER_ALL);
+        resolver.registerContentObserver(Settings.System.getUriFor(
+                Settings.System.SCREEN_BRIGHTNESS_FOR_VR),
+                false, mSettingsObserver, UserHandle.USER_ALL);
+        resolver.registerContentObserver(Settings.System.getUriFor(
+                Settings.System.SCREEN_BRIGHTNESS_MODE),
+                false, mSettingsObserver, UserHandle.USER_ALL);
+        resolver.registerContentObserver(Settings.System.getUriFor(
+                Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ),
+                false, mSettingsObserver, UserHandle.USER_ALL);
+        resolver.registerContentObserver(Settings.Global.getUriFor(
+                Settings.Global.LOW_POWER_MODE),
+                false, mSettingsObserver, UserHandle.USER_ALL);
+        resolver.registerContentObserver(Settings.Global.getUriFor(
+                Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL),
+                false, mSettingsObserver, UserHandle.USER_ALL);
+        resolver.registerContentObserver(Settings.Global.getUriFor(
+                Settings.Global.THEATER_MODE_ON),
+                false, mSettingsObserver, UserHandle.USER_ALL);
+        resolver.registerContentObserver(Settings.Secure.getUriFor(
+                Settings.Secure.DOUBLE_TAP_TO_WAKE),
+                false, mSettingsObserver, UserHandle.USER_ALL);
+        IVrManager vrManager = (IVrManager) getBinderService(Context.VR_SERVICE);
+        if (vrManager != null) {
+            try {
+                vrManager.registerListener(mVrStateCallbacks);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Failed to register VR mode state listener: " + e);
+            }
+        }
+
         // Register for broadcasts from other components of the system.
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_BATTERY_CHANGED);
@@ -929,8 +959,12 @@
                         listeners = new ArrayList<PowerManagerInternal.LowPowerModeListener>(
                                 mLowPowerModeListeners);
                     }
-                    for (int i=0; i<listeners.size(); i++) {
-                        listeners.get(i).onLowPowerModeChanged(lowPowerModeEnabled);
+                    for (int i = 0; i < listeners.size(); i++) {
+                        final PowerManagerInternal.LowPowerModeListener listener = listeners.get(i);
+                        final PowerSaveState result =
+                                mBatterySaverPolicy.getBatterySaverPolicy(
+                                        listener.getServiceType(), lowPowerModeEnabled);
+                        listener.onLowPowerModeChanged(result);
                     }
                     intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
                     intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
@@ -2242,9 +2276,10 @@
             mDisplayPowerRequest.brightnessSetByUser = brightnessSetByUser;
             mDisplayPowerRequest.useAutoBrightness = autoBrightness;
             mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();
-            mDisplayPowerRequest.lowPowerMode = mLowPowerModeEnabled;
             mDisplayPowerRequest.boostScreenBrightness = shouldBoostScreenBrightness();
 
+            updatePowerRequestFromBatterySaverPolicy(mDisplayPowerRequest);
+
             if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {
                 mDisplayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager;
                 if (mDisplayPowerRequest.dozeScreenState == Display.STATE_DOZE_SUSPEND
@@ -2661,6 +2696,14 @@
         }
     }
 
+    @VisibleForTesting
+    void updatePowerRequestFromBatterySaverPolicy(DisplayPowerRequest displayPowerRequest) {
+        PowerSaveState state = mBatterySaverPolicy.
+                getBatterySaverPolicy(ServiceType.SCREEN_BRIGHTNESS, mLowPowerModeEnabled);
+        displayPowerRequest.lowPowerMode = state.batterySaverEnabled;
+        displayPowerRequest.screenLowPowerBrightnessFactor = state.brightnessFactor;
+    }
+
     void setStayOnSettingInternal(int val) {
         Settings.Global.putInt(mContext.getContentResolver(),
                 Settings.Global.STAY_ON_WHILE_PLUGGED_IN, val);
@@ -3235,6 +3278,8 @@
             pw.println();
             pw.println("Display Power: " + mDisplayPowerCallbacks);
 
+            mBatterySaverPolicy.dump(pw);
+
             wcd = mWirelessChargerDetector;
         }
 
@@ -3243,6 +3288,354 @@
         }
     }
 
+    private void dumpProto(FileDescriptor fd) {
+        final WirelessChargerDetector wcd;
+        final ProtoOutputStream proto = new ProtoOutputStream(fd);
+
+        synchronized (mLock) {
+            mConstants.dumpProto(proto);
+            proto.write(PowerServiceDumpProto.DIRTY, mDirty);
+            proto.write(PowerServiceDumpProto.WAKEFULNESS, mWakefulness);
+            proto.write(PowerServiceDumpProto.IS_WAKEFULNESS_CHANGING, mWakefulnessChanging);
+            proto.write(PowerServiceDumpProto.IS_POWERED, mIsPowered);
+            proto.write(PowerServiceDumpProto.PLUG_TYPE, mPlugType);
+            proto.write(PowerServiceDumpProto.BATTERY_LEVEL, mBatteryLevel);
+            proto.write(
+                    PowerServiceDumpProto.BATTERY_LEVEL_WHEN_DREAM_STARTED,
+                    mBatteryLevelWhenDreamStarted);
+            proto.write(PowerServiceDumpProto.DOCK_STATE, mDockState);
+            proto.write(PowerServiceDumpProto.IS_STAY_ON, mStayOn);
+            proto.write(PowerServiceDumpProto.IS_PROXIMITY_POSITIVE, mProximityPositive);
+            proto.write(PowerServiceDumpProto.IS_BOOT_COMPLETED, mBootCompleted);
+            proto.write(PowerServiceDumpProto.IS_SYSTEM_READY, mSystemReady);
+            proto.write(
+                    PowerServiceDumpProto.IS_HAL_AUTO_SUSPEND_MODE_ENABLED,
+                    mHalAutoSuspendModeEnabled);
+            proto.write(
+                    PowerServiceDumpProto.IS_HAL_AUTO_INTERACTIVE_MODE_ENABLED,
+                    mHalInteractiveModeEnabled);
+
+            final long activeWakeLocksToken = proto.start(PowerServiceDumpProto.ACTIVE_WAKE_LOCKS);
+            proto.write(
+                    PowerServiceDumpProto.ActiveWakeLocksProto.IS_CPU,
+                    (mWakeLockSummary & WAKE_LOCK_CPU) != 0);
+            proto.write(
+                    PowerServiceDumpProto.ActiveWakeLocksProto.IS_SCREEN_BRIGHT,
+                    (mWakeLockSummary & WAKE_LOCK_SCREEN_BRIGHT) != 0);
+            proto.write(
+                    PowerServiceDumpProto.ActiveWakeLocksProto.IS_SCREEN_DIM,
+                    (mWakeLockSummary & WAKE_LOCK_SCREEN_DIM) != 0);
+            proto.write(
+                    PowerServiceDumpProto.ActiveWakeLocksProto.IS_BUTTON_BRIGHT,
+                    (mWakeLockSummary & WAKE_LOCK_BUTTON_BRIGHT) != 0);
+            proto.write(
+                    PowerServiceDumpProto.ActiveWakeLocksProto.IS_PROXIMITY_SCREEN_OFF,
+                    (mWakeLockSummary & WAKE_LOCK_PROXIMITY_SCREEN_OFF) != 0);
+            proto.write(
+                    PowerServiceDumpProto.ActiveWakeLocksProto.IS_STAY_AWAKE,
+                    (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) != 0);
+            proto.write(
+                    PowerServiceDumpProto.ActiveWakeLocksProto.IS_DOZE,
+                    (mWakeLockSummary & WAKE_LOCK_DOZE) != 0);
+            proto.write(
+                    PowerServiceDumpProto.ActiveWakeLocksProto.IS_DRAW,
+                    (mWakeLockSummary & WAKE_LOCK_DRAW) != 0);
+            proto.end(activeWakeLocksToken);
+
+            proto.write(PowerServiceDumpProto.NOTIFY_LONG_SCHEDULED_MS, mNotifyLongScheduled);
+            proto.write(PowerServiceDumpProto.NOTIFY_LONG_DISPATCHED_MS, mNotifyLongDispatched);
+            proto.write(PowerServiceDumpProto.NOTIFY_LONG_NEXT_CHECK_MS, mNotifyLongNextCheck);
+
+            final long userActivityToken = proto.start(PowerServiceDumpProto.USER_ACTIVITY);
+            proto.write(
+                    PowerServiceDumpProto.UserActivityProto.IS_SCREEN_BRIGHT,
+                    (mUserActivitySummary & USER_ACTIVITY_SCREEN_BRIGHT) != 0);
+            proto.write(
+                    PowerServiceDumpProto.UserActivityProto.IS_SCREEN_DIM,
+                    (mUserActivitySummary & USER_ACTIVITY_SCREEN_DIM) != 0);
+            proto.write(
+                    PowerServiceDumpProto.UserActivityProto.IS_SCREEN_DREAM,
+                    (mUserActivitySummary & USER_ACTIVITY_SCREEN_DREAM) != 0);
+            proto.end(userActivityToken);
+
+            proto.write(
+                    PowerServiceDumpProto.IS_REQUEST_WAIT_FOR_NEGATIVE_PROXIMITY,
+                    mRequestWaitForNegativeProximity);
+            proto.write(PowerServiceDumpProto.IS_SANDMAN_SCHEDULED, mSandmanScheduled);
+            proto.write(PowerServiceDumpProto.IS_SANDMAN_SUMMONED, mSandmanSummoned);
+            proto.write(PowerServiceDumpProto.IS_LOW_POWER_MODE_ENABLED, mLowPowerModeEnabled);
+            proto.write(PowerServiceDumpProto.IS_BATTERY_LEVEL_LOW, mBatteryLevelLow);
+            proto.write(PowerServiceDumpProto.IS_LIGHT_DEVICE_IDLE_MODE, mLightDeviceIdleMode);
+            proto.write(PowerServiceDumpProto.IS_DEVICE_IDLE_MODE, mDeviceIdleMode);
+
+            for (int id : mDeviceIdleWhitelist) {
+                proto.write(PowerServiceDumpProto.DEVICE_IDLE_WHITELIST, id);
+            }
+            for (int id : mDeviceIdleTempWhitelist) {
+                proto.write(PowerServiceDumpProto.DEVICE_IDLE_TEMP_WHITELIST, id);
+            }
+
+            proto.write(PowerServiceDumpProto.LAST_WAKE_TIME_MS, mLastWakeTime);
+            proto.write(PowerServiceDumpProto.LAST_SLEEP_TIME_MS, mLastSleepTime);
+            proto.write(PowerServiceDumpProto.LAST_USER_ACTIVITY_TIME_MS, mLastUserActivityTime);
+            proto.write(
+                    PowerServiceDumpProto.LAST_USER_ACTIVITY_TIME_NO_CHANGE_LIGHTS_MS,
+                    mLastUserActivityTimeNoChangeLights);
+            proto.write(
+                    PowerServiceDumpProto.LAST_INTERACTIVE_POWER_HINT_TIME_MS,
+                    mLastInteractivePowerHintTime);
+            proto.write(
+                    PowerServiceDumpProto.LAST_SCREEN_BRIGHTNESS_BOOST_TIME_MS,
+                    mLastScreenBrightnessBoostTime);
+            proto.write(
+                    PowerServiceDumpProto.IS_SCREEN_BRIGHTNESS_BOOST_IN_PROGRESS,
+                    mScreenBrightnessBoostInProgress);
+            proto.write(PowerServiceDumpProto.IS_DISPLAY_READY, mDisplayReady);
+            proto.write(
+                    PowerServiceDumpProto.IS_HOLDING_WAKE_LOCK_SUSPEND_BLOCKER,
+                    mHoldingWakeLockSuspendBlocker);
+            proto.write(
+                    PowerServiceDumpProto.IS_HOLDING_DISPLAY_SUSPEND_BLOCKER,
+                    mHoldingDisplaySuspendBlocker);
+
+            final long settingsAndConfigurationToken =
+                    proto.start(PowerServiceDumpProto.SETTINGS_AND_CONFIGURATION);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto
+                            .IS_DECOUPLE_HAL_AUTO_SUSPEND_MODE_FROM_DISPLAY_CONFIG,
+                    mDecoupleHalAutoSuspendModeFromDisplayConfig);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto
+                            .IS_DECOUPLE_HAL_INTERACTIVE_MODE_FROM_DISPLAY_CONFIG,
+                    mDecoupleHalInteractiveModeFromDisplayConfig);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto
+                            .IS_WAKE_UP_WHEN_PLUGGED_OR_UNPLUGGED_CONFIG,
+                    mWakeUpWhenPluggedOrUnpluggedConfig);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto
+                            .IS_WAKE_UP_WHEN_PLUGGED_OR_UNPLUGGED_IN_THEATER_MODE_CONFIG,
+                    mWakeUpWhenPluggedOrUnpluggedInTheaterModeConfig);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto.IS_THEATER_MODE_ENABLED,
+                    mTheaterModeEnabled);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto
+                            .IS_SUSPEND_WHEN_SCREEN_OFF_DUE_TO_PROXIMITY_CONFIG,
+                    mSuspendWhenScreenOffDueToProximityConfig);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto.ARE_DREAMS_SUPPORTED_CONFIG,
+                    mDreamsSupportedConfig);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto
+                            .ARE_DREAMS_ENABLED_BY_DEFAULT_CONFIG,
+                    mDreamsEnabledByDefaultConfig);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto
+                            .ARE_DREAMS_ACTIVATED_ON_SLEEP_BY_DEFAULT_CONFIG,
+                    mDreamsActivatedOnSleepByDefaultConfig);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto
+                            .ARE_DREAMS_ACTIVATED_ON_DOCK_BY_DEFAULT_CONFIG,
+                    mDreamsActivatedOnDockByDefaultConfig);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto
+                            .ARE_DREAMS_ENABLED_ON_BATTERY_CONFIG,
+                    mDreamsEnabledOnBatteryConfig);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto
+                            .DREAMS_BATTERY_LEVEL_MINIMUM_WHEN_POWERED_CONFIG,
+                    mDreamsBatteryLevelMinimumWhenPoweredConfig);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto
+                            .DREAMS_BATTERY_LEVEL_MINIMUM_WHEN_NOT_POWERED_CONFIG,
+                    mDreamsBatteryLevelMinimumWhenNotPoweredConfig);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto
+                            .DREAMS_BATTERY_LEVEL_DRAIN_CUTOFF_CONFIG,
+                    mDreamsBatteryLevelDrainCutoffConfig);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto.ARE_DREAMS_ENABLED_SETTING,
+                    mDreamsEnabledSetting);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto
+                            .ARE_DREAMS_ACTIVATE_ON_SLEEP_SETTING,
+                    mDreamsActivateOnSleepSetting);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto
+                            .ARE_DREAMS_ACTIVATE_ON_DOCK_SETTING,
+                    mDreamsActivateOnDockSetting);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto.IS_DOZE_AFTER_SCREEN_OFF_CONFIG,
+                    mDozeAfterScreenOffConfig);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto.IS_LOW_POWER_MODE_SETTING,
+                    mLowPowerModeSetting);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto.IS_AUTO_LOW_POWER_MODE_CONFIGURED,
+                    mAutoLowPowerModeConfigured);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto.IS_AUTO_LOW_POWER_MODE_SNOOZING,
+                    mAutoLowPowerModeSnoozing);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto
+                            .MINIMUM_SCREEN_OFF_TIMEOUT_CONFIG_MS,
+                    mMinimumScreenOffTimeoutConfig);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto
+                            .MAXIMUM_SCREEN_DIM_DURATION_CONFIG_MS,
+                    mMaximumScreenDimDurationConfig);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto.MAXIMUM_SCREEN_DIM_RATIO_CONFIG,
+                    mMaximumScreenDimRatioConfig);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto.SCREEN_OFF_TIMEOUT_SETTING_MS,
+                    mScreenOffTimeoutSetting);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto.SLEEP_TIMEOUT_SETTING_MS,
+                    mSleepTimeoutSetting);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto
+                            .MAXIMUM_SCREEN_OFF_TIMEOUT_FROM_DEVICE_ADMIN_MS,
+                    mMaximumScreenOffTimeoutFromDeviceAdmin);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto
+                            .IS_MAXIMUM_SCREEN_OFF_TIMEOUT_FROM_DEVICE_ADMIN_ENFORCED_LOCKED,
+                    isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked());
+
+            final long stayOnWhilePluggedInToken =
+                    proto.start(
+                            PowerServiceSettingsAndConfigurationDumpProto.STAY_ON_WHILE_PLUGGED_IN);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto.StayOnWhilePluggedInProto
+                            .IS_STAY_ON_WHILE_PLUGGED_IN_AC,
+                    ((mStayOnWhilePluggedInSetting & BatteryManager.BATTERY_PLUGGED_AC) != 0));
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto.StayOnWhilePluggedInProto
+                            .IS_STAY_ON_WHILE_PLUGGED_IN_USB,
+                    ((mStayOnWhilePluggedInSetting & BatteryManager.BATTERY_PLUGGED_USB) != 0));
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto.StayOnWhilePluggedInProto
+                            .IS_STAY_ON_WHILE_PLUGGED_IN_WIRELESS,
+                    ((mStayOnWhilePluggedInSetting & BatteryManager.BATTERY_PLUGGED_WIRELESS)
+                            != 0));
+            proto.end(stayOnWhilePluggedInToken);
+
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto.SCREEN_BRIGHTNESS_SETTING,
+                    mScreenBrightnessSetting);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto
+                            .SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT_SETTING,
+                    mScreenAutoBrightnessAdjustmentSetting);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto.SCREEN_BRIGHTNESS_MODE_SETTING,
+                    mScreenBrightnessModeSetting);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto
+                            .SCREEN_BRIGHTNESS_OVERRIDE_FROM_WINDOW_MANAGER,
+                    mScreenBrightnessOverrideFromWindowManager);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto
+                            .USER_ACTIVITY_TIMEOUT_OVERRIDE_FROM_WINDOW_MANAGER_MS,
+                    mUserActivityTimeoutOverrideFromWindowManager);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto
+                            .IS_USER_INACTIVE_OVERRIDE_FROM_WINDOW_MANAGER,
+                    mUserInactiveOverrideFromWindowManager);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto
+                            .TEMPORARY_SCREEN_BRIGHTNESS_SETTING_OVERRIDE,
+                    mTemporaryScreenBrightnessSettingOverride);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto
+                            .TEMPORARY_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT_SETTING_OVERRIDE,
+                    mTemporaryScreenAutoBrightnessAdjustmentSettingOverride);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto
+                            .DOZE_SCREEN_STATE_OVERRIDE_FROM_DREAM_MANAGER,
+                    mDozeScreenStateOverrideFromDreamManager);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto
+                            .DOZED_SCREEN_BRIGHTNESS_OVERRIDE_FROM_DREAM_MANAGER,
+                    mDozeScreenBrightnessOverrideFromDreamManager);
+
+            final long screenBrightnessSettingLimitsToken =
+                    proto.start(
+                            PowerServiceSettingsAndConfigurationDumpProto
+                                    .SCREEN_BRIGHTNESS_SETTING_LIMITS);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto.ScreenBrightnessSettingLimitsProto
+                            .SETTING_MINIMUM,
+                    mScreenBrightnessSettingMinimum);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto.ScreenBrightnessSettingLimitsProto
+                            .SETTING_MAXIMUM,
+                    mScreenBrightnessSettingMaximum);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto.ScreenBrightnessSettingLimitsProto
+                            .SETTING_DEFAULT,
+                    mScreenBrightnessSettingDefault);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto.ScreenBrightnessSettingLimitsProto
+                            .SETTING_FOR_VR_DEFAULT,
+                    mScreenBrightnessForVrSettingDefault);
+            proto.end(screenBrightnessSettingLimitsToken);
+
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto.SCREEN_BRIGHTNESS_FOR_VR_SETTING,
+                    mScreenBrightnessForVrSetting);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto.IS_DOUBLE_TAP_WAKE_ENABLED,
+                    mDoubleTapWakeEnabled);
+            proto.write(
+                    PowerServiceSettingsAndConfigurationDumpProto.IS_VR_MODE_ENABLED,
+                    mIsVrModeEnabled);
+            proto.end(settingsAndConfigurationToken);
+
+            final int sleepTimeout = getSleepTimeoutLocked();
+            final int screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout);
+            final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);
+            proto.write(PowerServiceDumpProto.SLEEP_TIMEOUT_MS, sleepTimeout);
+            proto.write(PowerServiceDumpProto.SCREEN_OFF_TIMEOUT_MS, screenOffTimeout);
+            proto.write(PowerServiceDumpProto.SCREEN_DIM_DURATION_MS, screenDimDuration);
+            proto.write(PowerServiceDumpProto.ARE_UIDS_CHANGING, mUidsChanging);
+            proto.write(PowerServiceDumpProto.ARE_UIDS_CHANGED, mUidsChanged);
+
+            for (int i = 0; i < mUidState.size(); i++) {
+                final UidState state = mUidState.valueAt(i);
+                final long uIDToken = proto.start(PowerServiceDumpProto.UIDS);
+                final int uid = mUidState.keyAt(i);
+                proto.write(PowerServiceDumpProto.UidProto.UID, uid);
+                proto.write(PowerServiceDumpProto.UidProto.UID_STRING, UserHandle.formatUid(uid));
+                proto.write(PowerServiceDumpProto.UidProto.IS_ACTIVE, state.mActive);
+                proto.write(PowerServiceDumpProto.UidProto.NUM_WAKE_LOCKS, state.mNumWakeLocks);
+                if (state.mProcState == ActivityManager.PROCESS_STATE_UNKNOWN) {
+                    proto.write(PowerServiceDumpProto.UidProto.IS_PROCESS_STATE_UNKNOWN, true);
+                } else {
+                    proto.write(PowerServiceDumpProto.UidProto.PROCESS_STATE, state.mProcState);
+                }
+                proto.end(uIDToken);
+            }
+
+            mHandler.getLooper().writeToProto(proto, PowerServiceDumpProto.LOOPER);
+
+            for (WakeLock wl : mWakeLocks) {
+                wl.writeToProto(proto, PowerServiceDumpProto.WAKE_LOCKS);
+            }
+
+            for (SuspendBlocker sb : mSuspendBlockers) {
+                sb.writeToProto(proto, PowerServiceDumpProto.SUSPEND_BLOCKERS);
+            }
+            wcd = mWirelessChargerDetector;
+        }
+
+        if (wcd != null) {
+            wcd.writeToProto(proto, PowerServiceDumpProto.WIRELESS_CHARGER_DETECTOR);
+        }
+        proto.flush();
+    }
+
     private SuspendBlocker createSuspendBlockerLocked(String name) {
         SuspendBlocker suspendBlocker = new SuspendBlockerImpl(name);
         mSuspendBlockers.add(suspendBlocker);
@@ -3470,6 +3863,32 @@
             return sb.toString();
         }
 
+        public void writeToProto(ProtoOutputStream proto, long fieldId) {
+            final long wakeLockToken = proto.start(fieldId);
+            proto.write(WakeLockProto.LOCK_LEVEL, (mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK));
+            proto.write(WakeLockProto.TAG, mTag);
+
+            final long wakeLockFlagsToken = proto.start(WakeLockProto.FLAGS);
+            proto.write(WakeLockProto.WakeLockFlagsProto.IS_ACQUIRE_CAUSES_WAKEUP,
+                    (mFlags & PowerManager.ACQUIRE_CAUSES_WAKEUP)!=0);
+            proto.write(WakeLockProto.WakeLockFlagsProto.IS_ON_AFTER_RELEASE,
+                    (mFlags & PowerManager.ON_AFTER_RELEASE)!=0);
+            proto.end(wakeLockFlagsToken);
+
+            proto.write(WakeLockProto.IS_DISABLED, mDisabled);
+            if (mNotifiedAcquired) {
+                proto.write(WakeLockProto.ACQ_MS, mAcquireTime);
+            }
+            proto.write(WakeLockProto.IS_NOTIFIED_LONG, mNotifiedLong);
+            proto.write(WakeLockProto.UID, mOwnerUid);
+            proto.write(WakeLockProto.PID, mOwnerPid);
+
+            if (mWorkSource != null) {
+                mWorkSource.writeToProto(proto, WakeLockProto.WORK_SOURCE);
+            }
+            proto.end(wakeLockToken);
+        }
+
         @SuppressWarnings("deprecation")
         private String getLockLevelString() {
             switch (mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
@@ -3567,6 +3986,15 @@
                 return mName + ": ref count=" + mReferenceCount;
             }
         }
+
+        public void writeToProto(ProtoOutputStream proto, long fieldId) {
+            final long sbToken = proto.start(fieldId);
+            synchronized (this) {
+                proto.write(SuspendBlockerProto.NAME, mName);
+                proto.write(SuspendBlockerProto.REFERENCE_COUNT, mReferenceCount);
+            }
+            proto.end(sbToken);
+        }
     }
 
     static final class UidState {
@@ -3808,6 +4236,19 @@
             }
         }
 
+        // Binder call
+        public PowerSaveState getPowerSaveState(@ServiceType int serviceType) {
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    return mBatterySaverPolicy.getBatterySaverPolicy(
+                            serviceType, isLowPowerModeInternal());
+                }
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
         @Override // Binder call
         public boolean setPowerSaveMode(boolean mode) {
             mContext.enforceCallingOrSelfPermission(
@@ -4054,8 +4495,19 @@
             }
 
             final long ident = Binder.clearCallingIdentity();
+
+            boolean isDumpProto = false;
+            for (String arg : args) {
+                if (arg.equals("--proto")) {
+                    isDumpProto = true;
+                }
+            }
             try {
-                dumpInternal(pw);
+                if (isDumpProto) {
+                    dumpProto(fd);
+                } else {
+                    dumpInternal(pw);
+                }
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -4115,9 +4567,9 @@
         }
 
         @Override
-        public boolean getLowPowerModeEnabled() {
+        public PowerSaveState getLowPowerState(@ServiceType int serviceType) {
             synchronized (mLock) {
-                return mLowPowerModeEnabled;
+                return mBatterySaverPolicy.getBatterySaverPolicy(serviceType, mLowPowerModeEnabled);
             }
         }
 
diff --git a/services/core/java/com/android/server/power/SuspendBlocker.java b/services/core/java/com/android/server/power/SuspendBlocker.java
index 70b278a..30b35f0 100644
--- a/services/core/java/com/android/server/power/SuspendBlocker.java
+++ b/services/core/java/com/android/server/power/SuspendBlocker.java
@@ -16,6 +16,8 @@
 
 package com.android.server.power;
 
+import android.util.proto.ProtoOutputStream;
+
 /**
  * Low-level suspend blocker mechanism equivalent to holding a partial wake lock.
  *
@@ -40,4 +42,6 @@
      * The system may crash.
      */
     void release();
+
+    void writeToProto(ProtoOutputStream proto, long fieldId);
 }
diff --git a/services/core/java/com/android/server/power/WirelessChargerDetector.java b/services/core/java/com/android/server/power/WirelessChargerDetector.java
index 38f5d77..6ee9dcd 100644
--- a/services/core/java/com/android/server/power/WirelessChargerDetector.java
+++ b/services/core/java/com/android/server/power/WirelessChargerDetector.java
@@ -24,8 +24,10 @@
 import android.os.Handler;
 import android.os.Message;
 import android.os.SystemClock;
+import android.service.power.WirelessChargerDetectorProto;
 import android.util.Slog;
 import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
 
 import java.io.PrintWriter;
 
@@ -170,6 +172,44 @@
         }
     }
 
+    public void writeToProto(ProtoOutputStream proto, long fieldId) {
+        final long wcdToken = proto.start(fieldId);
+        synchronized (mLock) {
+            proto.write(WirelessChargerDetectorProto.IS_POWERED_WIRELESSLY, mPoweredWirelessly);
+            proto.write(WirelessChargerDetectorProto.IS_AT_REST, mAtRest);
+
+            final long restVectorToken = proto.start(WirelessChargerDetectorProto.REST);
+            proto.write(WirelessChargerDetectorProto.VectorProto.X, mRestX);
+            proto.write(WirelessChargerDetectorProto.VectorProto.Y, mRestY);
+            proto.write(WirelessChargerDetectorProto.VectorProto.Z, mRestZ);
+            proto.end(restVectorToken);
+
+            proto.write(
+                    WirelessChargerDetectorProto.IS_DETECTION_IN_PROGRESS, mDetectionInProgress);
+            proto.write(WirelessChargerDetectorProto.DETECTION_START_TIME_MS, mDetectionStartTime);
+            proto.write(
+                    WirelessChargerDetectorProto.IS_MUST_UPDATE_REST_POSITION,
+                    mMustUpdateRestPosition);
+            proto.write(WirelessChargerDetectorProto.TOTAL_SAMPLES, mTotalSamples);
+            proto.write(WirelessChargerDetectorProto.MOVING_SAMPLES, mMovingSamples);
+
+            final long firstSampleVectorToken =
+                    proto.start(WirelessChargerDetectorProto.FIRST_SAMPLE);
+            proto.write(WirelessChargerDetectorProto.VectorProto.X, mFirstSampleX);
+            proto.write(WirelessChargerDetectorProto.VectorProto.Y, mFirstSampleY);
+            proto.write(WirelessChargerDetectorProto.VectorProto.Z, mFirstSampleZ);
+            proto.end(firstSampleVectorToken);
+
+            final long lastSampleVectorToken =
+                    proto.start(WirelessChargerDetectorProto.LAST_SAMPLE);
+            proto.write(WirelessChargerDetectorProto.VectorProto.X, mLastSampleX);
+            proto.write(WirelessChargerDetectorProto.VectorProto.Y, mLastSampleY);
+            proto.write(WirelessChargerDetectorProto.VectorProto.Z, mLastSampleZ);
+            proto.end(lastSampleVectorToken);
+        }
+        proto.end(wcdToken);
+    }
+
     /**
      * Updates the charging state and returns true if docking was detected.
      *
diff --git a/services/core/java/com/android/server/storage/AppCollector.java b/services/core/java/com/android/server/storage/AppCollector.java
index cf05e9f..25880fb 100644
--- a/services/core/java/com/android/server/storage/AppCollector.java
+++ b/services/core/java/com/android/server/storage/AppCollector.java
@@ -16,6 +16,9 @@
 
 package com.android.server.storage;
 
+import android.annotation.NonNull;
+import android.app.usage.StorageStats;
+import android.app.usage.StorageStatsManager;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageStatsObserver;
@@ -32,6 +35,7 @@
 import android.os.storage.VolumeInfo;
 import android.util.Log;
 import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.Preconditions;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -56,11 +60,14 @@
      * @param context Android context used to get
      * @param volume Volume to check for apps.
      */
-    public AppCollector(Context context, VolumeInfo volume) {
+    public AppCollector(Context context, @NonNull VolumeInfo volume) {
+        Preconditions.checkNotNull(volume);
+
         mBackgroundHandler = new BackgroundHandler(BackgroundThread.get().getLooper(),
                 volume,
                 context.getPackageManager(),
-                (UserManager) context.getSystemService(Context.USER_SERVICE));
+                (UserManager) context.getSystemService(Context.USER_SERVICE),
+                (StorageStatsManager) context.getSystemService(Context.STORAGE_STATS_SERVICE));
     }
 
     /**
@@ -89,39 +96,20 @@
         return value;
     }
 
-    private class StatsObserver extends IPackageStatsObserver.Stub {
-        private AtomicInteger mCount;
-        private final ArrayList<PackageStats> mPackageStats;
-
-        public StatsObserver(int count) {
-            mCount = new AtomicInteger(count);
-            mPackageStats = new ArrayList<>(count);
-        }
-
-        @Override
-        public void onGetStatsCompleted(PackageStats packageStats, boolean succeeded)
-                throws RemoteException {
-            if (succeeded) {
-                mPackageStats.add(packageStats);
-            }
-
-            if (mCount.decrementAndGet() == 0) {
-                mStats.complete(mPackageStats);
-            }
-        }
-    }
-
     private class BackgroundHandler extends Handler {
         static final int MSG_START_LOADING_SIZES = 0;
         private final VolumeInfo mVolume;
         private final PackageManager mPm;
         private final UserManager mUm;
+        private final StorageStatsManager mStorageStatsManager;
 
-        BackgroundHandler(Looper looper, VolumeInfo volume, PackageManager pm, UserManager um) {
+        BackgroundHandler(Looper looper, @NonNull VolumeInfo volume,
+                PackageManager pm, UserManager um, StorageStatsManager storageStatsManager) {
             super(looper);
             mVolume = volume;
             mPm = pm;
             mUm = um;
+            mStorageStatsManager = storageStatsManager;
         }
 
         @Override
@@ -145,14 +133,20 @@
                         mStats.complete(new ArrayList<>());
                     }
 
-                    // Kick off the async package size query for all apps.
-                    final StatsObserver observer = new StatsObserver(count);
+                    List<PackageStats> stats = new ArrayList<>();
                     for (UserInfo user : users) {
                         for (ApplicationInfo app : volumeApps) {
-                            mPm.getPackageSizeInfoAsUser(app.packageName, user.id,
-                                    observer);
+                            PackageStats packageStats = new PackageStats(app.packageName, user.id);
+                            StorageStats storageStats = mStorageStatsManager.queryStatsForPackage(
+                                    app.volumeUuid, app.packageName, user.getUserHandle());
+                            packageStats.cacheSize = storageStats.getCacheBytes();
+                            packageStats.codeSize = storageStats.getCodeBytes();
+                            packageStats.dataSize = storageStats.getDataBytes();
+                            stats.add(packageStats);
                         }
                     }
+
+                    mStats.complete(stats);
                 }
             }
         }
diff --git a/services/core/java/com/android/server/storage/CacheQuotaStrategy.java b/services/core/java/com/android/server/storage/CacheQuotaStrategy.java
new file mode 100644
index 0000000..c064392
--- /dev/null
+++ b/services/core/java/com/android/server/storage/CacheQuotaStrategy.java
@@ -0,0 +1,387 @@
+/*
+ * 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.storage;
+
+import android.annotation.MainThread;
+import android.app.usage.CacheQuotaHint;
+import android.app.usage.CacheQuotaService;
+import android.app.usage.ICacheQuotaService;
+import android.app.usage.UsageStats;
+import android.app.usage.UsageStatsManager;
+import android.app.usage.UsageStatsManagerInternal;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.content.pm.UserInfo;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Environment;
+import android.os.IBinder;
+import android.os.RemoteCallback;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.text.format.DateUtils;
+import android.util.Pair;
+import android.util.Slog;
+import android.util.Xml;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.AtomicFile;
+import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.Preconditions;
+import com.android.server.pm.Installer;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * CacheQuotaStrategy is a strategy for determining cache quotas using usage stats and foreground
+ * time using the calculation as defined in the refuel rocket.
+ */
+public class CacheQuotaStrategy implements RemoteCallback.OnResultListener {
+    private static final String TAG = "CacheQuotaStrategy";
+
+    private final Object mLock = new Object();
+
+    // XML Constants
+    private static final String CACHE_INFO_TAG = "cache-info";
+    private static final String ATTR_PREVIOUS_BYTES = "previousBytes";
+    private static final String TAG_QUOTA = "quota";
+    private static final String ATTR_UUID = "uuid";
+    private static final String ATTR_UID = "uid";
+    private static final String ATTR_QUOTA_IN_BYTES = "bytes";
+
+    private final Context mContext;
+    private final UsageStatsManagerInternal mUsageStats;
+    private final Installer mInstaller;
+    private ServiceConnection mServiceConnection;
+    private ICacheQuotaService mRemoteService;
+    private AtomicFile mPreviousValuesFile;
+
+    public CacheQuotaStrategy(
+            Context context, UsageStatsManagerInternal usageStatsManager, Installer installer) {
+        mContext = Preconditions.checkNotNull(context);
+        mUsageStats = Preconditions.checkNotNull(usageStatsManager);
+        mInstaller = Preconditions.checkNotNull(installer);
+        mPreviousValuesFile = new AtomicFile(new File(
+                new File(Environment.getDataDirectory(), "system"), "cachequota.xml"));
+    }
+
+    /**
+     * Recalculates the quotas and stores them to installd.
+     */
+    public void recalculateQuotas() {
+        createServiceConnection();
+
+        ComponentName component = getServiceComponentName();
+        if (component != null) {
+            Intent intent = new Intent();
+            intent.setComponent(component);
+            mContext.bindServiceAsUser(
+                    intent, mServiceConnection, Context.BIND_AUTO_CREATE, UserHandle.CURRENT);
+        }
+    }
+
+    private void createServiceConnection() {
+        // If we're already connected, don't create a new connection.
+        if (mServiceConnection != null) {
+            return;
+        }
+
+        mServiceConnection = new ServiceConnection() {
+            @Override
+            @MainThread
+            public void onServiceConnected(ComponentName name, IBinder service) {
+                Runnable runnable = new Runnable() {
+                    @Override
+                    public void run() {
+                        synchronized (mLock) {
+                            mRemoteService = ICacheQuotaService.Stub.asInterface(service);
+                            List<CacheQuotaHint> requests = getUnfulfilledRequests();
+                            final RemoteCallback remoteCallback =
+                                    new RemoteCallback(CacheQuotaStrategy.this);
+                            try {
+                                mRemoteService.computeCacheQuotaHints(remoteCallback, requests);
+                            } catch (RemoteException ex) {
+                                Slog.w(TAG,
+                                        "Remote exception occurred while trying to get cache quota",
+                                        ex);
+                            }
+                        }
+                    }
+                };
+                AsyncTask.execute(runnable);
+            }
+
+            @Override
+            @MainThread
+            public void onServiceDisconnected(ComponentName name) {
+                synchronized (mLock) {
+                    mRemoteService = null;
+                }
+            }
+        };
+    }
+
+    /**
+     * Returns a list of CacheQuotaHints which do not have their quotas filled out for apps
+     * which have been used in the last year.
+     */
+    private List<CacheQuotaHint> getUnfulfilledRequests() {
+        long timeNow = System.currentTimeMillis();
+        long oneYearAgo = timeNow - DateUtils.YEAR_IN_MILLIS;
+
+        List<CacheQuotaHint> requests = new ArrayList<>();
+        UserManager um = mContext.getSystemService(UserManager.class);
+        final List<UserInfo> users = um.getUsers();
+        final int userCount = users.size();
+        final PackageManager packageManager = mContext.getPackageManager();
+        for (int i = 0; i < userCount; i++) {
+            UserInfo info = users.get(i);
+            List<UsageStats> stats =
+                    mUsageStats.queryUsageStatsForUser(info.id, UsageStatsManager.INTERVAL_BEST,
+                            oneYearAgo, timeNow);
+            if (stats == null) {
+                continue;
+            }
+
+            for (UsageStats stat : stats) {
+                String packageName = stat.getPackageName();
+                try {
+                    // We need the app info to determine the uid and the uuid of the volume
+                    // where the app is installed.
+                    ApplicationInfo appInfo = packageManager.getApplicationInfo(packageName, 0);
+                    requests.add(
+                            new CacheQuotaHint.Builder()
+                                    .setVolumeUuid(appInfo.volumeUuid)
+                                    .setUid(appInfo.uid)
+                                    .setUsageStats(stat)
+                                    .setQuota(CacheQuotaHint.QUOTA_NOT_SET)
+                                    .build());
+                } catch (PackageManager.NameNotFoundException e) {
+                    Slog.w(TAG, "Unable to find package for quota calculation", e);
+                    continue;
+                }
+            }
+        }
+        return requests;
+    }
+
+    @Override
+    public void onResult(Bundle data) {
+        final List<CacheQuotaHint> processedRequests =
+                data.getParcelableArrayList(
+                        CacheQuotaService.REQUEST_LIST_KEY);
+        pushProcessedQuotas(processedRequests);
+        writeXmlToFile(processedRequests);
+    }
+
+    private void pushProcessedQuotas(List<CacheQuotaHint> processedRequests) {
+        final int requestSize = processedRequests.size();
+        for (int i = 0; i < requestSize; i++) {
+            CacheQuotaHint request = processedRequests.get(i);
+            long proposedQuota = request.getQuota();
+            if (proposedQuota == CacheQuotaHint.QUOTA_NOT_SET) {
+                continue;
+            }
+
+            try {
+                int uid = request.getUid();
+                mInstaller.setAppQuota(request.getVolumeUuid(),
+                        UserHandle.getUserId(uid),
+                        UserHandle.getAppId(uid), proposedQuota);
+            } catch (Installer.InstallerException ex) {
+                Slog.w(TAG,
+                        "Failed to set cache quota for " + request.getUid(),
+                        ex);
+            }
+        }
+
+        disconnectService();
+    }
+
+    private void disconnectService() {
+        if (mServiceConnection != null) {
+            mContext.unbindService(mServiceConnection);
+            mServiceConnection = null;
+        }
+    }
+
+    private ComponentName getServiceComponentName() {
+        String packageName =
+                mContext.getPackageManager().getServicesSystemSharedLibraryPackageName();
+        if (packageName == null) {
+            Slog.w(TAG, "could not access the cache quota service: no package!");
+            return null;
+        }
+
+        Intent intent = new Intent(CacheQuotaService.SERVICE_INTERFACE);
+        intent.setPackage(packageName);
+        ResolveInfo resolveInfo = mContext.getPackageManager().resolveService(intent,
+                PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
+        if (resolveInfo == null || resolveInfo.serviceInfo == null) {
+            Slog.w(TAG, "No valid components found.");
+            return null;
+        }
+        ServiceInfo serviceInfo = resolveInfo.serviceInfo;
+        return new ComponentName(serviceInfo.packageName, serviceInfo.name);
+    }
+
+    private void writeXmlToFile(List<CacheQuotaHint> processedRequests) {
+        FileOutputStream fileStream = null;
+        try {
+            XmlSerializer out = new FastXmlSerializer();
+            fileStream = mPreviousValuesFile.startWrite();
+            out.setOutput(fileStream, StandardCharsets.UTF_8.name());
+            saveToXml(out, processedRequests, 0);
+            mPreviousValuesFile.finishWrite(fileStream);
+        } catch (Exception e) {
+            Slog.e(TAG, "An error occurred while writing the cache quota file.", e);
+            mPreviousValuesFile.failWrite(fileStream);
+        }
+    }
+
+    /**
+     * Initializes the quotas from the file.
+     * @return the number of bytes that were free on the device when the quotas were last calced.
+     */
+    public long setupQuotasFromFile() throws IOException {
+        FileInputStream stream;
+        try {
+            stream = mPreviousValuesFile.openRead();
+        } catch (FileNotFoundException e) {
+            // The file may not exist yet -- this isn't truly exceptional.
+            return -1;
+        }
+
+        Pair<Long, List<CacheQuotaHint>> cachedValues = null;
+        try {
+            cachedValues = readFromXml(stream);
+        } catch (XmlPullParserException e) {
+            throw new IllegalStateException(e.getMessage());
+        }
+
+        if (cachedValues == null) {
+            Slog.e(TAG, "An error occurred while parsing the cache quota file.");
+            return -1;
+        }
+        pushProcessedQuotas(cachedValues.second);
+        return cachedValues.first;
+    }
+
+    @VisibleForTesting
+    static void saveToXml(XmlSerializer out,
+            List<CacheQuotaHint> requests, long bytesWhenCalculated) throws IOException {
+        out.startDocument(null, true);
+        out.startTag(null, CACHE_INFO_TAG);
+        int requestSize = requests.size();
+        out.attribute(null, ATTR_PREVIOUS_BYTES, Long.toString(bytesWhenCalculated));
+
+        for (int i = 0; i < requestSize; i++) {
+            CacheQuotaHint request = requests.get(i);
+            out.startTag(null, TAG_QUOTA);
+            String uuid = request.getVolumeUuid();
+            if (uuid != null) {
+                out.attribute(null, ATTR_UUID, request.getVolumeUuid());
+            }
+            out.attribute(null, ATTR_UID, Integer.toString(request.getUid()));
+            out.attribute(null, ATTR_QUOTA_IN_BYTES, Long.toString(request.getQuota()));
+            out.endTag(null, TAG_QUOTA);
+        }
+        out.endTag(null, CACHE_INFO_TAG);
+        out.endDocument();
+    }
+
+    protected static Pair<Long, List<CacheQuotaHint>> readFromXml(InputStream inputStream)
+            throws XmlPullParserException, IOException {
+        XmlPullParser parser = Xml.newPullParser();
+        parser.setInput(inputStream, StandardCharsets.UTF_8.name());
+
+        int eventType = parser.getEventType();
+        while (eventType != XmlPullParser.START_TAG &&
+                eventType != XmlPullParser.END_DOCUMENT) {
+            eventType = parser.next();
+        }
+
+        if (eventType == XmlPullParser.END_DOCUMENT) {
+            Slog.d(TAG, "No quotas found in quota file.");
+            return null;
+        }
+
+        String tagName = parser.getName();
+        if (!CACHE_INFO_TAG.equals(tagName)) {
+            throw new IllegalStateException("Invalid starting tag.");
+        }
+
+        final List<CacheQuotaHint> quotas = new ArrayList<>();
+        long previousBytes;
+        try {
+            previousBytes = Long.parseLong(parser.getAttributeValue(
+                    null, ATTR_PREVIOUS_BYTES));
+        } catch (NumberFormatException e) {
+            throw new IllegalStateException(
+                    "Previous bytes formatted incorrectly; aborting quota read.");
+        }
+
+        eventType = parser.next();
+        do {
+            if (eventType == XmlPullParser.START_TAG) {
+                tagName = parser.getName();
+                if (TAG_QUOTA.equals(tagName)) {
+                    CacheQuotaHint request = getRequestFromXml(parser);
+                    if (request == null) {
+                        continue;
+                    }
+                    quotas.add(request);
+                }
+            }
+            eventType = parser.next();
+        } while (eventType != XmlPullParser.END_DOCUMENT);
+        return new Pair<>(previousBytes, quotas);
+    }
+
+    @VisibleForTesting
+    static CacheQuotaHint getRequestFromXml(XmlPullParser parser) {
+        try {
+            String uuid = parser.getAttributeValue(null, ATTR_UUID);
+            int uid = Integer.parseInt(parser.getAttributeValue(null, ATTR_UID));
+            long bytes = Long.parseLong(parser.getAttributeValue(null, ATTR_QUOTA_IN_BYTES));
+            return new CacheQuotaHint.Builder()
+                    .setVolumeUuid(uuid).setUid(uid).setQuota(bytes).build();
+        } catch (NumberFormatException e) {
+            Slog.e(TAG, "Invalid cache quota request, skipping.");
+            return null;
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
index afdec9f..12836db 100644
--- a/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
+++ b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
@@ -17,6 +17,7 @@
 package com.android.server.storage;
 
 import android.app.NotificationChannel;
+import com.android.internal.notification.SystemNotificationChannels;
 import com.android.server.EventLogTags;
 import com.android.server.SystemService;
 import com.android.server.pm.InstructionSets;
@@ -141,7 +142,7 @@
      */
     static final String SERVICE = "devicestoragemonitor";
 
-    private static final String NOTIFICATION_CHANNEL_ID = SERVICE;
+    private static final String TV_NOTIFICATION_CHANNEL_ID = "devicestoragemonitor.tv";
 
     /**
     * Handler that checks the amount of disk space on the device and sends a
@@ -388,14 +389,13 @@
         PackageManager packageManager = context.getPackageManager();
         boolean isTv = packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK);
 
-        int importance = isTv
-            ? NotificationManager.IMPORTANCE_HIGH   // Do not change: this is TV-specific
-            : NotificationManager.IMPORTANCE_LOW;
-        notificationMgr.createNotificationChannel(
-            new NotificationChannel(NOTIFICATION_CHANNEL_ID,
-                context.getString(
-                    com.android.internal.R.string.device_storage_monitor_notification_channel),
-                importance));
+        if (isTv) {
+            notificationMgr.createNotificationChannel(new NotificationChannel(
+                    TV_NOTIFICATION_CHANNEL_ID,
+                    context.getString(
+                        com.android.internal.R.string.device_storage_monitor_notification_channel),
+                    NotificationManager.IMPORTANCE_HIGH));
+        }
 
         publishBinderService(SERVICE, mRemoteService);
         publishLocalService(DeviceStorageMonitorInternal.class, mLocalService);
@@ -495,21 +495,22 @@
                 : com.android.internal.R.string.low_internal_storage_view_text_no_boot);
         PendingIntent intent = PendingIntent.getActivityAsUser(context, 0,  lowMemIntent, 0,
                 null, UserHandle.CURRENT);
-        Notification notification = new Notification.Builder(context)
-                .setSmallIcon(com.android.internal.R.drawable.stat_notify_disk_full)
-                .setTicker(title)
-                .setColor(context.getColor(
-                    com.android.internal.R.color.system_notification_accent_color))
-                .setContentTitle(title)
-                .setContentText(details)
-                .setContentIntent(intent)
-                .setStyle(new Notification.BigTextStyle()
-                      .bigText(details))
-                .setVisibility(Notification.VISIBILITY_PUBLIC)
-                .setCategory(Notification.CATEGORY_SYSTEM)
-                .setChannel(NOTIFICATION_CHANNEL_ID)
-                .extend(new Notification.TvExtender())
-                .build();
+        Notification notification =
+                new Notification.Builder(context, SystemNotificationChannels.ALERTS)
+                        .setSmallIcon(com.android.internal.R.drawable.stat_notify_disk_full)
+                        .setTicker(title)
+                        .setColor(context.getColor(
+                            com.android.internal.R.color.system_notification_accent_color))
+                        .setContentTitle(title)
+                        .setContentText(details)
+                        .setContentIntent(intent)
+                        .setStyle(new Notification.BigTextStyle()
+                              .bigText(details))
+                        .setVisibility(Notification.VISIBILITY_PUBLIC)
+                        .setCategory(Notification.CATEGORY_SYSTEM)
+                        .extend(new Notification.TvExtender()
+                                .setChannel(TV_NOTIFICATION_CHANNEL_ID))
+                        .build();
         notification.flags |= Notification.FLAG_NO_CLEAR;
         notificationMgr.notifyAsUser(null, LOW_MEMORY_NOTIFICATION_ID, notification,
                 UserHandle.ALL);
diff --git a/services/core/java/com/android/server/storage/DiskStatsLoggingService.java b/services/core/java/com/android/server/storage/DiskStatsLoggingService.java
index 7c43162..4035ade 100644
--- a/services/core/java/com/android/server/storage/DiskStatsLoggingService.java
+++ b/services/core/java/com/android/server/storage/DiskStatsLoggingService.java
@@ -29,6 +29,7 @@
 import android.os.Environment;
 import android.os.Environment.UserEnvironment;
 import android.os.UserHandle;
+import android.os.storage.VolumeInfo;
 import android.provider.Settings;
 import android.util.Log;
 
@@ -61,10 +62,16 @@
             return false;
         }
 
+
+        VolumeInfo volume = getPackageManager().getPrimaryStorageCurrentVolume();
+        // volume is null if the primary storage is not yet mounted.
+        if (volume == null) {
+            return false;
+        }
+        AppCollector collector = new AppCollector(this, volume);
+
         final int userId = UserHandle.myUserId();
         UserEnvironment environment = new UserEnvironment(userId);
-        AppCollector collector = new AppCollector(this,
-                getPackageManager().getPrimaryStorageCurrentVolume());
         LogRunnable task = new LogRunnable();
         task.setRootDirectory(environment.getExternalStorageDirectory());
         task.setDownloadsDirectory(
diff --git a/services/core/java/com/android/server/trust/TrustAgentWrapper.java b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
index 6c1648c..1382894 100644
--- a/services/core/java/com/android/server/trust/TrustAgentWrapper.java
+++ b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
@@ -16,6 +16,7 @@
 
 package com.android.server.trust;
 
+import android.annotation.TargetApi;
 import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.app.admin.DevicePolicyManager;
@@ -27,6 +28,7 @@
 import android.content.ServiceConnection;
 import android.net.Uri;
 import android.os.Binder;
+import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
@@ -35,11 +37,11 @@
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.UserHandle;
-import android.util.Log;
-import android.util.Slog;
 import android.service.trust.ITrustAgentService;
 import android.service.trust.ITrustAgentServiceCallback;
-
+import android.service.trust.TrustAgentService;
+import android.util.Log;
+import android.util.Slog;
 import java.util.Collections;
 import java.util.List;
 
@@ -47,6 +49,7 @@
  * A wrapper around a TrustAgentService interface. Coordinates communication between
  * TrustManager and the actual TrustAgent.
  */
+@TargetApi(Build.VERSION_CODES.LOLLIPOP)
 public class TrustAgentWrapper {
     private static final String EXTRA_COMPONENT_NAME = "componentName";
     private static final String TRUST_EXPIRED_ACTION = "android.server.trust.TRUST_EXPIRED_ACTION";
@@ -60,6 +63,10 @@
     private static final int MSG_RESTART_TIMEOUT = 4;
     private static final int MSG_SET_TRUST_AGENT_FEATURES_COMPLETED = 5;
     private static final int MSG_MANAGING_TRUST = 6;
+    private static final int MSG_ADD_ESCROW_TOKEN = 7;
+    private static final int MSG_REMOVE_ESCROW_TOKEN = 8;
+    private static final int MSG_ESCROW_TOKEN_STATE = 9;
+    private static final int MSG_UNLOCK_USER = 10;
 
     /**
      * Time in uptime millis that we wait for the service connection, both when starting
@@ -71,6 +78,9 @@
      * Long extra for {@link #MSG_GRANT_TRUST}
      */
     private static final String DATA_DURATION = "duration";
+    private static final String DATA_ESCROW_TOKEN = "escrow_token";
+    private static final String DATA_HANDLE = "handle";
+    private static final String DATA_USER_ID = "user_id";
 
     private final TrustManagerService mTrustManagerService;
     private final int mUserId;
@@ -190,6 +200,61 @@
                     mTrustManagerService.mArchive.logManagingTrust(mUserId, mName, mManagingTrust);
                     mTrustManagerService.updateTrust(mUserId, 0);
                     break;
+                case MSG_ADD_ESCROW_TOKEN: {
+                    byte[] eToken = msg.getData().getByteArray(DATA_ESCROW_TOKEN);
+                    int userId = msg.getData().getInt(DATA_USER_ID);
+                    long handle = mTrustManagerService.addEscrowToken(eToken, userId);
+                    boolean resultDeliverred = false;
+                    try {
+                        if (mTrustAgentService != null) {
+                            mTrustAgentService.onEscrowTokenAdded(
+                                    eToken, handle, UserHandle.of(userId));
+                            resultDeliverred = true;
+                        }
+                    } catch (RemoteException e) {
+                        onError(e);
+                    }
+
+                    if (!resultDeliverred) {
+                        mTrustManagerService.removeEscrowToken(handle, userId);
+                    }
+                    break;
+                }
+                case MSG_ESCROW_TOKEN_STATE: {
+                    long handle = msg.getData().getLong(DATA_HANDLE);
+                    int userId = msg.getData().getInt(DATA_USER_ID);
+                    boolean active = mTrustManagerService.isEscrowTokenActive(handle, userId);
+                    try {
+                        if (mTrustAgentService != null) {
+                            mTrustAgentService.onTokenStateReceived(handle,
+                                    active ? TrustAgentService.TOKEN_STATE_ACTIVE
+                                            : TrustAgentService.TOKEN_STATE_INACTIVE);
+                        }
+                    } catch (RemoteException e) {
+                        onError(e);
+                    }
+                    break;
+                }
+                case MSG_REMOVE_ESCROW_TOKEN: {
+                    long handle = msg.getData().getLong(DATA_HANDLE);
+                    int userId = msg.getData().getInt(DATA_USER_ID);
+                    boolean success = mTrustManagerService.removeEscrowToken(handle, userId);
+                    try {
+                        if (mTrustAgentService != null) {
+                            mTrustAgentService.onEscrowTokenRemoved(handle, success);
+                        }
+                    } catch (RemoteException e) {
+                        onError(e);
+                    }
+                    break;
+                }
+                case MSG_UNLOCK_USER: {
+                    long handle = msg.getData().getLong(DATA_HANDLE);
+                    int userId = msg.getData().getInt(DATA_USER_ID);
+                    byte[] eToken = msg.getData().getByteArray(DATA_ESCROW_TOKEN);
+                    mTrustManagerService.unlockUserWithToken(handle, eToken, userId);
+                    break;
+                }
             }
         }
     };
@@ -225,6 +290,63 @@
             mHandler.obtainMessage(MSG_SET_TRUST_AGENT_FEATURES_COMPLETED,
                     result ? 1 : 0, 0, token).sendToTarget();
         }
+
+        @Override
+        public void addEscrowToken(byte[] token, int userId) {
+            if (mContext.getResources()
+                    .getBoolean(com.android.internal.R.bool.config_allowEscrowTokenForTrustAgent)) {
+                throw  new SecurityException("Escrow token API is not allowed.");
+            }
+
+            if (DEBUG) Slog.d(TAG, "adding escrow token for user " + userId);
+            Message msg = mHandler.obtainMessage(MSG_ADD_ESCROW_TOKEN);
+            msg.getData().putByteArray(DATA_ESCROW_TOKEN, token);
+            msg.getData().putInt(DATA_USER_ID, userId);
+            msg.sendToTarget();
+        }
+
+        @Override
+        public void isEscrowTokenActive(long handle, int userId) {
+            if (mContext.getResources()
+                    .getBoolean(com.android.internal.R.bool.config_allowEscrowTokenForTrustAgent)) {
+                throw new SecurityException("Escrow token API is not allowed.");
+            }
+
+            if (DEBUG) Slog.d(TAG, "checking the state of escrow token on user " + userId);
+            Message msg = mHandler.obtainMessage(MSG_ESCROW_TOKEN_STATE);
+            msg.getData().putLong(DATA_HANDLE, handle);
+            msg.getData().putInt(DATA_USER_ID, userId);
+            msg.sendToTarget();
+        }
+
+        @Override
+        public void removeEscrowToken(long handle, int userId) {
+            if (mContext.getResources()
+                    .getBoolean(com.android.internal.R.bool.config_allowEscrowTokenForTrustAgent)) {
+                throw new SecurityException("Escrow token API is not allowed.");
+            }
+
+            if (DEBUG) Slog.d(TAG, "removing escrow token on user " + userId);
+            Message msg = mHandler.obtainMessage(MSG_REMOVE_ESCROW_TOKEN);
+            msg.getData().putLong(DATA_HANDLE, handle);
+            msg.getData().putInt(DATA_USER_ID, userId);
+            msg.sendToTarget();
+        }
+
+        @Override
+        public void unlockUserWithToken(long handle, byte[] token, int userId) {
+            if (mContext.getResources()
+                    .getBoolean(com.android.internal.R.bool.config_allowEscrowTokenForTrustAgent)) {
+                throw new SecurityException("Escrow token API is not allowed.");
+            }
+
+            if (DEBUG) Slog.d(TAG, "unlocking user " + userId);
+            Message msg = mHandler.obtainMessage(MSG_UNLOCK_USER);
+            msg.getData().putInt(DATA_USER_ID, userId);
+            msg.getData().putLong(DATA_HANDLE, handle);
+            msg.getData().putByteArray(DATA_ESCROW_TOKEN, token);
+            msg.sendToTarget();
+        }
     };
 
     private final ServiceConnection mConnection = new ServiceConnection() {
@@ -294,7 +416,7 @@
     }
 
     private void onError(Exception e) {
-        Slog.w(TAG , "Remote Exception", e);
+        Slog.w(TAG , "Exception ", e);
     }
 
     private void onTrustTimeout() {
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 71b725e..4570b0d 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -16,14 +16,6 @@
 
 package com.android.server.trust;
 
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.content.PackageMonitor;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.server.SystemService;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
 import android.Manifest;
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
@@ -65,12 +57,17 @@
 import android.util.Xml;
 import android.view.IWindowManager;
 import android.view.WindowManagerGlobal;
-
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.content.PackageMonitor;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.server.SystemService;
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
 
 /**
  * Manages trust agents and trust listeners.
@@ -229,6 +226,22 @@
                 TRUST_USUALLY_MANAGED_FLUSH_DELAY);
     }
 
+    public long addEscrowToken(byte[] token, int userId) {
+        return mLockPatternUtils.addEscrowToken(token, userId);
+    }
+
+    public boolean removeEscrowToken(long handle, int userId) {
+        return mLockPatternUtils.removeEscrowToken(handle, userId);
+    }
+
+    public boolean isEscrowTokenActive(long handle, int userId) {
+        return mLockPatternUtils.isEscrowTokenActive(handle, userId);
+    }
+
+    public void unlockUserWithToken(long handle, byte[] token, int userId) {
+        mLockPatternUtils.unlockUserWithToken(handle, token, userId);
+    }
+
     void refreshAgentList(int userIdOrAll) {
         if (DEBUG) Slog.d(TAG, "refreshAgentList(" + userIdOrAll + ")");
         if (!mTrustAgentsCanRun) {
@@ -329,7 +342,7 @@
                 if (!StorageManager.isUserKeyUnlocked(userInfo.id)
                         && !directUnlock) {
                     if (DEBUG) Slog.d(TAG, "refreshAgentList: skipping user " + userInfo.id
-                            + "'s trust agent " + name + ": FDE still locked and "
+                            + "'s trust agent " + name + ": FBE still locked and "
                             + " the agent cannot unlock user profile.");
                     continue;
                 }
diff --git a/services/core/java/com/android/server/vr/CompatibilityDisplay.java b/services/core/java/com/android/server/vr/CompatibilityDisplay.java
index 15edaaf..c54fd9a 100644
--- a/services/core/java/com/android/server/vr/CompatibilityDisplay.java
+++ b/services/core/java/com/android/server/vr/CompatibilityDisplay.java
@@ -2,8 +2,10 @@
 package com.android.server.vr;
 
 import android.app.Service;
+import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.VirtualDisplay;
 import android.os.Build;
@@ -14,6 +16,7 @@
 import android.service.vr.IVrStateCallbacks;
 import android.service.vr.IVrManager;
 import android.util.Log;
+import android.view.Surface;
 
 import com.android.server.vr.VrManagerService;
 
@@ -26,10 +29,19 @@
     private final static boolean DEBUG = false;
 
     // TODO: Go over these values and figure out what is best
-    private final static int HEIGHT = 960;
-    private final static int WIDTH = 720;
+    private final static int HEIGHT = 1800;
+    private final static int WIDTH = 1400;
     private final static int DPI = 320;
 
+    private final static String DEBUG_ACTION_SET_MODE =
+            "com.android.server.vr.CompatibilityDisplay.SET_MODE";
+    private final static String DEBUG_EXTRA_MODE_ON =
+            "com.android.servier.vr.CompatibilityDisplay.EXTRA_MODE_ON";
+    private final static String DEBUG_ACTION_SET_SURFACE =
+            "com.android.server.vr.CompatibilityDisplay.SET_SURFACE";
+    private final static String DEBUG_EXTRA_SURFACE =
+            "com.android.server.vr.CompatibilityDisplay.EXTRA_SURFACE";
+
     private final DisplayManager mDisplayManager;
     private final IVrManager mVrManager;
 
@@ -42,18 +54,14 @@
         public void onVrStateChanged(boolean enabled) {
             if (enabled != mIsVrModeEnabled) {
                 mIsVrModeEnabled = enabled;
-                if (enabled) {
-                    // TODO: Consider not creating the display until ActivityManager needs one on
-                    // which to display a 2D application.
-                    startVirtualDisplay();
-                } else {
-                    stopVirtualDisplay();
-                }
+                updateVirtualDisplay();
             }
         }
     };
 
     private VirtualDisplay mVirtualDisplay;
+    private Surface mSurface;
+    private boolean mIsDebugOverrideEnabled;
     private boolean mIsVrModeEnabled;
 
     public CompatibilityDisplay(DisplayManager displayManager, IVrManager vrManager) {
@@ -64,8 +72,60 @@
     /**
      * Initializes the compabilitiy display by listening to VR mode changes.
      */
-    public void init() {
+    public void init(Context context) {
         startVrModeListener();
+        startDebugOnlyBroadcastReceiver(context);
+    }
+
+    private void updateVirtualDisplay() {
+        if (mIsVrModeEnabled || (DEBUG && mIsDebugOverrideEnabled)) {
+            // TODO: Consider not creating the display until ActivityManager needs one on
+            // which to display a 2D application.
+            // TODO: STOPSHIP Remove DEBUG conditional before launching.
+            if (DEBUG) {
+                startVirtualDisplay();
+            }
+        } else {
+            // TODO: Remove conditional when launching apps 2D doesn't force VrMode to stop.
+            if (!DEBUG) {
+                stopVirtualDisplay();
+            }
+        }
+    }
+
+    private void startDebugOnlyBroadcastReceiver(Context context) {
+        if (DEBUG) {
+            IntentFilter intentFilter = new IntentFilter(DEBUG_ACTION_SET_MODE);
+            intentFilter.addAction(DEBUG_ACTION_SET_SURFACE);
+
+            context.registerReceiver(new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    final String action = intent.getAction();
+                    if (DEBUG_ACTION_SET_MODE.equals(action)) {
+                        mIsDebugOverrideEnabled =
+                                intent.getBooleanExtra(DEBUG_EXTRA_MODE_ON, false);
+                        updateVirtualDisplay();
+                    } else if (DEBUG_ACTION_SET_SURFACE.equals(action)) {
+                        if (mVirtualDisplay != null) {
+                            final Surface newSurface =
+                                    intent.getParcelableExtra(DEBUG_EXTRA_SURFACE);
+
+                            Log.i(TAG, "Setting the new surface from " + mSurface + " to " + newSurface);
+                            if (newSurface != mSurface) {
+                                mVirtualDisplay.setSurface(newSurface);
+                                if (mSurface != null) {
+                                    mSurface.release();
+                                }
+                                mSurface = newSurface;
+                            }
+                        } else {
+                            Log.w(TAG, "Cannot set the surface because the VD is null.");
+                        }
+                    }
+                }
+            }, intentFilter);
+        }
     }
 
     private void startVrModeListener() {
@@ -80,7 +140,7 @@
 
     private void startVirtualDisplay() {
         if (DEBUG) {
-            Log.d(TAG, "Starting VD, DM:" + mDisplayManager);
+            Log.d(TAG, "Request to start VD, DM:" + mDisplayManager);
         }
 
         if (mDisplayManager == null) {
@@ -90,13 +150,16 @@
 
         synchronized (vdLock) {
             if (mVirtualDisplay != null) {
-                Log.e(TAG, "Starting the virtual display when one already exists", new Exception());
+                Log.i(TAG, "VD already exists, ignoring request");
                 return;
             }
 
             mVirtualDisplay = mDisplayManager.createVirtualDisplay("VR 2D Display", WIDTH, HEIGHT,
-                    DPI,
-                    null /* Surface */, 0 /* flags */);
+                    DPI, null /* Surface */, 0 /* flags */);
+            if (mSurface != null && mSurface.isValid()) {
+              // TODO: Need to protect all setSurface calls with a lock.
+              mVirtualDisplay.setSurface(mSurface);
+            }
         }
 
         if (DEBUG) {
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index 21a4f74..8a23173 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -26,6 +26,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.hardware.display.DisplayManager;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
@@ -130,7 +131,8 @@
     private final ArrayDeque<VrState> mLoggingDeque = new ArrayDeque<>(EVENT_LOG_SIZE);
     private final NotificationAccessManager mNotifAccessManager = new NotificationAccessManager();
     /** Tracks the state of the screen and keyguard UI.*/
-    private int mSystemSleepFlags = FLAG_NONE;
+    private int mSystemSleepFlags = FLAG_AWAKE;
+    private CompatibilityDisplay mCompatibilityDisplay;
 
     private static final int MSG_VR_STATE_CHANGE = 0;
     private static final int MSG_PENDING_VR_STATE_CHANGE = 1;
@@ -537,6 +539,11 @@
             } else {
                 Slog.i(TAG, "No default vr listener service found.");
             }
+
+            DisplayManager dm =
+                    (DisplayManager) getContext().getSystemService(Context.DISPLAY_SERVICE);
+            mCompatibilityDisplay = new CompatibilityDisplay(dm, mVrManager);
+            mCompatibilityDisplay.init(getContext());
         } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
             synchronized (mLock) {
                 mVrModeAllowed = true;
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index f7a9e41..b7479da 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -226,8 +226,8 @@
             Matrix outMatrix) {
         sTempFloats[Matrix.MSCALE_X] = windowState.mWinAnimator.mDsDx;
         sTempFloats[Matrix.MSKEW_Y] = windowState.mWinAnimator.mDtDx;
-        sTempFloats[Matrix.MSKEW_X] = windowState.mWinAnimator.mDsDy;
-        sTempFloats[Matrix.MSCALE_Y] = windowState.mWinAnimator.mDtDy;
+        sTempFloats[Matrix.MSKEW_X] = windowState.mWinAnimator.mDtDy;
+        sTempFloats[Matrix.MSCALE_Y] = windowState.mWinAnimator.mDsDy;
         sTempFloats[Matrix.MTRANS_X] = windowState.mShownPosition.x;
         sTempFloats[Matrix.MTRANS_Y] = windowState.mShownPosition.y;
         sTempFloats[Matrix.MPERSP_0] = 0;
diff --git a/services/core/java/com/android/server/wm/AlertWindowNotification.java b/services/core/java/com/android/server/wm/AlertWindowNotification.java
new file mode 100644
index 0000000..b7b419b
--- /dev/null
+++ b/services/core/java/com/android/server/wm/AlertWindowNotification.java
@@ -0,0 +1,156 @@
+/*
+ * 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.wm;
+
+import static android.app.NotificationManager.IMPORTANCE_MIN;
+import static android.app.PendingIntent.FLAG_CANCEL_CURRENT;
+import static android.content.Context.NOTIFICATION_SERVICE;
+import static android.content.Intent.EXTRA_PACKAGE_NAME;
+import static android.content.Intent.EXTRA_UID;
+import static com.android.server.wm.WindowManagerService.ACTION_REVOKE_SYSTEM_ALERT_WINDOW_PERMISSION;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.graphics.drawable.Drawable;
+
+import com.android.internal.R;
+import com.android.server.policy.IconUtilities;
+
+/** Displays an ongoing notification for a process displaying an alert window */
+class AlertWindowNotification {
+    private static final String CHANNEL_PREFIX = "com.android.server.wm.AlertWindowNotification - ";
+    private static final int NOTIFICATION_ID = 0;
+
+    private static int sNextRequestCode = 0;
+    private final int mRequestCode;
+    private final WindowManagerService mService;
+    private String mNotificationTag;
+    private final NotificationManager mNotificationManager;
+    private final String mPackageName;
+    private final int mUid;
+    private boolean mCancelled;
+    private IconUtilities mIconUtilities;
+
+    AlertWindowNotification(WindowManagerService service, String packageName, int uid) {
+        mService = service;
+        mPackageName = packageName;
+        mUid = uid;
+        mNotificationManager =
+                (NotificationManager) mService.mContext.getSystemService(NOTIFICATION_SERVICE);
+        mNotificationTag = CHANNEL_PREFIX + mPackageName;
+        mRequestCode = sNextRequestCode++;
+        mIconUtilities = new IconUtilities(mService.mContext);
+
+        // We can't create/post the notification while the window manager lock is held since it will
+        // end up calling into activity manager. So, we post a message to do it later.
+        mService.mH.post(this::onPostNotification);
+    }
+
+    /** Cancels the notification */
+    void cancel() {
+        // We can't call into NotificationManager with WM lock held since it might call into AM.
+        // So, we post a message to do it later.
+        mService.mH.post(this::onCancelNotification);
+    }
+
+    /** Don't call with the window manager lock held! */
+    private void onCancelNotification() {
+        mNotificationManager.cancel(mNotificationTag, NOTIFICATION_ID);
+        mCancelled = true;
+    }
+
+    /** Don't call with the window manager lock held! */
+    private void onPostNotification() {
+        if (mCancelled) {
+            // Notification was cancelled, so nothing more to do...
+            return;
+        }
+
+        final Context context = mService.mContext;
+        final PackageManager pm = context.getPackageManager();
+        final ApplicationInfo aInfo = getApplicationInfo(pm, mPackageName);
+        final String appName = (aInfo != null)
+                ? pm.getApplicationLabel(aInfo).toString() : mPackageName;
+
+        createNotificationChannelIfNeeded(context, appName);
+
+        final String message = context.getString(R.string.alert_windows_notification_message);
+        final Notification.Builder builder = new Notification.Builder(context, mNotificationTag)
+                .setOngoing(true)
+                .setContentTitle(
+                        context.getString(R.string.alert_windows_notification_title, appName))
+                .setContentText(message)
+                .setSmallIcon(R.drawable.alert_window_layer)
+                .setColor(context.getColor(R.color.system_notification_accent_color))
+                .setStyle(new Notification.BigTextStyle().bigText(message))
+                .setLocalOnly(true)
+                .addAction(getTurnOffAction(context, mPackageName, mUid));
+
+        if (aInfo != null) {
+            final Drawable drawable = pm.getApplicationIcon(aInfo);
+            if (drawable != null) {
+                final Bitmap bitmap = mIconUtilities.createIconBitmap(drawable);
+                builder.setLargeIcon(bitmap);
+            }
+        }
+
+        mNotificationManager.notify(mNotificationTag, NOTIFICATION_ID, builder.build());
+    }
+
+    private Notification.Action getTurnOffAction(Context context, String packageName, int uid) {
+        final Intent intent = new Intent(ACTION_REVOKE_SYSTEM_ALERT_WINDOW_PERMISSION);
+        intent.putExtra(EXTRA_PACKAGE_NAME, packageName);
+        intent.putExtra(EXTRA_UID, uid);
+        // Calls into activity manager...
+        final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, mRequestCode,
+                intent, FLAG_CANCEL_CURRENT);
+        return new Notification.Action.Builder(R.drawable.alert_window_layer,
+                context.getString(R.string.alert_windows_notification_turn_off_action),
+                pendingIntent).build();
+
+    }
+
+    private void createNotificationChannelIfNeeded(Context context, String appName) {
+        if (mNotificationManager.getNotificationChannel(mNotificationTag) != null) {
+            return;
+        }
+        final String nameChannel =
+                context.getString(R.string.alert_windows_notification_channel_name, appName);
+        final NotificationChannel channel =
+                new NotificationChannel(mNotificationTag, nameChannel, IMPORTANCE_MIN);
+        channel.enableLights(false);
+        channel.enableVibration(false);
+        mNotificationManager.createNotificationChannel(channel);
+    }
+
+
+    private ApplicationInfo getApplicationInfo(PackageManager pm, String packageName) {
+        try {
+            return pm.getApplicationInfo(packageName, 0);
+        } catch (PackageManager.NameNotFoundException e) {
+            return null;
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java
index c42647e..e3941b9 100644
--- a/services/core/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java
@@ -248,8 +248,9 @@
         }
     }
 
-    void updateLayers() {
-        thumbnailLayer = mAppToken.adjustAnimLayer(animLayerAdjustment);
+    private void updateLayers() {
+        mAppToken.getDisplayContent().assignWindowLayers(false /* relayoutNeeded */);
+        thumbnailLayer = mAppToken.getHighestAnimLayer();
     }
 
     private void stepThumbnailAnimation(long currentTime) {
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
index 3a86874..266ab4c 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -525,7 +525,8 @@
 
     private boolean createSnapshot() {
         final TaskSnapshot snapshot = mService.mTaskSnapshotController.getSnapshot(
-                mContainer.mTask.mTaskId, mContainer.mTask.mUserId, false /* restoreFromDisk */);
+                mContainer.getTask().mTaskId, mContainer.getTask().mUserId,
+            false /* restoreFromDisk */);
 
         if (snapshot == null) {
             return false;
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 2263042..647adbf 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -84,14 +84,16 @@
 
     final boolean mVoiceInteraction;
 
-    // TODO: Use getParent instead?
-    Task mTask;
     /** @see WindowContainer#fillsParent() */
     private boolean mFillsParent;
     boolean layoutConfigChanges;
     boolean mShowForAllUsers;
     int mTargetSdk;
 
+    // Flag set while reparenting to prevent actions normally triggered by an individual parent
+    // change.
+    private boolean mReparenting;
+
     // The input dispatching timeout for this application token in nanoseconds.
     long mInputDispatchingTimeoutNanos;
 
@@ -407,7 +409,7 @@
     }
 
     boolean windowsAreFocusable() {
-        return StackId.canReceiveKeys(mTask.mStack.mStackId) || mAlwaysFocusable;
+        return StackId.canReceiveKeys(getTask().mStack.mStackId) || mAlwaysFocusable;
     }
 
     AppWindowContainerController getController() {
@@ -426,10 +428,7 @@
     void removeIfPossible() {
         mIsExiting = false;
         removeAllWindowsIfPossible();
-        if (mTask != null) {
-            mTask.mStack.mExitingAppTokens.remove(this);
-            removeImmediately();
-        }
+        removeImmediately();
     }
 
     @Override
@@ -466,7 +465,7 @@
             getController().removeStartingWindow();
         }
 
-        final TaskStack stack = mTask.mStack;
+        final TaskStack stack = getTask().mStack;
         if (delayed && !isEmpty()) {
             // set the token aside because it has an active animation to be finished
             if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM,
@@ -483,6 +482,7 @@
 
         removed = true;
         stopFreezingScreen(true, true);
+
         if (mService.mFocusedApp == this) {
             if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + this);
             mService.mFocusedApp = null;
@@ -664,6 +664,29 @@
         allDrawnExcludingSaved = false;
     }
 
+    Task getTask() {
+        return (Task) getParent();
+    }
+
+    @Override
+    void onParentSet() {
+        super.onParentSet();
+
+        // When the associated task is {@code null}, the {@link AppWindowToken} can no longer
+        // access visual elements like the {@link DisplayContent}. We must remove any associations
+        // such as animations.
+        if (!mReparenting) {
+            final Task task = getTask();
+            if (task == null) {
+                // It is possible we have been marked as a closing app earlier. We must remove ourselves
+                // from this list so we do not participate in any future animations.
+                mService.mClosingApps.remove(this);
+            } else if (task.mStack != null) {
+                task.mStack.mExitingAppTokens.remove(this);
+            }
+        }
+    }
+
     void postWindowRemoveStartingWindowCleanup(WindowState win) {
         // TODO: Something smells about the code below...Is there a better way?
         if (startingWindow == win) {
@@ -852,17 +875,29 @@
     }
 
     void reparent(Task task, int position) {
-        if (task == mTask) {
+        final Task currentTask = getTask();
+        if (task == currentTask) {
             throw new IllegalArgumentException(
-                    "window token=" + this + " already child of task=" + mTask);
+                    "window token=" + this + " already child of task=" + currentTask);
         }
+
+        if (currentTask.mStack != task.mStack) {
+            throw new IllegalArgumentException(
+                    "window token=" + this + " current task=" + currentTask
+                        + " belongs to a different stack than " + task);
+        }
+
         if (DEBUG_ADD_REMOVE) Slog.i(TAG, "reParentWindowToken: removing window token=" + this
-                + " from task=" + mTask);
+                + " from task=" + currentTask);
         final DisplayContent prevDisplayContent = getDisplayContent();
 
+        mReparenting = true;
+
         getParent().removeChild(this);
         task.addChild(this, position);
 
+        mReparenting = false;
+
         // Relayout display(s).
         final DisplayContent displayContent = task.getDisplayContent();
         displayContent.setLayoutNeeded();
@@ -873,9 +908,11 @@
     }
 
     private boolean canFreezeBounds() {
+        final Task task = getTask();
+
         // For freeform windows, we can't freeze the bounds at the moment because this would make
         // the resizing unresponsive.
-        return mTask != null && !mTask.inFreeformWorkspace();
+        return task != null && !task.inFreeformWorkspace();
     }
 
     /**
@@ -885,16 +922,17 @@
      * with a queue.
      */
     private void freezeBounds() {
-        mFrozenBounds.offer(new Rect(mTask.mPreparedFrozenBounds));
+        final Task task = getTask();
+        mFrozenBounds.offer(new Rect(task.mPreparedFrozenBounds));
 
-        if (mTask.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
+        if (task.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
             // We didn't call prepareFreezingBounds on the task, so use the current value.
-            mFrozenMergedConfig.offer(new Configuration(mTask.getConfiguration()));
+            mFrozenMergedConfig.offer(new Configuration(task.getConfiguration()));
         } else {
-            mFrozenMergedConfig.offer(new Configuration(mTask.mPreparedFrozenMergedConfig));
+            mFrozenMergedConfig.offer(new Configuration(task.mPreparedFrozenMergedConfig));
         }
         // Calling unset() to make it equal to Configuration.EMPTY.
-        mTask.mPreparedFrozenMergedConfig.unset();
+        task.mPreparedFrozenMergedConfig.unset();
     }
 
     /**
@@ -1409,12 +1447,17 @@
     }
 
     @Override
+    int getAnimLayerAdjustment() {
+        return mAppAnimator.animLayerAdjustment;
+    }
+
+    @Override
     void dump(PrintWriter pw, String prefix) {
         super.dump(pw, prefix);
         if (appToken != null) {
             pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
         }
-        pw.print(prefix); pw.print("task="); pw.println(mTask);
+        pw.print(prefix); pw.print("task="); pw.println(getTask());
         pw.print(prefix); pw.print(" mFillsParent="); pw.print(mFillsParent);
                 pw.print(" mOrientation="); pw.println(mOrientation);
         pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested);
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
index cf5cecda..cd0e6cc 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationController.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -23,12 +23,15 @@
 
 import android.animation.Animator;
 import android.animation.ValueAnimator;
+import android.content.Context;
 import android.graphics.Rect;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Debug;
 import android.util.ArrayMap;
 import android.util.Slog;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
 import android.view.animation.LinearInterpolator;
 import android.view.WindowManagerInternal;
 
@@ -51,6 +54,8 @@
             ? "BoundsAnimationController" : TAG_WM;
     private static final int DEBUG_ANIMATION_SLOW_DOWN_FACTOR = 1;
 
+    private static final int DEFAULT_TRANSITION_DURATION = 425;
+
     // Only accessed on UI thread.
     private ArrayMap<AnimateBoundsUser, BoundsAnimator> mRunningAnimations = new ArrayMap<>();
 
@@ -85,12 +90,15 @@
     private final Handler mHandler;
     private final AppTransition mAppTransition;
     private final AppTransitionNotifier mAppTransitionNotifier = new AppTransitionNotifier();
+    private final Interpolator mFastOutSlowInInterpolator;
     private boolean mFinishAnimationAfterTransition = false;
 
-    BoundsAnimationController(AppTransition transition, Handler handler) {
+    BoundsAnimationController(Context context, AppTransition transition, Handler handler) {
         mHandler = handler;
         mAppTransition = transition;
         mAppTransition.registerListenerLocked(mAppTransitionNotifier);
+        mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
+                com.android.internal.R.interpolator.fast_out_slow_in);
     }
 
     private final class BoundsAnimator extends ValueAnimator
@@ -176,7 +184,7 @@
             // we trigger any size changes, so it can swap surfaces
             // in to appropriate modes, or do as it wishes otherwise.
             if (!mReplacement) {
-                mTarget.onAnimationStart();
+                mTarget.onAnimationStart(mMoveToFullScreen);
             }
 
             // Immediately update the task bounds if they have to become larger, but preserve
@@ -263,7 +271,7 @@
          */
         boolean setPinnedStackSize(Rect bounds, Rect taskBounds);
 
-        void onAnimationStart();
+        void onAnimationStart(boolean toFullscreen);
 
         /**
          * Callback for the target to inform it that the animation has ended, so it can do some
@@ -272,18 +280,10 @@
         void onAnimationEnd();
 
         void moveToFullscreen();
-
-        void getFullScreenBounds(Rect bounds);
     }
 
-    void animateBounds(final AnimateBoundsUser target, Rect from, Rect to, int animationDuration) {
-        boolean moveToFullscreen = false;
-        if (to == null) {
-            to = new Rect();
-            target.getFullScreenBounds(to);
-            moveToFullscreen = true;
-        }
-
+    void animateBounds(final AnimateBoundsUser target, Rect from, Rect to, int animationDuration,
+            boolean moveToFullscreen) {
         final BoundsAnimator existing = mRunningAnimations.get(target);
         final boolean replacing = existing != null;
 
@@ -305,8 +305,8 @@
         mRunningAnimations.put(target, animator);
         animator.setFloatValues(0f, 1f);
         animator.setDuration((animationDuration != -1 ? animationDuration
-                : DEFAULT_APP_TRANSITION_DURATION) * DEBUG_ANIMATION_SLOW_DOWN_FACTOR);
-        animator.setInterpolator(new LinearInterpolator());
+                : DEFAULT_TRANSITION_DURATION) * DEBUG_ANIMATION_SLOW_DOWN_FACTOR);
+        animator.setInterpolator(mFastOutSlowInInterpolator);
         animator.start();
     }
 }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 8f38be8..461c3fa 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -341,9 +341,6 @@
         }
     };
 
-    private final Consumer<WindowState> mSetInputMethodAnimLayerAdjustment =
-            w -> w.adjustAnimLayer(mInputMethodAnimLayerAdjustment);
-
     private final Consumer<WindowState> mScheduleToastTimeout = w -> {
         final int lostFocusUid = mTmpWindow.mOwnerUid;
         final Handler handler = mService.mH;
@@ -919,10 +916,6 @@
     void updateDisplayInfo() {
         mDisplay.getDisplayInfo(mDisplayInfo);
         mDisplay.getMetrics(mDisplayMetrics);
-
-        // Check if display metrics changed and update base values if needed.
-        updateBaseDisplayMetricsIfNeeded();
-
         for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
             mTaskStackContainers.get(i).updateDisplayInfo(null);
         }
@@ -938,8 +931,10 @@
             }
         }
 
-        updateBaseDisplayMetrics(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight,
-                mDisplayInfo.logicalDensityDpi);
+        mBaseDisplayWidth = mInitialDisplayWidth = mDisplayInfo.logicalWidth;
+        mBaseDisplayHeight = mInitialDisplayHeight = mDisplayInfo.logicalHeight;
+        mBaseDisplayDensity = mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi;
+        mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight);
     }
 
     void getLogicalDisplayRect(Rect out) {
@@ -969,30 +964,6 @@
         }
     }
 
-    /** If display metrics changed and it's not just a rotation - update base values. */
-    private void updateBaseDisplayMetricsIfNeeded() {
-        final int orientation = mDisplayInfo.rotation;
-        final boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270);
-        final int newWidth = rotated ? mDisplayInfo.logicalHeight : mDisplayInfo.logicalWidth;
-        final int newHeight = rotated ? mDisplayInfo.logicalWidth : mDisplayInfo.logicalHeight;
-
-        boolean displayMetricsChanged
-                = mBaseDisplayWidth != newWidth || mBaseDisplayHeight != newHeight;
-        displayMetricsChanged |= mBaseDisplayDensity != mDisplayInfo.logicalDensityDpi;
-
-        if (displayMetricsChanged) {
-            updateBaseDisplayMetrics(newWidth, newHeight, mDisplayInfo.logicalDensityDpi);
-            mService.reconfigureDisplayLocked(this);
-        }
-    }
-
-    void updateBaseDisplayMetrics(int baseWidth, int baseHeight, int baseDensity) {
-        mBaseDisplayWidth = mInitialDisplayWidth = baseWidth;
-        mBaseDisplayHeight = mInitialDisplayHeight = baseHeight;
-        mBaseDisplayDensity = mInitialDisplayDensity = baseDensity;
-        mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight);
-    }
-
     void getContentRect(Rect out) {
         out.set(mContentRect);
     }
@@ -1307,8 +1278,7 @@
     void setInputMethodAnimLayerAdjustment(int adj) {
         if (DEBUG_LAYERS) Slog.v(TAG_WM, "Setting im layer adj to " + adj);
         mInputMethodAnimLayerAdjustment = adj;
-        mImeWindowsContainers.forAllWindows(mSetInputMethodAnimLayerAdjustment,
-                true /* traverseTopToBottom */);
+        assignWindowLayers(false /* relayoutNeeded */);
     }
 
     /**
@@ -1614,9 +1584,24 @@
         // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the
         // same display. Or even when the current IME/target are not on the same screen as the next
         // IME/target. For now only look for input windows on the main screen.
-        mUpdateImeTarget = updateImeTarget;
-        WindowState target = getWindow(mComputeImeTargetPredicate);
 
+        // The target candidate provided by the IME tells us which window token, but not which
+        // window within the token (e.g. child windows...). So, we use the token to look-up the
+        // best target window.
+        // TODO: Have the input method service report the right window with the token vs. just the
+        // base window of the token.
+        final WindowState baseWin = mService.getWindow(mService.mInputMethodTargetCandidate);
+        final WindowToken targetToken = baseWin != null ? baseWin.mToken : null;
+        WindowState target = targetToken != null ?
+                targetToken.getWindow(mComputeImeTargetPredicate) : null;
+        // If there isn't a better candidate in the token (maybe because they are not visible), then
+        // fall back to targeting the base window of the token, so the IME can still maintain the
+        // right z-order based on the last person that set it vs. changing its z-order to the very
+        // up since there if target is null.
+        // TODO: Consider z-ordering IME to bottom instead of top if there is no visible target.
+        // Also, consider tying the visible the visibility of the IME to the current target. I.e if
+        // target isn't visible, then IME shouldn't be visible.
+        target = target == null ? baseWin : target;
 
         // Yet more tricksyness!  If this window is a "starting" window, we do actually want
         // to be on top of it, but it is not -really- where input will go. So look down below
@@ -1699,7 +1684,7 @@
             if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to "
                     + target + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : ""));
             setInputMethodTarget(target, false, target.mAppToken != null
-                    ? target.mAppToken.mAppAnimator.animLayerAdjustment : 0);
+                    ? target.mAppToken.getAnimLayerAdjustment() : 0);
         }
 
         return target;
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 75a79fd..aa8e377 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -588,7 +588,7 @@
     private boolean containsAppInDockedStack(ArraySet<AppWindowToken> apps) {
         for (int i = apps.size() - 1; i >= 0; i--) {
             final AppWindowToken token = apps.valueAt(i);
-            if (token.mTask != null && token.mTask.mStack.mStackId == DOCKED_STACK_ID) {
+            if (token.getTask() != null && token.getTask().mStack.mStackId == DOCKED_STACK_ID) {
                 return true;
             }
         }
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 37b8deb..dc4806a 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -631,14 +631,26 @@
                 return;
             }
 
-            if (mAddPipInputConsumerHandle
-                    && w.getStackId() == PINNED_STACK_ID
-                    && inputWindowHandle.layer <= pipInputConsumer.mWindowHandle.layer) {
-                // Update the bounds of the Pip input consumer to match the Pinned stack
-                w.getStack().getBounds(pipTouchableBounds);
-                pipInputConsumer.mWindowHandle.touchableRegion.set(pipTouchableBounds);
-                addInputWindowHandle(pipInputConsumer.mWindowHandle);
-                mAddPipInputConsumerHandle = false;
+            final int flags = w.mAttrs.flags;
+            final int privateFlags = w.mAttrs.privateFlags;
+            final int type = w.mAttrs.type;
+            final boolean hasFocus = w == mInputFocus;
+            final boolean isVisible = w.isVisibleLw();
+
+            if (w.getStackId() == PINNED_STACK_ID) {
+                if (mAddPipInputConsumerHandle
+                        && (inputWindowHandle.layer <= pipInputConsumer.mWindowHandle.layer)) {
+                    // Update the bounds of the Pip input consumer to match the Pinned stack
+                    w.getStack().getBounds(pipTouchableBounds);
+                    pipInputConsumer.mWindowHandle.touchableRegion.set(pipTouchableBounds);
+                    addInputWindowHandle(pipInputConsumer.mWindowHandle);
+                    mAddPipInputConsumerHandle = false;
+                }
+                // TODO: Fix w.canReceiveTouchInput() to handle this case
+                if (!hasFocus) {
+                    // Skip this pinned stack window if it does not have focus
+                    return;
+                }
             }
 
             if (mAddInputConsumerHandle
@@ -655,12 +667,6 @@
                 }
             }
 
-            final int flags = w.mAttrs.flags;
-            final int privateFlags = w.mAttrs.privateFlags;
-            final int type = w.mAttrs.type;
-
-            final boolean hasFocus = w == mInputFocus;
-            final boolean isVisible = w.isVisibleLw();
             if ((privateFlags & PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS) != 0) {
                 mDisableWallpaperTouchEvents = true;
             }
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index cfeb198..1d50d0d 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -94,13 +94,16 @@
 
     // The size and position information that describes where the pinned stack will go by default.
     private int mDefaultStackGravity;
-    private Size mDefaultStackSize;
+    private float mDefaultAspectRatio;
     private Point mScreenEdgeInsets;
 
     // The aspect ratio bounds of the PIP.
     private float mMinAspectRatio;
     private float mMaxAspectRatio;
 
+    // The minimum edge size of the normal PiP bounds.
+    private int mMinSize;
+
     // Temp vars for calculation
     private final DisplayMetrics mTmpMetrics = new DisplayMetrics();
     private final Rect mTmpInsets = new Rect();
@@ -151,15 +154,15 @@
      */
     void reloadResources() {
         final Resources res = mService.mContext.getResources();
-        final Size defaultSizeDp = Size.parseSize(res.getString(
-                com.android.internal.R.string.config_defaultPictureInPictureSize));
+        mMinSize = res.getDimensionPixelSize(
+                com.android.internal.R.dimen.default_minimal_size_pip_resizable_task);
+        mDefaultAspectRatio = res.getFloat(
+                com.android.internal.R.dimen.config_pictureInPictureDefaultAspectRatio);
         final Size screenEdgeInsetsDp = Size.parseSize(res.getString(
                 com.android.internal.R.string.config_defaultPictureInPictureScreenEdgeInsets));
         mDefaultStackGravity = res.getInteger(
                 com.android.internal.R.integer.config_defaultPictureInPictureGravity);
         mDisplayContent.getDisplay().getRealMetrics(mTmpMetrics);
-        mDefaultStackSize = new Size(dpToPx(defaultSizeDp.getWidth(), mTmpMetrics),
-                dpToPx(defaultSizeDp.getHeight(), mTmpMetrics));
         mScreenEdgeInsets = new Point(dpToPx(screenEdgeInsetsDp.getWidth(), mTmpMetrics),
                 dpToPx(screenEdgeInsetsDp.getHeight(), mTmpMetrics));
         mMinAspectRatio = res.getFloat(
@@ -199,16 +202,13 @@
      * specified aspect ratio.
      */
     Rect transformBoundsToAspectRatio(Rect stackBounds, float aspectRatio) {
-        // Save the snap fraction, calculate the aspect ratio based on the current bounds
+        // Save the snap fraction, calculate the aspect ratio based on screen size
         final float snapFraction = mSnapAlgorithm.getSnapFraction(stackBounds,
                 getMovementBounds(stackBounds));
-        final float radius = PointF.length(stackBounds.width(), stackBounds.height());
-        final int height = (int) Math.round(Math.sqrt((radius * radius) /
-                (aspectRatio * aspectRatio + 1)));
-        final int width = Math.round(height * aspectRatio);
-        final int left = (int) (stackBounds.centerX() - width / 2f);
-        final int top = (int) (stackBounds.centerY() - height / 2f);
-        stackBounds.set(left, top, left + width, top + height);
+        final Size size = getSize(aspectRatio);
+        final int left = (int) (stackBounds.centerX() - size.getWidth() / 2f);
+        final int top = (int) (stackBounds.centerY() - size.getHeight() / 2f);
+        stackBounds.set(left, top, left + size.getWidth(), top + size.getHeight());
         mSnapAlgorithm.applySnapFraction(stackBounds, getMovementBounds(stackBounds), snapFraction);
         if (mIsMinimized) {
             applyMinimizedOffset(stackBounds, getMovementBounds(stackBounds));
@@ -217,6 +217,14 @@
     }
 
     /**
+     * @return the size of the PIP based on the given {@param aspectRatio}.
+     */
+    Size getSize(float aspectRatio) {
+        return mSnapAlgorithm.getSizeForAspectRatio(aspectRatio, mMinSize,
+                mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
+    }
+
+    /**
      * @return the default bounds to show the PIP when there is no active PIP.
      */
     Rect getDefaultBounds() {
@@ -224,60 +232,44 @@
         getInsetBounds(insetBounds);
 
         final Rect defaultBounds = new Rect();
-        Gravity.apply(mDefaultStackGravity, mDefaultStackSize.getWidth(),
-                mDefaultStackSize.getHeight(), insetBounds, 0, 0, defaultBounds);
+        final Size size = getSize(mDefaultAspectRatio);
+        Gravity.apply(mDefaultStackGravity, size.getWidth(), size.getHeight(), insetBounds,
+                0, mIsImeShowing ? mImeHeight : 0, defaultBounds);
         return defaultBounds;
     }
 
     /**
-     * @return the movement bounds for the given {@param stackBounds} and the current state of the
-     *         controller.
+     * Updates the display info, calculating and returning the new stack and movement bounds in the
+     * new orientation of the device if necessary.
      */
-    private Rect getMovementBounds(Rect stackBounds) {
-        return getMovementBounds(stackBounds, true /* adjustForIme */);
-    }
-
-    /**
-     * @return the movement bounds for the given {@param stackBounds} and the current state of the
-     *         controller.
-     */
-    private Rect getMovementBounds(Rect stackBounds, boolean adjustForIme) {
-        final Rect movementBounds = new Rect();
-        getInsetBounds(movementBounds);
-
-        // Apply the movement bounds adjustments based on the current state
-        mSnapAlgorithm.getMovementBounds(stackBounds, movementBounds, movementBounds,
-                (adjustForIme && mIsImeShowing) ? mImeHeight : 0);
-        return movementBounds;
-    }
-
-    /**
-     * @param preChangeTargetBounds The final bounds of the stack if it is currently animating
-     * @return the repositioned PIP bounds given it's pre-change bounds, and the new display
-     *         content.
-     */
-    Rect onDisplayChanged(Rect preChangeStackBounds, Rect preChangeTargetBounds,
-            DisplayContent displayContent) {
-        final Rect postChangeStackBounds = new Rect(preChangeTargetBounds);
-        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
-        if (!mDisplayInfo.equals(displayInfo)) {
-            // Calculate the snap fraction of the current stack along the old movement bounds, and
-            // then update the stack bounds to the same fraction along the rotated movement bounds.
-            final Rect preChangeMovementBounds = getMovementBounds(preChangeStackBounds);
-            final float snapFraction = mSnapAlgorithm.getSnapFraction(preChangeStackBounds,
-                    preChangeMovementBounds);
-            mDisplayInfo.copyFrom(displayInfo);
-
-            final Rect postChangeMovementBounds = getMovementBounds(preChangeStackBounds,
-                    false /* adjustForIme */);
-            mSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds,
-                    snapFraction);
-            if (mIsMinimized) {
-                applyMinimizedOffset(postChangeStackBounds, postChangeMovementBounds);
-            }
-            notifyMovementBoundsChanged(false /* fromImeAdjustment */);
+    void onTaskStackBoundsChanged(Rect targetBounds, Rect outBounds) {
+        final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
+        if (mDisplayInfo.equals(displayInfo)) {
+            return;
         }
-        return postChangeStackBounds;
+
+        mTmpRect.set(targetBounds);
+        final Rect postChangeStackBounds = mTmpRect;
+
+        // Calculate the snap fraction of the current stack along the old movement bounds
+        final Rect preChangeMovementBounds = getMovementBounds(postChangeStackBounds);
+        final float snapFraction = mSnapAlgorithm.getSnapFraction(postChangeStackBounds,
+                preChangeMovementBounds);
+        mDisplayInfo.copyFrom(displayInfo);
+
+        // Calculate the stack bounds in the new orientation to the same same fraction along the
+        // rotated movement bounds.
+        final Rect postChangeMovementBounds = getMovementBounds(postChangeStackBounds,
+                false /* adjustForIme */);
+        mSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds,
+                snapFraction);
+        if (mIsMinimized) {
+            applyMinimizedOffset(postChangeStackBounds, postChangeMovementBounds);
+        }
+
+        notifyMovementBoundsChanged(false /* fromImeAdjustment */);
+
+        outBounds.set(postChangeStackBounds);
     }
 
     /**
@@ -361,14 +353,21 @@
     private void notifyMovementBoundsChanged(boolean fromImeAdjustement) {
         if (mPinnedStackListener != null) {
             try {
-                Rect insetBounds = new Rect();
+                final Rect insetBounds = new Rect();
                 getInsetBounds(insetBounds);
-                Rect normalBounds = getDefaultBounds();
+                final Rect normalBounds = getDefaultBounds();
                 if (isValidPictureInPictureAspectRatio(mAspectRatio)) {
                     transformBoundsToAspectRatio(normalBounds, mAspectRatio);
                 }
+                final Rect animatingBounds = mTmpRect;
+                final TaskStack pinnedStack = mDisplayContent.getStackById(PINNED_STACK_ID);
+                if (pinnedStack != null) {
+                    pinnedStack.getAnimatingBounds(animatingBounds);
+                } else {
+                    animatingBounds.set(normalBounds);
+                }
                 mPinnedStackListener.onMovementBoundsChanged(insetBounds, normalBounds,
-                        fromImeAdjustement);
+                        animatingBounds, fromImeAdjustement);
             } catch (RemoteException e) {
                 Slog.e(TAG_WM, "Error delivering actions changed event.", e);
             }
@@ -387,6 +386,28 @@
     }
 
     /**
+     * @return the movement bounds for the given {@param stackBounds} and the current state of the
+     *         controller.
+     */
+    private Rect getMovementBounds(Rect stackBounds) {
+        return getMovementBounds(stackBounds, true /* adjustForIme */);
+    }
+
+    /**
+     * @return the movement bounds for the given {@param stackBounds} and the current state of the
+     *         controller.
+     */
+    private Rect getMovementBounds(Rect stackBounds, boolean adjustForIme) {
+        final Rect movementBounds = new Rect();
+        getInsetBounds(movementBounds);
+
+        // Apply the movement bounds adjustments based on the current state
+        mSnapAlgorithm.getMovementBounds(stackBounds, movementBounds, movementBounds,
+                (adjustForIme && mIsImeShowing) ? mImeHeight : 0);
+        return movementBounds;
+    }
+
+    /**
      * Applies the minimized offsets to the given stack bounds.
      */
     private void applyMinimizedOffset(Rect stackBounds, Rect movementBounds) {
diff --git a/services/core/java/com/android/server/wm/PinnedStackWindowController.java b/services/core/java/com/android/server/wm/PinnedStackWindowController.java
new file mode 100644
index 0000000..71f88de
--- /dev/null
+++ b/services/core/java/com/android/server/wm/PinnedStackWindowController.java
@@ -0,0 +1,122 @@
+/*
+ * 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.wm;
+
+import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+
+import android.app.RemoteAction;
+import android.graphics.Rect;
+
+import com.android.server.UiThread;
+
+import java.util.List;
+
+/**
+ * Controller for the pinned stack container. See {@link StackWindowController}.
+ */
+public class PinnedStackWindowController extends StackWindowController {
+
+    private Rect mTmpBoundsRect = new Rect();
+
+    public PinnedStackWindowController(int stackId, StackWindowListener listener, int displayId,
+            boolean onTop, Rect outBounds) {
+        super(stackId, listener, displayId, onTop, outBounds, WindowManagerService.getInstance());
+    }
+
+    /**
+     * Animates the pinned stack.
+     */
+    public void animateResizePinnedStack(Rect bounds, int animationDuration) {
+        synchronized (mWindowMap) {
+            if (mContainer == null) {
+                throw new IllegalArgumentException("Pinned stack container not found :(");
+            }
+
+            // Get non-null fullscreen bounds if the bounds are null
+            final boolean moveToFullscreen = bounds == null;
+            bounds = getPinnedStackAnimationBounds(bounds);
+
+            // If the bounds are truly null, then there was no fullscreen stack at this time, so
+            // animate this to the full display bounds
+            final Rect toBounds;
+            if (bounds == null) {
+                toBounds = new Rect();
+                mContainer.getDisplayContent().getLogicalDisplayRect(toBounds);
+            } else {
+                toBounds = bounds;
+            }
+
+            final Rect originalBounds = new Rect();
+            mContainer.getBounds(originalBounds);
+            mContainer.setAnimatingBounds(toBounds);
+            UiThread.getHandler().post(() -> {
+                mService.mBoundsAnimationController.animateBounds(mContainer, originalBounds,
+                        toBounds, animationDuration, moveToFullscreen);
+            });
+        }
+    }
+
+    /**
+     * Sets the current picture-in-picture aspect ratio.
+     */
+    public void setPictureInPictureAspectRatio(float aspectRatio) {
+        synchronized (mWindowMap) {
+            if (!mService.mSupportsPictureInPicture || mContainer == null) {
+                return;
+            }
+
+            final int displayId = mContainer.getDisplayContent().getDisplayId();
+            final Rect toBounds = mService.getPictureInPictureBounds(displayId, aspectRatio);
+            final Rect targetBounds = new Rect();
+            mContainer.getAnimatingBounds(targetBounds);
+            if (!toBounds.equals(targetBounds)) {
+                animateResizePinnedStack(toBounds, -1 /* duration */);
+            }
+
+            final PinnedStackController pinnedStackController =
+                    mContainer.getDisplayContent().getPinnedStackController();
+            pinnedStackController.setAspectRatio(
+                    pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio)
+                            ? aspectRatio : -1f);
+        }
+    }
+
+    /**
+     * Sets the current picture-in-picture actions.
+     */
+    public void setPictureInPictureActions(List<RemoteAction> actions) {
+        synchronized (mWindowMap) {
+            if (!mService.mSupportsPictureInPicture || mContainer == null) {
+                return;
+            }
+
+            mContainer.getDisplayContent().getPinnedStackController().setActions(actions);
+        }
+    }
+
+    /**
+     * Checks the {@param bounds} and retirms non-null fullscreen bounds for the pinned stack
+     * animation if necessary.
+     */
+    private Rect getPinnedStackAnimationBounds(Rect bounds) {
+        mService.getStackBounds(FULLSCREEN_WORKSPACE_STACK_ID, mTmpBoundsRect);
+        if (bounds == null && !mTmpBoundsRect.isEmpty()) {
+            bounds = new Rect(mTmpBoundsRect);
+        }
+        return bounds;
+    }
+}
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 782f9f2..720a454 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -16,7 +16,10 @@
 
 package com.android.server.wm;
 
+import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 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;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
@@ -54,6 +57,8 @@
 import com.android.server.wm.WindowManagerService.H;
 
 import java.io.PrintWriter;
+import java.util.HashSet;
+import java.util.Set;
 
 /**
  * This class represents an active client session.  There is generally one
@@ -70,9 +75,15 @@
     private final String mStringName;
     SurfaceSession mSurfaceSession;
     private int mNumWindow = 0;
-    private int mNumOverlayWindow = 0;
+    // Set of visible application overlay window surfaces connected to this session.
+    private final Set<WindowSurfaceController> mAppOverlaySurfaces = new HashSet<>();
+    // Set of visible alert window surfaces connected to this session.
+    private final Set<WindowSurfaceController> mAlertWindowSurfaces = new HashSet<>();
+    final boolean mCanAddInternalSystemWindow;
+    private AlertWindowNotification mAlertWindowNotification;
     private boolean mClientDead = false;
     private float mLastReportedAnimatorScale;
+    private String mPackageName;
 
     public Session(WindowManagerService service, IWindowSessionCallback callback,
             IInputMethodClient client, IInputContext inputContext) {
@@ -82,6 +93,8 @@
         mUid = Binder.getCallingUid();
         mPid = Binder.getCallingPid();
         mLastReportedAnimatorScale = service.getCurrentAnimatorScale();
+        mCanAddInternalSystemWindow = service.mContext.checkCallingOrSelfPermission(
+                INTERNAL_SYSTEM_WINDOW) == PERMISSION_GRANTED;
         StringBuilder sb = new StringBuilder();
         sb.append("Session{");
         sb.append(Integer.toHexString(System.identityHashCode(this)));
@@ -544,7 +557,8 @@
         }
     }
 
-    void windowAddedLocked(int type) {
+    void windowAddedLocked(String packageName) {
+        mPackageName = packageName;
         if (mSurfaceSession == null) {
             if (WindowManagerService.localLOGV) Slog.v(
                 TAG_WM, "First window added to " + this + ", creating SurfaceSession");
@@ -557,24 +571,57 @@
             }
         }
         mNumWindow++;
-        if (type == TYPE_APPLICATION_OVERLAY) {
-            mNumOverlayWindow++;
-            setHasOverlayUi(true);
-        }
     }
 
-    void windowRemovedLocked(int type) {
+    void windowRemovedLocked() {
         mNumWindow--;
-        if (type == TYPE_APPLICATION_OVERLAY) {
-            mNumOverlayWindow--;
-            if (mNumOverlayWindow == 0) {
-                setHasOverlayUi(false);
-            } else if (mNumOverlayWindow < 0) {
-                throw new IllegalStateException("mNumOverlayWindow=" + mNumOverlayWindow
-                        + " less than 0 for session=" + this);
+        killSessionLocked();
+    }
+
+
+    void onWindowSurfaceVisibilityChanged(WindowSurfaceController surfaceController,
+            boolean visible, int type) {
+
+        if (!isSystemAlertWindowType(type)) {
+            return;
+        }
+
+        boolean changed;
+
+        if (!mCanAddInternalSystemWindow) {
+            // We want to track non-system signature apps adding alert windows so we can post an
+            // on-going notification for the user to control their visibility.
+            if (visible) {
+                changed = mAlertWindowSurfaces.add(surfaceController);
+            } else {
+                changed = mAlertWindowSurfaces.remove(surfaceController);
+            }
+
+            if (changed) {
+                if (mAlertWindowSurfaces.isEmpty()) {
+                    cancelAlertWindowNotification();
+                } else if (mAlertWindowNotification == null){
+                    mAlertWindowNotification = new AlertWindowNotification(
+                            mService, mPackageName, mUid);
+                }
             }
         }
-        killSessionLocked();
+
+        if (type != TYPE_APPLICATION_OVERLAY) {
+            return;
+        }
+
+        if (visible) {
+            changed = mAppOverlaySurfaces.add(surfaceController);
+        } else {
+            changed = mAppOverlaySurfaces.remove(surfaceController);
+        }
+
+        if (changed) {
+            // Notify activity manager of changes to app overlay windows so it can adjust the
+            // importance score for the process.
+            setHasOverlayUi(!mAppOverlaySurfaces.isEmpty());
+        }
     }
 
     private void killSessionLocked() {
@@ -597,16 +644,29 @@
                     + " in session " + this + ": " + e.toString());
         }
         mSurfaceSession = null;
+        mAlertWindowSurfaces.clear();
+        mAppOverlaySurfaces.clear();
         setHasOverlayUi(false);
+        cancelAlertWindowNotification();
     }
 
     private void setHasOverlayUi(boolean hasOverlayUi) {
         mService.mH.obtainMessage(H.SET_HAS_OVERLAY_UI, mPid, hasOverlayUi ? 1 : 0).sendToTarget();
     }
 
+    private void cancelAlertWindowNotification() {
+        if (mAlertWindowNotification == null) {
+            return;
+        }
+        mAlertWindowNotification.cancel();
+        mAlertWindowNotification = null;
+    }
+
     void dump(PrintWriter pw, String prefix) {
         pw.print(prefix); pw.print("mNumWindow="); pw.print(mNumWindow);
-                pw.print(" mNumOverlayWindow="); pw.print(mNumOverlayWindow);
+                pw.print(" mCanAddInternalSystemWindow="); pw.print(mCanAddInternalSystemWindow);
+                pw.print(" mAppOverlaySurfaces="); pw.print(mAppOverlaySurfaces);
+                pw.print(" mAlertWindowSurfaces="); pw.print(mAlertWindowSurfaces);
                 pw.print(" mClientDead="); pw.print(mClientDead);
                 pw.print(" mSurfaceSession="); pw.println(mSurfaceSession);
     }
diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java
index 142f69a..b0e115b 100644
--- a/services/core/java/com/android/server/wm/StackWindowController.java
+++ b/services/core/java/com/android/server/wm/StackWindowController.java
@@ -199,59 +199,6 @@
         }
     }
 
-    // TODO: This and similar methods should be separated into PinnedStackWindowContainerController
-    public void animateResizePinnedStack(final Rect bounds, final int animationDuration) {
-        synchronized (mWindowMap) {
-            if (mContainer == null) {
-                throw new IllegalArgumentException("Pinned stack container not found :(");
-            }
-            final Rect originalBounds = new Rect();
-            mContainer.getBounds(originalBounds);
-            mContainer.setAnimatingBounds(bounds);
-            UiThread.getHandler().post(new Runnable() {
-                @Override
-                public void run() {
-                    mService.mBoundsAnimationController.animateBounds(
-                            mContainer, originalBounds, bounds, animationDuration);
-                }
-            });
-        }
-    }
-
-    /** Sets the current picture-in-picture aspect ratio. */
-    public void setPictureInPictureAspectRatio(float aspectRatio) {
-        synchronized (mWindowMap) {
-            if (!mService.mSupportsPictureInPicture || mContainer == null) {
-                return;
-            }
-
-            final int displayId = mContainer.getDisplayContent().getDisplayId();
-            final Rect toBounds = mService.getPictureInPictureBounds(displayId, aspectRatio);
-            final Rect targetBounds = new Rect();
-            mContainer.getAnimatingBounds(targetBounds);
-            if (!toBounds.equals(targetBounds)) {
-                animateResizePinnedStack(toBounds, -1 /* duration */);
-            }
-
-            final PinnedStackController pinnedStackController =
-                    mContainer.getDisplayContent().getPinnedStackController();
-            pinnedStackController.setAspectRatio(
-                    pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio)
-                            ? aspectRatio : -1f);
-        }
-    }
-
-    /** Sets the current picture-in-picture actions. */
-    public void setPictureInPictureActions(List<RemoteAction> actions) {
-        synchronized (mWindowMap) {
-            if (!mService.mSupportsPictureInPicture || mContainer == null) {
-                return;
-            }
-
-            mContainer.getDisplayContent().getPinnedStackController().setActions(actions);
-        }
-    }
-
     public void getStackDockedModeBounds(Rect outBounds, Rect outTempBounds,
             Rect outTempInsetBounds, boolean ignoreVisibility) {
         synchronized (mWindowMap) {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index ab9a378..99c085f 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -133,7 +133,6 @@
     void addChild(AppWindowToken wtoken, int position) {
         position = getAdjustedAddPosition(position);
         super.addChild(wtoken, position);
-        wtoken.mTask = this;
         mDeferRemoval = false;
     }
 
@@ -244,7 +243,6 @@
                 removeIfPossible();
             }
         }
-        token.mTask = null;
     }
 
     void setSendingToBottom(boolean toBottom) {
@@ -592,8 +590,15 @@
         return mStack != null && mStack.mStackId == PINNED_STACK_ID;
     }
 
+    /**
+     * When we are in a floating stack (Freeform, Pinned, ...) we calculate
+     * insets differently. However if we are animating to the fullscreen stack
+     * we need to begin calculating insets as if we were fullscreen, otherwise
+     * we will have a jump at the end.
+     */
     boolean isFloating() {
-        return StackId.tasksAreFloating(mStack.mStackId);
+        return StackId.tasksAreFloating(mStack.mStackId)
+            && !mStack.isBoundsAnimatingToFullscreen();
     }
 
     WindowState getTopVisibleAppMainWindow() {
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index 90106a9..53c24e1 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -215,7 +215,7 @@
                                     : DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
                             mService.mActivityManager.moveTaskToDockedStack(
                                     mTask.mTaskId, createMode, true /*toTop*/, true /* animate */,
-                                    null /* initialBounds */, false /* moveHomeStackFront */);
+                                    null /* initialBounds */);
                         }
                     } catch(RemoteException e) {}
 
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotCache.java b/services/core/java/com/android/server/wm/TaskSnapshotCache.java
index 601bf28..4028336 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotCache.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotCache.java
@@ -106,8 +106,8 @@
         if (taskId != null) {
             removeRunningEntry(taskId);
         }
-        if (wtoken.mTask != null) {
-            mRetrievalCache.remove(wtoken.mTask.mTaskId);
+        if (wtoken.getTask() != null) {
+            mRetrievalCache.remove(wtoken.getTask().mTaskId);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 2b74f84..5995bba 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -19,6 +19,7 @@
 import static android.app.ActivityManager.ENABLE_TASK_SNAPSHOTS;
 
 import android.annotation.Nullable;
+import android.app.ActivityManager;
 import android.app.ActivityManager.StackId;
 import android.app.ActivityManager.TaskSnapshot;
 import android.graphics.GraphicBuffer;
@@ -65,26 +66,22 @@
     }
 
     void onTransitionStarting() {
-        if (!ENABLE_TASK_SNAPSHOTS) {
-            return;
-        }
         handleClosingApps(mService.mClosingApps);
     }
 
-
     /**
      * Called when the visibility of an app changes outside of the regular app transition flow.
      */
     void notifyAppVisibilityChanged(AppWindowToken appWindowToken, boolean visible) {
-        if (!ENABLE_TASK_SNAPSHOTS) {
-            return;
-        }
         if (!visible) {
             handleClosingApps(Sets.newArraySet(appWindowToken));
         }
     }
 
     private void handleClosingApps(ArraySet<AppWindowToken> closingApps) {
+        if (!ENABLE_TASK_SNAPSHOTS || ActivityManager.isLowRamDeviceStatic()) {
+            return;
+        }
 
         // We need to take a snapshot of the task if and only if all activities of the task are
         // either closing or hidden.
@@ -144,11 +141,12 @@
         outClosingTasks.clear();
         for (int i = closingApps.size() - 1; i >= 0; i--) {
             final AppWindowToken atoken = closingApps.valueAt(i);
+            final Task task = atoken.getTask();
 
             // If the task of the app is not visible anymore, it means no other app in that task
             // is opening. Thus, the task is closing.
-            if (atoken.mTask != null && !atoken.mTask.isVisible()) {
-                outClosingTasks.add(closingApps.valueAt(i).mTask);
+            if (task != null && !task.isVisible()) {
+                outClosingTasks.add(task);
             }
         }
     }
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 9f52412..9f34bd7 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -96,9 +96,11 @@
             // TODO: Inherit behavior whether to draw behind status bar/nav bar.
             layoutParams.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                     | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
-            layoutParams.setTitle(String.format(TITLE_FORMAT, token.mTask.mTaskId));
-            if (token.mTask != null) {
-                final TaskDescription taskDescription = token.mTask.getTaskDescription();
+            final Task task = token.getTask();
+            if (task != null) {
+                layoutParams.setTitle(String.format(TITLE_FORMAT,task.mTaskId));
+
+                final TaskDescription taskDescription = task.getTaskDescription();
                 if (taskDescription != null) {
                     fillBackgroundColor = taskDescription.getBackgroundColor();
                 }
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index b9429f4..7588b71 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -19,6 +19,7 @@
 import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
 import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
 import static android.app.ActivityManager.StackId.HOME_STACK_ID;
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
@@ -125,6 +126,7 @@
     // perfectly fit the region it would have been cropped to. We may also avoid certain logic we
     // would otherwise apply while resizing, while resizing in the bounds animating mode.
     private boolean mBoundsAnimating = false;
+    private boolean mBoundsAnimatingToFullscreen = false;
     private Rect mBoundsAnimationTarget = new Rect();
 
     // Temporary storage for the new bounds that should be used after the configuration change.
@@ -260,6 +262,12 @@
 
         if (mDisplayContent != null) {
             mDisplayContent.mDimLayerController.updateDimLayer(this);
+            if (mStackId == PINNED_STACK_ID) {
+                // Update the bounds based on any changes to the display info
+                getAnimatingBounds(mTmpRect2);
+                mDisplayContent.mPinnedStackControllerLocked.onTaskStackBoundsChanged(mTmpRect2,
+                        bounds);
+            }
             mAnimationBackgroundSurface.setBounds(bounds);
         }
 
@@ -389,15 +397,18 @@
             return false;
         }
 
+        if (StackId.tasksAreFloating(mStackId)) {
+            // Update stack bounds again since the display info has changed since updateDisplayInfo,
+            // however, for floating tasks, we don't need to apply the new rotation to the bounds,
+            // we can just update and return them here
+            setBounds(mBounds);
+            mBoundsAfterRotation.set(mBounds);
+            return true;
+        }
+
         mTmpRect2.set(mBounds);
         mDisplayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
         switch (mStackId) {
-            case PINNED_STACK_ID:
-                Rect targetBounds = new Rect();
-                getAnimatingBounds(targetBounds);
-                mTmpRect2 = mDisplayContent.getPinnedStackController().onDisplayChanged(mBounds,
-                        targetBounds, mDisplayContent);
-                break;
             case DOCKED_STACK_ID:
                 repositionDockedStackAfterRotation(mTmpRect2);
                 snapDockedStackAfterRotation(mTmpRect2);
@@ -633,7 +644,7 @@
         }
         for (int appNdx = mExitingAppTokens.size() - 1; appNdx >= 0; --appNdx) {
             final AppWindowToken wtoken = mExitingAppTokens.get(appNdx);
-            if (wtoken.mTask == task) {
+            if (wtoken.getTask() == task) {
                 wtoken.mIsExiting = false;
                 mExitingAppTokens.remove(appNdx);
             }
@@ -649,7 +660,6 @@
         mAnimationBackgroundSurface = new DimLayer(mService, this, mDisplayContent.getDisplayId(),
                 "animation background stackId=" + mStackId);
 
-        final Rect oldBounds = new Rect(mBounds);
         Rect bounds = null;
         final TaskStack dockedStack = dc.getDockedStackIgnoringVisibility();
         if (mStackId == DOCKED_STACK_ID
@@ -673,15 +683,6 @@
         }
 
         updateDisplayInfo(bounds);
-
-        // Update the pinned stack controller after the display info is updated
-        if (mStackId == PINNED_STACK_ID) {
-            Rect targetBounds = new Rect();
-            getAnimatingBounds(targetBounds);
-            mDisplayContent.getPinnedStackController().onDisplayChanged(oldBounds, targetBounds,
-                    mDisplayContent);
-        }
-
         super.onDisplayChanged(dc);
     }
 
@@ -1424,16 +1425,6 @@
     }
 
     public boolean setPinnedStackSize(Rect bounds, Rect tempTaskBounds) {
-        synchronized (mService.mWindowMap) {
-            if (mDisplayContent == null) {
-                return false;
-            }
-            if (mStackId != PINNED_STACK_ID) {
-                Slog.w(TAG_WM, "Attempt to use pinned stack resize animation helper on"
-                        + "non pinned stack");
-                return false;
-            }
-        }
         try {
             mService.mActivityManager.resizePinnedStack(bounds, tempTaskBounds);
         } catch (RemoteException e) {
@@ -1443,9 +1434,18 @@
     }
 
     @Override  // AnimatesBounds
-    public void onAnimationStart() {
+    public void onAnimationStart(boolean toFullscreen) {
         synchronized (mService.mWindowMap) {
             mBoundsAnimating = true;
+            mBoundsAnimatingToFullscreen = toFullscreen;
+        }
+
+        if (mStackId == PINNED_STACK_ID) {
+            try {
+                mService.mActivityManager.notifyPinnedStackAnimationStarted();
+            } catch (RemoteException e) {
+                // I don't believe you...
+            }
         }
     }
 
@@ -1456,6 +1456,7 @@
             mBoundsAnimationTarget.setEmpty();
             mService.requestTraversal();
         }
+
         if (mStackId == PINNED_STACK_ID) {
             try {
                 mService.mActivityManager.notifyPinnedStackAnimationEnded();
@@ -1474,19 +1475,11 @@
         }
     }
 
-    @Override
-    public void getFullScreenBounds(Rect bounds) {
-        // This is currently only used for the pinned stack animation when leaving PiP
-        // (see {@link BoundsAnimationController}), and in that case we need to animate this back
-        // to the full bounds to match the fullscreen stack
-        getDisplayContent().getLogicalDisplayRect(bounds);
-    }
-
     public boolean hasMovementAnimations() {
         return StackId.hasMovementAnimations(mStackId);
     }
 
-    public boolean getForceScaleToStack() {
+    public boolean isForceScaled() {
         return mBoundsAnimating;
     }
 
@@ -1494,6 +1487,10 @@
         return mBoundsAnimating;
     }
 
+    public boolean isBoundsAnimatingToFullscreen() {
+        return mBoundsAnimating && mBoundsAnimatingToFullscreen;
+    }
+
     /** Returns true if a removal action is still being deferred. */
     boolean checkCompleteDeferredRemoval() {
         if (isAnimating()) {
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index c32e689..7213c95 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -547,6 +547,7 @@
         for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
             final WallpaperWindowToken token = mWallpaperTokens.get(curTokenNdx);
             token.updateWallpaperWindows(visible, mWallpaperAnimLayerAdjustment);
+            token.getDisplayContent().assignWindowLayers(false);
         }
     }
 
@@ -568,7 +569,7 @@
             // Only do this if we are not transferring between two wallpaper targets.
             mWallpaperAnimLayerAdjustment =
                     (mPrevWallpaperTarget == null && mWallpaperTarget.mAppToken != null)
-                            ? mWallpaperTarget.mAppToken.mAppAnimator.animLayerAdjustment : 0;
+                            ? mWallpaperTarget.mAppToken.getAnimLayerAdjustment() : 0;
 
             if (mWallpaperTarget.mWallpaperX >= 0) {
                 mLastWallpaperX = mWallpaperTarget.mWallpaperX;
diff --git a/services/core/java/com/android/server/wm/WallpaperWindowToken.java b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
index 28aebbb..a12c0e5 100644
--- a/services/core/java/com/android/server/wm/WallpaperWindowToken.java
+++ b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
@@ -142,7 +142,6 @@
 
             // First, make sure the client has the current visibility state.
             wallpaper.dispatchWallpaperVisibility(visible);
-            wallpaper.adjustAnimLayer(animLayerAdj);
 
             if (DEBUG_LAYERS || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "adjustWallpaper win "
                     + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
diff --git a/services/core/java/com/android/server/wm/WindowLayersController.java b/services/core/java/com/android/server/wm/WindowLayersController.java
index 1cd2b53d..172ec48 100644
--- a/services/core/java/com/android/server/wm/WindowLayersController.java
+++ b/services/core/java/com/android/server/wm/WindowLayersController.java
@@ -129,7 +129,7 @@
             final WindowStateAnimator winAnimator = w.mWinAnimator;
             Slog.v(TAG_WM, "Assign layer " + w + ": " + "mBase=" + w.mBaseLayer
                     + " mLayer=" + w.mLayer + (w.mAppToken == null
-                    ? "" : " mAppLayer=" + w.mAppToken.mAppAnimator.animLayerAdjustment)
+                    ? "" : " mAppLayer=" + w.mAppToken.getAnimLayerAdjustment())
                     + " =mAnimLayer=" + winAnimator.mAnimLayer);
         }, false /* traverseTopToBottom */);
     }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 5653113..8b859d1 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -16,16 +16,19 @@
 
 package com.android.server.wm;
 
-import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
 import static android.Manifest.permission.MANAGE_APP_TOKENS;
 import static android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS;
 import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.app.AppOpsManager.MODE_IGNORED;
+import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
 import static android.app.StatusBarManager.DISABLE_MASK;
+import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
 import static android.content.Intent.ACTION_USER_REMOVED;
+import static android.content.Intent.EXTRA_PACKAGE_NAME;
+import static android.content.Intent.EXTRA_UID;
 import static android.content.Intent.EXTRA_USER_HANDLE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.os.UserHandle.USER_NULL;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.WindowManager.DOCKED_INVALID;
@@ -64,8 +67,7 @@
 import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
 import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_END;
 import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_START;
-import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
-import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
+import static com.android.server.wm.KeyguardDisableHandler.KEYGUARD_POLICY_CHANGED;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
@@ -106,7 +108,6 @@
 import android.app.ActivityManagerInternal;
 import android.app.AppOpsManager;
 import android.app.IActivityManager;
-import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -128,6 +129,7 @@
 import android.hardware.display.DisplayManagerInternal;
 import android.hardware.input.InputManager;
 import android.net.Uri;
+import android.os.PowerSaveState;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
@@ -218,6 +220,7 @@
 import com.android.server.UiThread;
 import com.android.server.Watchdog;
 import com.android.server.input.InputManagerService;
+import com.android.server.power.BatterySaverPolicy.ServiceType;
 import com.android.server.power.ShutdownThread;
 
 import java.io.BufferedWriter;
@@ -343,20 +346,34 @@
 
     final private KeyguardDisableHandler mKeyguardDisableHandler;
 
-    final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+    static final String ACTION_REVOKE_SYSTEM_ALERT_WINDOW_PERMISSION =
+            "com.android.server.wm.ACTION_REVOKE_SYSTEM_ALERT_WINDOW_PERMISSION";
+
+    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            final String action = intent.getAction();
-            if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) {
-                mKeyguardDisableHandler.sendEmptyMessage(
-                    KeyguardDisableHandler.KEYGUARD_POLICY_CHANGED);
-            } else if (ACTION_USER_REMOVED.equals(action)) {
-                final int userId = intent.getIntExtra(EXTRA_USER_HANDLE, USER_NULL);
-                if (userId != USER_NULL) {
-                    synchronized (mWindowMap) {
-                        mScreenCaptureDisabled.remove(userId);
+            switch (intent.getAction()) {
+                case ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED:
+                    mKeyguardDisableHandler.sendEmptyMessage(KEYGUARD_POLICY_CHANGED);
+                    break;
+                case ACTION_USER_REMOVED:
+                    final int userId = intent.getIntExtra(EXTRA_USER_HANDLE, USER_NULL);
+                    if (userId != USER_NULL) {
+                        synchronized (mWindowMap) {
+                            mScreenCaptureDisabled.remove(userId);
+                        }
                     }
-                }
+                    break;
+                case ACTION_REVOKE_SYSTEM_ALERT_WINDOW_PERMISSION:
+                    final String packageName = intent.getStringExtra(EXTRA_PACKAGE_NAME);
+                    final int uid = intent.getIntExtra(EXTRA_UID, -1);
+                    if (packageName != null && uid != -1) {
+                        synchronized (mWindowMap) {
+                            // Revoke permission.
+                            mAppOps.setMode(OP_SYSTEM_ALERT_WINDOW, uid, packageName, MODE_IGNORED);
+                        }
+                    }
+                    break;
             }
         }
     };
@@ -606,9 +623,14 @@
     WindowState mCurrentFocus = null;
     WindowState mLastFocus = null;
 
-    /** This just indicates the window the input method is on top of, not
-     * necessarily the window its input is going to. */
+    // TODO: All the IME window tracking should be moved to DisplayContent and tracked per display.
+    // This just indicates the window the input method is on top of, not necessarily the window its
+    // input is going to.
     WindowState mInputMethodTarget = null;
+    // The binder token currently using the IME as determined by the input method service.
+    // Window manager uses this to determine the final input method target
+    // (almost always this candidate) for z-ordering.
+    IBinder mInputMethodTargetCandidate = null;
 
     /** If true hold off on modifying the animation layer of mInputMethodTarget */
     boolean mInputMethodTargetWaitingAnim;
@@ -989,15 +1011,26 @@
         mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
 
         if (mPowerManagerInternal != null) {
-            mPowerManagerInternal.registerLowPowerModeObserver((enabled) -> {
-                synchronized (mWindowMap) {
-                    if (mAnimationsDisabled != enabled && !mAllowAnimationsInLowPowerMode) {
-                        mAnimationsDisabled = enabled;
-                        dispatchNewAnimatorScaleLocked(null);
+            mPowerManagerInternal.registerLowPowerModeObserver(
+                    new PowerManagerInternal.LowPowerModeListener() {
+                @Override
+                public int getServiceType() {
+                    return ServiceType.ANIMATION;
+                }
+
+                @Override
+                public void onLowPowerModeChanged(PowerSaveState result) {
+                    synchronized (mWindowMap) {
+                        final boolean enabled = result.batterySaverEnabled;
+                        if (mAnimationsDisabled != enabled && !mAllowAnimationsInLowPowerMode) {
+                            mAnimationsDisabled = enabled;
+                            dispatchNewAnimatorScaleLocked(null);
+                        }
                     }
                 }
             });
-            mAnimationsDisabled = mPowerManagerInternal.getLowPowerModeEnabled();
+            mAnimationsDisabled = mPowerManagerInternal
+                    .getLowPowerState(ServiceType.ANIMATION).batterySaverEnabled;
         }
         mScreenFrozenLock = mPowerManager.newWakeLock(
                 PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN");
@@ -1006,8 +1039,8 @@
         mAppTransition = new AppTransition(context, this);
         mAppTransition.registerListenerLocked(mActivityManagerAppTransitionNotifier);
 
-        mBoundsAnimationController =
-                new BoundsAnimationController(mAppTransition, UiThread.getHandler());
+        mBoundsAnimationController = new BoundsAnimationController(context, mAppTransition,
+                UiThread.getHandler());
 
         mActivityManager = ActivityManager.getService();
         mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
@@ -1018,7 +1051,7 @@
                         updateAppOpsState();
                     }
                 };
-        mAppOps.startWatchingMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, null, opListener);
+        mAppOps.startWatchingMode(OP_SYSTEM_ALERT_WINDOW, null, opListener);
         mAppOps.startWatchingMode(AppOpsManager.OP_TOAST_WINDOW, null, opListener);
 
         // Get persisted window scale setting
@@ -1034,9 +1067,10 @@
 
         IntentFilter filter = new IntentFilter();
         // Track changes to DevicePolicyManager state so we can enable/disable keyguard.
-        filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
+        filter.addAction(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
         // Listen to user removal broadcasts so that we can remove the user-specific data.
         filter.addAction(Intent.ACTION_USER_REMOVED);
+        filter.addAction(ACTION_REVOKE_SYSTEM_ALERT_WINDOW_PERMISSION);
         mContext.registerReceiver(mBroadcastReceiver, filter);
 
         mSettingsObserver = new SettingsObserver();
@@ -1111,8 +1145,6 @@
         long origId;
         final int callingUid = Binder.getCallingUid();
         final int type = attrs.type;
-        final boolean ownerCanAddInternalSystemWindow =
-                mContext.checkCallingPermission(INTERNAL_SYSTEM_WINDOW) == PERMISSION_GRANTED;
 
         synchronized(mWindowMap) {
             if (!mDisplayReady) {
@@ -1215,7 +1247,7 @@
                     }
                 }
                 token = new WindowToken(this, attrs.token, type, false, displayContent,
-                        ownerCanAddInternalSystemWindow);
+                        session.mCanAddInternalSystemWindow);
             } else if (rootType >= FIRST_APPLICATION_WINDOW && rootType <= LAST_APPLICATION_WINDOW) {
                 atoken = token.asAppWindowToken();
                 if (atoken == null) {
@@ -1286,12 +1318,12 @@
                 // instead make a new token for it (as if null had been passed in for the token).
                 attrs.token = null;
                 token = new WindowToken(this, null, type, false, displayContent,
-                        ownerCanAddInternalSystemWindow);
+                        session.mCanAddInternalSystemWindow);
             }
 
             final WindowState win = new WindowState(this, session, client, token, parentWindow,
                     appOp[0], seq, attrs, viewVisibility, session.mUid,
-                    ownerCanAddInternalSystemWindow);
+                    session.mCanAddInternalSystemWindow);
             if (win.mDeathRecipient == null) {
                 // Client has apparently died, so there is no reason to
                 // continue.
@@ -1426,9 +1458,9 @@
             if (displayContent.isDefaultDisplay) {
                 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
                 final Rect taskBounds;
-                if (atoken != null && atoken.mTask != null) {
+                if (atoken != null && atoken.getTask() != null) {
                     taskBounds = mTmpRect;
-                    atoken.mTask.getBounds(mTmpRect);
+                    atoken.getTask().getBounds(mTmpRect);
                 } else {
                     taskBounds = null;
                 }
@@ -1984,7 +2016,7 @@
             if (viewVisibility == View.VISIBLE &&
                     (win.mAppToken == null || win.mAttrs.type == TYPE_APPLICATION_STARTING
                             || !win.mAppToken.clientHidden)) {
-                result = relayoutVisibleWindow(outConfig, result, win, winAnimator, attrChanges,
+                result = win.relayoutVisibleWindow(outConfig, result, attrChanges,
                         oldVisibility);
                 try {
                     result = createSurfaceControl(outSurface, result, win, winAnimator);
@@ -2202,69 +2234,6 @@
         return result;
     }
 
-    private int relayoutVisibleWindow(Configuration outConfig, int result, WindowState win,
-            WindowStateAnimator winAnimator, int attrChanges, int oldVisibility) {
-        result |= !win.isVisibleLw() ? WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME : 0;
-        if (win.mAnimatingExit) {
-            Slog.d(TAG, "relayoutVisibleWindow: " + win + " mAnimatingExit=true, mRemoveOnExit="
-                    + win.mRemoveOnExit + ", mDestroying=" + win.mDestroying);
-
-            winAnimator.cancelExitAnimationForNextAnimationLocked();
-            win.mAnimatingExit = false;
-        }
-        if (win.mDestroying) {
-            win.mDestroying = false;
-            mDestroySurface.remove(win);
-        }
-        if (oldVisibility == View.GONE) {
-            winAnimator.mEnterAnimationPending = true;
-        }
-
-        win.mLastVisibleLayoutRotation = mRotation;
-
-        winAnimator.mEnteringAnimation = true;
-        if ((result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
-            win.prepareWindowToDisplayDuringRelayout(outConfig);
-        }
-        if ((attrChanges & LayoutParams.FORMAT_CHANGED) != 0) {
-            // If the format can't be changed in place, preserve the old surface until the app draws
-            // on the new one. This prevents blinking when we change elevation of freeform and
-            // pinned windows.
-            if (!winAnimator.tryChangeFormatInPlaceLocked()) {
-                winAnimator.preserveSurfaceLocked();
-                result |= RELAYOUT_RES_SURFACE_CHANGED
-                        | WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME;
-            }
-        }
-
-        // If we're starting a drag-resize, we'll be changing the surface size as well as
-        // notifying the client to render to with an offset from the surface's top-left.
-        if (win.isDragResizeChanged() || win.isResizedWhileNotDragResizing()) {
-            win.setDragResizing();
-            win.setResizedWhileNotDragResizing(false);
-            // We can only change top level windows to the full-screen surface when
-            // resizing (as we only have one full-screen surface). So there is no need
-            // to preserve and destroy windows which are attached to another, they
-            // will keep their surface and its size may change over time.
-            if (win.mHasSurface && !win.isChildWindow()) {
-                winAnimator.preserveSurfaceLocked();
-                result |= WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME;
-            }
-        }
-        final boolean freeformResizing = win.isDragResizing()
-                && win.getResizeMode() == DRAG_RESIZE_MODE_FREEFORM;
-        final boolean dockedResizing = win.isDragResizing()
-                && win.getResizeMode() == DRAG_RESIZE_MODE_DOCKED_DIVIDER;
-        result |= freeformResizing ? WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_FREEFORM : 0;
-        result |= dockedResizing ? WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_DOCKED : 0;
-        if (win.isAnimatingWithSavedSurface()) {
-            // If we're animating with a saved surface now, request client to report draw.
-            // We still need to know when the real thing is drawn.
-            result |= WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME;
-        }
-        return result;
-    }
-
     public void performDeferredDestroyWindow(Session session, IWindow client) {
         long origId = Binder.clearCallingIdentity();
 
@@ -2327,7 +2296,7 @@
         // is running.
         Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "WM#applyAnimationLocked");
         if (okToDisplay()) {
-            final DisplayContent displayContent = atoken.mTask.getDisplayContent();
+            final DisplayContent displayContent = atoken.getTask().getDisplayContent();
             final DisplayInfo displayInfo = displayContent.getDisplayInfo();
             final int width = displayInfo.appWidth;
             final int height = displayInfo.appHeight;
@@ -2368,7 +2337,7 @@
             final Configuration displayConfig = displayContent.getConfiguration();
             Animation a = mAppTransition.loadAnimation(lp, transit, enter, displayConfig.uiMode,
                     displayConfig.orientation, frame, displayFrame, insets, surfaceInsets,
-                    isVoiceInteraction, freeform, atoken.mTask.mTaskId);
+                    isVoiceInteraction, freeform, atoken.getTask().mTaskId);
             if (a != null) {
                 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + atoken);
                 final int containingWidth = frame.width();
@@ -2588,8 +2557,8 @@
     }
 
     void setFocusTaskRegionLocked(AppWindowToken previousFocus) {
-        final Task focusedTask = mFocusedApp != null ? mFocusedApp.mTask : null;
-        final Task previousTask = previousFocus != null ? previousFocus.mTask : null;
+        final Task focusedTask = mFocusedApp != null ? mFocusedApp.getTask() : null;
+        final Task previousTask = previousFocus != null ? previousFocus.getTask() : null;
         final DisplayContent focusedDisplayContent =
                 focusedTask != null ? focusedTask.getDisplayContent() : null;
         final DisplayContent previousDisplayContent =
@@ -5120,8 +5089,8 @@
         // Also don't use mInputMethodTarget's stack, because some window with FLAG_NOT_FOCUSABLE
         // and FLAG_ALT_FOCUSABLE_IM flags both set might be set to IME target so they're moved
         // to make room for IME, but the window is not the focused window that's taking input.
-        return (mFocusedApp != null && mFocusedApp.mTask != null) ?
-                mFocusedApp.mTask.mStack : null;
+        return (mFocusedApp != null && mFocusedApp.getTask() != null) ?
+                mFocusedApp.getTask().mStack : null;
     }
 
     public boolean detectSafeMode() {
@@ -5216,7 +5185,7 @@
     // Async Handler
     // -------------------------------------------------------------
 
-    final class H extends Handler {
+    final class H extends android.os.Handler {
         public static final int REPORT_FOCUS_CHANGE = 2;
         public static final int REPORT_LOSING_FOCUS = 3;
         public static final int DO_TRAVERSAL = 4;
@@ -5932,8 +5901,8 @@
                     if (displayContent.mBaseDisplayWidth != width
                             || displayContent.mBaseDisplayHeight != height) {
                         Slog.i(TAG_WM, "FORCED DISPLAY SIZE: " + width + "x" + height);
-                        displayContent.updateBaseDisplayMetrics(width, height,
-                                displayContent.mBaseDisplayDensity);
+                        displayContent.mBaseDisplayWidth = width;
+                        displayContent.mBaseDisplayHeight = height;
                     }
                 } catch (NumberFormatException ex) {
                 }
@@ -5958,7 +5927,8 @@
     // displayContent must not be null
     private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
         Slog.i(TAG_WM, "Using new display size: " + width + "x" + height);
-        displayContent.updateBaseDisplayMetrics(width, height, displayContent.mBaseDisplayDensity);
+        displayContent.mBaseDisplayWidth = width;
+        displayContent.mBaseDisplayHeight = height;
         reconfigureDisplayLocked(displayContent);
     }
 
@@ -6994,8 +6964,9 @@
             pw.print("  mLastFocus="); pw.println(mLastFocus);
         }
         pw.print("  mFocusedApp="); pw.println(mFocusedApp);
-        if (mInputMethodTarget != null) {
-            pw.print("  mInputMethodTarget="); pw.println(mInputMethodTarget);
+        if (mInputMethodTarget != null || mInputMethodTargetCandidate != null) {
+            pw.println("  mInputMethodTarget=" + mInputMethodTarget
+                    + " mInputMethodTargetCandidate=" + getWindow(mInputMethodTargetCandidate));
         }
         pw.print("  mInTouchMode="); pw.print(mInTouchMode);
                 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
@@ -7310,10 +7281,6 @@
         return mRoot.getDisplayContentOrCreate(DEFAULT_DISPLAY);
     }
 
-    private DisplayInfo getDefaultDisplayInfoLocked() {
-        return getDefaultDisplayContentLocked().getDisplayInfo();
-    }
-
     public void onDisplayAdded(int displayId) {
         mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0));
     }
@@ -7866,11 +7833,28 @@
         @Override
         public void updateInputMethodWindowStatus(@NonNull IBinder imeToken,
                 boolean imeWindowVisible, @Nullable IBinder targetWindowToken) {
-            // TODO (b/34628091): Use this method to address the window animation issue.
-            if (DEBUG_INPUT_METHOD) {
-                Slog.w(TAG_WM, "updateInputMethodWindowStatus: imeToken=" + imeToken
-                        + " imeWindowVisible=" + imeWindowVisible
-                        + " targetWindowToken=" + targetWindowToken);
+            synchronized (mWindowMap) {
+                final WindowState newTargetWin = getWindow(targetWindowToken);
+                final WindowState currentTargetWin = getWindow(mInputMethodTargetCandidate);
+
+                if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "updateInputMethodWindowStatus: imeToken="
+                        + imeToken + " imeWindowVisible=" + imeWindowVisible
+                        + " targetWindowToken=" + targetWindowToken
+                        + " newTargetWin=" + newTargetWin
+                        + " currentTargetWin=" + currentTargetWin);
+
+                if (newTargetWin == currentTargetWin) {
+                    return;
+                }
+
+                final DisplayContent dc = newTargetWin != null
+                        ? newTargetWin.getDisplayContent() : currentTargetWin.getDisplayContent();
+
+                // It is possible the window for the target candidate isn't added yet, so we
+                // remember the token instead and use it to look-up the window each time we compute
+                // the ime target.
+                mInputMethodTargetCandidate = targetWindowToken;
+                dc.computeImeTarget(true /* updateImeTarget */);
             }
         }
 
@@ -7916,6 +7900,10 @@
         }
     }
 
+    WindowState getWindow(IBinder binder) {
+        return binder == null ? null : mWindowMap.get(binder);
+    }
+
     void registerAppFreezeListener(AppFreezeListener listener) {
         if (!mAppFreezeListeners.contains(listener)) {
             mAppFreezeListeners.add(listener);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 7de6856..6d572d7 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -40,6 +40,7 @@
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
 import static android.view.WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
+import static android.view.WindowManager.LayoutParams.FORMAT_CHANGED;
 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
 import static android.view.WindowManager.LayoutParams.MATCH_PARENT;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
@@ -56,6 +57,10 @@
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+import static android.view.WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_DOCKED;
+import static android.view.WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_FREEFORM;
+import static android.view.WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME;
+import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
 import static android.view.WindowManagerPolicy.TRANSIT_ENTER;
 import static android.view.WindowManagerPolicy.TRANSIT_EXIT;
@@ -540,6 +545,12 @@
     private static final Region sEmptyRegion = new Region();
 
     /**
+     * Surface insets from the previous call to relayout(), used to track
+     * if we are changing the Surface insets.
+     */
+    final Rect mLastSurfaceInsets = new Rect();
+
+    /**
      * Compares two window sub-layers and returns -1 if the first is lesser than the second in terms
      * of z-order and 1 otherwise.
      */
@@ -665,7 +676,7 @@
 
     void attach() {
         if (localLOGV) Slog.v(TAG, "Attaching " + this + " token=" + mToken);
-        mSession.windowAddedLocked(mAttrs.type);
+        mSession.windowAddedLocked(mAttrs.packageName);
     }
 
     @Override
@@ -833,20 +844,24 @@
         // Make sure the content and visible frames are inside of the
         // final window frame.
         if (windowsAreFloating && !mFrame.isEmpty()) {
+            // For pinned workspace the frame isn't limited in any particular
+            // way since SystemUI controls the bounds. For freeform however
+            // we want to keep things inside the content frame.
+            final Rect limitFrame = task.inPinnedWorkspace() ? mFrame : mContentFrame;
             // Keep the frame out of the blocked system area, limit it in size to the content area
             // and make sure that there is always a minimum visible so that the user can drag it
             // into a usable area..
-            final int height = Math.min(mFrame.height(), mContentFrame.height());
-            final int width = Math.min(mContentFrame.width(), mFrame.width());
+            final int height = Math.min(mFrame.height(), limitFrame.height());
+            final int width = Math.min(limitFrame.width(), mFrame.width());
             final DisplayMetrics displayMetrics = getDisplayContent().getDisplayMetrics();
             final int minVisibleHeight = Math.min(height, WindowManagerService.dipToPixel(
                     MINIMUM_VISIBLE_HEIGHT_IN_DP, displayMetrics));
             final int minVisibleWidth = Math.min(width, WindowManagerService.dipToPixel(
                     MINIMUM_VISIBLE_WIDTH_IN_DP, displayMetrics));
-            final int top = Math.max(mContentFrame.top,
-                    Math.min(mFrame.top, mContentFrame.bottom - minVisibleHeight));
-            final int left = Math.max(mContentFrame.left + minVisibleWidth - width,
-                    Math.min(mFrame.left, mContentFrame.right - minVisibleWidth));
+            final int top = Math.max(limitFrame.top,
+                    Math.min(mFrame.top, limitFrame.bottom - minVisibleHeight));
+            final int left = Math.max(limitFrame.left + minVisibleWidth - width,
+                    Math.min(mFrame.left, limitFrame.right - minVisibleWidth));
             mFrame.set(left, top, left + width, top + height);
             mContentFrame.set(mFrame);
             mVisibleFrame.set(mContentFrame);
@@ -1191,7 +1206,7 @@
     }
 
     Task getTask() {
-        return mAppToken != null ? mAppToken.mTask : null;
+        return mAppToken != null ? mAppToken.getTask() : null;
     }
 
     TaskStack getStack() {
@@ -1581,7 +1596,7 @@
             // Anyway we don't need to synchronize position and content updates for these
             // windows since they aren't at the base layer and could be moved around anyway.
             if (!computeDragResizing() && mAttrs.type == TYPE_BASE_APPLICATION &&
-                    !getTask().mStack.getBoundsAnimating() && !isGoneForLayoutLw() &&
+                    !mWinAnimator.isForceScaled() && !isGoneForLayoutLw() &&
                     !getTask().inPinnedWorkspace()) {
                 setResizedWhileNotDragResizing(true);
             }
@@ -1738,7 +1753,7 @@
 
         mWinAnimator.destroyDeferredSurfaceLocked();
         mWinAnimator.destroySurfaceLocked();
-        mSession.windowRemovedLocked(mAttrs.type);
+        mSession.windowRemovedLocked();
         try {
             mClient.asBinder().unlinkToDeath(mDeathRecipient, 0);
         } catch (RuntimeException e) {
@@ -1912,16 +1927,11 @@
         if (mIsImWindow && mService.mInputMethodTarget != null) {
             final AppWindowToken appToken = mService.mInputMethodTarget.mAppToken;
             if (appToken != null) {
-                return appToken.mAppAnimator.animLayerAdjustment;
+                return appToken.getAnimLayerAdjustment();
             }
         }
 
-        if (mAppToken != null) {
-            return mAppToken.mAppAnimator.animLayerAdjustment;
-        }
-
-        // Nothing is animating, so there is no animation adjustment.
-        return 0;
+        return mToken.getAnimLayerAdjustment();
     }
 
     int getSpecialWindowAnimLayerAdjustment() {
@@ -2372,8 +2382,8 @@
 
     /** @return true if this window desires touch events. */
     boolean canReceiveTouchInput() {
-        return mAppToken != null && mAppToken.mTask != null
-                && mAppToken.mTask.mStack.shouldIgnoreInput();
+        return mAppToken != null && mAppToken.getTask() != null
+                && mAppToken.getTask().mStack.shouldIgnoreInput();
     }
 
     @Override
@@ -2706,29 +2716,32 @@
             destroyedSomething |= c.destroySurface(cleanupOnResume, appStopped);
         }
 
-        if (appStopped || mWindowRemovalAllowed || cleanupOnResume) {
-
-            mWinAnimator.destroyPreservedSurfaceLocked();
-
-            if (mDestroying) {
-                if (DEBUG_ADD_REMOVE) Slog.e(TAG_WM, "win=" + this
-                        + " destroySurfaces: appStopped=" + appStopped
-                        + " win.mWindowRemovalAllowed=" + mWindowRemovalAllowed
-                        + " win.mRemoveOnExit=" + mRemoveOnExit);
-
-                if (!cleanupOnResume || mRemoveOnExit) {
-                    destroyOrSaveSurface();
-                }
-                if (mRemoveOnExit) {
-                    removeImmediately();
-                }
-                if (cleanupOnResume) {
-                    requestUpdateWallpaperIfNeeded();
-                }
-                mDestroying = false;
-                destroyedSomething = true;
-            }
+        if (!(appStopped || mWindowRemovalAllowed || cleanupOnResume)) {
+            return destroyedSomething;
         }
+
+        if (appStopped || mWindowRemovalAllowed) {
+            mWinAnimator.destroyPreservedSurfaceLocked();
+        }
+
+        if (mDestroying) {
+            if (DEBUG_ADD_REMOVE) Slog.e(TAG_WM, "win=" + this
+                    + " destroySurfaces: appStopped=" + appStopped
+                    + " win.mWindowRemovalAllowed=" + mWindowRemovalAllowed
+                    + " win.mRemoveOnExit=" + mRemoveOnExit);
+            if (!cleanupOnResume || mRemoveOnExit) {
+                destroyOrSaveSurface();
+            }
+            if (mRemoveOnExit) {
+                removeImmediately();
+            }
+            if (cleanupOnResume) {
+                requestUpdateWallpaperIfNeeded();
+            }
+            mDestroying = false;
+            destroyedSomething = true;
+        }
+
         return destroyedSomething;
     }
 
@@ -3849,20 +3862,6 @@
         return highest;
     }
 
-    int adjustAnimLayer(int adj) {
-        int highestAnimLayer = mWinAnimator.mAnimLayer = mLayer + adj;
-        if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG_WM,
-                "adjustAnimLayer win=" + this + " anim layer: " + mWinAnimator.mAnimLayer);
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final WindowState childWindow = mChildren.get(i);
-            childWindow.adjustAnimLayer(adj);
-            if (childWindow.mWinAnimator.mAnimLayer > highestAnimLayer) {
-                highestAnimLayer = childWindow.mWinAnimator.mAnimLayer;
-            }
-        }
-        return highestAnimLayer;
-    }
-
     @Override
     boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
         if (mChildren.isEmpty()) {
@@ -3878,7 +3877,7 @@
     }
 
     private boolean forAllWindowBottomToTop(ToBooleanFunction<WindowState> callback) {
-        // We want to consumer the negative sublayer children first because they need to appear
+        // We want to consume the negative sublayer children first because they need to appear
         // below the parent, then this window (the parent), and then the positive sublayer children
         // because they need to appear above the parent.
         int i = 0;
@@ -3886,7 +3885,7 @@
         WindowState child = mChildren.get(i);
 
         while (i < count && child.mSubLayer < 0) {
-            if (callback.apply(child)) {
+            if (child.applyInOrderWithImeWindows(callback, false /* traverseTopToBottom */)) {
                 return true;
             }
             i++;
@@ -3901,7 +3900,7 @@
         }
 
         while (i < count) {
-            if (callback.apply(child)) {
+            if (child.applyInOrderWithImeWindows(callback, false /* traverseTopToBottom */)) {
                 return true;
             }
             i++;
@@ -3915,14 +3914,14 @@
     }
 
     private boolean forAllWindowTopToBottom(ToBooleanFunction<WindowState> callback) {
-        // We want to consumer the positive sublayer children first because they need to appear
+        // We want to consume the positive sublayer children first because they need to appear
         // above the parent, then this window (the parent), and then the negative sublayer children
         // because they need to appear above the parent.
         int i = mChildren.size() - 1;
         WindowState child = mChildren.get(i);
 
         while (i >= 0 && child.mSubLayer >= 0) {
-            if (callback.apply(child)) {
+            if (child.applyInOrderWithImeWindows(callback, true /* traverseTopToBottom */)) {
                 return true;
             }
             --i;
@@ -3937,7 +3936,7 @@
         }
 
         while (i >= 0) {
-            if (callback.apply(child)) {
+            if (child.applyInOrderWithImeWindows(callback, true /* traverseTopToBottom */)) {
                 return true;
             }
             --i;
@@ -3980,10 +3979,43 @@
     }
 
     WindowState getWindow(Predicate<WindowState> callback) {
+        if (mChildren.isEmpty()) {
+            return callback.test(this) ? this : null;
+        }
+
+        // We want to consume the positive sublayer children first because they need to appear
+        // above the parent, then this window (the parent), and then the negative sublayer children
+        // because they need to appear above the parent.
+        int i = mChildren.size() - 1;
+        WindowState child = mChildren.get(i);
+
+        while (i >= 0 && child.mSubLayer >= 0) {
+            if (callback.test(child)) {
+                return child;
+            }
+            --i;
+            if (i < 0) {
+                break;
+            }
+            child = mChildren.get(i);
+        }
+
         if (callback.test(this)) {
             return this;
         }
-        return super.getWindow(callback);
+
+        while (i >= 0) {
+            if (callback.test(child)) {
+                return child;
+            }
+            --i;
+            if (i < 0) {
+                break;
+            }
+            child = mChildren.get(i);
+        }
+
+        return null;
     }
 
     boolean isWindowAnimationSet() {
@@ -4298,6 +4330,79 @@
                 -mAttrs.surfaceInsets.bottom);
     }
 
+    boolean surfaceInsetsChanging() {
+        return !mLastSurfaceInsets.equals(mAttrs.surfaceInsets);
+    }
+
+    int relayoutVisibleWindow(Configuration outConfig, int result,
+            int attrChanges, int oldVisibility) {
+        result |= !isVisibleLw() ? RELAYOUT_RES_FIRST_TIME : 0;
+        if (mAnimatingExit) {
+            Slog.d(TAG, "relayoutVisibleWindow: " + this + " mAnimatingExit=true, mRemoveOnExit="
+                    + mRemoveOnExit + ", mDestroying=" + mDestroying);
+
+            mWinAnimator.cancelExitAnimationForNextAnimationLocked();
+            mAnimatingExit = false;
+        }
+        if (mDestroying) {
+            mDestroying = false;
+            mService.mDestroySurface.remove(this);
+        }
+        if (oldVisibility == View.GONE) {
+            mWinAnimator.mEnterAnimationPending = true;
+        }
+
+        mLastVisibleLayoutRotation = mService.mRotation;
+
+        mWinAnimator.mEnteringAnimation = true;
+        if ((result & RELAYOUT_RES_FIRST_TIME) != 0) {
+            prepareWindowToDisplayDuringRelayout(outConfig);
+        }
+        if ((attrChanges & FORMAT_CHANGED) != 0) {
+            // If the format can't be changed in place, preserve the old surface until the app draws
+            // on the new one. This prevents blinking when we change elevation of freeform and
+            // pinned windows.
+            if (!mWinAnimator.tryChangeFormatInPlaceLocked()) {
+                mWinAnimator.preserveSurfaceLocked();
+                result |= RELAYOUT_RES_SURFACE_CHANGED
+                        | RELAYOUT_RES_FIRST_TIME;
+            }
+        }
+
+        // When we change the Surface size, in scenarios which may require changing
+        // the surface position in sync with the resize, we use a preserved surface
+        // so we can freeze it while waiting for the client to report draw on the newly
+        // sized surface.
+        if (isDragResizeChanged() || isResizedWhileNotDragResizing()
+                || surfaceInsetsChanging()) {
+            mLastSurfaceInsets.set(mAttrs.surfaceInsets);
+
+            setDragResizing();
+            setResizedWhileNotDragResizing(false);
+            // We can only change top level windows to the full-screen surface when
+            // resizing (as we only have one full-screen surface). So there is no need
+            // to preserve and destroy windows which are attached to another, they
+            // will keep their surface and its size may change over time.
+            if (mHasSurface && !isChildWindow()) {
+                mWinAnimator.preserveSurfaceLocked();
+                result |= RELAYOUT_RES_SURFACE_CHANGED |
+                    RELAYOUT_RES_FIRST_TIME;
+            }
+        }
+        final boolean freeformResizing = isDragResizing()
+                && getResizeMode() == DRAG_RESIZE_MODE_FREEFORM;
+        final boolean dockedResizing = isDragResizing()
+                && getResizeMode() == DRAG_RESIZE_MODE_DOCKED_DIVIDER;
+        result |= freeformResizing ? RELAYOUT_RES_DRAG_RESIZING_FREEFORM : 0;
+        result |= dockedResizing ? RELAYOUT_RES_DRAG_RESIZING_DOCKED : 0;
+        if (isAnimatingWithSavedSurface()) {
+            // If we're animating with a saved surface now, request client to report draw.
+            // We still need to know when the real thing is drawn.
+            result |= RELAYOUT_RES_FIRST_TIME;
+        }
+        return result;
+    }
+
     // TODO: Hack to work around the number of states AppWindowToken needs to access without having
     // access to its windows children. Need to investigate re-writing
     // {@link AppWindowToken#updateReportedVisibilityLocked} so this can be removed.
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index d2ea64c8..98598e1 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -172,7 +172,7 @@
     private boolean mAnimateMove = false;
 
     float mDsDx=1, mDtDx=0, mDsDy=0, mDtDy=1;
-    float mLastDsDx=1, mLastDtDx=0, mLastDsDy=0, mLastDtDy=1;
+    private float mLastDsDx=1, mLastDtDx=0, mLastDsDy=0, mLastDtDy=1;
 
     boolean mHaveMatrix;
 
@@ -945,8 +945,8 @@
             tmpMatrix.getValues(tmpFloats);
             mDsDx = tmpFloats[Matrix.MSCALE_X];
             mDtDx = tmpFloats[Matrix.MSKEW_Y];
-            mDsDy = tmpFloats[Matrix.MSKEW_X];
-            mDtDy = tmpFloats[Matrix.MSCALE_Y];
+            mDtDy = tmpFloats[Matrix.MSKEW_X];
+            mDsDy = tmpFloats[Matrix.MSCALE_Y];
             float x = tmpFloats[Matrix.MTRANS_X];
             float y = tmpFloats[Matrix.MTRANS_Y];
             mWin.mShownPosition.set(Math.round(x), Math.round(y));
@@ -959,7 +959,7 @@
             mShownAlpha = mAlpha;
             if (!mService.mLimitedAlphaCompositing
                     || (!PixelFormat.formatHasAlpha(mWin.mAttrs.format)
-                    || (mWin.isIdentityMatrix(mDsDx, mDtDx, mDsDy, mDtDy)
+                    || (mWin.isIdentityMatrix(mDsDx, mDtDx, mDtDy, mDsDy)
                             && x == frame.left && y == frame.top))) {
                 //Slog.i(TAG_WM, "Applying alpha transform");
                 if (selfTransformation) {
@@ -1038,8 +1038,8 @@
             mHaveMatrix = true;
             mDsDx = tmpFloats[Matrix.MSCALE_X];
             mDtDx = tmpFloats[Matrix.MSKEW_Y];
-            mDsDy = tmpFloats[Matrix.MSKEW_X];
-            mDtDy = tmpFloats[Matrix.MSCALE_Y];
+            mDtDy = tmpFloats[Matrix.MSKEW_X];
+            mDsDy = tmpFloats[Matrix.MSCALE_Y];
             float x = tmpFloats[Matrix.MTRANS_X];
             float y = tmpFloats[Matrix.MTRANS_Y];
             mWin.mShownPosition.set(Math.round(x), Math.round(y));
@@ -1054,8 +1054,8 @@
             mHaveMatrix = false;
             mDsDx = mWin.mGlobalScale;
             mDtDx = 0;
-            mDsDy = 0;
-            mDtDy = mWin.mGlobalScale;
+            mDtDy = 0;
+            mDsDy = mWin.mGlobalScale;
         }
     }
 
@@ -1318,7 +1318,7 @@
         float surfaceWidth = mSurfaceController.getWidth();
         float surfaceHeight = mSurfaceController.getHeight();
 
-        if ((task != null && task.mStack.getForceScaleToStack()) || mForceScaleUntilResize) {
+        if (isForceScaled()) {
             int hInsets = w.getAttrs().surfaceInsets.left + w.getAttrs().surfaceInsets.right;
             int vInsets = w.getAttrs().surfaceInsets.top + w.getAttrs().surfaceInsets.bottom;
             if (!mForceScaleUntilResize) {
@@ -1328,8 +1328,8 @@
             task.mStack.getDimBounds(mTmpStackBounds);
             // We want to calculate the scaling based on the content area, not based on
             // the entire surface, so that we scale in sync with windows that don't have insets.
-            mExtraHScale = (mTmpStackBounds.width() - hInsets) / (float)(surfaceWidth - hInsets);
-            mExtraVScale = (mTmpStackBounds.height() - vInsets) / (float)(surfaceHeight - vInsets);
+            mExtraHScale = mTmpStackBounds.width() / (float)(surfaceWidth - hInsets);
+            mExtraVScale = mTmpStackBounds.height() / (float)(surfaceHeight - vInsets);
 
             // In the case of ForceScaleToStack we scale entire tasks together,
             // and so we need to scale our offsets relative to the task bounds
@@ -1353,6 +1353,7 @@
             // expose the whole window in buffer space, and not risk extending
             // past where the system would have cropped us
             clipRect = null;
+            finalClipRect = null;
 
             // Various surfaces in the scaled stack may resize at different times.
             // We need to ensure for each surface, that we disable transformation matrix
@@ -1383,8 +1384,8 @@
             applyCrop(clipRect, finalClipRect, recoveringMemory);
             mSurfaceController.setMatrixInTransaction(mDsDx * w.mHScale * mExtraHScale,
                     mDtDx * w.mVScale * mExtraVScale,
-                    mDsDy * w.mHScale * mExtraHScale,
-                    mDtDy * w.mVScale * mExtraVScale, recoveringMemory);
+                    mDtDy * w.mHScale * mExtraHScale,
+                    mDsDy * w.mVScale * mExtraVScale, recoveringMemory);
         }
 
         if (mSurfaceResized) {
@@ -1466,15 +1467,15 @@
                     "alpha=" + mShownAlpha + " layer=" + mAnimLayer
                     + " matrix=[" + mDsDx + "*" + w.mHScale
                     + "," + mDtDx + "*" + w.mVScale
-                    + "][" + mDsDy + "*" + w.mHScale
-                    + "," + mDtDy + "*" + w.mVScale + "]", false);
+                    + "][" + mDtDy + "*" + w.mHScale
+                    + "," + mDsDy + "*" + w.mVScale + "]", false);
 
             boolean prepared =
                 mSurfaceController.prepareToShowInTransaction(mShownAlpha, mAnimLayer,
                         mDsDx * w.mHScale * mExtraHScale,
                         mDtDx * w.mVScale * mExtraVScale,
-                        mDsDy * w.mHScale * mExtraHScale,
-                        mDtDy * w.mVScale * mExtraVScale,
+                        mDtDy * w.mHScale * mExtraHScale,
+                        mDsDy * w.mVScale * mExtraVScale,
                         recoveringMemory);
 
             if (prepared && mLastHidden && mDrawState == HAS_DRAWN) {
@@ -1776,8 +1777,8 @@
             pw.print(prefix); pw.print("mGlobalScale="); pw.print(mWin.mGlobalScale);
                     pw.print(" mDsDx="); pw.print(mDsDx);
                     pw.print(" mDtDx="); pw.print(mDtDx);
-                    pw.print(" mDsDy="); pw.print(mDsDy);
-                    pw.print(" mDtDy="); pw.println(mDtDy);
+                    pw.print(" mDtDy="); pw.print(mDtDy);
+                    pw.print(" mDsDy="); pw.println(mDsDy);
         }
         if (mAnimationStartDelayed) {
             pw.print(prefix); pw.print("mAnimationStartDelayed="); pw.print(mAnimationStartDelayed);
@@ -1925,15 +1926,15 @@
 
             float DsDx = mService.mTmpFloats[Matrix.MSCALE_X];
             float DtDx = mService.mTmpFloats[Matrix.MSKEW_Y];
-            float DsDy = mService.mTmpFloats[Matrix.MSKEW_X];
-            float DtDy = mService.mTmpFloats[Matrix.MSCALE_Y];
+            float DtDy = mService.mTmpFloats[Matrix.MSKEW_X];
+            float DsDy = mService.mTmpFloats[Matrix.MSCALE_Y];
             float nx = mService.mTmpFloats[Matrix.MTRANS_X];
             float ny = mService.mTmpFloats[Matrix.MTRANS_Y];
             mSurfaceController.setPositionInTransaction(nx, ny, false);
             mSurfaceController.setMatrixInTransaction(DsDx * w.mHScale,
                     DtDx * w.mVScale,
-                    DsDy * w.mHScale,
-                    DtDy * w.mVScale, false);
+                    DtDy * w.mHScale,
+                    DsDy * w.mVScale, false);
         }
     }
 
@@ -1952,4 +1953,16 @@
             }
         }
     }
+
+    /** The force-scaled state for a given window can persist past
+     * the state for it's stack as the windows complete resizing
+     * independently of one another.
+     */
+    boolean isForceScaled() {
+        final Task task = mWin.getTask();
+        if (task != null && task.mStack.isForceScaled()) {
+            return true;
+        }
+        return mForceScaleUntilResize;
+    }
 }
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index 1096ede..f8e7428 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -52,6 +52,7 @@
 
     private SurfaceControl mSurfaceControl;
 
+    // Should only be set from within setShown().
     private boolean mSurfaceShown = false;
     private float mSurfaceX = 0;
     private float mSurfaceY = 0;
@@ -79,6 +80,9 @@
 
     private final WindowManagerService mService;
 
+    private final int mWindowType;
+    private final Session mWindowSession;
+
     public WindowSurfaceController(SurfaceSession s, String name, int w, int h, int format,
             int flags, WindowStateAnimator animator, int windowType, int ownerUid) {
         mAnimator = animator;
@@ -89,16 +93,16 @@
         title = name;
 
         mService = animator.mService;
+        final WindowState win = animator.mWin;
+        mWindowType = windowType;
+        mWindowSession = win.mSession;
 
-        // For opaque child windows placed under parent windows,
-        // we use a special SurfaceControl which mirrors commands
-        // to a black-out layer placed one Z-layer below the surface.
+        // For opaque child windows placed under parent windows, we use a special SurfaceControl
+        // which mirrors commands to a black-out layer placed one Z-layer below the surface.
         // This prevents holes to whatever app/wallpaper is underneath.
-        if (animator.mWin.isChildWindow() &&
-                animator.mWin.mSubLayer < 0 &&
-                animator.mWin.mAppToken != null) {
-            mSurfaceControl = new SurfaceControlWithBackground(s,
-                    name, w, h, format, flags, animator.mWin.mAppToken, windowType, ownerUid);
+        if (win.isChildWindow() && win.mSubLayer < 0 && win.mAppToken != null) {
+            mSurfaceControl = new SurfaceControlWithBackground(
+                    s, name, w, h, format, flags, win.mAppToken, windowType, ownerUid);
         } else if (DEBUG_SURFACE_TRACE) {
             mSurfaceControl = new SurfaceTrace(
                     s, name, w, h, format, flags, windowType, ownerUid);
@@ -109,8 +113,7 @@
 
         if (mService.mRoot.mSurfaceTraceEnabled) {
             mSurfaceControl = new RemoteSurfaceTrace(
-                    mService.mRoot.mSurfaceTraceFd.getFileDescriptor(),
-                    mSurfaceControl, animator.mWin);
+                    mService.mRoot.mSurfaceTraceFd.getFileDescriptor(), mSurfaceControl, win);
         }
     }
 
@@ -141,13 +144,14 @@
     }
 
     private void hideSurface() {
-        if (mSurfaceControl != null) {
-            mSurfaceShown = false;
-            try {
-                mSurfaceControl.hide();
-            } catch (RuntimeException e) {
-                Slog.w(TAG, "Exception hiding surface in " + this);
-            }
+        if (mSurfaceControl == null) {
+            return;
+        }
+        setShown(false);
+        try {
+            mSurfaceControl.hide();
+        } catch (RuntimeException e) {
+            Slog.w(TAG, "Exception hiding surface in " + this);
         }
     }
 
@@ -165,7 +169,7 @@
 
                 mSurfaceControl.setLayer(layer);
                 mSurfaceControl.setAlpha(0);
-                mSurfaceShown = false;
+                setShown(false);
             } catch (RuntimeException e) {
                 Slog.w(TAG, "Error creating surface in " + this, e);
                 mAnimator.reclaimSomeSurfaceMemory("create-init", true);
@@ -188,7 +192,7 @@
         } catch (RuntimeException e) {
             Slog.w(TAG, "Error destroying surface in: " + this, e);
         } finally {
-            mSurfaceShown = false;
+            setShown(false);
             mSurfaceControl = null;
         }
     }
@@ -447,7 +451,7 @@
 
     private boolean showSurface() {
         try {
-            mSurfaceShown = true;
+            setShown(true);
             mSurfaceControl.show();
             return true;
         } catch (RuntimeException e) {
@@ -515,6 +519,10 @@
 
     void setShown(boolean surfaceShown) {
         mSurfaceShown = surfaceShown;
+
+        if (mWindowSession != null) {
+            mWindowSession.onWindowSurfaceVisibilityChanged(this, mSurfaceShown, mWindowType);
+        }
     }
 
     float getX() {
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 897d5b86..f247ebe 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -651,7 +651,7 @@
         if (openingAppAnimator == null || openingAppAnimator.animation == null) {
             return;
         }
-        final int taskId = appToken.mTask.mTaskId;
+        final int taskId = appToken.getTask().mTaskId;
         Bitmap thumbnailHeader = mService.mAppTransition.getAppTransitionThumbnailHeader(taskId);
         if (thumbnailHeader == null || thumbnailHeader.getConfig() == Bitmap.Config.ALPHA_8) {
             if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "No thumbnail header bitmap for: " + taskId);
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 8beb87d..fab59d6 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -151,21 +151,6 @@
         }
     }
 
-    int adjustAnimLayer(int adj) {
-        int highestAnimLayer = -1;
-        for (int j = mChildren.size() - 1; j >= 0; j--) {
-            final WindowState w = mChildren.get(j);
-            final int winHighestAnimLayer = w.adjustAnimLayer(adj);
-            if (winHighestAnimLayer > highestAnimLayer) {
-                highestAnimLayer = winHighestAnimLayer;
-            }
-            if (w == mService.mInputMethodTarget && !mService.mInputMethodTargetWaitingAnim) {
-                mDisplayContent.setInputMethodAnimLayerAdjustment(adj);
-            }
-        }
-        return highestAnimLayer;
-    }
-
     /**
      * Returns true if the new window is considered greater than the existing window in terms of
      * z-order.
@@ -197,6 +182,11 @@
         return mChildren.isEmpty();
     }
 
+    // Used by AppWindowToken.
+    int getAnimLayerAdjustment() {
+        return 0;
+    }
+
     WindowState getReplacingWindow() {
         for (int i = mChildren.size() - 1; i >= 0; i--) {
             final WindowState win = mChildren.get(i);
diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk
index 2c3cda5..ac95db5 100644
--- a/services/core/jni/Android.mk
+++ b/services/core/jni/Android.mk
@@ -30,6 +30,7 @@
     $(LOCAL_REL_DIR)/com_android_server_UsbHostManager.cpp \
     $(LOCAL_REL_DIR)/com_android_server_VibratorService.cpp \
     $(LOCAL_REL_DIR)/com_android_server_PersistentDataBlockService.cpp \
+    $(LOCAL_REL_DIR)/com_android_server_GraphicsStatsService.cpp \
     $(LOCAL_REL_DIR)/onload.cpp
 
 LOCAL_C_INCLUDES += \
@@ -37,7 +38,6 @@
     external/scrypt/lib/crypto \
     frameworks/base/services \
     frameworks/base/libs \
-    frameworks/base/libs/hwui \
     frameworks/base/core/jni \
     frameworks/native/services \
     system/core/libappfuse/include \
@@ -76,6 +76,7 @@
     libhidltransport \
     libhwbinder \
     libutils \
+    libhwui \
     android.hardware.audio.common@2.0 \
     android.hardware.contexthub@1.0 \
     android.hardware.gnss@1.0 \
diff --git a/services/core/jni/com_android_server_GraphicsStatsService.cpp b/services/core/jni/com_android_server_GraphicsStatsService.cpp
new file mode 100644
index 0000000..5d5728d
--- /dev/null
+++ b/services/core/jni/com_android_server_GraphicsStatsService.cpp
@@ -0,0 +1,110 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "GraphicsStatsService"
+
+#include <jni.h>
+#include <log/log.h>
+#include <nativehelper/JNIHelp.h>
+#include <ScopedPrimitiveArray.h>
+#include <ScopedUtfChars.h>
+#include <JankTracker.h>
+#include <service/GraphicsStatsService.h>
+
+namespace android {
+
+using namespace android::uirenderer;
+
+static jint getAshmemSize(JNIEnv*, jobject) {
+    return sizeof(ProfileData);
+}
+
+static jlong createDump(JNIEnv*, jobject, jint fd, jboolean isProto) {
+    GraphicsStatsService::Dump* dump = GraphicsStatsService::createDump(fd, isProto
+            ? GraphicsStatsService::DumpType::Protobuf : GraphicsStatsService::DumpType::Text);
+    return reinterpret_cast<jlong>(dump);
+}
+
+static void addToDump(JNIEnv* env, jobject, jlong dumpPtr, jstring jpath, jstring jpackage,
+        jint versionCode, jlong startTime, jlong endTime, jbyteArray jdata) {
+    std::string path;
+    const ProfileData* data = nullptr;
+    LOG_ALWAYS_FATAL_IF(jdata == nullptr && jpath == nullptr, "Path and data can't both be null");
+    if (jdata != nullptr) {
+        ScopedByteArrayRO buffer(env, jdata);
+        LOG_ALWAYS_FATAL_IF(buffer.size() != sizeof(ProfileData),
+                "Buffer size %zu doesn't match expected %zu!", buffer.size(), sizeof(ProfileData));
+        data = reinterpret_cast<const ProfileData*>(buffer.get());
+    }
+    if (jpath != nullptr) {
+        ScopedUtfChars pathChars(env, jpath);
+        LOG_ALWAYS_FATAL_IF(pathChars.size() <= 0 || !pathChars.c_str(), "Failed to get path chars");
+        path.assign(pathChars.c_str(), pathChars.size());
+    }
+    ScopedUtfChars packageChars(env, jpackage);
+    LOG_ALWAYS_FATAL_IF(packageChars.size() <= 0 || !packageChars.c_str(), "Failed to get path chars");
+    GraphicsStatsService::Dump* dump = reinterpret_cast<GraphicsStatsService::Dump*>(dumpPtr);
+    LOG_ALWAYS_FATAL_IF(!dump, "null passed for dump pointer");
+
+    const std::string package(packageChars.c_str(), packageChars.size());
+    GraphicsStatsService::addToDump(dump, path, package, versionCode, startTime, endTime, data);
+}
+
+static void addFileToDump(JNIEnv* env, jobject, jlong dumpPtr, jstring jpath) {
+    ScopedUtfChars pathChars(env, jpath);
+    LOG_ALWAYS_FATAL_IF(pathChars.size() <= 0 || !pathChars.c_str(), "Failed to get path chars");
+    const std::string path(pathChars.c_str(), pathChars.size());
+    GraphicsStatsService::Dump* dump = reinterpret_cast<GraphicsStatsService::Dump*>(dumpPtr);
+    GraphicsStatsService::addToDump(dump, path);
+}
+
+static void finishDump(JNIEnv*, jobject, jlong dumpPtr) {
+    GraphicsStatsService::Dump* dump = reinterpret_cast<GraphicsStatsService::Dump*>(dumpPtr);
+    GraphicsStatsService::finishDump(dump);
+}
+
+static void saveBuffer(JNIEnv* env, jobject clazz, jstring jpath, jstring jpackage,
+        jint versionCode, jlong startTime, jlong endTime, jbyteArray jdata) {
+    ScopedByteArrayRO buffer(env, jdata);
+    LOG_ALWAYS_FATAL_IF(buffer.size() != sizeof(ProfileData),
+            "Buffer size %zu doesn't match expected %zu!", buffer.size(), sizeof(ProfileData));
+    ScopedUtfChars pathChars(env, jpath);
+    LOG_ALWAYS_FATAL_IF(pathChars.size() <= 0 || !pathChars.c_str(), "Failed to get path chars");
+    ScopedUtfChars packageChars(env, jpackage);
+    LOG_ALWAYS_FATAL_IF(packageChars.size() <= 0 || !packageChars.c_str(), "Failed to get path chars");
+
+    const std::string path(pathChars.c_str(), pathChars.size());
+    const std::string package(packageChars.c_str(), packageChars.size());
+    const ProfileData* data = reinterpret_cast<const ProfileData*>(buffer.get());
+    GraphicsStatsService::saveBuffer(path, package, versionCode, startTime, endTime, data);
+}
+
+static const JNINativeMethod sMethods[] = {
+    { "nGetAshmemSize", "()I", (void*) getAshmemSize },
+    { "nCreateDump", "(IZ)J", (void*) createDump },
+    { "nAddToDump", "(JLjava/lang/String;Ljava/lang/String;IJJ[B)V", (void*) addToDump },
+    { "nAddToDump", "(JLjava/lang/String;)V", (void*) addFileToDump },
+    { "nFinishDump", "(J)V", (void*) finishDump },
+    { "nSaveBuffer", "(Ljava/lang/String;Ljava/lang/String;IJJ[B)V", (void*) saveBuffer },
+};
+
+int register_android_server_GraphicsStatsService(JNIEnv* env)
+{
+    return jniRegisterNativeMethods(env, "com/android/server/GraphicsStatsService",
+                                    sMethods, NELEM(sMethods));
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp b/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp
index 7790d15..4df7256 100644
--- a/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp
+++ b/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp
@@ -336,7 +336,7 @@
 static jlong nativeInit(JNIEnv* env, jclass clazz, jobject callbacksObj,
         jobject messageQueueObj) {
     // TODO(b/31632518)
-    sp<IHdmiCec> hdmiCec = IHdmiCec::getService("tv.cec");
+    sp<IHdmiCec> hdmiCec = IHdmiCec::getService();
     if (hdmiCec == nullptr) {
         ALOGE("Couldn't get tv.cec service.");
         return 0;
diff --git a/services/core/jni/com_android_server_lights_LightsService.cpp b/services/core/jni/com_android_server_lights_LightsService.cpp
index 74af639..813dcf5 100644
--- a/services/core/jni/com_android_server_lights_LightsService.cpp
+++ b/services/core/jni/com_android_server_lights_LightsService.cpp
@@ -43,28 +43,86 @@
 static bool validate(jint light, jint flash, jint brightness) {
     bool valid = true;
 
-    if (light < 0 || light >= static_cast<int>(Type::COUNT)) {
+    if (light < 0 || light >= static_cast<jint>(Type::COUNT)) {
         ALOGE("Invalid light parameter %d.", light);
         valid = false;
     }
 
-    if (flash != static_cast<int>(Flash::NONE) &&
-        flash != static_cast<int>(Flash::TIMED) &&
-        flash != static_cast<int>(Flash::HARDWARE)) {
+    if (flash != static_cast<jint>(Flash::NONE) &&
+        flash != static_cast<jint>(Flash::TIMED) &&
+        flash != static_cast<jint>(Flash::HARDWARE)) {
         ALOGE("Invalid flash parameter %d.", flash);
         valid = false;
     }
 
-    if (brightness != static_cast<int>(Brightness::USER) &&
-        brightness != static_cast<int>(Brightness::SENSOR) &&
-        brightness != static_cast<int>(Brightness::LOW_PERSISTENCE)) {
+    if (brightness != static_cast<jint>(Brightness::USER) &&
+        brightness != static_cast<jint>(Brightness::SENSOR) &&
+        brightness != static_cast<jint>(Brightness::LOW_PERSISTENCE)) {
         ALOGE("Invalid brightness parameter %d.", brightness);
         valid = false;
     }
 
+    if (brightness == static_cast<jint>(Brightness::LOW_PERSISTENCE) &&
+        light != static_cast<jint>(Type::BACKLIGHT)) {
+        ALOGE("Cannot set low-persistence mode for non-backlight device.");
+        valid = false;
+    }
+
     return valid;
 }
 
+static LightState constructState(
+        jint colorARGB,
+        jint flashMode,
+        jint onMS,
+        jint offMS,
+        jint brightnessMode){
+    Flash flash = static_cast<Flash>(flashMode);
+    Brightness brightness = static_cast<Brightness>(brightnessMode);
+
+    LightState state{};
+
+    if (brightness == Brightness::LOW_PERSISTENCE) {
+        state.flashMode = Flash::NONE;
+    } else {
+        // Only set non-brightness settings when not in low-persistence mode
+        state.flashMode = flash;
+        state.flashOnMs = onMS;
+        state.flashOffMs = offMS;
+    }
+
+    state.color = colorARGB;
+    state.brightnessMode = brightness;
+
+    return state;
+}
+
+static void processReturn(
+        const Return<Status> &ret,
+        Type type,
+        const LightState &state) {
+    if (!ret.isOk()) {
+        ALOGE("Failed to issue set light command.");
+        gLight = nullptr;
+        return;
+    }
+
+    switch (static_cast<Status>(ret)) {
+        case Status::SUCCESS:
+            break;
+        case Status::LIGHT_NOT_SUPPORTED:
+            ALOGE("Light requested not available on this device. %d", type);
+            break;
+        case Status::BRIGHTNESS_NOT_SUPPORTED:
+            ALOGE("Brightness parameter not supported on this device: %d",
+                state.brightnessMode);
+            break;
+        case Status::UNKNOWN:
+        default:
+            ALOGE("Unknown error setting light.");
+    }
+}
+
 static void setLight_native(
         JNIEnv* /* env */,
         jobject /* clazz */,
@@ -79,63 +137,23 @@
         return;
     }
 
-    // TODO(b/31632518)
-    if (gLight == nullptr) {
+    if (gLight == nullptr || !gLight->ping().isOk()) {
         gLight = ILight::getService();
     }
 
     if (gLight == nullptr) {
-        ALOGE("LightService unable to get ILight interface.");
+        ALOGE("Unable to get ILight interface.");
         return;
     }
 
     Type type = static_cast<Type>(light);
-    Flash flash = static_cast<Flash>(flashMode);
-    Brightness brightness = static_cast<Brightness>(brightnessMode);
+    LightState state = constructState(
+        colorARGB, flashMode, onMS, offMS, brightnessMode);
 
-    LightState state{};
-
-    if (brightnessMode == static_cast<int>(Brightness::LOW_PERSISTENCE)) {
-        if (light != static_cast<int>(Type::BACKLIGHT)) {
-            ALOGE("Cannot set low-persistence mode for non-backlight device.");
-            return;
-        }
-        state.flashMode = Flash::NONE;
-    } else {
-        // Only set non-brightness settings when not in low-persistence mode
-        state.flashMode = flash;
-        state.flashOnMs = onMS;
-        state.flashOffMs = offMS;
-    }
-
-    state.color = colorARGB;
-    state.brightnessMode = brightness;
-
-    Status status;
     {
         ALOGD_IF_SLOW(50, "Excessive delay setting light");
         Return<Status> ret = gLight->setLight(type, state);
-
-        if (!ret.isOk()) {
-            ALOGE("Failed to issue set light command.");
-            return;
-        }
-
-        status = static_cast<Status>(ret); // hal status
-    }
-
-    switch (status) {
-        case Status::SUCCESS:
-            break;
-        case Status::LIGHT_NOT_SUPPORTED:
-            ALOGE("Light requested not availale on this device.");
-            break;
-        case Status::BRIGHTNESS_NOT_SUPPORTED:
-            ALOGE("Brightness parameter not supported on this device.");
-            break;
-        case Status::UNKNOWN:
-        default:
-            ALOGE("Unknown error setting light.");
+        processReturn(ret, type, state);
     }
 }
 
diff --git a/services/core/jni/com_android_server_location_ContextHubService.cpp b/services/core/jni/com_android_server_location_ContextHubService.cpp
index 05ef0d1..c976fe5 100644
--- a/services/core/jni/com_android_server_location_ContextHubService.cpp
+++ b/services/core/jni/com_android_server_location_ContextHubService.cpp
@@ -331,7 +331,9 @@
 
     virtual Return<void> handleAppsInfo(
             const android::hardware::hidl_vec<HubAppInfo>& apps) {
+        TransactionResult result = TransactionResult::SUCCESS;
         handleQueryAppsResponse(apps,mContextHubId);
+        passOnOsResponse(mContextHubId, CONTEXT_HUB_QUERY_APPS, result, nullptr, 0);
         return android::hardware::Void();
     }
 
@@ -558,7 +560,7 @@
 void initContextHubService() {
     db.hubInfo.numHubs = 0;
 
-    db.hubInfo.contextHub = IContexthub::getService("context_hub");
+    db.hubInfo.contextHub = IContexthub::getService();
 
     if (db.hubInfo.contextHub == nullptr) {
         ALOGE("Could not load context hub hal");
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 4c89705..78d8b53 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -1036,7 +1036,7 @@
     }
 
     // TODO(b/31632518)
-    gnssHal = IGnss::getService("gnss");
+    gnssHal = IGnss::getService();
     if (gnssHal != nullptr) {
         auto gnssXtra = gnssHal->getExtensionXtra();
         if (!gnssXtra.isOk()) {
@@ -1144,7 +1144,7 @@
     }
 
     auto result = gnssHal->setCallback(gnssCbIface);
-    if ((!result) || (!result.isOk())) {
+    if (!result.isOk() || !result) {
         ALOGE("SetCallback for Gnss Interface fails\n");
         return JNI_FALSE;
     }
@@ -1154,7 +1154,7 @@
         ALOGE("Unable to initialize GNSS Xtra interface\n");
     } else {
         result = gnssXtraIface->setCallback(gnssXtraCbIface);
-        if ((!result) || (!result.isOk())) {
+        if (!result.isOk() || !result) {
             gnssXtraIface = nullptr;
             ALOGE("SetCallback for Gnss Xtra Interface fails\n");
         }
@@ -1175,7 +1175,7 @@
     }
 
     sp<IGnssNiCallback> gnssNiCbIface = new GnssNiCallback();
-    if (gnssNiCbIface != nullptr) {
+    if (gnssNiIface != nullptr) {
         gnssNiIface->setCallback(gnssNiCbIface);
     } else {
         ALOGE("Unable to initialize GNSS NI interface\n");
@@ -1344,7 +1344,7 @@
         jlong time, jlong timeReference, jint uncertainty) {
     if (gnssHal != nullptr) {
         auto result = gnssHal->injectTime(time, timeReference, uncertainty);
-        if (!result || !result.isOk()) {
+        if (!result.isOk() || !result) {
             ALOGE("%s: Gnss injectTime() failed", __func__);
         }
     }
@@ -1354,7 +1354,7 @@
         jobject /* obj */, jdouble latitude, jdouble longitude, jfloat accuracy) {
     if (gnssHal != nullptr) {
         auto result = gnssHal->injectLocation(latitude, longitude, accuracy);
-        if (!result || !result.isOk()) {
+        if (!result.isOk() || !result) {
             ALOGE("%s: Gnss injectLocation() failed", __func__);
         }
     }
@@ -1391,7 +1391,7 @@
     const char *apnStr = env->GetStringUTFChars(apn, NULL);
 
     auto result = agnssIface->dataConnOpen(apnStr, static_cast<IAGnss::ApnIpType>(apnIpType));
-    if ((!result) || (!result.isOk())) {
+    if (!result.isOk() || !result){
         ALOGE("%s: Failed to set APN and its IP type", __func__);
     }
     env->ReleaseStringUTFChars(apn, apnStr);
@@ -1405,7 +1405,7 @@
     }
 
     auto result = agnssIface->dataConnClosed();
-    if ((!result) || (!result.isOk())) {
+    if (!result.isOk() || !result) {
         ALOGE("%s: Failed to close AGnss data connection", __func__);
     }
 }
@@ -1418,7 +1418,7 @@
     }
 
     auto result = agnssIface->dataConnFailed();
-    if ((!result) || (!result.isOk())) {
+    if (!result.isOk() || !result) {
         ALOGE("%s: Failed to notify unavailability of AGnss data connection", __func__);
     }
 }
@@ -1434,7 +1434,7 @@
     auto result = agnssIface->setServer(static_cast<IAGnssCallback::AGnssType>(type),
                                        c_hostname,
                                        port);
-    if ((!result) || (!result.isOk())) {
+    if (!result.isOk() || !result) {
         ALOGE("%s: Failed to set AGnss host name and port", __func__);
     }
 
@@ -1512,13 +1512,13 @@
         auto result = agnssRilIface->updateNetworkState(connected,
                                                        static_cast<IAGnssRil::NetworkType>(type),
                                                        roaming);
-        if ((!result) || (!result.isOk())) {
+        if (!result.isOk() || !result) {
             ALOGE("updateNetworkState failed");
         }
 
         const char *c_apn = env->GetStringUTFChars(apn, NULL);
         result = agnssRilIface->updateNetworkAvailability(available, c_apn);
-        if ((!result) || (!result.isOk())) {
+        if (!result.isOk() || !result) {
             ALOGE("updateNetworkAvailability failed");
         }
 
diff --git a/services/core/jni/com_android_server_vr_VrManagerService.cpp b/services/core/jni/com_android_server_vr_VrManagerService.cpp
index e06e051..9052697 100644
--- a/services/core/jni/com_android_server_vr_VrManagerService.cpp
+++ b/services/core/jni/com_android_server_vr_VrManagerService.cpp
@@ -38,7 +38,7 @@
         return;
     }
 
-    gVr = IVr::getService("vr");
+    gVr = IVr::getService();
     if (gVr == nullptr) {
         ALOGW("%s: Could not open IVr interface", __FUNCTION__);
         return;
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index 899640e..f22b330 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -46,6 +46,7 @@
 int register_android_server_Watchdog(JNIEnv* env);
 int register_android_server_HardwarePropertiesManagerService(JNIEnv* env);
 int register_android_server_SyntheticPasswordManager(JNIEnv* env);
+int register_android_server_GraphicsStatsService(JNIEnv* env);
 };
 
 using namespace android;
@@ -87,6 +88,7 @@
     register_android_server_HardwarePropertiesManagerService(env);
     register_android_server_storage_AppFuse(env);
     register_android_server_SyntheticPasswordManager(env);
+    register_android_server_GraphicsStatsService(env);
 
     return JNI_VERSION_1_4;
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 14b1741..7ad0292 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -41,6 +41,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_EXTERNAL_STORAGE;
 import static android.app.admin.DevicePolicyManager.WIPE_RESET_PROTECTION_DATA;
 import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
@@ -98,6 +99,7 @@
 import android.content.pm.ParceledListSlice;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
+import android.content.pm.StringParceledListSlice;
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.database.ContentObserver;
@@ -164,10 +166,11 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.notification.SystemNotificationChannels;
+import com.android.internal.os.BackgroundThread;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.JournaledFile;
-import com.android.internal.util.ParcelableString;
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.XmlUtils;
 import com.android.internal.widget.LockPatternUtils;
@@ -194,6 +197,7 @@
 import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
 import java.text.DateFormat;
+import java.text.NumberFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -239,12 +243,16 @@
 
     private static final String TAG_ADMIN_BROADCAST_PENDING = "admin-broadcast-pending";
 
-    private static final String TAG_DEFAULT_INPUT_METHOD_SET = "default-ime-set";
+    private static final String TAG_CURRENT_INPUT_METHOD_SET = "current-ime-set";
+
+    private static final String TAG_OWNER_INSTALLED_CA_CERT = "owner-installed-ca-cert";
 
     private static final String ATTR_ID = "id";
 
     private static final String ATTR_VALUE = "value";
 
+    private static final String ATTR_ALIAS = "alias";
+
     private static final String TAG_INITIALIZATION_BUNDLE = "initialization-bundle";
 
     private static final String TAG_PASSWORD_TOKEN_HANDLE = "password-token";
@@ -331,15 +339,6 @@
     }
 
     /**
-     * Keyguard features that when set on a managed profile that doesn't have its own challenge will
-     * affect the profile's parent user. These can also be set on the managed profile's parent DPM
-     * instance.
-     */
-    private static final int PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER =
-            DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS
-            | DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT;
-
-    /**
      * Keyguard features that when set on a profile affect the profile content or challenge only.
      * These cannot be set on the managed profile's parent DPM instance
      */
@@ -487,6 +486,7 @@
         final ArrayList<ActiveAdmin> mAdminList = new ArrayList<>();
         final ArrayList<ComponentName> mRemovingAdmins = new ArrayList<>();
 
+        // TODO(b/35385311): Keep track of metadata in TrustedCertificateStore instead.
         final ArraySet<String> mAcceptedCaCertificates = new ArraySet<>();
 
         // This is the list of component allowed to start lock task mode.
@@ -509,7 +509,10 @@
 
         long mLastNetworkLogsRetrievalTime = -1;
 
-        boolean mDefaultInputMethodSet = false;
+        boolean mCurrentInputMethodSet = false;
+
+        // TODO(b/35385311): Keep track of metadata in TrustedCertificateStore instead.
+        Set<String> mOwnerInstalledCaCerts = new ArraySet<>();
 
         // Used for initialization of users created by createAndManageUsers.
         boolean mAdminBroadcastPending = false;
@@ -525,6 +528,7 @@
     final SparseArray<DevicePolicyData> mUserData = new SparseArray<>();
 
     final Handler mHandler;
+    final Handler mBackgroundHandler;
 
     /** Listens on any device, even when mHasFeature == false. */
     final BroadcastReceiver mRootCaReceiver = new BroadcastReceiver() {
@@ -626,6 +630,25 @@
                 handlePackagesChanged(intent.getData().getSchemeSpecificPart(), userHandle);
             } else if (Intent.ACTION_MANAGED_PROFILE_ADDED.equals(action)) {
                 clearWipeProfileNotification();
+            } else if (KeyChain.ACTION_TRUST_STORE_CHANGED.equals(intent.getAction())) {
+                mBackgroundHandler.post(() ->  {
+                    try (final KeyChainConnection keyChainConnection = mInjector.keyChainBindAsUser(
+                            UserHandle.of(userHandle))) {
+                        final List<String> caCerts =
+                                keyChainConnection.getService().getUserCaAliases().getList();
+                        synchronized (DevicePolicyManagerService.this) {
+                            if (getUserData(userHandle).mOwnerInstalledCaCerts
+                                    .retainAll(caCerts)) {
+                                saveSettingsLocked(userHandle);
+                            }
+                        }
+                    } catch (InterruptedException e) {
+                        Slog.w(LOG_TAG, "error talking to IKeyChainService", e);
+                        Thread.currentThread().interrupt();
+                    } catch (RemoteException e) {
+                        Slog.w(LOG_TAG, "error talking to IKeyChainService", e);
+                    }
+                });
             }
         }
 
@@ -1793,6 +1816,7 @@
                 .hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN);
         mIsWatch = mInjector.getPackageManager()
                 .hasSystemFeature(PackageManager.FEATURE_WATCH);
+        mBackgroundHandler = BackgroundThread.getHandler();
 
         // Broadcast filter for changes to the trusted certificate store. These changes get a
         // separate intent filter so we can listen to them even when device_admin is off.
@@ -1814,6 +1838,7 @@
         filter.addAction(Intent.ACTION_USER_ADDED);
         filter.addAction(Intent.ACTION_USER_REMOVED);
         filter.addAction(Intent.ACTION_USER_STARTED);
+        filter.addAction(KeyChain.ACTION_TRUST_STORE_CHANGED);
         filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
         mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler);
         filter = new IntentFilter();
@@ -2582,9 +2607,15 @@
                 out.endTag(null, TAG_PASSWORD_TOKEN_HANDLE);
             }
 
-            if (policy.mDefaultInputMethodSet) {
-                out.startTag(null, TAG_DEFAULT_INPUT_METHOD_SET);
-                out.endTag(null, TAG_DEFAULT_INPUT_METHOD_SET);
+            if (policy.mCurrentInputMethodSet) {
+                out.startTag(null, TAG_CURRENT_INPUT_METHOD_SET);
+                out.endTag(null, TAG_CURRENT_INPUT_METHOD_SET);
+            }
+
+            for (final String cert : policy.mOwnerInstalledCaCerts) {
+                out.startTag(null, TAG_OWNER_INSTALLED_CA_CERT);
+                out.attribute(null, ATTR_ALIAS, cert);
+                out.endTag(null, TAG_OWNER_INSTALLED_CA_CERT);
             }
 
             out.endTag(null, "policies");
@@ -2703,6 +2734,7 @@
             policy.mAdminList.clear();
             policy.mAdminMap.clear();
             policy.mAffiliationIds.clear();
+            policy.mOwnerInstalledCaCerts.clear();
             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
                 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
@@ -2796,8 +2828,10 @@
                 } else if (TAG_PASSWORD_TOKEN_HANDLE.equals(tag)) {
                     policy.mPasswordTokenHandle = Long.parseLong(
                             parser.getAttributeValue(null, ATTR_VALUE));
-                } else if (TAG_DEFAULT_INPUT_METHOD_SET.equals(tag)) {
-                    policy.mDefaultInputMethodSet = true;
+                } else if (TAG_CURRENT_INPUT_METHOD_SET.equals(tag)) {
+                    policy.mCurrentInputMethodSet = true;
+                } else if (TAG_OWNER_INSTALLED_CA_CERT.equals(tag)) {
+                    policy.mOwnerInstalledCaCerts.add(parser.getAttributeValue(null, ATTR_ALIAS));
                 } else {
                     Slog.w(LOG_TAG, "Unknown tag: " + tag);
                     XmlUtils.skipCurrentTag(parser);
@@ -2911,11 +2945,41 @@
         }
     }
 
+    private void ensureUnknownSourcesRestrictionForProfileOwners() {
+        synchronized (this) {
+            for (int userId : mOwners.getProfileOwnerKeys()) {
+                if (!mUserManager.isManagedProfile(userId) ||
+                        mInjector.settingsSecureGetIntForUser(
+                        Settings.Secure.UNKNOWN_SOURCES_DEFAULT_REVERSED, 0, userId) == 0) {
+                    continue;
+                }
+                setUserRestrictionOnBehalfOfProfileOwnerLocked(
+                        UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, userId);
+                mInjector.settingsSecurePutIntForUser(
+                        Settings.Secure.UNKNOWN_SOURCES_DEFAULT_REVERSED, 0, userId);
+            }
+        }
+    }
+
+    private void setUserRestrictionOnBehalfOfProfileOwnerLocked(String userRestrictionKey,
+            int userId) {
+        if (UserRestrictionsUtils.isValidRestriction(userRestrictionKey) &&
+                UserRestrictionsUtils.canProfileOwnerChange(userRestrictionKey, userId)) {
+            ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userId);
+            if (profileOwner == null) {
+                return;
+            }
+            Bundle restrictions = profileOwner.ensureUserRestrictions();
+            restrictions.putBoolean(userRestrictionKey, true);
+            saveUserRestrictionsLocked(userId);
+        }
+    }
+
     private void onLockSettingsReady() {
         getUserData(UserHandle.USER_SYSTEM);
         loadOwners();
         cleanUpOldUsers();
-
+        ensureUnknownSourcesRestrictionForProfileOwners();
         onStartUser(UserHandle.USER_SYSTEM);
 
         // Register an observer for watching for user setup complete and settings changes.
@@ -4668,17 +4732,15 @@
             return false;
         }
 
-        final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId());
+        final UserHandle userHandle = UserHandle.of(mInjector.userHandleGetCallingUserId());
         final long id = mInjector.binderClearCallingIdentity();
+        String alias = null;
         try {
-            final KeyChainConnection keyChainConnection = KeyChain.bindAsUser(mContext, userHandle);
-            try {
-                keyChainConnection.getService().installCaCertificate(pemCert);
-                return true;
+            try (final KeyChainConnection keyChainConnection = mInjector.keyChainBindAsUser(
+                    userHandle)) {
+                alias = keyChainConnection.getService().installCaCertificate(pemCert);
             } catch (RemoteException e) {
                 Log.e(LOG_TAG, "installCaCertsToKeyChain(): ", e);
-            } finally {
-                keyChainConnection.close();
             }
         } catch (InterruptedException e1) {
             Log.w(LOG_TAG, "installCaCertsToKeyChain(): ", e1);
@@ -4686,6 +4748,16 @@
         } finally {
             mInjector.binderRestoreCallingIdentity(id);
         }
+        if (alias == null) {
+            Log.w(LOG_TAG, "Problem installing cert");
+        } else {
+            synchronized (this) {
+                final int userId = userHandle.getIdentifier();
+                getUserData(userId).mOwnerInstalledCaCerts.add(alias);
+                saveSettingsLocked(userId);
+            }
+            return true;
+        }
         return false;
     }
 
@@ -4699,25 +4771,31 @@
     public void uninstallCaCerts(ComponentName admin, String callerPackage, String[] aliases) {
         enforceCanManageCaCerts(admin, callerPackage);
 
-        final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId());
+        final int userId = mInjector.userHandleGetCallingUserId();
+        final UserHandle userHandle = UserHandle.of(userId);
         final long id = mInjector.binderClearCallingIdentity();
         try {
-            final KeyChainConnection keyChainConnection = KeyChain.bindAsUser(mContext, userHandle);
-            try {
+            try (final KeyChainConnection keyChainConnection = mInjector.keyChainBindAsUser(
+                    userHandle)) {
                 for (int i = 0 ; i < aliases.length; i++) {
                     keyChainConnection.getService().deleteCaCertificate(aliases[i]);
                 }
             } catch (RemoteException e) {
                 Log.e(LOG_TAG, "from CaCertUninstaller: ", e);
-            } finally {
-                keyChainConnection.close();
+                return;
             }
         } catch (InterruptedException ie) {
             Log.w(LOG_TAG, "CaCertUninstaller: ", ie);
             Thread.currentThread().interrupt();
+            return;
         } finally {
             mInjector.binderRestoreCallingIdentity(id);
         }
+        synchronized (this) {
+            if (getUserData(userId).mOwnerInstalledCaCerts.removeAll(Arrays.asList(aliases))) {
+                saveSettingsLocked(userId);
+            }
+        }
     }
 
     @Override
@@ -4828,19 +4906,37 @@
     private void sendPrivateKeyAliasResponse(final String alias, final IBinder responseBinder) {
         final IKeyChainAliasCallback keyChainAliasResponse =
                 IKeyChainAliasCallback.Stub.asInterface(responseBinder);
-        new AsyncTask<Void, Void, Void>() {
-            @Override
-            protected Void doInBackground(Void... unused) {
-                try {
-                    keyChainAliasResponse.alias(alias);
-                } catch (Exception e) {
-                    // Catch everything (not just RemoteException): caller could throw a
-                    // RuntimeException back across processes.
-                    Log.e(LOG_TAG, "error while responding to callback", e);
-                }
-                return null;
-            }
-        }.execute();
+        // Send the response. It's OK to do this from the main thread because IKeyChainAliasCallback
+        // is oneway, which means it won't block if the recipient lives in another process.
+        try {
+            keyChainAliasResponse.alias(alias);
+        } catch (Exception e) {
+            // Caller could throw RuntimeException or RemoteException back across processes. Catch
+            // everything just to be sure.
+            Log.e(LOG_TAG, "error while responding to callback", e);
+        }
+    }
+
+    /**
+     * Determine whether DPMS should check if a delegate package is already installed before
+     * granting it new delegations via {@link #setDelegatedScopes}.
+     */
+    private static boolean shouldCheckIfDelegatePackageIsInstalled(String delegatePackage,
+            int targetSdk, List<String> scopes) {
+        // 1) Never skip is installed check from N.
+        if (targetSdk >= Build.VERSION_CODES.N) {
+            return true;
+        }
+        // 2) Skip if DELEGATION_CERT_INSTALL is the only scope being given.
+        if (scopes.size() == 1 && scopes.get(0).equals(DELEGATION_CERT_INSTALL)) {
+            return false;
+        }
+        // 3) Skip if all previously granted scopes are being cleared.
+        if (scopes.isEmpty()) {
+            return false;
+        }
+        // Otherwise it should check that delegatePackage is installed.
+        return true;
     }
 
     /**
@@ -4869,8 +4965,8 @@
             // Ensure calling process is device/profile owner.
             getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
             // Ensure the delegate is installed (skip this for DELEGATION_CERT_INSTALL in pre-N).
-            if (scopes.size() == 1 && scopes.get(0).equals(DELEGATION_CERT_INSTALL) ||
-                    getTargetSdk(who.getPackageName(), userId) >= Build.VERSION_CODES.N) {
+            if (shouldCheckIfDelegatePackageIsInstalled(delegatePackage,
+                        getTargetSdk(who.getPackageName(), userId), scopes)) {
                 // Throw when the delegate package is not installed.
                 if (!isPackageInstalledForUser(delegatePackage, userId)) {
                     throw new IllegalArgumentException("Package " + delegatePackage
@@ -5088,8 +5184,10 @@
                 final String currentPackage = policy.mDelegationMap.keyAt(i);
                 final List<String> currentScopes = policy.mDelegationMap.valueAt(i);
 
-                if (!currentPackage.equals(delegatePackage) && currentScopes.remove(scope)) {
-                    setDelegatedScopes(who, currentPackage, currentScopes);
+                if (!currentPackage.equals(delegatePackage) && currentScopes.contains(scope)) {
+                    final List<String> newScopes = new ArrayList(currentScopes);
+                    newScopes.remove(scope);
+                    setDelegatedScopes(who, currentPackage, newScopes);
                 }
             }
         }
@@ -5250,13 +5348,14 @@
 
     private void sendWipeProfileNotification() {
         String contentText = mContext.getString(R.string.work_profile_deleted_description_dpm_wipe);
-        Notification notification = new Notification.Builder(mContext)
-                .setSmallIcon(android.R.drawable.stat_sys_warning)
-                .setContentTitle(mContext.getString(R.string.work_profile_deleted))
-                .setContentText(contentText)
-                .setColor(mContext.getColor(R.color.system_notification_accent_color))
-                .setStyle(new Notification.BigTextStyle().bigText(contentText))
-                .build();
+        Notification notification =
+                new Notification.Builder(mContext, SystemNotificationChannels.DEVICE_ADMIN)
+                        .setSmallIcon(android.R.drawable.stat_sys_warning)
+                        .setContentTitle(mContext.getString(R.string.work_profile_deleted))
+                        .setContentText(contentText)
+                        .setColor(mContext.getColor(R.color.system_notification_accent_color))
+                        .setStyle(new Notification.BigTextStyle().bigText(contentText))
+                        .build();
         mInjector.getNotificationManager().notify(PROFILE_WIPED_NOTIFICATION_ID, notification);
     }
 
@@ -6581,7 +6680,7 @@
             mUserManagerInternal.setForceEphemeralUsers(admin.forceEphemeralUsers);
         }
         final DevicePolicyData policyData = getUserData(userId);
-        policyData.mDefaultInputMethodSet = false;
+        policyData.mCurrentInputMethodSet = false;
         saveSettingsLocked(userId);
         final DevicePolicyData systemPolicyData = getUserData(UserHandle.USER_SYSTEM);
         systemPolicyData.mLastSecurityLogRetrievalTime = -1;
@@ -6638,6 +6737,17 @@
             mOwners.writeProfileOwner(userHandle);
             Slog.i(LOG_TAG, "Profile owner set: " + who + " on user " + userHandle);
 
+            final long id = mInjector.binderClearCallingIdentity();
+            try {
+                if (mUserManager.isManagedProfile(userHandle)) {
+                    setUserRestrictionOnBehalfOfProfileOwnerLocked(
+                            UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, userHandle);
+                    mInjector.settingsSecurePutIntForUser(
+                            Settings.Secure.UNKNOWN_SOURCES_DEFAULT_REVERSED, 0, userHandle);
+                }
+            } finally {
+                mInjector.binderRestoreCallingIdentity(id);
+            }
             return true;
         }
     }
@@ -6675,7 +6785,8 @@
             admin.defaultEnabledRestrictionsAlreadySet.clear();
         }
         final DevicePolicyData policyData = getUserData(userId);
-        policyData.mDefaultInputMethodSet = false;
+        policyData.mCurrentInputMethodSet = false;
+        policyData.mOwnerInstalledCaCerts.clear();
         saveSettingsLocked(userId);
         clearUserPoliciesLocked(userId);
         mOwners.removeProfileOwner(userId);
@@ -7072,29 +7183,32 @@
     }
 
     private void enforceFullCrossUsersPermission(int userHandle) {
-        enforceSystemUserOrPermission(userHandle,
+        enforceSystemUserOrPermissionIfCrossUser(userHandle,
                 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
     }
 
     private void enforceCrossUsersPermission(int userHandle) {
-        enforceSystemUserOrPermission(userHandle,
+        enforceSystemUserOrPermissionIfCrossUser(userHandle,
                 android.Manifest.permission.INTERACT_ACROSS_USERS);
     }
 
-    private void enforceSystemUserOrPermission(int userHandle, String permission) {
-        if (userHandle < 0) {
-            throw new IllegalArgumentException("Invalid userId " + userHandle);
-        }
-        final int callingUid = mInjector.binderGetCallingUid();
-        if (userHandle == UserHandle.getUserId(callingUid)) {
-            return;
-        }
-        if (!(isCallerWithSystemUid() || callingUid == Process.ROOT_UID)) {
+    private void enforceSystemUserOrPermission(String permission) {
+        if (!(isCallerWithSystemUid() || mInjector.binderGetCallingUid() == Process.ROOT_UID)) {
             mContext.enforceCallingOrSelfPermission(permission,
                     "Must be system or have " + permission + " permission");
         }
     }
 
+    private void enforceSystemUserOrPermissionIfCrossUser(int userHandle, String permission) {
+        if (userHandle < 0) {
+            throw new IllegalArgumentException("Invalid userId " + userHandle);
+        }
+        if (userHandle == mInjector.userHandleGetCallingUserId()) {
+            return;
+        }
+        enforceSystemUserOrPermission(permission);
+    }
+
     private void enforceManagedProfile(int userHandle, String message) {
         if(!isManagedProfile(userHandle)) {
             throw new SecurityException("You can not " + message + " outside a managed profile.");
@@ -7117,9 +7231,9 @@
         enforceManageUsers();
     }
 
-    private void enforceProfileOwnerOrSystemUser(ComponentName admin) {
+    private void enforceProfileOwnerOrSystemUser() {
         synchronized (this) {
-            if (getActiveAdminWithPolicyForUidLocked(admin,
+            if (getActiveAdminWithPolicyForUidLocked(null,
                     DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, mInjector.binderGetCallingUid())
                             != null) {
                 return;
@@ -7129,6 +7243,21 @@
                 "Only profile owner, device owner and system may call this method.");
     }
 
+    private void enforceProfileOwnerOrFullCrossUsersPermission(int userId) {
+        if (userId == mInjector.userHandleGetCallingUserId()) {
+            synchronized (this) {
+                if (getActiveAdminWithPolicyForUidLocked(null,
+                        DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, mInjector.binderGetCallingUid())
+                                != null) {
+                    // Device Owner/Profile Owner may access the user it runs on.
+                    return;
+                }
+            }
+        }
+        // Otherwise, INTERACT_ACROSS_USERS_FULL permission, system UID or root UID is required.
+        enforceSystemUserOrPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
+    }
+
     private void ensureCallerPackage(@Nullable String packageName) {
         if (packageName == null) {
             Preconditions.checkState(isCallerWithSystemUid(),
@@ -8724,7 +8853,27 @@
                 throw new SecurityException(String.format(
                         "Permission denial: Profile owners cannot update %1$s", setting));
             }
-
+            if (setting.equals(Settings.Secure.INSTALL_NON_MARKET_APPS)) {
+                if (getTargetSdk(who.getPackageName(), callingUserId) >= Build.VERSION_CODES.O) {
+                    throw new UnsupportedOperationException(Settings.Secure.INSTALL_NON_MARKET_APPS
+                            + " is deprecated. Please use the user restriction "
+                            + UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES + " instead.");
+                }
+                if (!mUserManager.isManagedProfile(callingUserId)) {
+                    Slog.e(LOG_TAG, "Ignoring setSecureSetting request for "
+                            + setting + ". User restriction "
+                            + UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES
+                            + " should be used instead.");
+                } else {
+                    try {
+                        setUserRestriction(who, UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,
+                                (Integer.parseInt(value) == 0) ? true : false);
+                    } catch (NumberFormatException exc) {
+                        Slog.e(LOG_TAG, "Invalid value: " + value + " for setting " + setting);
+                    }
+                }
+                return;
+            }
             long id = mInjector.binderClearCallingIdentity();
             try {
                 if (Settings.Secure.DEFAULT_INPUT_METHOD.equals(setting)) {
@@ -8738,7 +8887,7 @@
                         // to trigger. This is a corner case that will have no impact in practice.
                         mSetupContentObserver.addPendingChangeByOwnerLocked(callingUserId);
                     }
-                    getUserData(callingUserId).mDefaultInputMethodSet = true;
+                    getUserData(callingUserId).mCurrentInputMethodSet = true;
                     saveSettingsLocked(callingUserId);
                 }
                 mInjector.settingsSecurePutStringForUser(setting, value, callingUserId);
@@ -8922,13 +9071,13 @@
             } else if (mDefaultImeChanged.equals(uri)) {
                 synchronized (DevicePolicyManagerService.this) {
                     if (mUserIdsWithPendingChangesByOwner.contains(userId)) {
-                        // This change notification was triggered by the owner changing the default
+                        // This change notification was triggered by the owner changing the current
                         // IME. Ignore it.
                         mUserIdsWithPendingChangesByOwner.remove(userId);
                     } else {
                         // This change notification was triggered by the user manually changing the
-                        // default IME.
-                        getUserData(userId).mDefaultInputMethodSet = false;
+                        // current IME.
+                        getUserData(userId).mCurrentInputMethodSet = false;
                         saveSettingsLocked(userId);
                     }
                 }
@@ -10645,7 +10794,8 @@
         intent.setPackage("com.android.systemui");
         final PendingIntent pendingIntent = PendingIntent.getBroadcastAsUser(mContext, 0, intent, 0,
                 UserHandle.CURRENT);
-        Notification notification = new Notification.Builder(mContext)
+        Notification notification =
+                new Notification.Builder(mContext, SystemNotificationChannels.DEVICE_ADMIN)
                 .setSmallIcon(R.drawable.ic_qs_network_logging)
                 .setContentTitle(mContext.getString(R.string.network_logging_notification_title))
                 .setContentText(mContext.getString(R.string.network_logging_notification_text))
@@ -10812,13 +10962,18 @@
     }
 
     @Override
-    public boolean isDefaultInputMethodSetByOwner(@NonNull UserHandle user) {
+    public boolean isCurrentInputMethodSetByOwner() {
+        enforceProfileOwnerOrSystemUser();
+        return getUserData(mInjector.userHandleGetCallingUserId()).mCurrentInputMethodSet;
+    }
+
+    @Override
+    public StringParceledListSlice getOwnerInstalledCaCerts(@NonNull UserHandle user) {
         final int userId = user.getIdentifier();
-        enforceProfileOwnerOrSystemUser(null);
-        if (!isCallerWithSystemUid() && mInjector.userHandleGetCallingUserId() != userId) {
-            throw new SecurityException(
-                    "Only the system can use this method to query information about another user");
+        enforceProfileOwnerOrFullCrossUsersPermission(userId);
+        synchronized (this) {
+            return new StringParceledListSlice(
+                    new ArrayList<>(getUserData(userId).mOwnerInstalledCaCerts));
         }
-        return getUserData(userId).mDefaultInputMethodSet;
     }
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/MonitoringCertNotificationTask.java b/services/devicepolicy/java/com/android/server/devicepolicy/MonitoringCertNotificationTask.java
index 03c137a..1933fe7 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/MonitoringCertNotificationTask.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/MonitoringCertNotificationTask.java
@@ -34,8 +34,8 @@
 import android.security.KeyChain.KeyChainConnection;
 import android.util.Log;
 
+import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.R;
-import com.android.internal.util.ParcelableString;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -132,16 +132,16 @@
                 dialogIntent, PendingIntent.FLAG_UPDATE_CURRENT, null,
                 UserHandle.of(parentUserId));
 
-        final Notification noti = new Notification.Builder(userContext)
-            .setSmallIcon(smallIconId)
-            .setContentTitle(resources.getQuantityText(R.plurals.ssl_ca_cert_warning,
-                    pendingCertificateCount))
-            .setContentText(contentText)
-            .setContentIntent(notifyIntent)
-            .setPriority(Notification.PRIORITY_HIGH)
-            .setShowWhen(false)
-            .setColor(R.color.system_notification_accent_color)
-            .build();
+        final Notification noti =
+                new Notification.Builder(userContext, SystemNotificationChannels.SECURITY)
+                        .setSmallIcon(smallIconId)
+                        .setContentTitle(resources.getQuantityText(R.plurals.ssl_ca_cert_warning,
+                                pendingCertificateCount))
+                        .setContentText(contentText)
+                        .setContentIntent(notifyIntent)
+                        .setShowWhen(false)
+                        .setColor(R.color.system_notification_accent_color)
+                        .build();
 
         mInjector.getNotificationManager().notifyAsUser(
                 LOG_TAG, MONITORING_CERT_NOTIFICATION_ID, noti, userHandle);
@@ -150,12 +150,7 @@
     private List<String> getInstalledCaCertificates(UserHandle userHandle)
             throws RemoteException, RuntimeException {
         try (KeyChainConnection conn = mInjector.keyChainBindAsUser(userHandle)) {
-            List<ParcelableString> aliases = conn.getService().getUserCaAliases().getList();
-            List<String> result = new ArrayList<>(aliases.size());
-            for (int i = 0; i < aliases.size(); i++) {
-                result.add(aliases.get(i).string);
-            }
-            return result;
+            return conn.getService().getUserCaAliases().getList();
         } catch (InterruptedException e) {
             Thread.currentThread().interrupt();
             return null;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportUtils.java b/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportUtils.java
index 6d42dc9..969c89e 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportUtils.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportUtils.java
@@ -28,6 +28,7 @@
 import android.text.format.DateUtils;
 
 import com.android.internal.R;
+import com.android.internal.notification.SystemNotificationChannels;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -62,14 +63,14 @@
         PendingIntent pendingDialogIntent = PendingIntent.getActivityAsUser(context, type,
                 dialogIntent, 0, null, UserHandle.CURRENT);
 
-        Notification.Builder builder = new Notification.Builder(context)
-                .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
-                .setOngoing(true)
-                .setLocalOnly(true)
-                .setPriority(Notification.PRIORITY_HIGH)
-                .setContentIntent(pendingDialogIntent)
-                .setColor(context.getColor(
-                        com.android.internal.R.color.system_notification_accent_color));
+        Notification.Builder builder =
+                new Notification.Builder(context, SystemNotificationChannels.DEVELOPER)
+                        .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
+                        .setOngoing(true)
+                        .setLocalOnly(true)
+                        .setContentIntent(pendingDialogIntent)
+                        .setColor(context.getColor(
+                                com.android.internal.R.color.system_notification_accent_color));
 
         if (type == DevicePolicyManager.NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED) {
             builder.setContentTitle(context.getString(
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java b/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
index 18f06be..2413561 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
@@ -69,6 +69,10 @@
      */
     private static final long RATE_LIMIT_INTERVAL_MILLISECONDS = TimeUnit.HOURS.toMillis(2);
     /**
+     * How often to retry the notification about available logs if it is ignored or missed by DO.
+     */
+    private static final long BROADCAST_RETRY_INTERVAL_MILLISECONDS = TimeUnit.MINUTES.toMillis(30);
+    /**
      * Internally how often should the monitor poll the security logs from logd.
      */
     private static final long POLLING_INTERVAL_MILLISECONDS = TimeUnit.MINUTES.toMillis(1);
@@ -82,7 +86,7 @@
 
     /**
      * When DO will be allowed to retrieve the log, in milliseconds since boot (as per
-     * {@link SystemClock#elapsedRealtime()})
+     * {@link SystemClock#elapsedRealtime()}). After that it will mark the time to retry broadcast.
      */
     @GuardedBy("mLock")
     private long mNextAllowedRetrievalTimeMillis = -1;
@@ -256,36 +260,35 @@
     }
 
     private void notifyDeviceOwnerIfNeeded() throws InterruptedException {
-        boolean shouldNotifyDO = false;
-        boolean allowToRetrieveNow = false;
+        boolean allowRetrievalAndNotifyDO = false;
         mLock.lockInterruptibly();
         try {
             if (mPaused) {
                 return;
             }
-
-            // STOPSHIP(b/34186771): If the previous notification didn't reach the DO and logs were
-            // not retrieved (e.g. the broadcast was sent before the user was unlocked), no more
-            // subsequent callbacks will be sent. We should make sure that the DO gets notified
-            // before logs are lost.
-            int logSize = mPendingLogs.size();
+            final int logSize = mPendingLogs.size();
             if (logSize >= BUFFER_ENTRIES_NOTIFICATION_LEVEL) {
                 // Allow DO to retrieve logs if too many pending logs
-                allowToRetrieveNow = true;
-                if (DEBUG) Slog.d(TAG, "Number of log entries over threshold: " + logSize);
-            } else if (logSize > 0) {
-                if (SystemClock.elapsedRealtime() >= mNextAllowedRetrievalTimeMillis) {
-                    // Rate limit reset
-                    allowToRetrieveNow = true;
-                    if (DEBUG) Slog.d(TAG, "Timeout reached");
+                if (!mAllowedToRetrieve) {
+                    allowRetrievalAndNotifyDO = true;
                 }
+                if (DEBUG) Slog.d(TAG, "Number of log entries over threshold: " + logSize);
             }
-            shouldNotifyDO = (!mAllowedToRetrieve) && allowToRetrieveNow;
-            mAllowedToRetrieve = allowToRetrieveNow;
+            if (logSize > 0 && SystemClock.elapsedRealtime() >= mNextAllowedRetrievalTimeMillis) {
+                // Rate limit reset
+                allowRetrievalAndNotifyDO = true;
+                if (DEBUG) Slog.d(TAG, "Timeout reached");
+            }
+            if (allowRetrievalAndNotifyDO) {
+                mAllowedToRetrieve = true;
+                // Set the timeout to retry the notification if the DO misses it.
+                mNextAllowedRetrievalTimeMillis = SystemClock.elapsedRealtime()
+                        + BROADCAST_RETRY_INTERVAL_MILLISECONDS;
+            }
         } finally {
             mLock.unlock();
         }
-        if (shouldNotifyDO) {
+        if (allowRetrievalAndNotifyDO) {
             Slog.i(TAG, "notify DO");
             mService.sendDeviceOwnerCommand(DeviceAdminReceiver.ACTION_SECURITY_LOGS_AVAILABLE,
                     null);
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 7917644..1a0aff7 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -53,6 +53,7 @@
 import com.android.internal.R;
 import com.android.internal.app.NightDisplayController;
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.os.BinderInternal;
 import com.android.internal.os.SamplingProfilerIntegration;
 import com.android.internal.policy.EmergencyAffordanceManager;
@@ -61,7 +62,7 @@
 import com.android.server.accessibility.AccessibilityManagerService;
 import com.android.server.am.ActivityManagerService;
 import com.android.server.audio.AudioService;
-import com.android.server.camera.CameraService;
+import com.android.server.camera.CameraServiceProxy;
 import com.android.server.clipboard.ClipboardService;
 import com.android.server.connectivity.IpConnectivityMetrics;
 import com.android.server.coverage.CoverageService;
@@ -82,6 +83,7 @@
 import com.android.server.net.NetworkPolicyManagerService;
 import com.android.server.net.NetworkStatsService;
 import com.android.server.notification.NotificationManagerService;
+import com.android.server.om.OverlayManagerService;
 import com.android.server.os.DeviceIdentifiersPolicyService;
 import com.android.server.os.SchedulingPolicyService;
 import com.android.server.pm.Installer;
@@ -182,10 +184,8 @@
             "com.google.android.clockwork.ThermalObserver";
     private static final String WEAR_BLUETOOTH_SERVICE_CLASS =
             "com.google.android.clockwork.bluetooth.WearBluetoothService";
-    private static final String WEAR_WIFI_MEDIATOR_SERVICE_CLASS =
-            "com.google.android.clockwork.wifi.WearWifiMediatorService";
-    private static final String WEAR_CELLULAR_MEDIATOR_SERVICE_CLASS =
-            "com.google.android.clockwork.cellular.WearCellularMediatorService";
+    private static final String WEAR_CONNECTIVITY_SERVICE_CLASS =
+            "com.google.android.clockwork.connectivity.WearConnectivityService";
     private static final String WEAR_TIME_SERVICE_CLASS =
             "com.google.android.clockwork.time.WearTimeService";
     private static final String ACCOUNT_SERVICE_CLASS =
@@ -376,6 +376,7 @@
             startBootstrapServices();
             startCoreServices();
             startOtherServices();
+            SystemServerInitThreadPool.shutdown();
         } catch (Throwable ex) {
             Slog.e("System", "******************************************");
             Slog.e("System", "************ Failure starting system services", ex);
@@ -383,7 +384,6 @@
         } finally {
             traceEnd();
         }
-        SystemServerInitThreadPool.shutdown();
 
         // For debug builds, log event loop stalls to dropbox for analysis.
         if (StrictMode.conditionallyEnableDebugLogging()) {
@@ -594,6 +594,11 @@
         mActivityManagerService.setSystemProcess();
         traceEnd();
 
+        // Manages Overlay packages
+        traceBeginAndSlog("StartOverlayManagerService");
+        mSystemServiceManager.startService(new OverlayManagerService(mSystemContext, installer));
+        traceEnd();
+
         // The sensor service needs access to package manager service, app ops
         // service, and permissions service, therefore we start it after them.
         // Start sensor service in a separate thread. Completion should be checked
@@ -735,9 +740,9 @@
             mContentResolver = context.getContentResolver();
 
             if (!disableCameraService) {
-                Slog.i(TAG, "Camera Service");
-                traceBeginAndSlog("StartCameraService");
-                mSystemServiceManager.startService(CameraService.class);
+                Slog.i(TAG, "Camera Service Proxy");
+                traceBeginAndSlog("StartCameraServiceProxy");
+                mSystemServiceManager.startService(CameraServiceProxy.class);
                 traceEnd();
             }
 
@@ -1114,6 +1119,7 @@
 
             traceBeginAndSlog("StartNotificationManager");
             mSystemServiceManager.startService(NotificationManagerService.class);
+            SystemNotificationChannels.createAll(context);
             notification = INotificationManager.Stub.asInterface(
                     ServiceManager.getService(Context.NOTIFICATION_SERVICE));
             networkPolicy.bindNotificationManager(notification);
@@ -1459,16 +1465,10 @@
             mSystemServiceManager.startService(WEAR_BLUETOOTH_SERVICE_CLASS);
             traceEnd();
 
-            traceBeginAndSlog("StartWearWifiMediator");
-            mSystemServiceManager.startService(WEAR_WIFI_MEDIATOR_SERVICE_CLASS);
+            traceBeginAndSlog("StartWearConnectivityService");
+            mSystemServiceManager.startService(WEAR_CONNECTIVITY_SERVICE_CLASS);
             traceEnd();
 
-            if (SystemProperties.getBoolean("config.enable_cellmediator", false)) {
-                traceBeginAndSlog("StartWearCellularMediator");
-                mSystemServiceManager.startService(WEAR_CELLULAR_MEDIATOR_SERVICE_CLASS);
-                traceEnd();
-            }
-
             if (!disableNonCoreServices) {
                 traceBeginAndSlog("StartWearTimeService");
                 mSystemServiceManager.startService(WEAR_TIME_SERVICE_CLASS);
@@ -1694,6 +1694,9 @@
             Watchdog.getInstance().start();
             traceEnd();
 
+            // Wait for all packages to be prepared
+            mPackageManagerService.waitForAppDataPrepared();
+
             // It is now okay to let the various system services start their
             // third party code...
             traceBeginAndSlog("PhaseThirdPartyAppsCanStart");
diff --git a/services/print/java/com/android/server/print/CompanionDeviceManagerService.java b/services/print/java/com/android/server/print/CompanionDeviceManagerService.java
index 9ac8295..ad64e4e 100644
--- a/services/print/java/com/android/server/print/CompanionDeviceManagerService.java
+++ b/services/print/java/com/android/server/print/CompanionDeviceManagerService.java
@@ -20,6 +20,7 @@
 import static com.android.internal.util.Preconditions.checkNotNull;
 
 import android.Manifest;
+import android.annotation.Nullable;
 import android.companion.AssociationRequest;
 import android.companion.CompanionDeviceManager;
 import android.companion.ICompanionDeviceDiscoveryService;
@@ -34,16 +35,39 @@
 import android.content.pm.PackageManager;
 import android.net.NetworkPolicyManager;
 import android.os.Binder;
+import android.os.Environment;
 import android.os.IBinder;
 import android.os.IDeviceIdleController;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.util.AtomicFile;
+import android.util.ExceptionUtils;
 import android.util.Slog;
+import android.util.Xml;
 
 import com.android.internal.util.ArrayUtils;
 import com.android.server.SystemService;
 
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.function.Function;
+
 //TODO move to own package!
+//TODO un/linkToDeath & onBinderDied - unbind
+//TODO onStop schedule unbind in 5 seconds
+//TODO Prune association on app uninstall
 /** @hide */
 public class CompanionDeviceManagerService extends SystemService {
 
@@ -54,7 +78,14 @@
     private static final boolean DEBUG = false;
     private static final String LOG_TAG = "CompanionDeviceManagerService";
 
+    private static final String XML_TAG_ASSOCIATIONS = "associations";
+    private static final String XML_TAG_ASSOCIATION = "association";
+    private static final String XML_ATTR_PACKAGE = "package";
+    private static final String XML_ATTR_DEVICE = "device";
+    private static final String XML_FILE_NAME = "companion_device_manager_associations.xml";
+
     private final CompanionDeviceManagerImpl mImpl;
+    private final ConcurrentMap<Integer, AtomicFile> mUidToStorage = new ConcurrentHashMap<>();
 
     public CompanionDeviceManagerService(Context context) {
         super(context);
@@ -89,6 +120,24 @@
                 Binder.restoreCallingIdentity(callingIdentity);
             }
         }
+
+
+        @Override
+        public List<String> getAssociations(String callingPackage) {
+            return ArrayUtils.map(
+                    readAllAssociations(getUserId(), callingPackage),
+                    (a) -> a.deviceAddress);
+        }
+
+        @Override
+        public void disassociate(String deviceMacAddress, String callingPackage) {
+            updateAssociations((associations) -> ArrayUtils.remove(associations,
+                    new Association(getUserId(), checkNotNull(deviceMacAddress), callingPackage)));
+        }
+    }
+
+    private int getUserId() {
+        return UserHandle.getUserId(Binder.getCallingUid());
     }
 
     private ServiceConnection getServiceConnection(
@@ -125,9 +174,12 @@
 
     private ICompanionDeviceDiscoveryServiceCallback.Stub getServiceCallback() {
         return new ICompanionDeviceDiscoveryServiceCallback.Stub() {
+
             @Override
-            public void onDeviceSelected(String packageName, int userId) {
+            public void onDeviceSelected(String packageName, int userId, String deviceAddress) {
+                //TODO unbind
                 grantSpecialAccessPermissionsIfNeeded(packageName, userId);
+                recordAssociation(packageName, deviceAddress);
             }
         };
     }
@@ -136,14 +188,14 @@
         final long identity = Binder.clearCallingIdentity();
         final PackageInfo packageInfo;
         try {
-            packageInfo = getContext().getPackageManager().getPackageInfoAsUser(
-                    packageName, PackageManager.GET_PERMISSIONS, userId);
-        } catch (PackageManager.NameNotFoundException e) {
-            Slog.e(LOG_TAG, "Error granting special access permissions to package:"
-                    + packageName, e);
-            return;
-        }
-        try {
+            try {
+                packageInfo = getContext().getPackageManager().getPackageInfoAsUser(
+                        packageName, PackageManager.GET_PERMISSIONS, userId);
+            } catch (PackageManager.NameNotFoundException e) {
+                Slog.e(LOG_TAG, "Error granting special access permissions to package:"
+                        + packageName, e);
+                return;
+            }
             if (ArrayUtils.contains(packageInfo.requestedPermissions,
                     Manifest.permission.RUN_IN_BACKGROUND)) {
                 IDeviceIdleController idleController = IDeviceIdleController.Stub.asInterface(
@@ -164,4 +216,134 @@
             Binder.restoreCallingIdentity(identity);
         }
     }
+
+    private void recordAssociation(String priviledgedPackage, String deviceAddress) {
+        updateAssociations((associations) -> ArrayUtils.add(associations,
+                new Association(getUserId(), deviceAddress, priviledgedPackage)));
+    }
+
+    private void updateAssociations(
+            Function<ArrayList<Association>, ArrayList<Association>> update) {
+        final int userId = getUserId();
+        final AtomicFile file = getStorageFileForUser(userId);
+        synchronized (file) {
+            final ArrayList<Association> old = readAllAssociations(userId);
+            final ArrayList<Association> associations = update.apply(old);
+            if (Objects.equals(old, associations)) return;
+
+            file.write((out) -> {
+                XmlSerializer xml = Xml.newSerializer();
+                try {
+                    xml.setOutput(out, StandardCharsets.UTF_8.name());
+                    xml.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
+                    xml.startDocument(null, true);
+                    xml.startTag(null, XML_TAG_ASSOCIATIONS);
+
+                    for (int i = 0; i < ArrayUtils.size(associations); i++) {
+                        Association association = associations.get(i);
+                        xml.startTag(null, XML_TAG_ASSOCIATION)
+                            .attribute(null, XML_ATTR_PACKAGE, association.companionAppPackage)
+                            .attribute(null, XML_ATTR_DEVICE, association.deviceAddress)
+                            .endTag(null, XML_TAG_ASSOCIATION);
+                    }
+
+                    xml.endTag(null, XML_TAG_ASSOCIATIONS);
+                    xml.endDocument();
+                } catch (Exception e) {
+                    Slog.e(LOG_TAG, "Error while writing associations file", e);
+                    throw ExceptionUtils.propagate(e);
+                }
+
+            });
+        }
+
+
+        //TODO Show dialog before recording notification access
+//        final SettingStringHelper setting =
+//                new SettingStringHelper(
+//                        getContext().getContentResolver(),
+//                        Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
+//                        getUserId());
+//        setting.write(ColonDelimitedSet.OfStrings.add(setting.read(), priviledgedPackage));
+    }
+
+    private AtomicFile getStorageFileForUser(int uid) {
+        return mUidToStorage.computeIfAbsent(uid, (u) ->
+                new AtomicFile(new File(
+                        //TODO deprecated method - what's the right replacement?
+                        Environment.getUserSystemDirectory(u),
+                        XML_FILE_NAME)));
+    }
+
+    @Nullable
+    private ArrayList<Association> readAllAssociations(int uid) {
+        return readAllAssociations(uid, null);
+    }
+
+    @Nullable
+    private ArrayList<Association> readAllAssociations(int userId, @Nullable String packageFilter) {
+        final AtomicFile file = getStorageFileForUser(userId);
+
+        if (!file.getBaseFile().exists()) return null;
+
+        ArrayList<Association> result = null;
+        final XmlPullParser parser = Xml.newPullParser();
+        synchronized (file) {
+            try (FileInputStream in = file.openRead()) {
+                parser.setInput(in, StandardCharsets.UTF_8.name());
+                int type;
+                while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+                    if (type != XmlPullParser.START_TAG
+                            && !XML_TAG_ASSOCIATIONS.equals(parser.getName())) continue;
+
+                    final String appPackage = parser.getAttributeValue(null, XML_ATTR_PACKAGE);
+                    final String deviceAddress = parser.getAttributeValue(null, XML_ATTR_DEVICE);
+
+                    if (appPackage == null || deviceAddress == null) continue;
+                    if (packageFilter != null && !packageFilter.equals(appPackage)) continue;
+
+                    result = ArrayUtils.add(result,
+                            new Association(userId, deviceAddress, appPackage));
+                }
+                return result;
+            } catch (XmlPullParserException | IOException e) {
+                Slog.e(LOG_TAG, "Error while reading associations file", e);
+                return null;
+            }
+        }
+    }
+
+    private class Association {
+        public final int uid;
+        public final String deviceAddress;
+        public final String companionAppPackage;
+
+        private Association(int uid, String deviceAddress, String companionAppPackage) {
+            this.uid = uid;
+            this.deviceAddress = checkNotNull(deviceAddress);
+            this.companionAppPackage = checkNotNull(companionAppPackage);
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            Association that = (Association) o;
+
+            if (uid != that.uid) return false;
+            if (!deviceAddress.equals(that.deviceAddress)) return false;
+            return companionAppPackage.equals(that.companionAppPackage);
+
+        }
+
+        @Override
+        public int hashCode() {
+            int result = uid;
+            result = 31 * result + deviceAddress.hashCode();
+            result = 31 * result + companionAppPackage.hashCode();
+            return result;
+        }
+    }
+
 }
diff --git a/services/profile-classes b/services/profile-classes
new file mode 100644
index 0000000..1b304e1
--- /dev/null
+++ b/services/profile-classes
@@ -0,0 +1,7272 @@
+Landroid/accessibilityservice/AccessibilityServiceInfo;
+Landroid/accessibilityservice/AccessibilityServiceInfo$1;
+Landroid/accessibilityservice/IAccessibilityServiceClient;
+Landroid/accessibilityservice/IAccessibilityServiceConnection;
+Landroid/accessibilityservice/IAccessibilityServiceConnection$Stub;
+Landroid/accounts/Account;
+Landroid/accounts/Account$1;
+Landroid/accounts/AccountAndUser;
+Landroid/accounts/AccountManager;
+Landroid/accounts/AccountManager$1;
+Landroid/accounts/AccountManagerInternal;
+Landroid/accounts/AccountManagerInternal$OnAppPermissionChangeListener;
+Landroid/accounts/AuthenticatorDescription;
+Landroid/accounts/AuthenticatorDescription$1;
+Landroid/accounts/IAccountAuthenticator;
+Landroid/accounts/IAccountAuthenticatorResponse;
+Landroid/accounts/IAccountAuthenticatorResponse$Stub;
+Landroid/accounts/IAccountAuthenticator$Stub;
+Landroid/accounts/IAccountAuthenticator$Stub$Proxy;
+Landroid/accounts/IAccountManager;
+Landroid/accounts/IAccountManagerResponse;
+Landroid/accounts/IAccountManagerResponse$Stub;
+Landroid/accounts/IAccountManagerResponse$Stub$Proxy;
+Landroid/accounts/IAccountManager$Stub;
+Landroid/animation/AnimationHandler;
+Landroid/animation/AnimationHandler$1;
+Landroid/animation/AnimationHandler$AnimationFrameCallback;
+Landroid/animation/AnimationHandler$AnimationFrameCallbackProvider;
+Landroid/animation/AnimationHandler$MyFrameCallbackProvider;
+Landroid/animation/Animator;
+Landroid/animation/Animator$AnimatorListener;
+Landroid/animation/Animator$AnimatorPauseListener;
+Landroid/animation/AnimatorListenerAdapter;
+Landroid/animation/ArgbEvaluator;
+Landroid/animation/FloatEvaluator;
+Landroid/animation/FloatKeyframeSet;
+Landroid/animation/IntEvaluator;
+Landroid/animation/Keyframe;
+Landroid/animation/Keyframe$FloatKeyframe;
+Landroid/animation/Keyframe$ObjectKeyframe;
+Landroid/animation/Keyframes;
+Landroid/animation/KeyframeSet;
+Landroid/animation/Keyframes$FloatKeyframes;
+Landroid/animation/LayoutTransition$TransitionListener;
+Landroid/animation/ObjectAnimator;
+Landroid/animation/PropertyValuesHolder;
+Landroid/animation/PropertyValuesHolder$FloatPropertyValuesHolder;
+Landroid/animation/PropertyValuesHolder$PropertyValues;
+Landroid/animation/RectEvaluator;
+Landroid/animation/TimeInterpolator;
+Landroid/animation/TypeEvaluator;
+Landroid/animation/ValueAnimator;
+Landroid/animation/ValueAnimator$AnimatorUpdateListener;
+Landroid/app/ActionBar$LayoutParams;
+Landroid/app/Activity;
+Landroid/app/ActivityManager;
+Landroid/app/ActivityManager$1;
+Landroid/app/ActivityManagerInternal;
+Landroid/app/ActivityManagerInternal$SleepToken;
+Landroid/app/ActivityManager$MemoryInfo;
+Landroid/app/ActivityManager$MemoryInfo$1;
+Landroid/app/ActivityManager$OnUidImportanceListener;
+Landroid/app/ActivityManager$RecentTaskInfo;
+Landroid/app/ActivityManager$RecentTaskInfo$1;
+Landroid/app/ActivityManager$RunningAppProcessInfo;
+Landroid/app/ActivityManager$RunningAppProcessInfo$1;
+Landroid/app/ActivityManager$RunningServiceInfo;
+Landroid/app/ActivityManager$RunningServiceInfo$1;
+Landroid/app/ActivityManager$RunningTaskInfo;
+Landroid/app/ActivityManager$RunningTaskInfo$1;
+Landroid/app/ActivityManager$StackId;
+Landroid/app/ActivityManager$StackInfo;
+Landroid/app/ActivityManager$StackInfo$1;
+Landroid/app/ActivityManager$TaskDescription;
+Landroid/app/ActivityManager$TaskDescription$1;
+Landroid/app/ActivityManager$TaskSnapshot;
+Landroid/app/ActivityManager$TaskSnapshot$1;
+Landroid/app/ActivityManager$TaskThumbnail;
+Landroid/app/ActivityManager$TaskThumbnailInfo;
+Landroid/app/ActivityManager$TaskThumbnailInfo$1;
+Landroid/app/ActivityManager$UidObserver;
+Landroid/app/ActivityOptions;
+Landroid/app/ActivityThread;
+Landroid/app/ActivityThread$3;
+Landroid/app/ActivityThread$ApplicationThread;
+Landroid/app/ActivityThread$BindServiceData;
+Landroid/app/ActivityThread$ContextCleanupInfo;
+Landroid/app/ActivityThread$CreateServiceData;
+Landroid/app/ActivityThread$DropBoxReporter;
+Landroid/app/ActivityThread$DumpComponentInfo;
+Landroid/app/ActivityThread$GcIdler;
+Landroid/app/ActivityThread$H;
+Landroid/app/ActivityThread$Profiler;
+Landroid/app/ActivityThread$ProviderClientRecord;
+Landroid/app/ActivityThread$ProviderKey;
+Landroid/app/ActivityThread$ProviderRefCount;
+Landroid/app/ActivityThread$ReceiverData;
+Landroid/app/ActivityThread$ServiceArgsData;
+Landroid/app/admin/DevicePolicyManager;
+Landroid/app/admin/DevicePolicyManagerInternal;
+Landroid/app/admin/DevicePolicyManagerInternal$OnCrossProfileWidgetProvidersChangeListener;
+Landroid/app/admin/IDevicePolicyManager;
+Landroid/app/admin/IDevicePolicyManager$Stub;
+Landroid/app/admin/PasswordMetrics;
+Landroid/app/admin/PasswordMetrics$1;
+Landroid/app/admin/SecurityLog;
+Landroid/app/admin/SecurityLog$SecurityEvent;
+Landroid/app/admin/SecurityLog$SecurityEvent$1;
+Landroid/app/admin/SystemUpdateInfo;
+Landroid/app/admin/SystemUpdatePolicy;
+Landroid/app/AlarmManager;
+Landroid/app/AlarmManager$AlarmClockInfo;
+Landroid/app/AlarmManager$ListenerWrapper;
+Landroid/app/AlarmManager$OnAlarmListener;
+Landroid/app/AppGlobals;
+Landroid/app/Application;
+Landroid/app/ApplicationErrorReport$CrashInfo;
+Landroid/app/ApplicationErrorReport$ParcelableCrashInfo;
+Landroid/app/ApplicationLoaders;
+Landroid/app/ApplicationPackageManager;
+Landroid/app/ApplicationPackageManager$OnPermissionsChangeListenerDelegate;
+Landroid/app/ApplicationPackageManager$ResourceName;
+Landroid/app/AppOpsManager;
+Landroid/app/AppOpsManager$1;
+Landroid/app/AppOpsManager$OnOpChangedInternalListener;
+Landroid/app/AppOpsManager$OnOpChangedListener;
+Landroid/app/AppOpsManager$OpEntry;
+Landroid/app/AppOpsManager$OpEntry$1;
+Landroid/app/AppOpsManager$PackageOps;
+Landroid/app/AppOpsManager$PackageOps$1;
+Landroid/app/assist/AssistContent;
+Landroid/app/assist/AssistContent$1;
+Landroid/app/assist/AssistStructure;
+Landroid/app/assist/AssistStructure$1;
+Landroid/app/AutomaticZenRule;
+Landroid/app/backup/BackupAgent;
+Landroid/app/backup/BackupDataInput;
+Landroid/app/backup/BackupDataInput$EntityHeader;
+Landroid/app/backup/BackupDataOutput;
+Landroid/app/backup/BackupHelper;
+Landroid/app/backup/BackupHelperDispatcher;
+Landroid/app/backup/BackupHelperDispatcher$Header;
+Landroid/app/backup/BackupManager;
+Landroid/app/backup/BackupTransport;
+Landroid/app/backup/BackupTransport$TransportImpl;
+Landroid/app/backup/FileBackupHelperBase;
+Landroid/app/backup/FullBackup;
+Landroid/app/backup/FullBackupDataOutput;
+Landroid/app/backup/IBackupManager;
+Landroid/app/backup/IBackupManager$Stub;
+Landroid/app/backup/IBackupObserver;
+Landroid/app/backup/IFullBackupRestoreObserver;
+Landroid/app/backup/IRestoreSession;
+Landroid/app/backup/ISelectBackupTransportCallback;
+Landroid/app/BroadcastOptions;
+Landroid/app/ContentProviderHolder;
+Landroid/app/ContentProviderHolder$1;
+Landroid/app/ContextImpl;
+Landroid/app/ContextImpl$ApplicationContentResolver;
+Landroid/app/DownloadManager;
+Landroid/app/IActivityContainer;
+Landroid/app/IActivityContainerCallback;
+Landroid/app/IActivityContainer$Stub;
+Landroid/app/IActivityController;
+Landroid/app/IActivityManager;
+Landroid/app/IActivityManager$Stub;
+Landroid/app/IAlarmCompleteListener;
+Landroid/app/IAlarmCompleteListener$Stub;
+Landroid/app/IAlarmListener;
+Landroid/app/IAlarmListener$Stub;
+Landroid/app/IAlarmManager;
+Landroid/app/IAlarmManager$Stub;
+Landroid/app/IApplicationThread;
+Landroid/app/IApplicationThread$Stub;
+Landroid/app/IApplicationThread$Stub$Proxy;
+Landroid/app/IAppTask;
+Landroid/app/IAppTask$Stub;
+Landroid/app/IInstrumentationWatcher;
+Landroid/app/INotificationManager;
+Landroid/app/INotificationManager$Stub;
+Landroid/app/Instrumentation;
+Landroid/app/IntentReceiverLeaked;
+Landroid/app/IProcessObserver;
+Landroid/app/IProcessObserver$Stub;
+Landroid/app/IProcessObserver$Stub$Proxy;
+Landroid/app/ISearchManager;
+Landroid/app/ISearchManager$Stub;
+Landroid/app/IServiceConnection;
+Landroid/app/IServiceConnection$Stub;
+Landroid/app/IServiceConnection$Stub$Proxy;
+Landroid/app/IStopUserCallback;
+Landroid/app/ITaskStackListener;
+Landroid/app/ITaskStackListener$Stub;
+Landroid/app/ITaskStackListener$Stub$Proxy;
+Landroid/app/ITransientNotification;
+Landroid/app/ITransientNotification$Stub;
+Landroid/app/ITransientNotification$Stub$Proxy;
+Landroid/app/IUiAutomationConnection;
+Landroid/app/IUidObserver;
+Landroid/app/IUidObserver$Stub;
+Landroid/app/IUiModeManager;
+Landroid/app/IUiModeManager$Stub;
+Landroid/app/IUserSwitchObserver;
+Landroid/app/IUserSwitchObserver$Stub;
+Landroid/app/IUserSwitchObserver$Stub$Proxy;
+Landroid/app/IWallpaperManager;
+Landroid/app/IWallpaperManagerCallback;
+Landroid/app/IWallpaperManagerCallback$Stub;
+Landroid/app/IWallpaperManagerCallback$Stub$Proxy;
+Landroid/app/IWallpaperManager$Stub;
+Landroid/app/job/IJobCallback;
+Landroid/app/job/IJobCallback$Stub;
+Landroid/app/job/IJobScheduler;
+Landroid/app/job/IJobScheduler$Stub;
+Landroid/app/job/IJobService;
+Landroid/app/job/IJobService$Stub;
+Landroid/app/job/IJobService$Stub$Proxy;
+Landroid/app/job/JobInfo;
+Landroid/app/job/JobInfo$1;
+Landroid/app/job/JobInfo$Builder;
+Landroid/app/job/JobInfo$TriggerContentUri;
+Landroid/app/job/JobInfo$TriggerContentUri$1;
+Landroid/app/job/JobParameters;
+Landroid/app/job/JobParameters$1;
+Landroid/app/job/JobScheduler;
+Landroid/app/job/JobService;
+Landroid/app/job/JobService$JobHandler;
+Landroid/app/job/JobService$JobInterface;
+Landroid/app/JobSchedulerImpl;
+Landroid/app/KeyguardManager;
+Landroid/app/LoadedApk;
+Landroid/app/LoadedApk$ReceiverDispatcher;
+Landroid/app/LoadedApk$ReceiverDispatcher$Args;
+Landroid/app/LoadedApk$ReceiverDispatcher$InnerReceiver;
+Landroid/app/LoadedApk$ServiceDispatcher;
+Landroid/app/LoadedApk$ServiceDispatcher$ConnectionInfo;
+Landroid/app/LoadedApk$ServiceDispatcher$DeathMonitor;
+Landroid/app/LoadedApk$ServiceDispatcher$InnerConnection;
+Landroid/app/LoadedApk$ServiceDispatcher$RunConnection;
+Landroid/app/LoadedApk$WarningContextClassLoader;
+Landroid/app/NativeActivity;
+Landroid/app/Notification;
+Landroid/app/Notification$1;
+Landroid/app/Notification$Action;
+Landroid/app/Notification$Action$1;
+Landroid/app/Notification$BigPictureStyle;
+Landroid/app/Notification$BigTextStyle;
+Landroid/app/Notification$Builder;
+Landroid/app/Notification$BuilderRemoteViews;
+Landroid/app/NotificationChannel;
+Landroid/app/NotificationChannel$1;
+Landroid/app/Notification$DecoratedCustomViewStyle;
+Landroid/app/Notification$DecoratedMediaCustomViewStyle;
+Landroid/app/Notification$InboxStyle;
+Landroid/app/NotificationManager;
+Landroid/app/NotificationManager$Policy;
+Landroid/app/NotificationManager$Policy$1;
+Landroid/app/Notification$MediaStyle;
+Landroid/app/Notification$MessagingStyle;
+Landroid/app/Notification$StandardTemplateParams;
+Landroid/app/Notification$Style;
+Landroid/app/PendingIntent;
+Landroid/app/PendingIntent$1;
+Landroid/app/PendingIntent$CanceledException;
+Landroid/app/PendingIntent$FinishedDispatcher;
+Landroid/app/PendingIntent$OnFinished;
+Landroid/app/PendingIntent$OnMarshaledListener;
+Landroid/app/PictureInPictureArgs;
+Landroid/app/PictureInPictureArgs$1;
+Landroid/app/ProfilerInfo;
+Landroid/app/QueuedWork;
+Landroid/app/QueuedWork$QueuedWorkHandler;
+Landroid/app/ReceiverRestrictedContext;
+Landroid/app/RemoteInput;
+Landroid/app/RemoteInput$1;
+Landroid/app/ResourcesManager;
+Landroid/app/ResourcesManager$1;
+Landroid/app/ResultInfo;
+Landroid/app/ResultInfo$1;
+Landroid/app/RetailDemoModeServiceInternal;
+Landroid/app/SearchableInfo;
+Landroid/app/SearchableInfo$1;
+Landroid/app/SearchManager;
+Landroid/app/Service;
+Landroid/app/ServiceConnectionLeaked;
+Landroid/app/StatusBarManager;
+Landroid/app/SynchronousUserSwitchObserver;
+Landroid/app/SystemServiceRegistry;
+Landroid/app/SystemServiceRegistry$1;
+Landroid/app/SystemServiceRegistry$10;
+Landroid/app/SystemServiceRegistry$11;
+Landroid/app/SystemServiceRegistry$12;
+Landroid/app/SystemServiceRegistry$13;
+Landroid/app/SystemServiceRegistry$14;
+Landroid/app/SystemServiceRegistry$15;
+Landroid/app/SystemServiceRegistry$16;
+Landroid/app/SystemServiceRegistry$17;
+Landroid/app/SystemServiceRegistry$18;
+Landroid/app/SystemServiceRegistry$19;
+Landroid/app/SystemServiceRegistry$2;
+Landroid/app/SystemServiceRegistry$20;
+Landroid/app/SystemServiceRegistry$21;
+Landroid/app/SystemServiceRegistry$22;
+Landroid/app/SystemServiceRegistry$23;
+Landroid/app/SystemServiceRegistry$24;
+Landroid/app/SystemServiceRegistry$25;
+Landroid/app/SystemServiceRegistry$26;
+Landroid/app/SystemServiceRegistry$27;
+Landroid/app/SystemServiceRegistry$28;
+Landroid/app/SystemServiceRegistry$29;
+Landroid/app/SystemServiceRegistry$3;
+Landroid/app/SystemServiceRegistry$30;
+Landroid/app/SystemServiceRegistry$31;
+Landroid/app/SystemServiceRegistry$32;
+Landroid/app/SystemServiceRegistry$33;
+Landroid/app/SystemServiceRegistry$34;
+Landroid/app/SystemServiceRegistry$35;
+Landroid/app/SystemServiceRegistry$36;
+Landroid/app/SystemServiceRegistry$37;
+Landroid/app/SystemServiceRegistry$38;
+Landroid/app/SystemServiceRegistry$39;
+Landroid/app/SystemServiceRegistry$4;
+Landroid/app/SystemServiceRegistry$40;
+Landroid/app/SystemServiceRegistry$41;
+Landroid/app/SystemServiceRegistry$42;
+Landroid/app/SystemServiceRegistry$43;
+Landroid/app/SystemServiceRegistry$44;
+Landroid/app/SystemServiceRegistry$45;
+Landroid/app/SystemServiceRegistry$46;
+Landroid/app/SystemServiceRegistry$47;
+Landroid/app/SystemServiceRegistry$48;
+Landroid/app/SystemServiceRegistry$49;
+Landroid/app/SystemServiceRegistry$5;
+Landroid/app/SystemServiceRegistry$50;
+Landroid/app/SystemServiceRegistry$51;
+Landroid/app/SystemServiceRegistry$52;
+Landroid/app/SystemServiceRegistry$53;
+Landroid/app/SystemServiceRegistry$54;
+Landroid/app/SystemServiceRegistry$55;
+Landroid/app/SystemServiceRegistry$56;
+Landroid/app/SystemServiceRegistry$57;
+Landroid/app/SystemServiceRegistry$58;
+Landroid/app/SystemServiceRegistry$59;
+Landroid/app/SystemServiceRegistry$6;
+Landroid/app/SystemServiceRegistry$60;
+Landroid/app/SystemServiceRegistry$61;
+Landroid/app/SystemServiceRegistry$62;
+Landroid/app/SystemServiceRegistry$63;
+Landroid/app/SystemServiceRegistry$64;
+Landroid/app/SystemServiceRegistry$65;
+Landroid/app/SystemServiceRegistry$66;
+Landroid/app/SystemServiceRegistry$67;
+Landroid/app/SystemServiceRegistry$68;
+Landroid/app/SystemServiceRegistry$69;
+Landroid/app/SystemServiceRegistry$7;
+Landroid/app/SystemServiceRegistry$70;
+Landroid/app/SystemServiceRegistry$71;
+Landroid/app/SystemServiceRegistry$72;
+Landroid/app/SystemServiceRegistry$73;
+Landroid/app/SystemServiceRegistry$74;
+Landroid/app/SystemServiceRegistry$75;
+Landroid/app/SystemServiceRegistry$76;
+Landroid/app/SystemServiceRegistry$77;
+Landroid/app/SystemServiceRegistry$78;
+Landroid/app/SystemServiceRegistry$79;
+Landroid/app/SystemServiceRegistry$8;
+Landroid/app/SystemServiceRegistry$9;
+Landroid/app/SystemServiceRegistry$CachedServiceFetcher;
+Landroid/app/SystemServiceRegistry$ServiceFetcher;
+Landroid/app/SystemServiceRegistry$StaticApplicationContextServiceFetcher;
+Landroid/app/SystemServiceRegistry$StaticServiceFetcher;
+Landroid/app/trust/IStrongAuthTracker;
+Landroid/app/trust/IStrongAuthTracker$Stub;
+Landroid/app/trust/IStrongAuthTracker$Stub$Proxy;
+Landroid/app/trust/ITrustListener;
+Landroid/app/trust/ITrustListener$Stub;
+Landroid/app/trust/ITrustListener$Stub$Proxy;
+Landroid/app/trust/ITrustManager;
+Landroid/app/trust/ITrustManager$Stub;
+Landroid/app/trust/TrustManager;
+Landroid/app/UiModeManager;
+Landroid/app/usage/ConfigurationStats;
+Landroid/app/usage/ConfigurationStats$1;
+Landroid/app/usage/ExternalStorageStats;
+Landroid/app/usage/IStorageStatsManager;
+Landroid/app/usage/IStorageStatsManager$Stub;
+Landroid/app/usage/IUsageStatsManager;
+Landroid/app/usage/IUsageStatsManager$Stub;
+Landroid/app/usage/NetworkStatsManager;
+Landroid/app/usage/StorageStats;
+Landroid/app/usage/StorageStatsManager;
+Landroid/app/usage/TimeSparseArray;
+Landroid/app/usage/UsageEvents;
+Landroid/app/usage/UsageEvents$1;
+Landroid/app/usage/UsageEvents$Event;
+Landroid/app/usage/UsageStats;
+Landroid/app/usage/UsageStats$1;
+Landroid/app/usage/UsageStatsManager;
+Landroid/app/usage/UsageStatsManagerInternal;
+Landroid/app/usage/UsageStatsManagerInternal$AppIdleStateChangeListener;
+Landroid/app/UserSwitchObserver;
+Landroid/app/WaitResult;
+Landroid/app/WallpaperInfo;
+Landroid/app/WallpaperInfo$1;
+Landroid/app/WallpaperManager;
+Landroid/appwidget/AppWidgetManager;
+Landroid/appwidget/AppWidgetProviderInfo;
+Landroid/appwidget/AppWidgetProviderInfo$1;
+Landroid/bluetooth/BluetoothA2dp;
+Landroid/bluetooth/BluetoothA2dp$1;
+Landroid/bluetooth/BluetoothA2dp$2;
+Landroid/bluetooth/BluetoothActivityEnergyInfo;
+Landroid/bluetooth/BluetoothActivityEnergyInfo$1;
+Landroid/bluetooth/BluetoothAdapter;
+Landroid/bluetooth/BluetoothAdapter$1;
+Landroid/bluetooth/BluetoothDevice;
+Landroid/bluetooth/BluetoothHeadset;
+Landroid/bluetooth/BluetoothHeadset$1;
+Landroid/bluetooth/BluetoothHeadset$2;
+Landroid/bluetooth/BluetoothHeadset$3;
+Landroid/bluetooth/BluetoothManager;
+Landroid/bluetooth/BluetoothProfile;
+Landroid/bluetooth/BluetoothProfile$ServiceListener;
+Landroid/bluetooth/IBluetooth;
+Landroid/bluetooth/IBluetoothA2dp;
+Landroid/bluetooth/IBluetoothA2dp$Stub;
+Landroid/bluetooth/IBluetoothA2dp$Stub$Proxy;
+Landroid/bluetooth/IBluetoothCallback;
+Landroid/bluetooth/IBluetoothCallback$Stub;
+Landroid/bluetooth/IBluetoothGatt;
+Landroid/bluetooth/IBluetoothGatt$Stub;
+Landroid/bluetooth/IBluetoothGatt$Stub$Proxy;
+Landroid/bluetooth/IBluetoothHeadset;
+Landroid/bluetooth/IBluetoothHeadsetPhone;
+Landroid/bluetooth/IBluetoothHeadsetPhone$Stub;
+Landroid/bluetooth/IBluetoothHeadset$Stub;
+Landroid/bluetooth/IBluetoothHeadset$Stub$Proxy;
+Landroid/bluetooth/IBluetoothManager;
+Landroid/bluetooth/IBluetoothManagerCallback;
+Landroid/bluetooth/IBluetoothManagerCallback$Stub;
+Landroid/bluetooth/IBluetoothManagerCallback$Stub$Proxy;
+Landroid/bluetooth/IBluetoothManager$Stub;
+Landroid/bluetooth/IBluetoothProfileServiceConnection;
+Landroid/bluetooth/IBluetoothProfileServiceConnection$Stub;
+Landroid/bluetooth/IBluetoothProfileServiceConnection$Stub$Proxy;
+Landroid/bluetooth/IBluetoothStateChangeCallback;
+Landroid/bluetooth/IBluetoothStateChangeCallback$Stub;
+Landroid/bluetooth/IBluetoothStateChangeCallback$Stub$Proxy;
+Landroid/bluetooth/IBluetooth$Stub;
+Landroid/bluetooth/IBluetooth$Stub$Proxy;
+Landroid/bluetooth/UidTraffic;
+Landroid/bluetooth/UidTraffic$1;
+Landroid/content/ActivityNotFoundException;
+Landroid/content/AsyncQueryHandler;
+Landroid/content/AsyncQueryHandler$WorkerArgs;
+Landroid/content/AsyncQueryHandler$WorkerHandler;
+Landroid/content/BroadcastReceiver;
+Landroid/content/BroadcastReceiver$PendingResult;
+Landroid/content/ClipboardManager;
+Landroid/content/ClipData;
+Landroid/content/ClipDescription;
+Landroid/content/ComponentCallbacks;
+Landroid/content/ComponentCallbacks2;
+Landroid/content/ComponentName;
+Landroid/content/ComponentName$1;
+Landroid/content/ContentProvider;
+Landroid/content/ContentProviderNative;
+Landroid/content/ContentProviderProxy;
+Landroid/content/ContentProvider$Transport;
+Landroid/content/ContentResolver;
+Landroid/content/ContentResolver$CursorWrapperInner;
+Landroid/content/ContentUris;
+Landroid/content/ContentValues;
+Landroid/content/ContentValues$1;
+Landroid/content/Context;
+Landroid/content/ContextWrapper;
+Landroid/content/DialogInterface$OnCancelListener;
+Landroid/content/DialogInterface$OnDismissListener;
+Landroid/content/IClipboard;
+Landroid/content/IClipboard$Stub;
+Landroid/content/IContentProvider;
+Landroid/content/IContentService;
+Landroid/content/IContentService$Stub;
+Landroid/content/IIntentReceiver;
+Landroid/content/IIntentReceiver$Stub;
+Landroid/content/IIntentReceiver$Stub$Proxy;
+Landroid/content/IIntentSender;
+Landroid/content/IIntentSender$Stub;
+Landroid/content/Intent;
+Landroid/content/Intent$1;
+Landroid/content/IntentFilter;
+Landroid/content/IntentFilter$1;
+Landroid/content/IntentFilter$AuthorityEntry;
+Landroid/content/Intent$FilterComparison;
+Landroid/content/IntentFilter$MalformedMimeTypeException;
+Landroid/content/IntentSender;
+Landroid/content/IntentSender$SendIntentException;
+Landroid/content/IOnPrimaryClipChangedListener;
+Landroid/content/IOnPrimaryClipChangedListener$Stub;
+Landroid/content/IOnPrimaryClipChangedListener$Stub$Proxy;
+Landroid/content/IRestrictionsManager;
+Landroid/content/IRestrictionsManager$Stub;
+Landroid/content/ISyncAdapter;
+Landroid/content/ISyncAdapter$Stub;
+Landroid/content/ISyncAdapter$Stub$Proxy;
+Landroid/content/ISyncContext;
+Landroid/content/ISyncContext$Stub;
+Landroid/content/ISyncStatusObserver;
+Landroid/content/ISyncStatusObserver$Stub;
+Landroid/content/ISyncStatusObserver$Stub$Proxy;
+Landroid/content/PeriodicSync;
+Landroid/content/PeriodicSync$1;
+Landroid/content/pm/ActivityInfo;
+Landroid/content/pm/ActivityInfo$1;
+Landroid/content/pm/ActivityInfo$WindowLayout;
+Landroid/content/pm/ApplicationInfo;
+Landroid/content/pm/ApplicationInfo$1;
+Landroid/content/pm/ComponentInfo;
+Landroid/content/pm/ConfigurationInfo;
+Landroid/content/pm/ConfigurationInfo$1;
+Landroid/content/pm/EphemeralResponse;
+Landroid/content/pm/FallbackCategoryProvider;
+Landroid/content/pm/FeatureInfo;
+Landroid/content/pm/FeatureInfo$1;
+Landroid/content/pm/ILauncherApps;
+Landroid/content/pm/ILauncherApps$Stub;
+Landroid/content/pm/InstrumentationInfo;
+Landroid/content/pm/IntentFilterVerificationInfo;
+Landroid/content/pm/IntentFilterVerificationInfo$1;
+Landroid/content/pm/IOnAppsChangedListener;
+Landroid/content/pm/IOnAppsChangedListener$Stub;
+Landroid/content/pm/IOnAppsChangedListener$Stub$Proxy;
+Landroid/content/pm/IOnPermissionsChangeListener;
+Landroid/content/pm/IOnPermissionsChangeListener$Stub;
+Landroid/content/pm/IOnPermissionsChangeListener$Stub$Proxy;
+Landroid/content/pm/IOtaDexopt;
+Landroid/content/pm/IOtaDexopt$Stub;
+Landroid/content/pm/IPackageDataObserver;
+Landroid/content/pm/IPackageDeleteObserver;
+Landroid/content/pm/IPackageDeleteObserver2;
+Landroid/content/pm/IPackageInstaller;
+Landroid/content/pm/IPackageInstallerCallback;
+Landroid/content/pm/IPackageInstallerCallback$Stub;
+Landroid/content/pm/IPackageInstallerCallback$Stub$Proxy;
+Landroid/content/pm/IPackageInstallerSession;
+Landroid/content/pm/IPackageInstaller$Stub;
+Landroid/content/pm/IPackageInstallObserver2;
+Landroid/content/pm/IPackageManager;
+Landroid/content/pm/IPackageManager$Stub;
+Landroid/content/pm/IPackageMoveObserver;
+Landroid/content/pm/IPackageMoveObserver$Stub;
+Landroid/content/pm/IPackageMoveObserver$Stub$Proxy;
+Landroid/content/pm/IPackageStatsObserver;
+Landroid/content/pm/IPackageStatsObserver$Stub;
+Landroid/content/pm/IPackageStatsObserver$Stub$Proxy;
+Landroid/content/pm/IShortcutService;
+Landroid/content/pm/IShortcutService$Stub;
+Landroid/content/pm/KeySet;
+Landroid/content/pm/LauncherApps;
+Landroid/content/pm/PackageCleanItem;
+Landroid/content/pm/PackageInfo;
+Landroid/content/pm/PackageInfo$1;
+Landroid/content/pm/PackageInstaller$SessionInfo;
+Landroid/content/pm/PackageInstaller$SessionParams;
+Landroid/content/pm/PackageItemInfo;
+Landroid/content/pm/PackageManager;
+Landroid/content/pm/PackageManagerInternal;
+Landroid/content/pm/PackageManagerInternal$ExternalSourcesPolicy;
+Landroid/content/pm/PackageManagerInternal$PackagesProvider;
+Landroid/content/pm/PackageManagerInternal$SyncAdapterPackagesProvider;
+Landroid/content/pm/PackageManager$NameNotFoundException;
+Landroid/content/pm/PackageManager$OnPermissionsChangedListener;
+Landroid/content/pm/PackageParser;
+Landroid/content/pm/PackageParser$Activity;
+Landroid/content/pm/PackageParser$Activity$1;
+Landroid/content/pm/PackageParser$ActivityIntentInfo;
+Landroid/content/pm/PackageParser$ApkLite;
+Landroid/content/pm/PackageParser$Component;
+Landroid/content/pm/PackageParser$IntentInfo;
+Landroid/content/pm/PackageParser$NewPermissionInfo;
+Landroid/content/pm/PackageParser$Package;
+Landroid/content/pm/PackageParser$Package$1;
+Landroid/content/pm/PackageParser$PackageParserException;
+Landroid/content/pm/PackageParser$Permission;
+Landroid/content/pm/PackageParser$Permission$1;
+Landroid/content/pm/PackageParser$PermissionGroup;
+Landroid/content/pm/PackageParser$PermissionGroup$1;
+Landroid/content/pm/PackageParser$Provider;
+Landroid/content/pm/PackageParser$Provider$1;
+Landroid/content/pm/PackageParser$ProviderIntentInfo;
+Landroid/content/pm/PackageParser$Service;
+Landroid/content/pm/PackageParser$Service$1;
+Landroid/content/pm/PackageParser$ServiceIntentInfo;
+Landroid/content/pm/PackageParser$SplitNameComparator;
+Landroid/content/pm/PackageParser$SplitPermissionInfo;
+Landroid/content/pm/PackageStats;
+Landroid/content/pm/PackageStats$1;
+Landroid/content/pm/PackageUserState;
+Landroid/content/pm/ParceledListSlice;
+Landroid/content/pm/ParceledListSlice$1;
+Landroid/content/pm/ParceledListSlice$2;
+Landroid/content/pm/PathPermission;
+Landroid/content/pm/PathPermission$1;
+Landroid/content/pm/PermissionGroupInfo;
+Landroid/content/pm/PermissionGroupInfo$1;
+Landroid/content/pm/PermissionInfo;
+Landroid/content/pm/PermissionInfo$1;
+Landroid/content/pm/ProviderInfo;
+Landroid/content/pm/ProviderInfo$1;
+Landroid/content/pm/RegisteredServicesCache;
+Landroid/content/pm/RegisteredServicesCache$1;
+Landroid/content/pm/RegisteredServicesCache$2;
+Landroid/content/pm/RegisteredServicesCache$3;
+Landroid/content/pm/RegisteredServicesCacheListener;
+Landroid/content/pm/RegisteredServicesCache$ServiceInfo;
+Landroid/content/pm/RegisteredServicesCache$UserServices;
+Landroid/content/pm/ResolveInfo;
+Landroid/content/pm/ResolveInfo$1;
+Landroid/content/pm/ServiceInfo;
+Landroid/content/pm/ServiceInfo$1;
+Landroid/content/pm/SharedLibraryInfo;
+Landroid/content/pm/SharedLibraryInfo$1;
+Landroid/content/pm/ShortcutInfo;
+Landroid/content/pm/ShortcutInfo$1;
+Landroid/content/pm/ShortcutManager;
+Landroid/content/pm/ShortcutServiceInternal;
+Landroid/content/pm/ShortcutServiceInternal$ShortcutChangeListener;
+Landroid/content/pm/Signature;
+Landroid/content/pm/Signature$1;
+Landroid/content/pm/UserInfo;
+Landroid/content/pm/UserInfo$1;
+Landroid/content/pm/VerifierDeviceIdentity;
+Landroid/content/pm/VersionedPackage;
+Landroid/content/pm/VersionedPackage$1;
+Landroid/content/pm/XmlSerializerAndParser;
+Landroid/content/res/AssetFileDescriptor;
+Landroid/content/res/AssetFileDescriptor$1;
+Landroid/content/res/AssetManager;
+Landroid/content/res/AssetManager$AssetInputStream;
+Landroid/content/res/ColorStateList;
+Landroid/content/res/ColorStateList$1;
+Landroid/content/res/ColorStateList$ColorStateListFactory;
+Landroid/content/res/CompatibilityInfo;
+Landroid/content/res/CompatibilityInfo$1;
+Landroid/content/res/CompatibilityInfo$2;
+Landroid/content/res/ComplexColor;
+Landroid/content/res/Configuration;
+Landroid/content/res/Configuration$1;
+Landroid/content/res/ConfigurationBoundResourceCache;
+Landroid/content/res/ConstantState;
+Landroid/content/res/DrawableCache;
+Landroid/content/res/GradientColor;
+Landroid/content/res/ObbInfo;
+Landroid/content/res/ObbInfo$1;
+Landroid/content/res/ObbScanner;
+Landroid/content/res/Resources;
+Landroid/content/res/ResourcesImpl;
+Landroid/content/res/ResourcesImpl$ThemeImpl;
+Landroid/content/res/ResourcesKey;
+Landroid/content/res/Resources$NotFoundException;
+Landroid/content/res/Resources$Theme;
+Landroid/content/res/Resources$ThemeKey;
+Landroid/content/res/StringBlock;
+Landroid/content/res/ThemedResourceCache;
+Landroid/content/RestrictionsManager;
+Landroid/content/res/TypedArray;
+Landroid/content/res/XmlBlock;
+Landroid/content/res/XmlBlock$Parser;
+Landroid/content/res/XmlResourceParser;
+Landroid/content/ServiceConnection;
+Landroid/content/SyncAdaptersCache;
+Landroid/content/SyncAdaptersCache$MySerializer;
+Landroid/content/SyncAdapterType;
+Landroid/content/SyncAdapterType$1;
+Landroid/content/SyncInfo;
+Landroid/content/SyncInfo$1;
+Landroid/content/SyncRequest;
+Landroid/content/SyncRequest$1;
+Landroid/content/SyncResult;
+Landroid/content/SyncResult$1;
+Landroid/content/SyncStats;
+Landroid/content/SyncStats$1;
+Landroid/content/SyncStatusInfo;
+Landroid/content/SyncStatusInfo$1;
+Landroid/database/AbstractCursor;
+Landroid/database/AbstractCursor$SelfContentObserver;
+Landroid/database/AbstractWindowedCursor;
+Landroid/database/BulkCursorDescriptor;
+Landroid/database/BulkCursorDescriptor$1;
+Landroid/database/BulkCursorNative;
+Landroid/database/BulkCursorProxy;
+Landroid/database/BulkCursorToCursorAdaptor;
+Landroid/database/CharArrayBuffer;
+Landroid/database/ContentObservable;
+Landroid/database/ContentObserver;
+Landroid/database/ContentObserver$NotificationRunnable;
+Landroid/database/ContentObserver$Transport;
+Landroid/database/CrossProcessCursor;
+Landroid/database/CrossProcessCursorWrapper;
+Landroid/database/Cursor;
+Landroid/database/CursorWindow;
+Landroid/database/CursorWindow$1;
+Landroid/database/CursorWrapper;
+Landroid/database/DatabaseErrorHandler;
+Landroid/database/DatabaseUtils;
+Landroid/database/DataSetObservable;
+Landroid/database/DefaultDatabaseErrorHandler;
+Landroid/database/IBulkCursor;
+Landroid/database/IContentObserver;
+Landroid/database/IContentObserver$Stub;
+Landroid/database/IContentObserver$Stub$Proxy;
+Landroid/database/Observable;
+Landroid/database/SQLException;
+Landroid/database/sqlite/DatabaseObjectNotClosedException;
+Landroid/database/sqlite/SQLiteClosable;
+Landroid/database/sqlite/SQLiteConnection;
+Landroid/database/sqlite/SQLiteConnection$Operation;
+Landroid/database/sqlite/SQLiteConnection$OperationLog;
+Landroid/database/sqlite/SQLiteConnectionPool;
+Landroid/database/sqlite/SQLiteConnectionPool$AcquiredConnectionStatus;
+Landroid/database/sqlite/SQLiteConnection$PreparedStatement;
+Landroid/database/sqlite/SQLiteConnection$PreparedStatementCache;
+Landroid/database/sqlite/SQLiteCursor;
+Landroid/database/sqlite/SQLiteCursorDriver;
+Landroid/database/sqlite/SQLiteCustomFunction;
+Landroid/database/sqlite/SQLiteDatabase;
+Landroid/database/sqlite/SQLiteDatabase$1;
+Landroid/database/sqlite/SQLiteDatabaseConfiguration;
+Landroid/database/sqlite/SQLiteDatabaseCorruptException;
+Landroid/database/sqlite/SQLiteDatabaseLockedException;
+Landroid/database/sqlite/SQLiteDebug;
+Landroid/database/sqlite/SQLiteDebug$PagerStats;
+Landroid/database/sqlite/SQLiteDirectCursorDriver;
+Landroid/database/sqlite/SQLiteException;
+Landroid/database/sqlite/SQLiteGlobal;
+Landroid/database/sqlite/SQLiteOpenHelper;
+Landroid/database/sqlite/SQLiteProgram;
+Landroid/database/sqlite/SQLiteQuery;
+Landroid/database/sqlite/SQLiteQueryBuilder;
+Landroid/database/sqlite/SQLiteSession;
+Landroid/database/sqlite/SQLiteSession$Transaction;
+Landroid/database/sqlite/SQLiteStatement;
+Landroid/database/sqlite/SQLiteStatementInfo;
+Landroid/ddm/DdmHandleAppName;
+Landroid/ddm/DdmHandleExit;
+Landroid/ddm/DdmHandleHeap;
+Landroid/ddm/DdmHandleHello;
+Landroid/ddm/DdmHandleNativeHeap;
+Landroid/ddm/DdmHandleProfiling;
+Landroid/ddm/DdmHandleThread;
+Landroid/ddm/DdmHandleViewDebug;
+Landroid/ddm/DdmRegister;
+Landroid/graphics/BaseCanvas;
+Landroid/graphics/Bitmap;
+Landroid/graphics/Bitmap$1;
+Landroid/graphics/Bitmap$CompressFormat;
+Landroid/graphics/Bitmap$Config;
+Landroid/graphics/BitmapFactory;
+Landroid/graphics/BitmapFactory$Options;
+Landroid/graphics/BitmapRegionDecoder;
+Landroid/graphics/BitmapShader;
+Landroid/graphics/BlurMaskFilter;
+Landroid/graphics/BlurMaskFilter$Blur;
+Landroid/graphics/Camera;
+Landroid/graphics/Canvas;
+Landroid/graphics/Canvas$EdgeType;
+Landroid/graphics/Canvas$NoImagePreloadHolder;
+Landroid/graphics/CanvasProperty;
+Landroid/graphics/Color;
+Landroid/graphics/ColorFilter;
+Landroid/graphics/ColorMatrix;
+Landroid/graphics/ColorMatrixColorFilter;
+Landroid/graphics/ComposePathEffect;
+Landroid/graphics/ComposeShader;
+Landroid/graphics/CornerPathEffect;
+Landroid/graphics/DashPathEffect;
+Landroid/graphics/DiscretePathEffect;
+Landroid/graphics/drawable/Animatable;
+Landroid/graphics/drawable/Animatable2;
+Landroid/graphics/drawable/AnimatedStateListDrawable;
+Landroid/graphics/drawable/AnimatedStateListDrawable$AnimatedStateListState;
+Landroid/graphics/drawable/AnimatedVectorDrawable;
+Landroid/graphics/drawable/AnimatedVectorDrawable$1;
+Landroid/graphics/drawable/AnimatedVectorDrawable$AnimatedVectorDrawableState;
+Landroid/graphics/drawable/AnimatedVectorDrawable$AnimatedVectorDrawableState$PendingAnimator;
+Landroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;
+Landroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT;
+Landroid/graphics/drawable/AnimationDrawable;
+Landroid/graphics/drawable/AnimationDrawable$AnimationState;
+Landroid/graphics/drawable/BitmapDrawable;
+Landroid/graphics/drawable/BitmapDrawable$BitmapState;
+Landroid/graphics/drawable/ColorDrawable;
+Landroid/graphics/drawable/ColorDrawable$ColorState;
+Landroid/graphics/drawable/Drawable;
+Landroid/graphics/drawable/Drawable$Callback;
+Landroid/graphics/drawable/Drawable$ConstantState;
+Landroid/graphics/drawable/DrawableContainer;
+Landroid/graphics/drawable/DrawableContainer$BlockInvalidateCallback;
+Landroid/graphics/drawable/DrawableContainer$DrawableContainerState;
+Landroid/graphics/drawable/DrawableInflater;
+Landroid/graphics/drawable/DrawableWrapper;
+Landroid/graphics/drawable/DrawableWrapper$DrawableWrapperState;
+Landroid/graphics/drawable/GradientDrawable;
+Landroid/graphics/drawable/GradientDrawable$GradientState;
+Landroid/graphics/drawable/GradientDrawable$Orientation;
+Landroid/graphics/drawable/Icon;
+Landroid/graphics/drawable/Icon$1;
+Landroid/graphics/drawable/InsetDrawable;
+Landroid/graphics/drawable/InsetDrawable$InsetState;
+Landroid/graphics/drawable/LayerDrawable;
+Landroid/graphics/drawable/LayerDrawable$ChildDrawable;
+Landroid/graphics/drawable/LayerDrawable$LayerState;
+Landroid/graphics/drawable/NinePatchDrawable;
+Landroid/graphics/drawable/NinePatchDrawable$NinePatchState;
+Landroid/graphics/drawable/RippleBackground;
+Landroid/graphics/drawable/RippleBackground$1;
+Landroid/graphics/drawable/RippleBackground$BackgroundProperty;
+Landroid/graphics/drawable/RippleComponent;
+Landroid/graphics/drawable/RippleDrawable;
+Landroid/graphics/drawable/RippleDrawable$RippleState;
+Landroid/graphics/drawable/RippleForeground;
+Landroid/graphics/drawable/RippleForeground$1;
+Landroid/graphics/drawable/RippleForeground$2;
+Landroid/graphics/drawable/RippleForeground$3;
+Landroid/graphics/drawable/RippleForeground$4;
+Landroid/graphics/drawable/RippleForeground$LogDecelerateInterpolator;
+Landroid/graphics/drawable/ScaleDrawable;
+Landroid/graphics/drawable/ScaleDrawable$ScaleState;
+Landroid/graphics/drawable/StateListDrawable;
+Landroid/graphics/drawable/StateListDrawable$StateListState;
+Landroid/graphics/drawable/VectorDrawable;
+Landroid/graphics/drawable/VectorDrawable$VectorDrawableState;
+Landroid/graphics/drawable/VectorDrawable$VectorDrawableState$1;
+Landroid/graphics/drawable/VectorDrawable$VFullPath;
+Landroid/graphics/drawable/VectorDrawable$VFullPath$1;
+Landroid/graphics/drawable/VectorDrawable$VFullPath$10;
+Landroid/graphics/drawable/VectorDrawable$VFullPath$2;
+Landroid/graphics/drawable/VectorDrawable$VFullPath$3;
+Landroid/graphics/drawable/VectorDrawable$VFullPath$4;
+Landroid/graphics/drawable/VectorDrawable$VFullPath$5;
+Landroid/graphics/drawable/VectorDrawable$VFullPath$6;
+Landroid/graphics/drawable/VectorDrawable$VFullPath$7;
+Landroid/graphics/drawable/VectorDrawable$VFullPath$8;
+Landroid/graphics/drawable/VectorDrawable$VFullPath$9;
+Landroid/graphics/drawable/VectorDrawable$VGroup;
+Landroid/graphics/drawable/VectorDrawable$VGroup$1;
+Landroid/graphics/drawable/VectorDrawable$VGroup$2;
+Landroid/graphics/drawable/VectorDrawable$VGroup$3;
+Landroid/graphics/drawable/VectorDrawable$VGroup$4;
+Landroid/graphics/drawable/VectorDrawable$VGroup$5;
+Landroid/graphics/drawable/VectorDrawable$VGroup$6;
+Landroid/graphics/drawable/VectorDrawable$VGroup$7;
+Landroid/graphics/drawable/VectorDrawable$VGroup$8;
+Landroid/graphics/drawable/VectorDrawable$VGroup$9;
+Landroid/graphics/drawable/VectorDrawable$VObject;
+Landroid/graphics/drawable/VectorDrawable$VPath;
+Landroid/graphics/drawable/VectorDrawable$VPath$1;
+Landroid/graphics/DrawFilter;
+Landroid/graphics/EmbossMaskFilter;
+Landroid/graphics/FontFamily;
+Landroid/graphics/FontListParser;
+Landroid/graphics/GraphicBuffer;
+Landroid/graphics/GraphicBuffer$1;
+Landroid/graphics/Insets;
+Landroid/graphics/Interpolator;
+Landroid/graphics/LightingColorFilter;
+Landroid/graphics/LinearGradient;
+Landroid/graphics/MaskFilter;
+Landroid/graphics/Matrix;
+Landroid/graphics/Matrix$1;
+Landroid/graphics/Matrix$NoImagePreloadHolder;
+Landroid/graphics/Matrix$ScaleToFit;
+Landroid/graphics/Movie;
+Landroid/graphics/NinePatch;
+Landroid/graphics/NinePatch$InsetStruct;
+Landroid/graphics/Outline;
+Landroid/graphics/Paint;
+Landroid/graphics/Paint$Align;
+Landroid/graphics/Paint$Cap;
+Landroid/graphics/PaintFlagsDrawFilter;
+Landroid/graphics/Paint$FontMetrics;
+Landroid/graphics/Paint$FontMetricsInt;
+Landroid/graphics/Paint$Join;
+Landroid/graphics/Paint$NoImagePreloadHolder;
+Landroid/graphics/Paint$Style;
+Landroid/graphics/Path;
+Landroid/graphics/PathDashPathEffect;
+Landroid/graphics/PathEffect;
+Landroid/graphics/Path$FillType;
+Landroid/graphics/PathMeasure;
+Landroid/graphics/pdf/PdfDocument;
+Landroid/graphics/pdf/PdfEditor;
+Landroid/graphics/pdf/PdfRenderer;
+Landroid/graphics/Picture;
+Landroid/graphics/PixelFormat;
+Landroid/graphics/Point;
+Landroid/graphics/Point$1;
+Landroid/graphics/PointF;
+Landroid/graphics/PointF$1;
+Landroid/graphics/PorterDuff;
+Landroid/graphics/PorterDuffColorFilter;
+Landroid/graphics/PorterDuff$Mode;
+Landroid/graphics/RadialGradient;
+Landroid/graphics/Rect;
+Landroid/graphics/Rect$1;
+Landroid/graphics/RectF;
+Landroid/graphics/RectF$1;
+Landroid/graphics/Region;
+Landroid/graphics/Region$1;
+Landroid/graphics/RegionIterator;
+Landroid/graphics/Region$Op;
+Landroid/graphics/Shader;
+Landroid/graphics/Shader$TileMode;
+Landroid/graphics/SumPathEffect;
+Landroid/graphics/SurfaceTexture;
+Landroid/graphics/SweepGradient;
+Landroid/graphics/TableMaskFilter;
+Landroid/graphics/TemporaryBuffer;
+Landroid/graphics/Typeface;
+Landroid/graphics/YuvImage;
+Landroid/hardware/biometrics/fingerprint/V2_1/IBiometricsFingerprint;
+Landroid/hardware/biometrics/fingerprint/V2_1/IBiometricsFingerprintClientCallback;
+Landroid/hardware/biometrics/fingerprint/V2_1/IBiometricsFingerprintClientCallback$Stub;
+Landroid/hardware/biometrics/fingerprint/V2_1/IBiometricsFingerprint$Proxy;
+Landroid/hardware/Camera;
+Landroid/hardware/camera2/CameraAccessException;
+Landroid/hardware/camera2/CameraCharacteristics$Key;
+Landroid/hardware/camera2/CameraManager;
+Landroid/hardware/camera2/CaptureRequest$Key;
+Landroid/hardware/camera2/CaptureResult$Key;
+Landroid/hardware/camera2/DngCreator;
+Landroid/hardware/camera2/impl/CameraMetadataNative;
+Landroid/hardware/camera2/legacy/LegacyCameraDevice;
+Landroid/hardware/camera2/legacy/PerfMeasurement;
+Landroid/hardware/Camera$CameraInfo;
+Landroid/hardware/Camera$Face;
+Landroid/hardware/ConsumerIrManager;
+Landroid/hardware/display/DisplayManager;
+Landroid/hardware/display/DisplayManager$DisplayListener;
+Landroid/hardware/display/DisplayManagerGlobal;
+Landroid/hardware/display/DisplayManagerGlobal$DisplayListenerDelegate;
+Landroid/hardware/display/DisplayManagerGlobal$DisplayManagerCallback;
+Landroid/hardware/display/DisplayManagerInternal;
+Landroid/hardware/display/DisplayManagerInternal$DisplayPowerCallbacks;
+Landroid/hardware/display/DisplayManagerInternal$DisplayPowerRequest;
+Landroid/hardware/display/DisplayManagerInternal$DisplayTransactionListener;
+Landroid/hardware/display/DisplayViewport;
+Landroid/hardware/display/IDisplayManager;
+Landroid/hardware/display/IDisplayManagerCallback;
+Landroid/hardware/display/IDisplayManagerCallback$Stub;
+Landroid/hardware/display/IDisplayManagerCallback$Stub$Proxy;
+Landroid/hardware/display/IDisplayManager$Stub;
+Landroid/hardware/display/IVirtualDisplayCallback;
+Landroid/hardware/display/WifiDisplay;
+Landroid/hardware/display/WifiDisplay$1;
+Landroid/hardware/display/WifiDisplaySessionInfo;
+Landroid/hardware/display/WifiDisplaySessionInfo$1;
+Landroid/hardware/display/WifiDisplayStatus;
+Landroid/hardware/display/WifiDisplayStatus$1;
+Landroid/hardware/fingerprint/FingerprintManager;
+Landroid/hardware/fingerprint/IFingerprintClientActiveCallback;
+Landroid/hardware/fingerprint/IFingerprintService;
+Landroid/hardware/fingerprint/IFingerprintServiceLockoutResetCallback;
+Landroid/hardware/fingerprint/IFingerprintServiceLockoutResetCallback$Stub;
+Landroid/hardware/fingerprint/IFingerprintServiceLockoutResetCallback$Stub$Proxy;
+Landroid/hardware/fingerprint/IFingerprintServiceReceiver;
+Landroid/hardware/fingerprint/IFingerprintService$Stub;
+Landroid/hardware/HardwareBuffer;
+Landroid/hardware/HardwareBuffer$1;
+Landroid/hardware/hdmi/HdmiControlManager;
+Landroid/hardware/hdmi/HdmiPlaybackClient$DisplayStatusCallback;
+Landroid/hardware/ICameraService;
+Landroid/hardware/ICameraServiceProxy;
+Landroid/hardware/ICameraServiceProxy$Stub;
+Landroid/hardware/ICameraService$Stub;
+Landroid/hardware/ICameraService$Stub$Proxy;
+Landroid/hardware/IConsumerIrService;
+Landroid/hardware/IConsumerIrService$Stub;
+Landroid/hardware/input/IInputDevicesChangedListener;
+Landroid/hardware/input/IInputDevicesChangedListener$Stub;
+Landroid/hardware/input/IInputDevicesChangedListener$Stub$Proxy;
+Landroid/hardware/input/IInputManager;
+Landroid/hardware/input/IInputManager$Stub;
+Landroid/hardware/input/InputDeviceIdentifier;
+Landroid/hardware/input/InputDeviceIdentifier$1;
+Landroid/hardware/input/InputManager;
+Landroid/hardware/input/InputManager$InputDeviceListener;
+Landroid/hardware/input/InputManagerInternal;
+Landroid/hardware/input/ITabletModeChangedListener;
+Landroid/hardware/input/KeyboardLayout;
+Landroid/hardware/input/KeyboardLayout$1;
+Landroid/hardware/input/TouchCalibration;
+Landroid/hardware/input/TouchCalibration$1;
+Landroid/hardware/ISerialManager;
+Landroid/hardware/ISerialManager$Stub;
+Landroid/hardware/location/ActivityRecognitionHardware;
+Landroid/hardware/location/ContextHubInfo;
+Landroid/hardware/location/ContextHubInfo$1;
+Landroid/hardware/location/ContextHubManager;
+Landroid/hardware/location/ContextHubMessage;
+Landroid/hardware/location/ContextHubMessage$1;
+Landroid/hardware/location/GeofenceHardwareImpl;
+Landroid/hardware/location/GeofenceHardwareImpl$1;
+Landroid/hardware/location/GeofenceHardwareImpl$2;
+Landroid/hardware/location/GeofenceHardwareImpl$3;
+Landroid/hardware/location/GeofenceHardwareImpl$Reaper;
+Landroid/hardware/location/GeofenceHardwareService;
+Landroid/hardware/location/GeofenceHardwareService$1;
+Landroid/hardware/location/IActivityRecognitionHardware;
+Landroid/hardware/location/IActivityRecognitionHardwareClient;
+Landroid/hardware/location/IActivityRecognitionHardwareClient$Stub;
+Landroid/hardware/location/IActivityRecognitionHardwareClient$Stub$Proxy;
+Landroid/hardware/location/IActivityRecognitionHardware$Stub;
+Landroid/hardware/location/IActivityRecognitionHardwareWatcher;
+Landroid/hardware/location/IContextHubCallback;
+Landroid/hardware/location/IContextHubCallback$Stub;
+Landroid/hardware/location/IContextHubCallback$Stub$Proxy;
+Landroid/hardware/location/IContextHubService;
+Landroid/hardware/location/IContextHubService$Stub;
+Landroid/hardware/location/IGeofenceHardware;
+Landroid/hardware/location/IGeofenceHardwareMonitorCallback;
+Landroid/hardware/location/IGeofenceHardwareMonitorCallback$Stub;
+Landroid/hardware/location/IGeofenceHardwareMonitorCallback$Stub$Proxy;
+Landroid/hardware/location/IGeofenceHardware$Stub;
+Landroid/hardware/location/MemoryRegion;
+Landroid/hardware/location/NanoApp;
+Landroid/hardware/location/NanoAppFilter;
+Landroid/hardware/location/NanoAppFilter$1;
+Landroid/hardware/location/NanoAppInstanceInfo;
+Landroid/hardware/location/NanoAppInstanceInfo$1;
+Landroid/hardware/radio/RadioManager;
+Landroid/hardware/radio/RadioManager$AmBandConfig;
+Landroid/hardware/radio/RadioManager$AmBandConfig$1;
+Landroid/hardware/radio/RadioManager$AmBandDescriptor;
+Landroid/hardware/radio/RadioManager$AmBandDescriptor$1;
+Landroid/hardware/radio/RadioManager$BandConfig;
+Landroid/hardware/radio/RadioManager$BandConfig$1;
+Landroid/hardware/radio/RadioManager$BandDescriptor;
+Landroid/hardware/radio/RadioManager$BandDescriptor$1;
+Landroid/hardware/radio/RadioManager$FmBandConfig;
+Landroid/hardware/radio/RadioManager$FmBandConfig$1;
+Landroid/hardware/radio/RadioManager$FmBandDescriptor;
+Landroid/hardware/radio/RadioManager$FmBandDescriptor$1;
+Landroid/hardware/radio/RadioManager$ModuleProperties;
+Landroid/hardware/radio/RadioManager$ModuleProperties$1;
+Landroid/hardware/radio/RadioManager$ProgramInfo;
+Landroid/hardware/radio/RadioManager$ProgramInfo$1;
+Landroid/hardware/radio/RadioMetadata;
+Landroid/hardware/radio/RadioMetadata$1;
+Landroid/hardware/radio/RadioModule;
+Landroid/hardware/radio/RadioTuner;
+Landroid/hardware/Sensor;
+Landroid/hardware/SensorEvent;
+Landroid/hardware/SensorEventListener;
+Landroid/hardware/SensorManager;
+Landroid/hardware/SerialManager;
+Landroid/hardware/SerialPort;
+Landroid/hardware/soundtrigger/IRecognitionStatusCallback;
+Landroid/hardware/soundtrigger/SoundTrigger;
+Landroid/hardware/soundtrigger/SoundTrigger$ConfidenceLevel;
+Landroid/hardware/soundtrigger/SoundTrigger$ConfidenceLevel$1;
+Landroid/hardware/soundtrigger/SoundTrigger$GenericRecognitionEvent;
+Landroid/hardware/soundtrigger/SoundTrigger$GenericRecognitionEvent$1;
+Landroid/hardware/soundtrigger/SoundTrigger$GenericSoundModel;
+Landroid/hardware/soundtrigger/SoundTrigger$Keyphrase;
+Landroid/hardware/soundtrigger/SoundTrigger$Keyphrase$1;
+Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionEvent;
+Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionEvent$1;
+Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;
+Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra$1;
+Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseSoundModel;
+Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseSoundModel$1;
+Landroid/hardware/soundtrigger/SoundTriggerModule;
+Landroid/hardware/soundtrigger/SoundTrigger$ModuleProperties;
+Landroid/hardware/soundtrigger/SoundTrigger$ModuleProperties$1;
+Landroid/hardware/soundtrigger/SoundTrigger$RecognitionConfig;
+Landroid/hardware/soundtrigger/SoundTrigger$RecognitionConfig$1;
+Landroid/hardware/soundtrigger/SoundTrigger$RecognitionEvent;
+Landroid/hardware/soundtrigger/SoundTrigger$RecognitionEvent$1;
+Landroid/hardware/soundtrigger/SoundTrigger$SoundModel;
+Landroid/hardware/soundtrigger/SoundTrigger$SoundModelEvent;
+Landroid/hardware/soundtrigger/SoundTrigger$SoundModelEvent$1;
+Landroid/hardware/soundtrigger/SoundTrigger$StatusListener;
+Landroid/hardware/SystemSensorManager;
+Landroid/hardware/SystemSensorManager$BaseEventQueue;
+Landroid/hardware/SystemSensorManager$SensorEventQueue;
+Landroid/hardware/TriggerEvent;
+Landroid/hardware/TriggerEventListener;
+Landroid/hardware/usb/IUsbManager;
+Landroid/hardware/usb/IUsbManager$Stub;
+Landroid/hardware/usb/UsbAccessory;
+Landroid/hardware/usb/UsbDevice;
+Landroid/hardware/usb/UsbDeviceConnection;
+Landroid/hardware/usb/UsbManager;
+Landroid/hardware/usb/UsbPort;
+Landroid/hardware/usb/UsbPort$1;
+Landroid/hardware/usb/UsbPortStatus;
+Landroid/hardware/usb/UsbPortStatus$1;
+Landroid/hardware/usb/UsbRequest;
+Landroid/hardware/usb/V1_0/IUsb;
+Landroid/hardware/usb/V1_0/IUsbCallback;
+Landroid/hardware/usb/V1_0/IUsbCallback$Stub;
+Landroid/hardware/usb/V1_0/IUsb$Proxy;
+Landroid/hardware/usb/V1_0/PortStatus;
+Landroid/hardware/wifi/V1_0/IWifiEventCallback;
+Landroid/hardware/wifi/V1_0/IWifiEventCallback$Stub;
+Landroid/hidl/base/V1_0/IBase;
+Landroid/hidl/manager/V1_0/IServiceManager;
+Landroid/hidl/manager/V1_0/IServiceManager$Proxy;
+Landroid/hidl/manager/V1_0/IServiceNotification;
+Landroid/hidl/manager/V1_0/IServiceNotification$Stub;
+Landroid/icu/impl/BMPSet;
+Landroid/icu/impl/CacheBase;
+Landroid/icu/impl/CacheValue;
+Landroid/icu/impl/CacheValue$NullValue;
+Landroid/icu/impl/CacheValue$SoftValue;
+Landroid/icu/impl/CacheValue$Strength;
+Landroid/icu/impl/CharTrie;
+Landroid/icu/impl/ClassLoaderUtil;
+Landroid/icu/impl/CurrencyData;
+Landroid/icu/impl/CurrencyData$CurrencyDisplayInfo;
+Landroid/icu/impl/CurrencyData$CurrencyDisplayInfoProvider;
+Landroid/icu/impl/CurrencyData$CurrencySpacingInfo;
+Landroid/icu/impl/CurrencyData$CurrencySpacingInfo$SpacingPattern;
+Landroid/icu/impl/CurrencyData$CurrencySpacingInfo$SpacingType;
+Landroid/icu/impl/ICUBinary;
+Landroid/icu/impl/ICUBinary$Authenticate;
+Landroid/icu/impl/ICUBinary$DataFile;
+Landroid/icu/impl/ICUBinary$DatPackageReader;
+Landroid/icu/impl/ICUBinary$DatPackageReader$IsAcceptable;
+Landroid/icu/impl/ICUBinary$PackageDataFile;
+Landroid/icu/impl/ICUCache;
+Landroid/icu/impl/ICUConfig;
+Landroid/icu/impl/ICUCurrencyDisplayInfoProvider;
+Landroid/icu/impl/ICUCurrencyDisplayInfoProvider$ICUCurrencyDisplayInfo;
+Landroid/icu/impl/ICUCurrencyDisplayInfoProvider$ICUCurrencyDisplayInfo$SpacingInfoSink;
+Landroid/icu/impl/ICUCurrencyMetaInfo;
+Landroid/icu/impl/ICUCurrencyMetaInfo$Collector;
+Landroid/icu/impl/ICUCurrencyMetaInfo$CurrencyCollector;
+Landroid/icu/impl/ICUCurrencyMetaInfo$UniqueList;
+Landroid/icu/impl/ICUData;
+Landroid/icu/impl/ICUDebug;
+Landroid/icu/impl/ICULangDataTables;
+Landroid/icu/impl/ICURegionDataTables;
+Landroid/icu/impl/ICUResourceBundle;
+Landroid/icu/impl/ICUResourceBundle$1;
+Landroid/icu/impl/ICUResourceBundle$2;
+Landroid/icu/impl/ICUResourceBundle$4;
+Landroid/icu/impl/ICUResourceBundleImpl;
+Landroid/icu/impl/ICUResourceBundleImpl$ResourceArray;
+Landroid/icu/impl/ICUResourceBundleImpl$ResourceContainer;
+Landroid/icu/impl/ICUResourceBundleImpl$ResourceInt;
+Landroid/icu/impl/ICUResourceBundleImpl$ResourceString;
+Landroid/icu/impl/ICUResourceBundleImpl$ResourceTable;
+Landroid/icu/impl/ICUResourceBundle$Loader;
+Landroid/icu/impl/ICUResourceBundle$OpenType;
+Landroid/icu/impl/ICUResourceBundleReader;
+Landroid/icu/impl/ICUResourceBundleReader$Array;
+Landroid/icu/impl/ICUResourceBundleReader$Array16;
+Landroid/icu/impl/ICUResourceBundleReader$Array32;
+Landroid/icu/impl/ICUResourceBundleReader$Container;
+Landroid/icu/impl/ICUResourceBundleReader$IsAcceptable;
+Landroid/icu/impl/ICUResourceBundleReader$ReaderCache;
+Landroid/icu/impl/ICUResourceBundleReader$ReaderCacheKey;
+Landroid/icu/impl/ICUResourceBundleReader$ReaderValue;
+Landroid/icu/impl/ICUResourceBundleReader$ResourceCache;
+Landroid/icu/impl/ICUResourceBundleReader$ResourceCache$Level;
+Landroid/icu/impl/ICUResourceBundleReader$Table;
+Landroid/icu/impl/ICUResourceBundleReader$Table16;
+Landroid/icu/impl/ICUResourceBundleReader$Table1632;
+Landroid/icu/impl/ICUResourceBundle$WholeBundle;
+Landroid/icu/impl/ICUResourceTableAccess;
+Landroid/icu/impl/IDNA2003;
+Landroid/icu/impl/locale/AsciiUtil;
+Landroid/icu/impl/locale/BaseLocale;
+Landroid/icu/impl/locale/BaseLocale$Cache;
+Landroid/icu/impl/locale/BaseLocale$Key;
+Landroid/icu/impl/LocaleDisplayNamesImpl;
+Landroid/icu/impl/LocaleDisplayNamesImpl$Cache;
+Landroid/icu/impl/LocaleDisplayNamesImpl$CapitalizationContextUsage;
+Landroid/icu/impl/LocaleDisplayNamesImpl$DataTable;
+Landroid/icu/impl/LocaleDisplayNamesImpl$DataTables;
+Landroid/icu/impl/LocaleDisplayNamesImpl$ICUDataTable;
+Landroid/icu/impl/LocaleDisplayNamesImpl$ICUDataTables;
+Landroid/icu/impl/LocaleDisplayNamesImpl$LangDataTables;
+Landroid/icu/impl/LocaleDisplayNamesImpl$RegionDataTables;
+Landroid/icu/impl/LocaleIDParser;
+Landroid/icu/impl/LocaleIDs;
+Landroid/icu/impl/locale/LocaleObjectCache;
+Landroid/icu/impl/locale/LocaleObjectCache$CacheEntry;
+Landroid/icu/impl/locale/LocaleSyntaxException;
+Landroid/icu/impl/Norm2AllModes;
+Landroid/icu/impl/Norm2AllModes$1;
+Landroid/icu/impl/Norm2AllModes$ComposeNormalizer2;
+Landroid/icu/impl/Norm2AllModes$DecomposeNormalizer2;
+Landroid/icu/impl/Norm2AllModes$FCDNormalizer2;
+Landroid/icu/impl/Norm2AllModes$NFKCSingleton;
+Landroid/icu/impl/Norm2AllModes$NoopNormalizer2;
+Landroid/icu/impl/Norm2AllModes$Norm2AllModesSingleton;
+Landroid/icu/impl/Norm2AllModes$Normalizer2WithImpl;
+Landroid/icu/impl/Normalizer2Impl;
+Landroid/icu/impl/Normalizer2Impl$1;
+Landroid/icu/impl/Normalizer2Impl$IsAcceptable;
+Landroid/icu/impl/Pair;
+Landroid/icu/impl/ReplaceableUCharacterIterator;
+Landroid/icu/impl/SimpleCache;
+Landroid/icu/impl/SimpleFormatterImpl;
+Landroid/icu/impl/SoftCache;
+Landroid/icu/impl/StringPrepDataReader;
+Landroid/icu/impl/Trie;
+Landroid/icu/impl/Trie2;
+Landroid/icu/impl/Trie2$1;
+Landroid/icu/impl/Trie2_16;
+Landroid/icu/impl/Trie2$UTrie2Header;
+Landroid/icu/impl/Trie2$ValueMapper;
+Landroid/icu/impl/Trie2$ValueWidth;
+Landroid/icu/impl/Trie$DataManipulate;
+Landroid/icu/impl/Trie$DefaultGetFoldingOffset;
+Landroid/icu/impl/UBiDiProps;
+Landroid/icu/impl/UBiDiProps$IsAcceptable;
+Landroid/icu/impl/UCharacterProperty;
+Landroid/icu/impl/UCharacterProperty$1;
+Landroid/icu/impl/UCharacterProperty$10;
+Landroid/icu/impl/UCharacterProperty$11;
+Landroid/icu/impl/UCharacterProperty$12;
+Landroid/icu/impl/UCharacterProperty$13;
+Landroid/icu/impl/UCharacterProperty$14;
+Landroid/icu/impl/UCharacterProperty$15;
+Landroid/icu/impl/UCharacterProperty$16;
+Landroid/icu/impl/UCharacterProperty$17;
+Landroid/icu/impl/UCharacterProperty$18;
+Landroid/icu/impl/UCharacterProperty$19;
+Landroid/icu/impl/UCharacterProperty$2;
+Landroid/icu/impl/UCharacterProperty$20;
+Landroid/icu/impl/UCharacterProperty$21;
+Landroid/icu/impl/UCharacterProperty$22;
+Landroid/icu/impl/UCharacterProperty$23;
+Landroid/icu/impl/UCharacterProperty$3;
+Landroid/icu/impl/UCharacterProperty$4;
+Landroid/icu/impl/UCharacterProperty$5;
+Landroid/icu/impl/UCharacterProperty$6;
+Landroid/icu/impl/UCharacterProperty$7;
+Landroid/icu/impl/UCharacterProperty$8;
+Landroid/icu/impl/UCharacterProperty$9;
+Landroid/icu/impl/UCharacterProperty$BiDiIntProperty;
+Landroid/icu/impl/UCharacterProperty$BinaryProperty;
+Landroid/icu/impl/UCharacterProperty$CaseBinaryProperty;
+Landroid/icu/impl/UCharacterProperty$CombiningClassIntProperty;
+Landroid/icu/impl/UCharacterProperty$IntProperty;
+Landroid/icu/impl/UCharacterProperty$IsAcceptable;
+Landroid/icu/impl/UCharacterProperty$NormInertBinaryProperty;
+Landroid/icu/impl/UCharacterProperty$NormQuickCheckIntProperty;
+Landroid/icu/impl/UResource$Array;
+Landroid/icu/impl/UResource$Key;
+Landroid/icu/impl/UResource$Sink;
+Landroid/icu/impl/UResource$Table;
+Landroid/icu/impl/UResource$Value;
+Landroid/icu/impl/Utility;
+Landroid/icu/lang/UCharacter;
+Landroid/icu/lang/UCharacterEnums$ECharacterCategory;
+Landroid/icu/lang/UCharacterEnums$ECharacterDirection;
+Landroid/icu/math/BigDecimal;
+Landroid/icu/math/MathContext;
+Landroid/icu/text/CurrencyDisplayNames;
+Landroid/icu/text/CurrencyMetaInfo;
+Landroid/icu/text/CurrencyMetaInfo$CurrencyDigits;
+Landroid/icu/text/CurrencyMetaInfo$CurrencyFilter;
+Landroid/icu/text/DecimalFormat;
+Landroid/icu/text/DecimalFormatSymbols;
+Landroid/icu/text/DecimalFormatSymbols$1;
+Landroid/icu/text/DecimalFormatSymbols$CacheData;
+Landroid/icu/text/DecimalFormatSymbols$DecFmtDataSink;
+Landroid/icu/text/DecimalFormat$Unit;
+Landroid/icu/text/DigitList;
+Landroid/icu/text/DisplayContext;
+Landroid/icu/text/DisplayContext$Type;
+Landroid/icu/text/IDNA;
+Landroid/icu/text/LocaleDisplayNames;
+Landroid/icu/text/LocaleDisplayNames$DialectHandling;
+Landroid/icu/text/Normalizer;
+Landroid/icu/text/Normalizer2;
+Landroid/icu/text/Normalizer$FCDMode;
+Landroid/icu/text/Normalizer$Mode;
+Landroid/icu/text/Normalizer$ModeImpl;
+Landroid/icu/text/Normalizer$NFCMode;
+Landroid/icu/text/Normalizer$NFDMode;
+Landroid/icu/text/Normalizer$NFKCMode;
+Landroid/icu/text/Normalizer$NFKDMode;
+Landroid/icu/text/Normalizer$NFKDModeImpl;
+Landroid/icu/text/Normalizer$NONEMode;
+Landroid/icu/text/Normalizer$QuickCheckResult;
+Landroid/icu/text/NumberFormat;
+Landroid/icu/text/NumberFormat$Field;
+Landroid/icu/text/NumberingSystem;
+Landroid/icu/text/NumberingSystem$1;
+Landroid/icu/text/NumberingSystem$2;
+Landroid/icu/text/NumberingSystem$LocaleLookupData;
+Landroid/icu/text/Replaceable;
+Landroid/icu/text/ReplaceableString;
+Landroid/icu/text/StringPrep;
+Landroid/icu/text/StringPrepParseException;
+Landroid/icu/text/TimeZoneNames$NameType;
+Landroid/icu/text/UCharacterIterator;
+Landroid/icu/text/UFieldPosition;
+Landroid/icu/text/UFormat;
+Landroid/icu/text/UForwardCharacterIterator;
+Landroid/icu/text/UnicodeFilter;
+Landroid/icu/text/UnicodeMatcher;
+Landroid/icu/text/UnicodeSet;
+Landroid/icu/text/UTF16;
+Landroid/icu/util/Currency;
+Landroid/icu/util/Currency$1;
+Landroid/icu/util/Currency$CurrencyUsage;
+Landroid/icu/util/Currency$EquivalenceRelation;
+Landroid/icu/util/Freezable;
+Landroid/icu/util/MeasureUnit;
+Landroid/icu/util/MeasureUnit$1;
+Landroid/icu/util/MeasureUnit$2;
+Landroid/icu/util/MeasureUnit$3;
+Landroid/icu/util/MeasureUnit$Factory;
+Landroid/icu/util/TimeUnit;
+Landroid/icu/util/TimeZone;
+Landroid/icu/util/TimeZone$ConstantZone;
+Landroid/icu/util/ULocale;
+Landroid/icu/util/ULocale$1;
+Landroid/icu/util/ULocale$2;
+Landroid/icu/util/ULocale$Category;
+Landroid/icu/util/ULocale$JDKLocaleHelper;
+Landroid/icu/util/ULocale$Type;
+Landroid/icu/util/UResourceBundle;
+Landroid/icu/util/UResourceBundle$RootType;
+Landroid/icu/util/UResourceTypeMismatchException;
+Landroid/icu/util/VersionInfo;
+Landroid/location/Address;
+Landroid/location/Address$1;
+Landroid/location/Country;
+Landroid/location/Country$1;
+Landroid/location/CountryDetector;
+Landroid/location/CountryDetector$ListenerTransport;
+Landroid/location/CountryListener;
+Landroid/location/Criteria;
+Landroid/location/Geocoder;
+Landroid/location/GeocoderParams;
+Landroid/location/GeocoderParams$1;
+Landroid/location/Geofence;
+Landroid/location/GnssMeasurementCallbackTransport;
+Landroid/location/GnssMeasurementCallbackTransport$ListenerTransport;
+Landroid/location/GnssNavigationMessageCallbackTransport;
+Landroid/location/GnssNavigationMessageCallbackTransport$ListenerTransport;
+Landroid/location/ICountryDetector;
+Landroid/location/ICountryDetector$Stub;
+Landroid/location/ICountryListener;
+Landroid/location/ICountryListener$Stub;
+Landroid/location/ICountryListener$Stub$Proxy;
+Landroid/location/IGeocodeProvider;
+Landroid/location/IGeocodeProvider$Stub;
+Landroid/location/IGeocodeProvider$Stub$Proxy;
+Landroid/location/IGeofenceProvider;
+Landroid/location/IGeofenceProvider$Stub;
+Landroid/location/IGeofenceProvider$Stub$Proxy;
+Landroid/location/IGnssMeasurementsListener;
+Landroid/location/IGnssMeasurementsListener$Stub;
+Landroid/location/IGnssNavigationMessageListener;
+Landroid/location/IGnssNavigationMessageListener$Stub;
+Landroid/location/IGnssStatusListener;
+Landroid/location/IGnssStatusListener$Stub;
+Landroid/location/IGnssStatusListener$Stub$Proxy;
+Landroid/location/IGnssStatusProvider;
+Landroid/location/IGnssStatusProvider$Stub;
+Landroid/location/IGpsGeofenceHardware;
+Landroid/location/IGpsGeofenceHardware$Stub;
+Landroid/location/ILocationListener;
+Landroid/location/ILocationListener$Stub;
+Landroid/location/ILocationListener$Stub$Proxy;
+Landroid/location/ILocationManager;
+Landroid/location/ILocationManager$Stub;
+Landroid/location/INetInitiatedListener;
+Landroid/location/INetInitiatedListener$Stub;
+Landroid/location/LocalListenerHelper;
+Landroid/location/Location;
+Landroid/location/Location$1;
+Landroid/location/Location$2;
+Landroid/location/LocationListener;
+Landroid/location/LocationManager;
+Landroid/location/LocationManager$ListenerTransport;
+Landroid/location/LocationManager$ListenerTransport$1;
+Landroid/location/LocationManager$ListenerTransport$2;
+Landroid/location/LocationRequest;
+Landroid/location/LocationRequest$1;
+Landroid/media/AudioAttributes;
+Landroid/media/AudioAttributes$1;
+Landroid/media/AudioAttributes$Builder;
+Landroid/media/AudioDeviceCallback;
+Landroid/media/AudioDeviceInfo;
+Landroid/media/AudioDevicePort;
+Landroid/media/AudioDevicePortConfig;
+Landroid/media/AudioFocusInfo;
+Landroid/media/AudioFocusInfo$1;
+Landroid/media/AudioFormat;
+Landroid/media/AudioFormat$1;
+Landroid/media/AudioFormat$Builder;
+Landroid/media/AudioGain;
+Landroid/media/AudioGainConfig;
+Landroid/media/AudioHandle;
+Landroid/media/AudioManager;
+Landroid/media/AudioManager$1;
+Landroid/media/AudioManager$2;
+Landroid/media/AudioManager$3;
+Landroid/media/AudioManagerInternal;
+Landroid/media/AudioManagerInternal$RingerModeDelegate;
+Landroid/media/AudioManager$NativeEventHandlerDelegate;
+Landroid/media/AudioManager$NativeEventHandlerDelegate$1;
+Landroid/media/AudioManager$OnAmPortUpdateListener;
+Landroid/media/AudioManager$OnAudioPortUpdateListener;
+Landroid/media/AudioManager$ServiceEventHandlerDelegate;
+Landroid/media/AudioManager$ServiceEventHandlerDelegate$1;
+Landroid/media/AudioMixPort;
+Landroid/media/AudioMixPortConfig;
+Landroid/media/AudioPatch;
+Landroid/media/AudioPlaybackConfiguration;
+Landroid/media/AudioPlaybackConfiguration$1;
+Landroid/media/AudioPlaybackConfiguration$IPlayerShell;
+Landroid/media/AudioPlaybackConfiguration$PlayerDeathMonitor;
+Landroid/media/audiopolicy/AudioMix;
+Landroid/media/audiopolicy/AudioMixingRule;
+Landroid/media/audiopolicy/AudioMixingRule$AudioMixMatchCriterion;
+Landroid/media/audiopolicy/AudioPolicyConfig;
+Landroid/media/audiopolicy/IAudioPolicyCallback;
+Landroid/media/audiopolicy/IAudioPolicyCallback$Stub;
+Landroid/media/AudioPort;
+Landroid/media/AudioPortConfig;
+Landroid/media/AudioPortEventHandler;
+Landroid/media/AudioPortEventHandler$1;
+Landroid/media/AudioRecord;
+Landroid/media/AudioRecordingConfiguration;
+Landroid/media/AudioRecordingConfiguration$1;
+Landroid/media/AudioRoutesInfo;
+Landroid/media/AudioRoutesInfo$1;
+Landroid/media/AudioRouting;
+Landroid/media/AudioSystem;
+Landroid/media/AudioSystem$AudioRecordingCallback;
+Landroid/media/AudioSystem$DynamicPolicyCallback;
+Landroid/media/AudioSystem$ErrorCallback;
+Landroid/media/AudioTimestamp;
+Landroid/media/AudioTrack;
+Landroid/media/CamcorderProfile;
+Landroid/media/CameraProfile;
+Landroid/media/DecoderCapabilities;
+Landroid/media/EncoderCapabilities;
+Landroid/media/IAudioFocusDispatcher;
+Landroid/media/IAudioFocusDispatcher$Stub;
+Landroid/media/IAudioFocusDispatcher$Stub$Proxy;
+Landroid/media/IAudioRoutesObserver;
+Landroid/media/IAudioRoutesObserver$Stub;
+Landroid/media/IAudioRoutesObserver$Stub$Proxy;
+Landroid/media/IAudioService;
+Landroid/media/IAudioService$Stub;
+Landroid/media/Image;
+Landroid/media/ImageReader;
+Landroid/media/ImageReader$SurfaceImage;
+Landroid/media/ImageWriter;
+Landroid/media/ImageWriter$WriterSurfaceImage;
+Landroid/media/IMediaHTTPConnection;
+Landroid/media/IMediaHTTPConnection$Stub;
+Landroid/media/IMediaResourceMonitor;
+Landroid/media/IMediaResourceMonitor$Stub;
+Landroid/media/IMediaRouterClient;
+Landroid/media/IMediaRouterClient$Stub;
+Landroid/media/IMediaRouterClient$Stub$Proxy;
+Landroid/media/IMediaRouterService;
+Landroid/media/IMediaRouterService$Stub;
+Landroid/media/IPlaybackConfigDispatcher;
+Landroid/media/IPlaybackConfigDispatcher$Stub;
+Landroid/media/IPlayer;
+Landroid/media/IPlayer$Stub;
+Landroid/media/IPlayer$Stub$Proxy;
+Landroid/media/IRecordingConfigDispatcher;
+Landroid/media/IRecordingConfigDispatcher$Stub;
+Landroid/media/IRemoteVolumeController;
+Landroid/media/IRemoteVolumeController$Stub;
+Landroid/media/IRemoteVolumeController$Stub$Proxy;
+Landroid/media/IRemoteVolumeObserver;
+Landroid/media/IRemoteVolumeObserver$Stub;
+Landroid/media/IRingtonePlayer;
+Landroid/media/IRingtonePlayer$Stub;
+Landroid/media/IRingtonePlayer$Stub$Proxy;
+Landroid/media/IVolumeController;
+Landroid/media/IVolumeController$Stub;
+Landroid/media/IVolumeController$Stub$Proxy;
+Landroid/media/JetPlayer;
+Landroid/media/MediaCodec;
+Landroid/media/MediaCodecList;
+Landroid/media/MediaCrypto;
+Landroid/media/MediaDescription;
+Landroid/media/MediaDescription$1;
+Landroid/media/MediaDrm;
+Landroid/media/MediaExtractor;
+Landroid/media/MediaHTTPConnection;
+Landroid/media/MediaMetadata;
+Landroid/media/MediaMetadata$1;
+Landroid/media/MediaMetadata$Builder;
+Landroid/media/MediaMetadataRetriever;
+Landroid/media/MediaMuxer;
+Landroid/media/MediaPlayer;
+Landroid/media/MediaRecorder;
+Landroid/media/MediaRouter;
+Landroid/media/MediaRouter$Callback;
+Landroid/media/MediaRouter$CallbackInfo;
+Landroid/media/MediaRouterClientState;
+Landroid/media/MediaRouterClientState$1;
+Landroid/media/MediaRouter$RouteCategory;
+Landroid/media/MediaRouter$RouteInfo;
+Landroid/media/MediaRouter$RouteInfo$1;
+Landroid/media/MediaRouter$SimpleCallback;
+Landroid/media/MediaRouter$Static;
+Landroid/media/MediaRouter$Static$1;
+Landroid/media/MediaRouter$Static$Client;
+Landroid/media/MediaRouter$Static$Client$1;
+Landroid/media/MediaRouter$VolumeChangeReceiver;
+Landroid/media/MediaRouter$WifiDisplayStatusChangedReceiver;
+Landroid/media/MediaScanner;
+Landroid/media/MediaSync;
+Landroid/media/midi/IMidiDeviceListener;
+Landroid/media/midi/IMidiDeviceOpenCallback;
+Landroid/media/midi/IMidiDeviceServer;
+Landroid/media/midi/IMidiManager;
+Landroid/media/midi/IMidiManager$Stub;
+Landroid/media/midi/MidiDeviceInfo;
+Landroid/media/midi/MidiDeviceStatus;
+Landroid/media/midi/MidiManager;
+Landroid/media/PlaybackParams;
+Landroid/media/PlaybackParams$1;
+Landroid/media/PlayerBase;
+Landroid/media/PlayerBase$1;
+Landroid/media/PlayerBase$2;
+Landroid/media/PlayerBase$PlayerIdCard;
+Landroid/media/PlayerBase$PlayerIdCard$1;
+Landroid/media/projection/IMediaProjection;
+Landroid/media/projection/IMediaProjectionManager;
+Landroid/media/projection/IMediaProjectionManager$Stub;
+Landroid/media/projection/IMediaProjectionWatcherCallback;
+Landroid/media/projection/IMediaProjectionWatcherCallback$Stub;
+Landroid/media/projection/IMediaProjectionWatcherCallback$Stub$Proxy;
+Landroid/media/projection/MediaProjectionInfo;
+Landroid/media/projection/MediaProjectionManager;
+Landroid/media/Rating;
+Landroid/media/Rating$1;
+Landroid/media/RemoteDisplay;
+Landroid/media/ResampleInputStream;
+Landroid/media/session/IActiveSessionsListener;
+Landroid/media/session/IActiveSessionsListener$Stub;
+Landroid/media/session/IActiveSessionsListener$Stub$Proxy;
+Landroid/media/session/IOnMediaKeyListener;
+Landroid/media/session/IOnVolumeKeyLongPressListener;
+Landroid/media/session/ISession;
+Landroid/media/session/ISessionCallback;
+Landroid/media/session/ISessionCallback$Stub;
+Landroid/media/session/ISessionCallback$Stub$Proxy;
+Landroid/media/session/ISessionController;
+Landroid/media/session/ISessionControllerCallback;
+Landroid/media/session/ISessionControllerCallback$Stub;
+Landroid/media/session/ISessionControllerCallback$Stub$Proxy;
+Landroid/media/session/ISessionController$Stub;
+Landroid/media/session/ISessionManager;
+Landroid/media/session/ISessionManager$Stub;
+Landroid/media/session/ISession$Stub;
+Landroid/media/session/MediaController;
+Landroid/media/session/MediaController$CallbackStub;
+Landroid/media/session/MediaController$TransportControls;
+Landroid/media/session/MediaSession;
+Landroid/media/session/MediaSession$Callback;
+Landroid/media/session/MediaSession$CallbackMessageHandler;
+Landroid/media/session/MediaSession$CallbackStub;
+Landroid/media/session/MediaSessionManager;
+Landroid/media/session/MediaSession$QueueItem;
+Landroid/media/session/MediaSession$QueueItem$1;
+Landroid/media/session/MediaSession$Token;
+Landroid/media/session/MediaSession$Token$1;
+Landroid/media/session/ParcelableVolumeInfo;
+Landroid/media/session/ParcelableVolumeInfo$1;
+Landroid/media/session/PlaybackState;
+Landroid/media/session/PlaybackState$1;
+Landroid/media/session/PlaybackState$Builder;
+Landroid/media/session/PlaybackState$CustomAction;
+Landroid/media/session/PlaybackState$CustomAction$1;
+Landroid/media/SoundPool;
+Landroid/media/SoundPool$Builder;
+Landroid/media/SoundPool$EventHandler;
+Landroid/media/SoundPool$OnLoadCompleteListener;
+Landroid/media/soundtrigger/SoundTriggerManager;
+Landroid/media/SubtitleController$Listener;
+Landroid/media/ToneGenerator;
+Landroid/media/tv/TvInputHardwareInfo$Builder;
+Landroid/media/tv/TvInputManager;
+Landroid/media/tv/TvStreamConfig;
+Landroid/media/tv/TvStreamConfig$Builder;
+Landroid/media/VolumePolicy;
+Landroid/media/VolumePolicy$1;
+Landroid/metrics/LogMaker;
+Landroid/mtp/MtpDatabase;
+Landroid/mtp/MtpDevice;
+Landroid/mtp/MtpDeviceInfo;
+Landroid/mtp/MtpEvent;
+Landroid/mtp/MtpObjectInfo;
+Landroid/mtp/MtpPropertyGroup;
+Landroid/mtp/MtpPropertyList;
+Landroid/mtp/MtpServer;
+Landroid/mtp/MtpStorage;
+Landroid/mtp/MtpStorageInfo;
+Landroid/net/apf/ApfCapabilities;
+Landroid/net/apf/ApfFilter;
+Landroid/net/apf/ApfFilter$ProcessRaResult;
+Landroid/net/apf/ApfFilter$Ra;
+Landroid/net/apf/ApfFilter$ReceiveThread;
+Landroid/net/apf/ApfGenerator;
+Landroid/net/apf/ApfGenerator$ExtendedOpcodes;
+Landroid/net/apf/ApfGenerator$IllegalInstructionException;
+Landroid/net/apf/ApfGenerator$Instruction;
+Landroid/net/apf/ApfGenerator$Opcodes;
+Landroid/net/apf/ApfGenerator$Register;
+Landroid/net/ConnectivityManager;
+Landroid/net/ConnectivityManager$CallbackHandler;
+Landroid/net/ConnectivityManager$NetworkCallback;
+Landroid/net/ConnectivityManager$OnNetworkActiveListener;
+Landroid/net/ConnectivityMetricsEvent;
+Landroid/net/ConnectivityMetricsEvent$1;
+Landroid/net/ConnectivityMetricsEvent$Reference;
+Landroid/net/ConnectivityThread;
+Landroid/net/ConnectivityThread$Singleton;
+Landroid/net/Credentials;
+Landroid/net/DataUsageRequest;
+Landroid/net/dhcp/DhcpAckPacket;
+Landroid/net/dhcp/DhcpClient;
+Landroid/net/dhcp/DhcpClient$ConfiguringInterfaceState;
+Landroid/net/dhcp/DhcpClient$DhcpBoundState;
+Landroid/net/dhcp/DhcpClient$DhcpHaveLeaseState;
+Landroid/net/dhcp/DhcpClient$DhcpInitRebootState;
+Landroid/net/dhcp/DhcpClient$DhcpInitState;
+Landroid/net/dhcp/DhcpClient$DhcpReacquiringState;
+Landroid/net/dhcp/DhcpClient$DhcpRebindingState;
+Landroid/net/dhcp/DhcpClient$DhcpRebootingState;
+Landroid/net/dhcp/DhcpClient$DhcpRenewingState;
+Landroid/net/dhcp/DhcpClient$DhcpRequestingState;
+Landroid/net/dhcp/DhcpClient$DhcpSelectingState;
+Landroid/net/dhcp/DhcpClient$DhcpState;
+Landroid/net/dhcp/DhcpClient$LoggingState;
+Landroid/net/dhcp/DhcpClient$PacketRetransmittingState;
+Landroid/net/dhcp/DhcpClient$ReceiveThread;
+Landroid/net/dhcp/DhcpClient$StoppedState;
+Landroid/net/dhcp/DhcpClient$WaitBeforeOtherState;
+Landroid/net/dhcp/DhcpClient$WaitBeforeRenewalState;
+Landroid/net/dhcp/DhcpClient$WaitBeforeStartState;
+Landroid/net/dhcp/DhcpDiscoverPacket;
+Landroid/net/dhcp/DhcpOfferPacket;
+Landroid/net/dhcp/DhcpPacket;
+Landroid/net/dhcp/DhcpPacket$ParseException;
+Landroid/net/dhcp/DhcpRequestPacket;
+Landroid/net/DhcpInfo;
+Landroid/net/DhcpInfo$1;
+Landroid/net/DhcpResults;
+Landroid/net/DhcpResults$1;
+Landroid/net/EthernetManager;
+Landroid/net/EthernetManager$1;
+Landroid/net/EthernetManager$2;
+Landroid/net/EventLogTags;
+Landroid/net/IConnectivityManager;
+Landroid/net/IConnectivityManager$Stub;
+Landroid/net/IConnectivityMetricsLogger;
+Landroid/net/IConnectivityMetricsLogger$Stub;
+Landroid/net/IEthernetManager;
+Landroid/net/IEthernetManager$Stub;
+Landroid/net/IEthernetServiceListener;
+Landroid/net/IEthernetServiceListener$Stub;
+Landroid/net/IIpConnectivityMetrics;
+Landroid/net/IIpConnectivityMetrics$Stub;
+Landroid/net/INetd;
+Landroid/net/INetdEventCallback;
+Landroid/net/INetd$Stub;
+Landroid/net/INetd$Stub$Proxy;
+Landroid/net/INetworkManagementEventObserver;
+Landroid/net/INetworkManagementEventObserver$Stub;
+Landroid/net/INetworkPolicyListener;
+Landroid/net/INetworkPolicyListener$Stub;
+Landroid/net/INetworkPolicyListener$Stub$Proxy;
+Landroid/net/INetworkPolicyManager;
+Landroid/net/INetworkPolicyManager$Stub;
+Landroid/net/INetworkScoreCache;
+Landroid/net/INetworkScoreCache$Stub;
+Landroid/net/INetworkScoreCache$Stub$Proxy;
+Landroid/net/INetworkScoreService;
+Landroid/net/INetworkScoreService$Stub;
+Landroid/net/INetworkStatsService;
+Landroid/net/INetworkStatsService$Stub;
+Landroid/net/INetworkStatsSession;
+Landroid/net/INetworkStatsSession$Stub;
+Landroid/net/InterfaceConfiguration;
+Landroid/net/InterfaceConfiguration$1;
+Landroid/net/IpConfiguration;
+Landroid/net/IpConfiguration$1;
+Landroid/net/IpConfiguration$IpAssignment;
+Landroid/net/IpConfiguration$ProxySettings;
+Landroid/net/ip/ConnectivityPacketTracker;
+Landroid/net/ip/ConnectivityPacketTracker$PacketListener;
+Landroid/net/ip/IpManager;
+Landroid/net/ip/IpManager$1;
+Landroid/net/ip/IpManager$2;
+Landroid/net/ip/IpManager$3;
+Landroid/net/ip/IpManager$Callback;
+Landroid/net/ip/IpManager$LoggingCallbackWrapper;
+Landroid/net/ip/IpManager$MessageHandlingLogger;
+Landroid/net/ip/IpManager$ProvisioningConfiguration;
+Landroid/net/ip/IpManager$ProvisioningConfiguration$Builder;
+Landroid/net/ip/IpManager$RunningState;
+Landroid/net/ip/IpManager$StartedState;
+Landroid/net/ip/IpManager$StoppedState;
+Landroid/net/ip/IpManager$StoppingState;
+Landroid/net/ip/IpReachabilityMonitor;
+Landroid/net/ip/IpReachabilityMonitor$Callback;
+Landroid/net/ip/IpReachabilityMonitor$NetlinkSocketObserver;
+Landroid/net/IpPrefix;
+Landroid/net/IpPrefix$1;
+Landroid/net/LinkAddress;
+Landroid/net/LinkAddress$1;
+Landroid/net/LinkProperties;
+Landroid/net/LinkProperties$1;
+Landroid/net/LinkProperties$CompareResult;
+Landroid/net/LinkProperties$ProvisioningChange;
+Landroid/net/LocalServerSocket;
+Landroid/net/LocalSocket;
+Landroid/net/LocalSocketAddress;
+Landroid/net/LocalSocketAddress$Namespace;
+Landroid/net/LocalSocketImpl;
+Landroid/net/LocalSocketImpl$SocketInputStream;
+Landroid/net/LocalSocketImpl$SocketOutputStream;
+Landroid/net/metrics/ApfProgramEvent;
+Landroid/net/metrics/ApfProgramEvent$1;
+Landroid/net/metrics/ConnectStats;
+Landroid/net/metrics/DefaultNetworkEvent;
+Landroid/net/metrics/DefaultNetworkEvent$1;
+Landroid/net/metrics/DhcpClientEvent;
+Landroid/net/metrics/DhcpClientEvent$1;
+Landroid/net/metrics/DnsEvent;
+Landroid/net/metrics/DnsEvent$1;
+Landroid/net/metrics/INetdEventListener;
+Landroid/net/metrics/INetdEventListener$Stub;
+Landroid/net/metrics/IpConnectivityLog;
+Landroid/net/metrics/IpManagerEvent;
+Landroid/net/metrics/IpManagerEvent$1;
+Landroid/net/metrics/NetworkEvent;
+Landroid/net/metrics/NetworkEvent$1;
+Landroid/net/metrics/RaEvent;
+Landroid/net/metrics/RaEvent$1;
+Landroid/net/metrics/RaEvent$Builder;
+Landroid/net/metrics/ValidationProbeEvent;
+Landroid/net/metrics/ValidationProbeEvent$1;
+Landroid/net/metrics/ValidationProbeEvent$Decoder;
+Landroid/net/netlink/NetlinkConstants;
+Landroid/net/netlink/NetlinkErrorMessage;
+Landroid/net/netlink/NetlinkMessage;
+Landroid/net/netlink/NetlinkSocket;
+Landroid/net/netlink/RtNetlinkNeighborMessage;
+Landroid/net/netlink/StructNdaCacheInfo;
+Landroid/net/netlink/StructNdMsg;
+Landroid/net/netlink/StructNlAttr;
+Landroid/net/netlink/StructNlMsgHdr;
+Landroid/net/Network;
+Landroid/net/Network$1;
+Landroid/net/Network$2;
+Landroid/net/NetworkAgent;
+Landroid/net/NetworkCapabilities;
+Landroid/net/NetworkCapabilities$1;
+Landroid/net/NetworkConfig;
+Landroid/net/NetworkFactory;
+Landroid/net/NetworkFactory$NetworkRequestInfo;
+Landroid/net/NetworkIdentity;
+Landroid/net/NetworkInfo;
+Landroid/net/NetworkInfo$1;
+Landroid/net/NetworkInfo$DetailedState;
+Landroid/net/NetworkInfo$State;
+Landroid/net/NetworkKey;
+Landroid/net/NetworkKey$1;
+Landroid/net/NetworkMisc;
+Landroid/net/NetworkMisc$1;
+Landroid/net/Network$NetworkBoundSocketFactory;
+Landroid/net/NetworkPolicy;
+Landroid/net/NetworkPolicyManager;
+Landroid/net/NetworkQuotaInfo;
+Landroid/net/NetworkRequest;
+Landroid/net/NetworkRequest$1;
+Landroid/net/NetworkRequest$Builder;
+Landroid/net/NetworkRequest$Type;
+Landroid/net/NetworkScoreManager;
+Landroid/net/NetworkScorerAppManager;
+Landroid/net/NetworkState;
+Landroid/net/NetworkState$1;
+Landroid/net/NetworkStats;
+Landroid/net/NetworkStats$1;
+Landroid/net/NetworkStats$Entry;
+Landroid/net/NetworkStatsHistory;
+Landroid/net/NetworkStatsHistory$1;
+Landroid/net/NetworkStatsHistory$DataStreamUtils;
+Landroid/net/NetworkStatsHistory$Entry;
+Landroid/net/NetworkStatsHistory$ParcelUtils;
+Landroid/net/NetworkStats$NonMonotonicObserver;
+Landroid/net/NetworkTemplate;
+Landroid/net/NetworkTemplate$1;
+Landroid/net/NetworkUtils;
+Landroid/net/nsd/INsdManager;
+Landroid/net/nsd/INsdManager$Stub;
+Landroid/net/nsd/NsdManager;
+Landroid/net/ProxyInfo;
+Landroid/net/RecommendationRequest;
+Landroid/net/RecommendationResult;
+Landroid/net/RouteInfo;
+Landroid/net/RouteInfo$1;
+Landroid/net/ScoredNetwork;
+Landroid/net/SntpClient;
+Landroid/net/StaticIpConfiguration;
+Landroid/net/StaticIpConfiguration$1;
+Landroid/net/TrafficStats;
+Landroid/net/UidRange;
+Landroid/net/Uri;
+Landroid/net/Uri$1;
+Landroid/net/Uri$AbstractHierarchicalUri;
+Landroid/net/Uri$AbstractPart;
+Landroid/net/Uri$Builder;
+Landroid/net/Uri$HierarchicalUri;
+Landroid/net/Uri$OpaqueUri;
+Landroid/net/Uri$Part;
+Landroid/net/Uri$Part$EmptyPart;
+Landroid/net/Uri$PathPart;
+Landroid/net/Uri$PathSegments;
+Landroid/net/Uri$PathSegmentsBuilder;
+Landroid/net/Uri$StringUri;
+Landroid/net/util/BlockingSocketReader;
+Landroid/net/util/ConnectivityPacketSummary;
+Landroid/net/util/MultinetworkPolicyTracker;
+Landroid/net/util/MultinetworkPolicyTracker$1;
+Landroid/net/util/MultinetworkPolicyTracker$SettingObserver;
+Landroid/net/util/NetworkConstants;
+Landroid/net/util/Stopwatch;
+Landroid/net/wifi/aware/WifiAwareManager;
+Landroid/net/wifi/hotspot2/PasspointConfiguration;
+Landroid/net/wifi/IApInterface;
+Landroid/net/wifi/IClientInterface;
+Landroid/net/wifi/IClientInterface$Stub;
+Landroid/net/wifi/IClientInterface$Stub$Proxy;
+Landroid/net/wifi/IInterfaceEventCallback;
+Landroid/net/wifi/IInterfaceEventCallback$Stub;
+Landroid/net/wifi/IRttManager;
+Landroid/net/wifi/IRttManager$Stub;
+Landroid/net/wifi/IWificond;
+Landroid/net/wifi/IWificond$Stub;
+Landroid/net/wifi/IWificond$Stub$Proxy;
+Landroid/net/wifi/IWifiManager;
+Landroid/net/wifi/IWifiManager$Stub;
+Landroid/net/wifi/IWifiScanner;
+Landroid/net/wifi/IWifiScanner$Stub;
+Landroid/net/WifiKey;
+Landroid/net/WifiKey$1;
+Landroid/net/wifi/p2p/IWifiP2pManager;
+Landroid/net/wifi/p2p/IWifiP2pManager$Stub;
+Landroid/net/wifi/p2p/WifiP2pConfig;
+Landroid/net/wifi/p2p/WifiP2pConfig$1;
+Landroid/net/wifi/p2p/WifiP2pDevice;
+Landroid/net/wifi/p2p/WifiP2pDevice$1;
+Landroid/net/wifi/p2p/WifiP2pDeviceList;
+Landroid/net/wifi/p2p/WifiP2pDeviceList$1;
+Landroid/net/wifi/p2p/WifiP2pGroup;
+Landroid/net/wifi/p2p/WifiP2pGroup$1;
+Landroid/net/wifi/p2p/WifiP2pGroupList;
+Landroid/net/wifi/p2p/WifiP2pGroupList$1;
+Landroid/net/wifi/p2p/WifiP2pGroupList$2;
+Landroid/net/wifi/p2p/WifiP2pGroupList$GroupDeleteListener;
+Landroid/net/wifi/p2p/WifiP2pInfo;
+Landroid/net/wifi/p2p/WifiP2pInfo$1;
+Landroid/net/wifi/p2p/WifiP2pManager;
+Landroid/net/wifi/p2p/WifiP2pWfdInfo;
+Landroid/net/wifi/p2p/WifiP2pWfdInfo$1;
+Landroid/net/wifi/ParcelUtil;
+Landroid/net/wifi/RssiPacketCountInfo;
+Landroid/net/wifi/RttManager;
+Landroid/net/wifi/RttManager$RttCapabilities;
+Landroid/net/wifi/ScanResult;
+Landroid/net/wifi/ScanResult$1;
+Landroid/net/wifi/ScanResult$InformationElement;
+Landroid/net/wifi/ScanSettings;
+Landroid/net/wifi/SupplicantState;
+Landroid/net/wifi/SupplicantState$1;
+Landroid/net/wifi/WifiActivityEnergyInfo;
+Landroid/net/wifi/WifiActivityEnergyInfo$1;
+Landroid/net/wifi/WifiChannel;
+Landroid/net/wifi/WifiConfiguration;
+Landroid/net/wifi/WifiConfiguration$1;
+Landroid/net/wifi/WifiConfiguration$AuthAlgorithm;
+Landroid/net/wifi/WifiConfiguration$GroupCipher;
+Landroid/net/wifi/WifiConfiguration$KeyMgmt;
+Landroid/net/wifi/WifiConfiguration$NetworkSelectionStatus;
+Landroid/net/wifi/WifiConfiguration$PairwiseCipher;
+Landroid/net/wifi/WifiConfiguration$Protocol;
+Landroid/net/wifi/WifiConfiguration$Visibility;
+Landroid/net/wifi/WifiConnectionStatistics;
+Landroid/net/wifi/WifiConnectionStatistics$1;
+Landroid/net/wifi/WifiEnterpriseConfig;
+Landroid/net/wifi/WifiEnterpriseConfig$1;
+Landroid/net/wifi/WifiInfo;
+Landroid/net/wifi/WifiInfo$1;
+Landroid/net/wifi/WifiLinkLayerStats;
+Landroid/net/wifi/WifiLinkLayerStats$1;
+Landroid/net/wifi/WifiManager;
+Landroid/net/wifi/WifiNetworkScoreCache;
+Landroid/net/wifi/WifiScanner;
+Landroid/net/wifi/WifiScanner$ActionListener;
+Landroid/net/wifi/WifiScanner$ChannelSpec;
+Landroid/net/wifi/WifiScanner$ParcelableScanData;
+Landroid/net/wifi/WifiScanner$ParcelableScanData$1;
+Landroid/net/wifi/WifiScanner$ParcelableScanResults;
+Landroid/net/wifi/WifiScanner$ParcelableScanResults$1;
+Landroid/net/wifi/WifiScanner$PnoScanListener;
+Landroid/net/wifi/WifiScanner$ScanData;
+Landroid/net/wifi/WifiScanner$ScanData$1;
+Landroid/net/wifi/WifiScanner$ScanListener;
+Landroid/net/wifi/WifiScanner$ScanSettings;
+Landroid/net/wifi/WifiScanner$ScanSettings$1;
+Landroid/net/wifi/WifiScanner$ScanSettings$HiddenNetwork;
+Landroid/net/wifi/WifiScanner$ServiceHandler;
+Landroid/net/wifi/WifiSsid;
+Landroid/net/wifi/WifiSsid$1;
+Landroid/net/wifi/WifiWakeReasonAndCounts;
+Landroid/net/wifi/WpsInfo;
+Landroid/net/wifi/WpsInfo$1;
+Landroid/nfc/INfcAdapter;
+Landroid/nfc/INfcAdapter$Stub;
+Landroid/nfc/INfcAdapter$Stub$Proxy;
+Landroid/nfc/NfcManager;
+Landroid/opengl/EGL14;
+Landroid/opengl/EGLConfig;
+Landroid/opengl/EGLContext;
+Landroid/opengl/EGLDisplay;
+Landroid/opengl/EGLExt;
+Landroid/opengl/EGLObjectHandle;
+Landroid/opengl/EGLSurface;
+Landroid/opengl/ETC1;
+Landroid/opengl/GLES10;
+Landroid/opengl/GLES10Ext;
+Landroid/opengl/GLES11;
+Landroid/opengl/GLES11Ext;
+Landroid/opengl/GLES20;
+Landroid/opengl/GLES30;
+Landroid/opengl/GLES31;
+Landroid/opengl/GLES31Ext;
+Landroid/opengl/GLES32;
+Landroid/opengl/GLUtils;
+Landroid/opengl/Matrix;
+Landroid/opengl/Visibility;
+Landroid/os/AsyncTask;
+Landroid/os/AsyncTask$1;
+Landroid/os/AsyncTask$2;
+Landroid/os/AsyncTask$3;
+Landroid/os/AsyncTask$AsyncTaskResult;
+Landroid/os/AsyncTask$InternalHandler;
+Landroid/os/AsyncTask$SerialExecutor;
+Landroid/os/AsyncTask$SerialExecutor$1;
+Landroid/os/AsyncTask$Status;
+Landroid/os/AsyncTask$WorkerRunnable;
+Landroid/os/BadParcelableException;
+Landroid/os/BaseBundle;
+Landroid/os/BaseBundle$NoImagePreloadHolder;
+Landroid/os/BatteryManager;
+Landroid/os/BatteryManagerInternal;
+Landroid/os/BatteryProperties;
+Landroid/os/BatteryProperties$1;
+Landroid/os/BatteryStats;
+Landroid/os/BatteryStats$BitDescription;
+Landroid/os/BatteryStats$ControllerActivityCounter;
+Landroid/os/BatteryStats$Counter;
+Landroid/os/BatteryStats$DailyItem;
+Landroid/os/BatteryStats$HistoryEventTracker;
+Landroid/os/BatteryStats$HistoryItem;
+Landroid/os/BatteryStats$HistoryPrinter;
+Landroid/os/BatteryStats$HistoryStepDetails;
+Landroid/os/BatteryStats$HistoryTag;
+Landroid/os/BatteryStats$IntToString;
+Landroid/os/BatteryStats$LevelStepTracker;
+Landroid/os/BatteryStats$LongCounter;
+Landroid/os/BatteryStats$PackageChange;
+Landroid/os/BatteryStats$Timer;
+Landroid/os/BatteryStats$Uid;
+Landroid/os/BatteryStats$Uid$Pid;
+Landroid/os/BatteryStats$Uid$Pkg;
+Landroid/os/BatteryStats$Uid$Pkg$Serv;
+Landroid/os/BatteryStats$Uid$Proc;
+Landroid/os/BatteryStats$Uid$Sensor;
+Landroid/os/BatteryStats$Uid$Wakelock;
+Landroid/os/Binder;
+Landroid/os/BinderProxy;
+Landroid/os/Build;
+Landroid/os/Build$VERSION;
+Landroid/os/Bundle;
+Landroid/os/Bundle$1;
+Landroid/os/CancellationSignal;
+Landroid/os/CancellationSignal$OnCancelListener;
+Landroid/os/CancellationSignal$Transport;
+Landroid/os/CommonTimeConfig$OnServerDiedListener;
+Landroid/os/CpuUsageInfo;
+Landroid/os/CpuUsageInfo$1;
+Landroid/os/DeadObjectException;
+Landroid/os/DeadSystemException;
+Landroid/os/Debug;
+Landroid/os/Debug$MemoryInfo;
+Landroid/os/Debug$MemoryInfo$1;
+Landroid/os/DropBoxManager;
+Landroid/os/DropBoxManager$Entry;
+Landroid/os/DropBoxManager$Entry$1;
+Landroid/os/Environment;
+Landroid/os/Environment$UserEnvironment;
+Landroid/os/FactoryTest;
+Landroid/os/FileObserver;
+Landroid/os/FileObserver$ObserverThread;
+Landroid/os/FileUtils;
+Landroid/os/GraphicsEnvironment;
+Landroid/os/Handler;
+Landroid/os/Handler$BlockingRunnable;
+Landroid/os/Handler$Callback;
+Landroid/os/Handler$MessengerImpl;
+Landroid/os/HandlerThread;
+Landroid/os/HardwarePropertiesManager;
+Landroid/os/health/HealthStatsParceler;
+Landroid/os/health/SystemHealthManager;
+Landroid/os/HwBinder;
+Landroid/os/HwBlob;
+Landroid/os/HwParcel;
+Landroid/os/HwRemoteBinder;
+Landroid/os/IBatteryPropertiesListener;
+Landroid/os/IBatteryPropertiesListener$Stub;
+Landroid/os/IBatteryPropertiesRegistrar;
+Landroid/os/IBatteryPropertiesRegistrar$Stub;
+Landroid/os/IBatteryPropertiesRegistrar$Stub$Proxy;
+Landroid/os/IBinder;
+Landroid/os/IBinder$DeathRecipient;
+Landroid/os/ICancellationSignal;
+Landroid/os/ICancellationSignal$Stub;
+Landroid/os/IDeviceIdentifiersPolicyService;
+Landroid/os/IDeviceIdentifiersPolicyService$Stub;
+Landroid/os/IDeviceIdleController;
+Landroid/os/IDeviceIdleController$Stub;
+Landroid/os/IHardwarePropertiesManager;
+Landroid/os/IHardwarePropertiesManager$Stub;
+Landroid/os/IHwBinder;
+Landroid/os/IHwBinder$DeathRecipient;
+Landroid/os/IHwInterface;
+Landroid/os/IIncidentManager;
+Landroid/os/IIncidentManager$Stub;
+Landroid/os/IInstalld;
+Landroid/os/IInstalld$Stub;
+Landroid/os/IInstalld$Stub$Proxy;
+Landroid/os/IInterface;
+Landroid/os/IMaintenanceActivityListener;
+Landroid/os/IMessenger;
+Landroid/os/IMessenger$Stub;
+Landroid/os/IMessenger$Stub$Proxy;
+Landroid/os/IncidentManager;
+Landroid/os/INetworkActivityListener;
+Landroid/os/INetworkManagementService;
+Landroid/os/INetworkManagementService$Stub;
+Landroid/os/IPermissionController;
+Landroid/os/IPermissionController$Stub;
+Landroid/os/IPowerManager;
+Landroid/os/IPowerManager$Stub;
+Landroid/os/IProcessInfoService;
+Landroid/os/IProcessInfoService$Stub;
+Landroid/os/IProgressListener;
+Landroid/os/IRecoverySystem;
+Landroid/os/IRecoverySystemProgressListener;
+Landroid/os/IRecoverySystem$Stub;
+Landroid/os/IRemoteCallback;
+Landroid/os/IRemoteCallback$Stub;
+Landroid/os/IRemoteCallback$Stub$Proxy;
+Landroid/os/ISchedulingPolicyService;
+Landroid/os/ISchedulingPolicyService$Stub;
+Landroid/os/IServiceManager;
+Landroid/os/IUpdateLock;
+Landroid/os/IUpdateLock$Stub;
+Landroid/os/IUserManager;
+Landroid/os/IUserManager$Stub;
+Landroid/os/IVibratorService;
+Landroid/os/IVibratorService$Stub;
+Landroid/os/LocaleList;
+Landroid/os/LocaleList$1;
+Landroid/os/Looper;
+Landroid/os/MemoryFile;
+Landroid/os/Message;
+Landroid/os/Message$1;
+Landroid/os/MessageQueue;
+Landroid/os/MessageQueue$IdleHandler;
+Landroid/os/Messenger;
+Landroid/os/Messenger$1;
+Landroid/os/OperationCanceledException;
+Landroid/os/Parcel;
+Landroid/os/Parcel$1;
+Landroid/os/Parcelable;
+Landroid/os/Parcelable$ClassLoaderCreator;
+Landroid/os/Parcelable$Creator;
+Landroid/os/ParcelFileDescriptor;
+Landroid/os/ParcelFileDescriptor$1;
+Landroid/os/ParcelFileDescriptor$AutoCloseInputStream;
+Landroid/os/ParcelFileDescriptor$AutoCloseOutputStream;
+Landroid/os/ParcelFormatException;
+Landroid/os/ParcelUuid;
+Landroid/os/PatternMatcher;
+Landroid/os/PatternMatcher$1;
+Landroid/os/PersistableBundle;
+Landroid/os/PersistableBundle$1;
+Landroid/os/PersistableBundle$MyReadMapCallback;
+Landroid/os/PowerManager;
+Landroid/os/PowerManagerInternal;
+Landroid/os/PowerManagerInternal$LowPowerModeListener;
+Landroid/os/PowerManager$WakeLock;
+Landroid/os/PowerManager$WakeLock$1;
+Landroid/os/Process;
+Landroid/os/Process$ProcessStartResult;
+Landroid/os/RecoverySystem;
+Landroid/os/RemoteCallback;
+Landroid/os/RemoteCallbackList;
+Landroid/os/RemoteCallbackList$Callback;
+Landroid/os/RemoteException;
+Landroid/os/ResultReceiver;
+Landroid/os/ResultReceiver$1;
+Landroid/os/ResultReceiver$MyResultReceiver;
+Landroid/os/SELinux;
+Landroid/os/ServiceManager;
+Landroid/os/ServiceManagerNative;
+Landroid/os/ServiceManagerProxy;
+Landroid/os/ServiceManager$ServiceNotFoundException;
+Landroid/os/ServiceSpecificException;
+Landroid/os/ShellCallback;
+Landroid/os/ShellCallback$1;
+Landroid/os/ShellCommand;
+Landroid/os/StatFs;
+Landroid/os/storage/DiskInfo;
+Landroid/os/storage/IObbActionListener;
+Landroid/os/storage/IObbActionListener$Stub;
+Landroid/os/storage/IStorageEventListener;
+Landroid/os/storage/IStorageEventListener$Stub;
+Landroid/os/storage/IStorageEventListener$Stub$Proxy;
+Landroid/os/storage/IStorageManager;
+Landroid/os/storage/IStorageManager$Stub;
+Landroid/os/storage/IStorageShutdownObserver;
+Landroid/os/storage/StorageEventListener;
+Landroid/os/storage/StorageManager;
+Landroid/os/storage/StorageManagerInternal;
+Landroid/os/storage/StorageManagerInternal$ExternalStorageMountPolicy;
+Landroid/os/storage/StorageManager$ObbActionListener;
+Landroid/os/storage/StorageManager$StorageEventListenerDelegate;
+Landroid/os/storage/StorageVolume;
+Landroid/os/storage/StorageVolume$1;
+Landroid/os/storage/VolumeInfo;
+Landroid/os/storage/VolumeInfo$1;
+Landroid/os/storage/VolumeInfo$2;
+Landroid/os/storage/VolumeRecord;
+Landroid/os/StrictMode;
+Landroid/os/StrictMode$1;
+Landroid/os/StrictMode$2;
+Landroid/os/StrictMode$3;
+Landroid/os/StrictMode$4;
+Landroid/os/StrictMode$5;
+Landroid/os/StrictMode$6;
+Landroid/os/StrictMode$7;
+Landroid/os/StrictMode$8;
+Landroid/os/StrictMode$9;
+Landroid/os/StrictMode$AndroidBlockGuardPolicy;
+Landroid/os/StrictMode$AndroidBlockGuardPolicy$1;
+Landroid/os/StrictMode$AndroidCloseGuardReporter;
+Landroid/os/StrictMode$InstanceCountViolation;
+Landroid/os/StrictMode$Span;
+Landroid/os/StrictMode$StrictModeDiskReadViolation;
+Landroid/os/StrictMode$StrictModeDiskWriteViolation;
+Landroid/os/StrictMode$StrictModeViolation;
+Landroid/os/StrictMode$ThreadPolicy;
+Landroid/os/StrictMode$ThreadSpanState;
+Landroid/os/StrictMode$ViolationInfo;
+Landroid/os/StrictMode$ViolationInfo$1;
+Landroid/os/StrictMode$VmPolicy;
+Landroid/os/StrictMode$VmPolicy$Builder;
+Landroid/os/SynchronousResultReceiver;
+Landroid/os/SynchronousResultReceiver$Result;
+Landroid/os/SystemClock;
+Landroid/os/SystemProperties;
+Landroid/os/SystemService;
+Landroid/os/SystemService$1;
+Landroid/os/SystemService$State;
+Landroid/os/SystemVibrator;
+Landroid/os/TokenWatcher;
+Landroid/os/TokenWatcher$1;
+Landroid/os/Trace;
+Landroid/os/Trace$1;
+Landroid/os/TransactionTooLargeException;
+Landroid/os/UEventObserver;
+Landroid/os/UEventObserver$UEvent;
+Landroid/os/UEventObserver$UEventThread;
+Landroid/os/UpdateLock;
+Landroid/os/UserHandle;
+Landroid/os/UserHandle$1;
+Landroid/os/UserManager;
+Landroid/os/UserManagerInternal;
+Landroid/os/UserManagerInternal$UserRestrictionsListener;
+Landroid/os/Vibrator;
+Landroid/os/WorkSource;
+Landroid/os/WorkSource$1;
+Landroid/os/ZygoteProcess;
+Landroid/os/ZygoteProcess$ZygoteState;
+Landroid/os/ZygoteStartFailedEx;
+Landroid/print/IPrintDocumentAdapter;
+Landroid/print/IPrinterDiscoveryObserver;
+Landroid/print/IPrintJobStateChangeListener;
+Landroid/print/IPrintManager;
+Landroid/print/IPrintManager$Stub;
+Landroid/print/IPrintServicesChangeListener;
+Landroid/print/IPrintServicesChangeListener$Stub;
+Landroid/print/IPrintServicesChangeListener$Stub$Proxy;
+Landroid/print/IPrintSpooler;
+Landroid/print/IPrintSpoolerCallbacks;
+Landroid/print/IPrintSpoolerCallbacks$Stub;
+Landroid/print/IPrintSpoolerClient;
+Landroid/print/IPrintSpoolerClient$Stub;
+Landroid/print/IPrintSpooler$Stub;
+Landroid/print/IPrintSpooler$Stub$Proxy;
+Landroid/print/PrintAttributes;
+Landroid/print/PrinterId;
+Landroid/print/PrintJobId;
+Landroid/print/PrintJobInfo;
+Landroid/print/PrintManager;
+Landroid/printservice/IPrintServiceClient;
+Landroid/printservice/IPrintServiceClient$Stub;
+Landroid/printservice/PrintServiceInfo;
+Landroid/printservice/PrintServiceInfo$1;
+Landroid/printservice/recommendation/IRecommendationsChangeListener;
+Landroid/provider/BaseColumns;
+Landroid/provider/CalendarContract$Attendees;
+Landroid/provider/CalendarContract$AttendeesColumns;
+Landroid/provider/CalendarContract$CalendarColumns;
+Landroid/provider/CalendarContract$Calendars;
+Landroid/provider/CalendarContract$CalendarSyncColumns;
+Landroid/provider/CalendarContract$Events;
+Landroid/provider/CalendarContract$EventsColumns;
+Landroid/provider/CalendarContract$Instances;
+Landroid/provider/CalendarContract$SyncColumns;
+Landroid/provider/CallLog$Calls;
+Landroid/provider/ContactsContract;
+Landroid/provider/ContactsContract$CommonDataKinds$BaseTypes;
+Landroid/provider/ContactsContract$CommonDataKinds$Callable;
+Landroid/provider/ContactsContract$CommonDataKinds$CommonColumns;
+Landroid/provider/ContactsContract$CommonDataKinds$Phone;
+Landroid/provider/ContactsContract$ContactCounts;
+Landroid/provider/ContactsContract$ContactNameColumns;
+Landroid/provider/ContactsContract$ContactOptionsColumns;
+Landroid/provider/ContactsContract$Contacts;
+Landroid/provider/ContactsContract$ContactsColumns;
+Landroid/provider/ContactsContract$ContactStatusColumns;
+Landroid/provider/ContactsContract$Data;
+Landroid/provider/ContactsContract$DataColumns;
+Landroid/provider/ContactsContract$DataColumnsWithJoins;
+Landroid/provider/ContactsContract$DataUsageFeedback;
+Landroid/provider/ContactsContract$DataUsageStatColumns;
+Landroid/provider/ContactsContract$PhoneLookup;
+Landroid/provider/ContactsContract$PhoneLookupColumns;
+Landroid/provider/ContactsContract$RawContactsColumns;
+Landroid/provider/ContactsContract$StatusColumns;
+Landroid/provider/Downloads;
+Landroid/provider/Downloads$Impl;
+Landroid/provider/Settings;
+Landroid/provider/Settings$ContentProviderHolder;
+Landroid/provider/Settings$GenerationTracker;
+Landroid/provider/Settings$Global;
+Landroid/provider/Settings$NameValueCache;
+Landroid/provider/Settings$NameValueTable;
+Landroid/provider/Settings$Secure;
+Landroid/provider/Settings$SettingNotFoundException;
+Landroid/provider/Settings$System;
+Landroid/provider/Settings$System$1;
+Landroid/provider/Settings$System$2;
+Landroid/provider/Settings$System$3;
+Landroid/provider/Settings$System$4;
+Landroid/provider/Settings$System$5;
+Landroid/provider/Settings$System$6;
+Landroid/provider/Settings$System$7;
+Landroid/provider/Settings$System$8;
+Landroid/provider/Settings$System$9;
+Landroid/provider/Settings$System$DiscreteValueValidator;
+Landroid/provider/Settings$System$InclusiveFloatRangeValidator;
+Landroid/provider/Settings$System$InclusiveIntegerRangeValidator;
+Landroid/provider/Settings$System$Validator;
+Landroid/R$styleable;
+Landroid/security/IKeyChainService;
+Landroid/security/IKeyChainService$Stub;
+Landroid/security/IKeyChainService$Stub$Proxy;
+Landroid/security/IKeystoreService;
+Landroid/security/IKeystoreService$Stub;
+Landroid/security/IKeystoreService$Stub$Proxy;
+Landroid/security/KeyChain;
+Landroid/security/KeyChain$1;
+Landroid/security/KeyChain$KeyChainConnection;
+Landroid/security/keymaster/IKeyAttestationApplicationIdProvider;
+Landroid/security/keymaster/IKeyAttestationApplicationIdProvider$Stub;
+Landroid/security/keymaster/KeyAttestationApplicationId;
+Landroid/security/KeyStore;
+Landroid/security/keystore/AndroidKeyStoreBCWorkaroundProvider;
+Landroid/security/keystore/AndroidKeyStoreProvider;
+Landroid/security/keystore/AndroidKeyStoreSpi;
+Landroid/service/autofill/IAutoFillManagerService;
+Landroid/service/autofill/IAutoFillManagerService$Stub;
+Landroid/service/dreams/DreamManagerInternal;
+Landroid/service/dreams/IDreamManager;
+Landroid/service/dreams/IDreamManager$Stub;
+Landroid/service/dreams/IDreamService;
+Landroid/service/dreams/IDreamService$Stub;
+Landroid/service/dreams/IDreamService$Stub$Proxy;
+Landroid/service/gatekeeper/IGateKeeperService;
+Landroid/service/gatekeeper/IGateKeeperService$Stub;
+Landroid/service/gatekeeper/IGateKeeperService$Stub$Proxy;
+Landroid/service/notification/Adjustment;
+Landroid/service/notification/Condition;
+Landroid/service/notification/Condition$1;
+Landroid/service/notification/ConditionProviderService;
+Landroid/service/notification/ConditionProviderService$H;
+Landroid/service/notification/ConditionProviderService$Provider;
+Landroid/service/notification/IConditionProvider;
+Landroid/service/notification/IConditionProvider$Stub;
+Landroid/service/notification/IConditionProvider$Stub$Proxy;
+Landroid/service/notification/INotificationListener;
+Landroid/service/notification/INotificationListener$Stub;
+Landroid/service/notification/INotificationListener$Stub$Proxy;
+Landroid/service/notification/IStatusBarNotificationHolder;
+Landroid/service/notification/IStatusBarNotificationHolder$Stub;
+Landroid/service/notification/NotificationListenerService$Ranking;
+Landroid/service/notification/NotificationRankingUpdate;
+Landroid/service/notification/NotificationRankingUpdate$1;
+Landroid/service/notification/StatusBarNotification;
+Landroid/service/notification/StatusBarNotification$1;
+Landroid/service/notification/ZenModeConfig;
+Landroid/service/notification/ZenModeConfig$1;
+Landroid/service/notification/ZenModeConfig$Diff;
+Landroid/service/notification/ZenModeConfig$EventInfo;
+Landroid/service/notification/ZenModeConfig$ScheduleInfo;
+Landroid/service/notification/ZenModeConfig$ZenRule;
+Landroid/service/notification/ZenModeConfig$ZenRule$1;
+Landroid/service/persistentdata/IPersistentDataBlockService;
+Landroid/service/persistentdata/IPersistentDataBlockService$Stub;
+Landroid/service/persistentdata/PersistentDataBlockManager;
+Landroid/service/voice/IVoiceInteractionService;
+Landroid/service/voice/IVoiceInteractionService$Stub;
+Landroid/service/voice/IVoiceInteractionService$Stub$Proxy;
+Landroid/service/voice/IVoiceInteractionSession;
+Landroid/service/voice/IVoiceInteractionSessionService;
+Landroid/service/voice/IVoiceInteractionSessionService$Stub;
+Landroid/service/voice/IVoiceInteractionSessionService$Stub$Proxy;
+Landroid/service/voice/IVoiceInteractionSession$Stub;
+Landroid/service/voice/IVoiceInteractionSession$Stub$Proxy;
+Landroid/service/voice/VoiceInteractionManagerInternal;
+Landroid/service/voice/VoiceInteractionServiceInfo;
+Landroid/service/vr/IVrManager;
+Landroid/service/vr/IVrManager$Stub;
+Landroid/service/vr/IVrStateCallbacks;
+Landroid/service/vr/IVrStateCallbacks$Stub;
+Landroid/service/vr/IVrStateCallbacks$Stub$Proxy;
+Landroid/service/wallpaper/IWallpaperConnection;
+Landroid/service/wallpaper/IWallpaperConnection$Stub;
+Landroid/service/wallpaper/IWallpaperEngine;
+Landroid/service/wallpaper/IWallpaperEngine$Stub;
+Landroid/service/wallpaper/IWallpaperEngine$Stub$Proxy;
+Landroid/service/wallpaper/IWallpaperService;
+Landroid/service/wallpaper/IWallpaperService$Stub;
+Landroid/service/wallpaper/IWallpaperService$Stub$Proxy;
+Landroid/system/ErrnoException;
+Landroid/system/GaiException;
+Landroid/system/NetlinkSocketAddress;
+Landroid/system/Os;
+Landroid/system/OsConstants;
+Landroid/system/PacketSocketAddress;
+Landroid/system/StructAddrinfo;
+Landroid/system/StructFlock;
+Landroid/system/StructGroupReq;
+Landroid/system/StructGroupSourceReq;
+Landroid/system/StructIfaddrs;
+Landroid/system/StructLinger;
+Landroid/system/StructPasswd;
+Landroid/system/StructPollfd;
+Landroid/system/StructStat;
+Landroid/system/StructStatVfs;
+Landroid/system/StructTimeval;
+Landroid/system/StructUcred;
+Landroid/system/StructUtsname;
+Landroid/system/UnixSocketAddress;
+Landroid/telecom/CallAudioState;
+Landroid/telecom/CallAudioState$1;
+Landroid/telecom/Conferenceable;
+Landroid/telecom/Connection;
+Landroid/telecom/ConnectionRequest;
+Landroid/telecom/ConnectionRequest$1;
+Landroid/telecom/DefaultDialerManager;
+Landroid/telecom/DisconnectCause;
+Landroid/telecom/DisconnectCause$1;
+Landroid/telecom/Log;
+Landroid/telecom/Log$1;
+Landroid/telecom/Logging/EventManager;
+Landroid/telecom/Logging/EventManager$Event;
+Landroid/telecom/Logging/EventManager$EventListener;
+Landroid/telecom/Logging/EventManager$EventRecord;
+Landroid/telecom/Logging/EventManager$Loggable;
+Landroid/telecom/Logging/EventManager$TimedEventPair;
+Landroid/telecom/Logging/Runnable;
+Landroid/telecom/Logging/Runnable$1;
+Landroid/telecom/Logging/Session;
+Landroid/telecom/Logging/Session$Info;
+Landroid/telecom/Logging/Session$Info$1;
+Landroid/telecom/Logging/SessionManager;
+Landroid/telecom/Logging/SessionManager$ICurrentThreadId;
+Landroid/telecom/Logging/SessionManager$ISessionCleanupTimeoutMs;
+Landroid/telecom/Logging/SessionManager$ISessionIdQueryHandler;
+Landroid/telecom/Logging/SessionManager$ISessionListener;
+Landroid/telecom/ParcelableCall;
+Landroid/telecom/ParcelableCall$1;
+Landroid/telecom/ParcelableConference;
+Landroid/telecom/ParcelableConnection;
+Landroid/telecom/ParcelableConnection$1;
+Landroid/telecom/PhoneAccount;
+Landroid/telecom/PhoneAccount$1;
+Landroid/telecom/PhoneAccount$Builder;
+Landroid/telecom/PhoneAccountHandle;
+Landroid/telecom/PhoneAccountHandle$1;
+Landroid/telecom/StatusHints;
+Landroid/telecom/TelecomAnalytics;
+Landroid/telecom/TelecomAnalytics$SessionTiming;
+Landroid/telecom/TelecomAnalytics$SessionTiming$1;
+Landroid/telecom/TelecomManager;
+Landroid/telecom/TimedEvent;
+Landroid/telecom/VideoProfile;
+Landroid/telecom/VideoProfile$1;
+Landroid/telephony/CarrierConfigManager;
+Landroid/telephony/CellLocation;
+Landroid/telephony/gsm/GsmCellLocation;
+Landroid/telephony/ModemActivityInfo;
+Landroid/telephony/ModemActivityInfo$1;
+Landroid/telephony/PhoneNumberUtils;
+Landroid/telephony/PhoneStateListener;
+Landroid/telephony/PhoneStateListener$1;
+Landroid/telephony/PhoneStateListener$IPhoneStateListenerStub;
+Landroid/telephony/PreciseCallState;
+Landroid/telephony/PreciseCallState$1;
+Landroid/telephony/PreciseDataConnectionState;
+Landroid/telephony/PreciseDataConnectionState$1;
+Landroid/telephony/Rlog;
+Landroid/telephony/ServiceState;
+Landroid/telephony/ServiceState$1;
+Landroid/telephony/SignalStrength;
+Landroid/telephony/SignalStrength$1;
+Landroid/telephony/SubscriptionInfo;
+Landroid/telephony/SubscriptionInfo$1;
+Landroid/telephony/SubscriptionManager;
+Landroid/telephony/SubscriptionManager$OnSubscriptionsChangedListener;
+Landroid/telephony/SubscriptionManager$OnSubscriptionsChangedListener$1;
+Landroid/telephony/SubscriptionManager$OnSubscriptionsChangedListener$2;
+Landroid/telephony/TelephonyManager;
+Landroid/telephony/TelephonyManager$MultiSimVariants;
+Landroid/telephony/VoLteServiceState;
+Landroid/telephony/VoLteServiceState$1;
+Landroid/text/AndroidBidi;
+Landroid/text/AndroidCharacter;
+Landroid/text/BoringLayout;
+Landroid/text/BoringLayout$Metrics;
+Landroid/text/ClipboardManager;
+Landroid/text/Editable;
+Landroid/text/Editable$Factory;
+Landroid/text/FontConfig;
+Landroid/text/FontConfig$1;
+Landroid/text/FontConfig$Alias;
+Landroid/text/FontConfig$Alias$1;
+Landroid/text/FontConfig$Axis;
+Landroid/text/FontConfig$Axis$1;
+Landroid/text/FontConfig$Family;
+Landroid/text/FontConfig$Family$1;
+Landroid/text/FontConfig$Font;
+Landroid/text/FontConfig$Font$1;
+Landroid/text/FontManager;
+Landroid/text/format/DateFormat;
+Landroid/text/format/Time;
+Landroid/text/format/Time$TimeCalculator;
+Landroid/text/GetChars;
+Landroid/text/GraphicsOperations;
+Landroid/text/Hyphenator;
+Landroid/text/InputFilter;
+Landroid/text/InputType;
+Landroid/text/ITextClassificationService;
+Landroid/text/ITextClassificationService$Stub;
+Landroid/text/Layout;
+Landroid/text/Layout$Alignment;
+Landroid/text/Layout$Directions;
+Landroid/text/method/AllCapsTransformationMethod;
+Landroid/text/method/PasswordTransformationMethod;
+Landroid/text/method/ReplacementTransformationMethod;
+Landroid/text/method/SingleLineTransformationMethod;
+Landroid/text/method/TransformationMethod;
+Landroid/text/method/TransformationMethod2;
+Landroid/text/NoCopySpan;
+Landroid/text/ParcelableSpan;
+Landroid/text/Selection;
+Landroid/text/Selection$END;
+Landroid/text/Selection$START;
+Landroid/text/Spannable;
+Landroid/text/Spannable$Factory;
+Landroid/text/SpannableString;
+Landroid/text/SpannableStringBuilder;
+Landroid/text/SpannableStringInternal;
+Landroid/text/Spanned;
+Landroid/text/SpannedString;
+Landroid/text/SpanSet;
+Landroid/text/SpanWatcher;
+Landroid/text/StaticLayout;
+Landroid/text/StaticLayout$LineBreaks;
+Landroid/text/style/CharacterStyle;
+Landroid/text/style/MetricAffectingSpan;
+Landroid/text/style/ParagraphStyle;
+Landroid/text/style/ReplacementSpan;
+Landroid/text/style/SpellCheckSpan;
+Landroid/text/style/StyleSpan;
+Landroid/text/style/SuggestionSpan;
+Landroid/text/style/UpdateAppearance;
+Landroid/text/style/UpdateLayout;
+Landroid/text/TextDirectionHeuristic;
+Landroid/text/TextDirectionHeuristics;
+Landroid/text/TextDirectionHeuristics$AnyStrong;
+Landroid/text/TextDirectionHeuristics$FirstStrong;
+Landroid/text/TextDirectionHeuristics$TextDirectionAlgorithm;
+Landroid/text/TextDirectionHeuristics$TextDirectionHeuristicImpl;
+Landroid/text/TextDirectionHeuristics$TextDirectionHeuristicInternal;
+Landroid/text/TextDirectionHeuristics$TextDirectionHeuristicLocale;
+Landroid/text/TextLine;
+Landroid/text/TextPaint;
+Landroid/text/TextUtils;
+Landroid/text/TextUtils$1;
+Landroid/text/TextUtils$EllipsizeCallback;
+Landroid/text/TextUtils$SimpleStringSplitter;
+Landroid/text/TextUtils$StringSplitter;
+Landroid/text/TextUtils$TruncateAt;
+Landroid/text/TextWatcher;
+Landroid/transition/AutoTransition;
+Landroid/transition/ChangeBounds;
+Landroid/transition/ChangeBounds$1;
+Landroid/transition/ChangeBounds$2;
+Landroid/transition/ChangeBounds$3;
+Landroid/transition/ChangeBounds$4;
+Landroid/transition/ChangeBounds$5;
+Landroid/transition/ChangeBounds$6;
+Landroid/transition/ChangeClipBounds;
+Landroid/transition/ChangeImageTransform;
+Landroid/transition/ChangeImageTransform$1;
+Landroid/transition/ChangeImageTransform$2;
+Landroid/transition/ChangeTransform;
+Landroid/transition/ChangeTransform$1;
+Landroid/transition/ChangeTransform$2;
+Landroid/transition/Fade;
+Landroid/transition/PathMotion;
+Landroid/transition/Transition;
+Landroid/transition/Transition$1;
+Landroid/transition/TransitionInflater;
+Landroid/transition/TransitionManager;
+Landroid/transition/TransitionSet;
+Landroid/transition/TransitionValuesMaps;
+Landroid/transition/Visibility;
+Landroid/util/AndroidException;
+Landroid/util/AndroidRuntimeException;
+Landroid/util/apk/ApkSignatureSchemeV2Verifier;
+Landroid/util/apk/ApkSignatureSchemeV2Verifier$ByteBufferDataSource;
+Landroid/util/apk/ApkSignatureSchemeV2Verifier$DataSource;
+Landroid/util/apk/ApkSignatureSchemeV2Verifier$MemoryMappedFileDataSource;
+Landroid/util/apk/ApkSignatureSchemeV2Verifier$SignatureInfo;
+Landroid/util/apk/ApkSignatureSchemeV2Verifier$SignatureNotFoundException;
+Landroid/util/apk/ApkSignatureSchemeV2Verifier$VerbatimX509Certificate;
+Landroid/util/apk/ApkSignatureSchemeV2Verifier$WrappedX509Certificate;
+Landroid/util/apk/ZipUtils;
+Landroid/util/ArrayMap;
+Landroid/util/ArrayMap$1;
+Landroid/util/ArraySet;
+Landroid/util/ArraySet$1;
+Landroid/util/AtomicFile;
+Landroid/util/AttributeSet;
+Landroid/util/Base64;
+Landroid/util/Base64$Coder;
+Landroid/util/Base64$Decoder;
+Landroid/util/Base64$Encoder;
+Landroid/util/BootTimingsTraceLog;
+Landroid/util/ContainerHelpers;
+Landroid/util/DebugUtils;
+Landroid/util/DisplayMetrics;
+Landroid/util/EventLog;
+Landroid/util/EventLog$Event;
+Landroid/util/FastImmutableArraySet;
+Landroid/util/FastImmutableArraySet$FastIterator;
+Landroid/util/FloatProperty;
+Landroid/util/IntArray;
+Landroid/util/IntProperty;
+Landroid/util/jar/StrictJarFile;
+Landroid/util/KeyValueListParser;
+Landroid/util/LocalLog;
+Landroid/util/LocalLog$ReadOnlyLocalLog;
+Landroid/util/Log;
+Landroid/util/Log$1;
+Landroid/util/Log$ImmediateLogWriter;
+Landroid/util/Log$NoPreloadHolder;
+Landroid/util/LogPrinter;
+Landroid/util/Log$TerribleFailureHandler;
+Landroid/util/LongArray;
+Landroid/util/LongSparseArray;
+Landroid/util/LongSparseLongArray;
+Landroid/util/LruCache;
+Landroid/util/MapCollections;
+Landroid/util/MapCollections$ArrayIterator;
+Landroid/util/MapCollections$EntrySet;
+Landroid/util/MapCollections$KeySet;
+Landroid/util/MapCollections$MapIterator;
+Landroid/util/MapCollections$ValuesCollection;
+Landroid/util/MathUtils;
+Landroid/util/MemoryIntArray;
+Landroid/util/MemoryIntArray$1;
+Landroid/util/MutableBoolean;
+Landroid/util/MutableInt;
+Landroid/util/MutableLong;
+Landroid/util/NtpTrustedTime;
+Landroid/util/Pair;
+Landroid/util/PathParser;
+Landroid/util/PathParser$PathData;
+Landroid/util/Pools$Pool;
+Landroid/util/Pools$SimplePool;
+Landroid/util/Pools$SynchronizedPool;
+Landroid/util/Printer;
+Landroid/util/Property;
+Landroid/util/Rational;
+Landroid/util/Singleton;
+Landroid/util/Size;
+Landroid/util/Slog;
+Landroid/util/SparseArray;
+Landroid/util/SparseBooleanArray;
+Landroid/util/SparseIntArray;
+Landroid/util/SparseLongArray;
+Landroid/util/Spline;
+Landroid/util/Spline$MonotoneCubicSpline;
+Landroid/util/StateSet;
+Landroid/util/SuperNotCalledException;
+Landroid/util/TimedRemoteCaller;
+Landroid/util/TimeUtils;
+Landroid/util/TrustedTime;
+Landroid/util/TypedValue;
+Landroid/util/Xml;
+Landroid/util/Xml$XmlSerializerFactory;
+Landroid/view/accessibility/AccessibilityEvent;
+Landroid/view/accessibility/AccessibilityEventSource;
+Landroid/view/accessibility/AccessibilityManager;
+Landroid/view/accessibility/AccessibilityManager$1;
+Landroid/view/accessibility/AccessibilityManager$AccessibilityServicesStateChangeListener;
+Landroid/view/accessibility/AccessibilityManager$AccessibilityStateChangeListener;
+Landroid/view/accessibility/AccessibilityManager$HighTextContrastChangeListener;
+Landroid/view/accessibility/AccessibilityManager$MyHandler;
+Landroid/view/accessibility/AccessibilityManager$TouchExplorationStateChangeListener;
+Landroid/view/accessibility/AccessibilityRecord;
+Landroid/view/accessibility/CaptioningManager;
+Landroid/view/accessibility/IAccessibilityInteractionConnection;
+Landroid/view/accessibility/IAccessibilityManager;
+Landroid/view/accessibility/IAccessibilityManagerClient;
+Landroid/view/accessibility/IAccessibilityManagerClient$Stub;
+Landroid/view/accessibility/IAccessibilityManagerClient$Stub$Proxy;
+Landroid/view/accessibility/IAccessibilityManager$Stub;
+Landroid/view/ActionMode;
+Landroid/view/ActionMode$Callback;
+Landroid/view/animation/AccelerateDecelerateInterpolator;
+Landroid/view/animation/AccelerateInterpolator;
+Landroid/view/animation/AlphaAnimation;
+Landroid/view/animation/Animation;
+Landroid/view/animation/Animation$Description;
+Landroid/view/animation/Animation$NoImagePreloadHolder;
+Landroid/view/animation/AnimationSet;
+Landroid/view/animation/AnimationUtils;
+Landroid/view/animation/AnimationUtils$1;
+Landroid/view/animation/AnimationUtils$AnimationState;
+Landroid/view/animation/BaseInterpolator;
+Landroid/view/animation/ClipRectAnimation;
+Landroid/view/animation/DecelerateInterpolator;
+Landroid/view/animation/Interpolator;
+Landroid/view/animation/LinearInterpolator;
+Landroid/view/animation/PathInterpolator;
+Landroid/view/animation/RotateAnimation;
+Landroid/view/animation/ScaleAnimation;
+Landroid/view/animation/Transformation;
+Landroid/view/animation/TranslateAnimation;
+Landroid/view/AppTransitionAnimationSpec;
+Landroid/view/AppTransitionAnimationSpec$1;
+Landroid/view/autofill/AutoFillId;
+Landroid/view/autofill/AutoFillId$1;
+Landroid/view/autofill/AutoFillManager;
+Landroid/view/Choreographer;
+Landroid/view/Choreographer$1;
+Landroid/view/Choreographer$2;
+Landroid/view/Choreographer$CallbackQueue;
+Landroid/view/Choreographer$CallbackRecord;
+Landroid/view/Choreographer$FrameCallback;
+Landroid/view/Choreographer$FrameDisplayEventReceiver;
+Landroid/view/Choreographer$FrameHandler;
+Landroid/view/ContextMenu;
+Landroid/view/ContextThemeWrapper;
+Landroid/view/Display;
+Landroid/view/DisplayAdjustments;
+Landroid/view/DisplayEventReceiver;
+Landroid/view/Display$HdrCapabilities;
+Landroid/view/Display$HdrCapabilities$1;
+Landroid/view/DisplayInfo;
+Landroid/view/DisplayInfo$1;
+Landroid/view/DisplayListCanvas;
+Landroid/view/Display$Mode;
+Landroid/view/Display$Mode$1;
+Landroid/view/DragEvent;
+Landroid/view/FallbackEventHandler;
+Landroid/view/FrameInfo;
+Landroid/view/FrameMetrics;
+Landroid/view/FrameMetricsObserver;
+Landroid/view/FrameStats;
+Landroid/view/GestureDetector;
+Landroid/view/GestureDetector$GestureHandler;
+Landroid/view/GestureDetector$OnContextClickListener;
+Landroid/view/GestureDetector$OnDoubleTapListener;
+Landroid/view/GestureDetector$OnGestureListener;
+Landroid/view/GestureDetector$SimpleOnGestureListener;
+Landroid/view/Gravity;
+Landroid/view/HandlerActionQueue;
+Landroid/view/HardwareLayer;
+Landroid/view/IApplicationToken;
+Landroid/view/IApplicationToken$Stub;
+Landroid/view/IAppTransitionAnimationSpecsFuture;
+Landroid/view/IAppTransitionAnimationSpecsFuture$Stub;
+Landroid/view/IAppTransitionAnimationSpecsFuture$Stub$Proxy;
+Landroid/view/IDockedStackListener;
+Landroid/view/IDockedStackListener$Stub;
+Landroid/view/IDockedStackListener$Stub$Proxy;
+Landroid/view/IGraphicsStats;
+Landroid/view/IGraphicsStats$Stub;
+Landroid/view/IInputFilter;
+Landroid/view/InflateException;
+Landroid/view/InputChannel;
+Landroid/view/InputChannel$1;
+Landroid/view/InputDevice;
+Landroid/view/InputDevice$1;
+Landroid/view/InputDevice$MotionRange;
+Landroid/view/InputEvent;
+Landroid/view/InputEvent$1;
+Landroid/view/InputEventConsistencyVerifier;
+Landroid/view/InputEventReceiver;
+Landroid/view/InputEventReceiver$Factory;
+Landroid/view/InputEventSender;
+Landroid/view/inputmethod/BaseInputConnection;
+Landroid/view/inputmethod/ComposingText;
+Landroid/view/inputmethod/EditorInfo;
+Landroid/view/inputmethod/EditorInfo$1;
+Landroid/view/inputmethod/InputBinding;
+Landroid/view/inputmethod/InputBinding$1;
+Landroid/view/inputmethod/InputConnection;
+Landroid/view/inputmethod/InputMethodInfo;
+Landroid/view/inputmethod/InputMethodInfo$1;
+Landroid/view/inputmethod/InputMethodManager;
+Landroid/view/inputmethod/InputMethodManager$1;
+Landroid/view/inputmethod/InputMethodManager$2;
+Landroid/view/inputmethod/InputMethodManager$ControlledInputConnectionWrapper;
+Landroid/view/inputmethod/InputMethodManager$FinishedInputEventCallback;
+Landroid/view/inputmethod/InputMethodManager$H;
+Landroid/view/inputmethod/InputMethodManagerInternal;
+Landroid/view/inputmethod/InputMethodSubtype;
+Landroid/view/inputmethod/InputMethodSubtype$1;
+Landroid/view/inputmethod/InputMethodSubtypeArray;
+Landroid/view/inputmethod/InputMethodSubtype$InputMethodSubtypeBuilder;
+Landroid/view/InputQueue;
+Landroid/view/InputQueue$Callback;
+Landroid/view/InputQueue$FinishedInputEventCallback;
+Landroid/view/IOnKeyguardExitResult;
+Landroid/view/IPinnedStackController;
+Landroid/view/IPinnedStackController$Stub;
+Landroid/view/IPinnedStackListener;
+Landroid/view/IPinnedStackListener$Stub;
+Landroid/view/IPinnedStackListener$Stub$Proxy;
+Landroid/view/IRotationWatcher;
+Landroid/view/IRotationWatcher$Stub;
+Landroid/view/IRotationWatcher$Stub$Proxy;
+Landroid/view/IWindow;
+Landroid/view/IWindowFocusObserver;
+Landroid/view/IWindowId;
+Landroid/view/IWindowId$Stub;
+Landroid/view/IWindowManager;
+Landroid/view/IWindowManager$Stub;
+Landroid/view/IWindowSession;
+Landroid/view/IWindowSessionCallback;
+Landroid/view/IWindowSessionCallback$Stub;
+Landroid/view/IWindowSessionCallback$Stub$Proxy;
+Landroid/view/IWindowSession$Stub;
+Landroid/view/IWindow$Stub;
+Landroid/view/IWindow$Stub$Proxy;
+Landroid/view/KeyCharacterMap;
+Landroid/view/KeyCharacterMap$1;
+Landroid/view/KeyCharacterMap$FallbackAction;
+Landroid/view/KeyEvent;
+Landroid/view/KeyEvent$1;
+Landroid/view/KeyEvent$Callback;
+Landroid/view/KeyEvent$DispatcherState;
+Landroid/view/LayoutInflater;
+Landroid/view/LayoutInflater$Factory;
+Landroid/view/LayoutInflater$Factory2;
+Landroid/view/LayoutInflater$Filter;
+Landroid/view/MagnificationSpec;
+Landroid/view/Menu;
+Landroid/view/MenuItem;
+Landroid/view/MotionEvent;
+Landroid/view/MotionEvent$1;
+Landroid/view/MotionEvent$PointerCoords;
+Landroid/view/MotionEvent$PointerProperties;
+Landroid/view/PointerIcon;
+Landroid/view/PointerIcon$1;
+Landroid/view/RecordingCanvas;
+Landroid/view/RenderNode;
+Landroid/view/RenderNodeAnimator;
+Landroid/view/RenderNodeAnimator$1;
+Landroid/view/RenderNode$NoImagePreloadHolder;
+Landroid/view/Surface;
+Landroid/view/Surface$1;
+Landroid/view/Surface$CompatibleCanvas;
+Landroid/view/SurfaceControl;
+Landroid/view/SurfaceControl$PhysicalDisplayInfo;
+Landroid/view/SurfaceHolder;
+Landroid/view/SurfaceHolder$Callback;
+Landroid/view/SurfaceHolder$Callback2;
+Landroid/view/Surface$HwuiContext;
+Landroid/view/Surface$OutOfResourcesException;
+Landroid/view/SurfaceSession;
+Landroid/view/SurfaceView;
+Landroid/view/textclassifier/TextClassificationManager;
+Landroid/view/textservice/SpellCheckerInfo;
+Landroid/view/textservice/SpellCheckerInfo$1;
+Landroid/view/textservice/SpellCheckerSubtype;
+Landroid/view/textservice/SpellCheckerSubtype$1;
+Landroid/view/textservice/TextServicesManager;
+Landroid/view/TextureView;
+Landroid/view/ThreadedRenderer;
+Landroid/view/ThreadedRenderer$DrawCallbacks;
+Landroid/view/ThreadedRenderer$ProcessInitializer;
+Landroid/view/VelocityTracker;
+Landroid/view/VelocityTracker$Estimator;
+Landroid/view/View;
+Landroid/view/View$1;
+Landroid/view/View$10;
+Landroid/view/View$11;
+Landroid/view/View$12;
+Landroid/view/View$2;
+Landroid/view/View$3;
+Landroid/view/View$4;
+Landroid/view/View$5;
+Landroid/view/View$6;
+Landroid/view/View$7;
+Landroid/view/View$8;
+Landroid/view/View$9;
+Landroid/view/View$AttachInfo;
+Landroid/view/View$AttachInfo$Callbacks;
+Landroid/view/ViewConfiguration;
+Landroid/view/View$ForegroundInfo;
+Landroid/view/ViewGroup;
+Landroid/view/ViewGroup$1;
+Landroid/view/ViewGroup$2;
+Landroid/view/ViewGroup$LayoutParams;
+Landroid/view/ViewGroup$MarginLayoutParams;
+Landroid/view/ViewGroup$TouchTarget;
+Landroid/view/View$ListenerInfo;
+Landroid/view/ViewManager;
+Landroid/view/View$MeasureSpec;
+Landroid/view/View$OnClickListener;
+Landroid/view/View$OnCreateContextMenuListener;
+Landroid/view/ViewOutlineProvider;
+Landroid/view/ViewOutlineProvider$1;
+Landroid/view/ViewOutlineProvider$2;
+Landroid/view/ViewOutlineProvider$3;
+Landroid/view/ViewParent;
+Landroid/view/View$PerformClick;
+Landroid/view/ViewPropertyAnimator;
+Landroid/view/ViewPropertyAnimator$1;
+Landroid/view/ViewPropertyAnimator$2;
+Landroid/view/ViewPropertyAnimator$3;
+Landroid/view/ViewPropertyAnimator$AnimatorEventListener;
+Landroid/view/ViewPropertyAnimator$NameValuesHolder;
+Landroid/view/ViewPropertyAnimator$PropertyBundle;
+Landroid/view/ViewRootImpl;
+Landroid/view/ViewRootImpl$1;
+Landroid/view/ViewRootImpl$4;
+Landroid/view/ViewRootImpl$AccessibilityInteractionConnectionManager;
+Landroid/view/ViewRootImpl$AsyncInputStage;
+Landroid/view/ViewRootImpl$ConsumeBatchedInputImmediatelyRunnable;
+Landroid/view/ViewRootImpl$ConsumeBatchedInputRunnable;
+Landroid/view/ViewRootImpl$EarlyPostImeInputStage;
+Landroid/view/ViewRootImpl$HighContrastTextManager;
+Landroid/view/ViewRootImpl$ImeInputStage;
+Landroid/view/ViewRootImpl$InputStage;
+Landroid/view/ViewRootImpl$InvalidateOnAnimationRunnable;
+Landroid/view/ViewRootImpl$NativePostImeInputStage;
+Landroid/view/ViewRootImpl$NativePreImeInputStage;
+Landroid/view/ViewRootImpl$QueuedInputEvent;
+Landroid/view/ViewRootImpl$SyntheticInputStage;
+Landroid/view/ViewRootImpl$SyntheticJoystickHandler;
+Landroid/view/ViewRootImpl$SyntheticKeyboardHandler;
+Landroid/view/ViewRootImpl$SyntheticTouchNavigationHandler;
+Landroid/view/ViewRootImpl$SyntheticTouchNavigationHandler$1;
+Landroid/view/ViewRootImpl$SyntheticTrackballHandler;
+Landroid/view/ViewRootImpl$TrackballAxis;
+Landroid/view/ViewRootImpl$TraversalRunnable;
+Landroid/view/ViewRootImpl$ViewPostImeInputStage;
+Landroid/view/ViewRootImpl$ViewPreImeInputStage;
+Landroid/view/ViewRootImpl$ViewRootHandler;
+Landroid/view/ViewRootImpl$W;
+Landroid/view/ViewRootImpl$WindowInputEventReceiver;
+Landroid/view/ViewStub;
+Landroid/view/View$TransformationInfo;
+Landroid/view/ViewTreeObserver;
+Landroid/view/ViewTreeObserver$CopyOnWriteArray;
+Landroid/view/ViewTreeObserver$CopyOnWriteArray$Access;
+Landroid/view/ViewTreeObserver$InternalInsetsInfo;
+Landroid/view/ViewTreeObserver$OnComputeInternalInsetsListener;
+Landroid/view/ViewTreeObserver$OnGlobalLayoutListener;
+Landroid/view/ViewTreeObserver$OnPreDrawListener;
+Landroid/view/View$UnsetPressedState;
+Landroid/view/Window;
+Landroid/view/WindowAnimationFrameStats;
+Landroid/view/WindowAnimationFrameStats$1;
+Landroid/view/Window$Callback;
+Landroid/view/WindowCallbacks;
+Landroid/view/WindowContentFrameStats;
+Landroid/view/WindowContentFrameStats$1;
+Landroid/view/WindowInsets;
+Landroid/view/WindowLeaked;
+Landroid/view/WindowManager;
+Landroid/view/WindowManager$BadTokenException;
+Landroid/view/WindowManagerGlobal;
+Landroid/view/WindowManagerGlobal$1;
+Landroid/view/WindowManagerGlobal$2;
+Landroid/view/WindowManagerImpl;
+Landroid/view/WindowManagerInternal;
+Landroid/view/WindowManagerInternal$AppTransitionListener;
+Landroid/view/WindowManagerInternal$MagnificationCallbacks;
+Landroid/view/WindowManagerInternal$OnHardKeyboardStatusChangeListener;
+Landroid/view/WindowManagerInternal$WindowsForAccessibilityCallback;
+Landroid/view/WindowManager$LayoutParams;
+Landroid/view/WindowManager$LayoutParams$1;
+Landroid/view/WindowManagerPolicy;
+Landroid/view/WindowManagerPolicy$InputConsumer;
+Landroid/view/WindowManagerPolicy$OnKeyguardExitResult;
+Landroid/view/WindowManagerPolicy$PointerEventListener;
+Landroid/view/WindowManagerPolicy$ScreenOnListener;
+Landroid/view/WindowManagerPolicy$StartingSurface;
+Landroid/view/WindowManagerPolicy$WindowManagerFuncs;
+Landroid/view/WindowManagerPolicy$WindowState;
+Landroid/view/Window$OnWindowDismissedCallback;
+Landroid/view/Window$WindowControllerCallback;
+Landroid/webkit/IWebViewUpdateService;
+Landroid/webkit/IWebViewUpdateService$Stub;
+Landroid/webkit/UserPackage;
+Landroid/webkit/WebViewFactory;
+Landroid/webkit/WebViewFactory$1;
+Landroid/webkit/WebViewFactory$MissingWebViewPackageException;
+Landroid/webkit/WebViewFactory$RelroFileCreator;
+Landroid/webkit/WebViewProviderInfo;
+Landroid/webkit/WebViewProviderInfo$1;
+Landroid/webkit/WebViewProviderResponse;
+Landroid/webkit/WebViewProviderResponse$1;
+Landroid/webkit/WebViewZygote;
+Landroid/widget/ActionMenuView$OnMenuItemClickListener;
+Landroid/widget/Button;
+Landroid/widget/FrameLayout;
+Landroid/widget/FrameLayout$LayoutParams;
+Landroid/widget/ImageButton;
+Landroid/widget/ImageView;
+Landroid/widget/ImageView$ScaleType;
+Landroid/widget/LinearLayout;
+Landroid/widget/LinearLayout$LayoutParams;
+Landroid/widget/OverScroller;
+Landroid/widget/OverScroller$SplineOverScroller;
+Landroid/widget/RelativeLayout;
+Landroid/widget/RelativeLayout$DependencyGraph;
+Landroid/widget/RelativeLayout$DependencyGraph$Node;
+Landroid/widget/RelativeLayout$LayoutParams;
+Landroid/widget/RemoteViews;
+Landroid/widget/RemoteViews$1;
+Landroid/widget/RemoteViews$2;
+Landroid/widget/RemoteViews$3;
+Landroid/widget/RemoteViews$Action;
+Landroid/widget/RemoteViews$ActionException;
+Landroid/widget/RemoteViews$BitmapCache;
+Landroid/widget/RemoteViews$BitmapReflectionAction;
+Landroid/widget/RemoteViews$MemoryUsageCounter;
+Landroid/widget/RemoteViews$MutablePair;
+Landroid/widget/RemoteViews$OnClickHandler;
+Landroid/widget/RemoteViews$ReflectionAction;
+Landroid/widget/RemoteViews$RuntimeAction;
+Landroid/widget/RemoteViews$SetOnClickPendingIntent;
+Landroid/widget/RtlSpacingHelper;
+Landroid/widget/Scroller$ViscousFluidInterpolator;
+Landroid/widget/TextView;
+Landroid/widget/TextView$BufferType;
+Landroid/widget/TextView$CharWrapper;
+Landroid/widget/Toolbar;
+Landroid/widget/Toolbar$1;
+Landroid/widget/Toolbar$2;
+Landroid/widget/Toolbar$LayoutParams;
+LB;
+LC;
+Lcom/android/dex/ClassData;
+Lcom/android/dex/ClassData$Method;
+Lcom/android/dex/ClassDef;
+Lcom/android/dex/Code;
+Lcom/android/dex/Dex;
+Lcom/android/dex/Dex$ClassDefIterable;
+Lcom/android/dex/DexException;
+Lcom/android/dex/Dex$FieldIdTable;
+Lcom/android/dex/DexFormat;
+Lcom/android/dex/Dex$MethodIdTable;
+Lcom/android/dex/Dex$ProtoIdTable;
+Lcom/android/dex/Dex$Section;
+Lcom/android/dex/Dex$StringTable;
+Lcom/android/dex/Dex$TypeIndexToDescriptorIndexTable;
+Lcom/android/dex/Dex$TypeIndexToDescriptorTable;
+Lcom/android/dex/FieldId;
+Lcom/android/dex/Leb128;
+Lcom/android/dex/MethodId;
+Lcom/android/dex/Mutf8;
+Lcom/android/dex/TableOfContents;
+Lcom/android/dex/TableOfContents$Section;
+Lcom/android/dex/TypeList;
+Lcom/android/dex/util/ByteInput;
+Lcom/android/dex/util/ByteOutput;
+Lcom/android/dex/util/ExceptionWithContext;
+Lcom/android/dex/util/FileUtils;
+Lcom/android/framework/protobuf/nano/CodedInputByteBufferNano;
+Lcom/android/framework/protobuf/nano/CodedOutputByteBufferNano;
+Lcom/android/framework/protobuf/nano/InternalNano;
+Lcom/android/framework/protobuf/nano/InvalidProtocolBufferNanoException;
+Lcom/android/framework/protobuf/nano/MessageNano;
+Lcom/android/framework/protobuf/nano/WireFormatNano;
+Lcom/android/i18n/phonenumbers/AlternateFormatsCountryCodeSet;
+Lcom/android/i18n/phonenumbers/CountryCodeToRegionCodeMap;
+Lcom/android/i18n/phonenumbers/MetadataLoader;
+Lcom/android/i18n/phonenumbers/MetadataManager;
+Lcom/android/i18n/phonenumbers/MetadataManager$1;
+Lcom/android/i18n/phonenumbers/MetadataSource;
+Lcom/android/i18n/phonenumbers/MultiFileMetadataSourceImpl;
+Lcom/android/i18n/phonenumbers/NumberParseException;
+Lcom/android/i18n/phonenumbers/NumberParseException$ErrorType;
+Lcom/android/i18n/phonenumbers/Phonemetadata$NumberFormat;
+Lcom/android/i18n/phonenumbers/Phonemetadata$PhoneMetadata;
+Lcom/android/i18n/phonenumbers/Phonemetadata$PhoneMetadataCollection;
+Lcom/android/i18n/phonenumbers/Phonemetadata$PhoneNumberDesc;
+Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;
+Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber$CountryCodeSource;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$ValidationResult;
+Lcom/android/i18n/phonenumbers/RegexCache;
+Lcom/android/i18n/phonenumbers/RegexCache$LRUCache;
+Lcom/android/i18n/phonenumbers/RegexCache$LRUCache$1;
+Lcom/android/i18n/phonenumbers/ShortNumbersRegionCodeSet;
+Lcom/android/internal/alsa/AlsaCardsParser;
+Lcom/android/internal/alsa/AlsaCardsParser$AlsaCardRecord;
+Lcom/android/internal/alsa/AlsaDevicesParser;
+Lcom/android/internal/alsa/LineTokenizer;
+Lcom/android/internal/app/AssistUtils;
+Lcom/android/internal/app/IAppOpsCallback;
+Lcom/android/internal/app/IAppOpsCallback$Stub;
+Lcom/android/internal/app/IAppOpsCallback$Stub$Proxy;
+Lcom/android/internal/app/IAppOpsService;
+Lcom/android/internal/app/IAppOpsService$Stub;
+Lcom/android/internal/app/IAssistScreenshotReceiver;
+Lcom/android/internal/app/IAssistScreenshotReceiver$Stub;
+Lcom/android/internal/app/IBatteryStats;
+Lcom/android/internal/app/IBatteryStats$Stub;
+Lcom/android/internal/app/IMediaContainerService;
+Lcom/android/internal/app/IMediaContainerService$Stub;
+Lcom/android/internal/app/IMediaContainerService$Stub$Proxy;
+Lcom/android/internal/app/ISoundTriggerService;
+Lcom/android/internal/app/ISoundTriggerService$Stub;
+Lcom/android/internal/app/IVoiceInteractionManagerService;
+Lcom/android/internal/app/IVoiceInteractionManagerService$Stub;
+Lcom/android/internal/app/IVoiceInteractionSessionListener;
+Lcom/android/internal/app/IVoiceInteractionSessionListener$Stub;
+Lcom/android/internal/app/IVoiceInteractionSessionListener$Stub$Proxy;
+Lcom/android/internal/app/IVoiceInteractionSessionShowCallback;
+Lcom/android/internal/app/IVoiceInteractionSessionShowCallback$Stub;
+Lcom/android/internal/app/IVoiceInteractionSessionShowCallback$Stub$Proxy;
+Lcom/android/internal/app/IVoiceInteractor;
+Lcom/android/internal/app/IVoiceInteractor$Stub;
+Lcom/android/internal/app/IVoiceInteractor$Stub$Proxy;
+Lcom/android/internal/app/NightDisplayController;
+Lcom/android/internal/app/NightDisplayController$1;
+Lcom/android/internal/app/NightDisplayController$Callback;
+Lcom/android/internal/app/NightDisplayController$LocalTime;
+Lcom/android/internal/app/ProcessMap;
+Lcom/android/internal/app/procstats/DumpUtils;
+Lcom/android/internal/app/procstats/DurationsTable;
+Lcom/android/internal/app/procstats/IProcessStats;
+Lcom/android/internal/app/procstats/IProcessStats$Stub;
+Lcom/android/internal/app/procstats/ProcessState;
+Lcom/android/internal/app/procstats/ProcessState$1;
+Lcom/android/internal/app/procstats/ProcessState$PssAggr;
+Lcom/android/internal/app/procstats/ProcessStats;
+Lcom/android/internal/app/procstats/ProcessStats$1;
+Lcom/android/internal/app/procstats/ProcessStats$PackageState;
+Lcom/android/internal/app/procstats/ProcessStats$ProcessStateHolder;
+Lcom/android/internal/app/procstats/ProcessStats$TotalMemoryUseCollection;
+Lcom/android/internal/app/procstats/PssTable;
+Lcom/android/internal/app/procstats/ServiceState;
+Lcom/android/internal/app/procstats/SparseMappingTable;
+Lcom/android/internal/app/procstats/SparseMappingTable$Table;
+Lcom/android/internal/app/procstats/SysMemUsageTable;
+Lcom/android/internal/app/ResolverActivity;
+Lcom/android/internal/appwidget/IAppWidgetHost;
+Lcom/android/internal/appwidget/IAppWidgetHost$Stub;
+Lcom/android/internal/appwidget/IAppWidgetHost$Stub$Proxy;
+Lcom/android/internal/appwidget/IAppWidgetService;
+Lcom/android/internal/appwidget/IAppWidgetService$Stub;
+Lcom/android/internal/backup/IBackupTransport;
+Lcom/android/internal/backup/IBackupTransport$Stub;
+Lcom/android/internal/backup/IBackupTransport$Stub$Proxy;
+Lcom/android/internal/backup/LocalTransport;
+Lcom/android/internal/backup/LocalTransportService;
+Lcom/android/internal/content/NativeLibraryHelper;
+Lcom/android/internal/content/PackageHelper;
+Lcom/android/internal/content/PackageMonitor;
+Lcom/android/internal/content/ReferrerIntent;
+Lcom/android/internal/content/ReferrerIntent$1;
+Lcom/android/internal/font/IFontManager;
+Lcom/android/internal/font/IFontManager$Stub;
+Lcom/android/internal/graphics/drawable/AnimationScaleListDrawable;
+Lcom/android/internal/graphics/drawable/AnimationScaleListDrawable$AnimationScaleListState;
+Lcom/android/internal/hardware/AmbientDisplayConfiguration;
+Lcom/android/internal/inputmethod/IInputContentUriToken;
+Lcom/android/internal/inputmethod/InputMethodSubtypeHandle;
+Lcom/android/internal/inputmethod/InputMethodSubtypeSwitchingController;
+Lcom/android/internal/inputmethod/InputMethodSubtypeSwitchingController$ControllerImpl;
+Lcom/android/internal/inputmethod/InputMethodSubtypeSwitchingController$DynamicRotationList;
+Lcom/android/internal/inputmethod/InputMethodSubtypeSwitchingController$ImeSubtypeListItem;
+Lcom/android/internal/inputmethod/InputMethodSubtypeSwitchingController$InputMethodAndSubtypeList;
+Lcom/android/internal/inputmethod/InputMethodSubtypeSwitchingController$InputMethodAndSubtypeList$1;
+Lcom/android/internal/inputmethod/InputMethodSubtypeSwitchingController$StaticRotationList;
+Lcom/android/internal/inputmethod/InputMethodUtils;
+Lcom/android/internal/inputmethod/InputMethodUtils$1;
+Lcom/android/internal/inputmethod/InputMethodUtils$InputMethodListBuilder;
+Lcom/android/internal/inputmethod/InputMethodUtils$InputMethodSettings;
+Lcom/android/internal/inputmethod/LocaleUtils;
+Lcom/android/internal/inputmethod/LocaleUtils$LocaleExtractor;
+Lcom/android/internal/inputmethod/LocaleUtils$ScoreEntry;
+Lcom/android/internal/location/GpsNetInitiatedHandler;
+Lcom/android/internal/location/GpsNetInitiatedHandler$1;
+Lcom/android/internal/location/GpsNetInitiatedHandler$2;
+Lcom/android/internal/location/ILocationProvider;
+Lcom/android/internal/location/ILocationProvider$Stub;
+Lcom/android/internal/location/ILocationProvider$Stub$Proxy;
+Lcom/android/internal/location/ProviderProperties;
+Lcom/android/internal/location/ProviderProperties$1;
+Lcom/android/internal/location/ProviderRequest;
+Lcom/android/internal/location/ProviderRequest$1;
+Lcom/android/internal/logging/AndroidConfig;
+Lcom/android/internal/logging/AndroidHandler;
+Lcom/android/internal/logging/AndroidHandler$1;
+Lcom/android/internal/logging/EventLogTags;
+Lcom/android/internal/logging/MetricsLogger;
+Lcom/android/internal/net/LegacyVpnInfo;
+Lcom/android/internal/net/NetworkStatsFactory;
+Lcom/android/internal/net/VpnConfig;
+Lcom/android/internal/net/VpnInfo;
+Lcom/android/internal/net/VpnProfile;
+Lcom/android/internal/os/AndroidPrintStream;
+Lcom/android/internal/os/AppFuseMount;
+Lcom/android/internal/os/AtomicFile;
+Lcom/android/internal/os/BackgroundThread;
+Lcom/android/internal/os/BatterySipper;
+Lcom/android/internal/os/BatterySipper$DrainType;
+Lcom/android/internal/os/BatteryStatsHelper;
+Lcom/android/internal/os/BatteryStatsHelper$1;
+Lcom/android/internal/os/BatteryStatsImpl;
+Lcom/android/internal/os/BatteryStatsImpl$1;
+Lcom/android/internal/os/BatteryStatsImpl$5;
+Lcom/android/internal/os/BatteryStatsImpl$BatchTimer;
+Lcom/android/internal/os/BatteryStatsImpl$BatteryCallback;
+Lcom/android/internal/os/BatteryStatsImpl$Clocks;
+Lcom/android/internal/os/BatteryStatsImpl$ControllerActivityCounterImpl;
+Lcom/android/internal/os/BatteryStatsImpl$Counter;
+Lcom/android/internal/os/BatteryStatsImpl$DurationTimer;
+Lcom/android/internal/os/BatteryStatsImpl$ExternalStatsSync;
+Lcom/android/internal/os/BatteryStatsImpl$LongSamplingCounter;
+Lcom/android/internal/os/BatteryStatsImpl$MyHandler;
+Lcom/android/internal/os/BatteryStatsImpl$OverflowArrayMap;
+Lcom/android/internal/os/BatteryStatsImpl$PlatformIdleStateCallback;
+Lcom/android/internal/os/BatteryStatsImpl$SamplingTimer;
+Lcom/android/internal/os/BatteryStatsImpl$StopwatchTimer;
+Lcom/android/internal/os/BatteryStatsImpl$SystemClocks;
+Lcom/android/internal/os/BatteryStatsImpl$TimeBase;
+Lcom/android/internal/os/BatteryStatsImpl$TimeBaseObs;
+Lcom/android/internal/os/BatteryStatsImpl$Timer;
+Lcom/android/internal/os/BatteryStatsImpl$Uid;
+Lcom/android/internal/os/BatteryStatsImpl$Uid$1;
+Lcom/android/internal/os/BatteryStatsImpl$Uid$2;
+Lcom/android/internal/os/BatteryStatsImpl$Uid$3;
+Lcom/android/internal/os/BatteryStatsImpl$Uid$Pkg;
+Lcom/android/internal/os/BatteryStatsImpl$Uid$Pkg$Serv;
+Lcom/android/internal/os/BatteryStatsImpl$Uid$Proc;
+Lcom/android/internal/os/BatteryStatsImpl$Uid$Sensor;
+Lcom/android/internal/os/BatteryStatsImpl$Uid$Wakelock;
+Lcom/android/internal/os/BinderInternal;
+Lcom/android/internal/os/BinderInternal$GcWatcher;
+Lcom/android/internal/os/BluetoothPowerCalculator;
+Lcom/android/internal/os/CameraPowerCalculator;
+Lcom/android/internal/os/CpuPowerCalculator;
+Lcom/android/internal/os/FlashlightPowerCalculator;
+Lcom/android/internal/os/FuseAppLoop;
+Lcom/android/internal/os/FuseAppLoop$1;
+Lcom/android/internal/os/FuseAppLoop$UnmountedException;
+Lcom/android/internal/os/HandlerCaller;
+Lcom/android/internal/os/HandlerCaller$Callback;
+Lcom/android/internal/os/HandlerCaller$MyHandler;
+Lcom/android/internal/os/IDropBoxManagerService;
+Lcom/android/internal/os/IDropBoxManagerService$Stub;
+Lcom/android/internal/os/IResultReceiver;
+Lcom/android/internal/os/IResultReceiver$Stub;
+Lcom/android/internal/os/IResultReceiver$Stub$Proxy;
+Lcom/android/internal/os/IShellCallback;
+Lcom/android/internal/os/IShellCallback$Stub;
+Lcom/android/internal/os/IShellCallback$Stub$Proxy;
+Lcom/android/internal/os/KernelCpuSpeedReader;
+Lcom/android/internal/os/KernelMemoryBandwidthStats;
+Lcom/android/internal/os/KernelUidCpuTimeReader;
+Lcom/android/internal/os/KernelWakelockReader;
+Lcom/android/internal/os/KernelWakelockStats;
+Lcom/android/internal/os/KernelWakelockStats$Entry;
+Lcom/android/internal/os/LoggingPrintStream;
+Lcom/android/internal/os/LoggingPrintStream$1;
+Lcom/android/internal/os/MemoryPowerCalculator;
+Lcom/android/internal/os/MobileRadioPowerCalculator;
+Lcom/android/internal/os/PathClassLoaderFactory;
+Lcom/android/internal/os/PowerCalculator;
+Lcom/android/internal/os/PowerProfile;
+Lcom/android/internal/os/PowerProfile$CpuClusterKey;
+Lcom/android/internal/os/ProcessCpuTracker;
+Lcom/android/internal/os/ProcessCpuTracker$1;
+Lcom/android/internal/os/ProcessCpuTracker$FilterStats;
+Lcom/android/internal/os/ProcessCpuTracker$Stats;
+Lcom/android/internal/os/RoSystemProperties;
+Lcom/android/internal/os/RuntimeInit;
+Lcom/android/internal/os/RuntimeInit$1;
+Lcom/android/internal/os/RuntimeInit$Arguments;
+Lcom/android/internal/os/RuntimeInit$KillApplicationHandler;
+Lcom/android/internal/os/RuntimeInit$LoggingHandler;
+Lcom/android/internal/os/SamplingProfilerIntegration;
+Lcom/android/internal/os/SensorPowerCalculator;
+Lcom/android/internal/os/SomeArgs;
+Lcom/android/internal/os/TransferPipe;
+Lcom/android/internal/os/WakelockPowerCalculator;
+Lcom/android/internal/os/WifiPowerCalculator;
+Lcom/android/internal/os/Zygote;
+Lcom/android/internal/os/ZygoteConnection;
+Lcom/android/internal/os/ZygoteConnection$Arguments;
+Lcom/android/internal/os/ZygoteInit;
+Lcom/android/internal/os/Zygote$MethodAndArgsCaller;
+Lcom/android/internal/os/ZygoteSecurityException;
+Lcom/android/internal/os/ZygoteServer;
+Lcom/android/internal/policy/DecorContext;
+Lcom/android/internal/policy/DecorView;
+Lcom/android/internal/policy/DecorView$ColorViewState;
+Lcom/android/internal/policy/DividerSnapAlgorithm;
+Lcom/android/internal/policy/DividerSnapAlgorithm$SnapTarget;
+Lcom/android/internal/policy/DockedDividerUtils;
+Lcom/android/internal/policy/IKeyguardDismissCallback;
+Lcom/android/internal/policy/IKeyguardDrawnCallback;
+Lcom/android/internal/policy/IKeyguardDrawnCallback$Stub;
+Lcom/android/internal/policy/IKeyguardExitCallback;
+Lcom/android/internal/policy/IKeyguardService;
+Lcom/android/internal/policy/IKeyguardService$Stub;
+Lcom/android/internal/policy/IKeyguardService$Stub$Proxy;
+Lcom/android/internal/policy/IKeyguardStateCallback;
+Lcom/android/internal/policy/IKeyguardStateCallback$Stub;
+Lcom/android/internal/policy/IShortcutService;
+Lcom/android/internal/policy/IShortcutService$Stub;
+Lcom/android/internal/policy/IShortcutService$Stub$Proxy;
+Lcom/android/internal/policy/PhoneFallbackEventHandler;
+Lcom/android/internal/policy/PhoneLayoutInflater;
+Lcom/android/internal/policy/PhoneWindow;
+Lcom/android/internal/policy/PhoneWindow$1;
+Lcom/android/internal/policy/PhoneWindow$PanelFeatureState;
+Lcom/android/internal/policy/PhoneWindow$PhoneWindowMenuCallback;
+Lcom/android/internal/policy/PhoneWindow$RotationWatcher;
+Lcom/android/internal/policy/PhoneWindow$RotationWatcher$1;
+Lcom/android/internal/policy/PipMotionHelper;
+Lcom/android/internal/policy/PipSnapAlgorithm;
+Lcom/android/internal/R$styleable;
+Lcom/android/internal/statusbar/IStatusBar;
+Lcom/android/internal/statusbar/IStatusBarService;
+Lcom/android/internal/statusbar/IStatusBarService$Stub;
+Lcom/android/internal/statusbar/IStatusBar$Stub;
+Lcom/android/internal/statusbar/IStatusBar$Stub$Proxy;
+Lcom/android/internal/statusbar/NotificationVisibility;
+Lcom/android/internal/statusbar/NotificationVisibility$1;
+Lcom/android/internal/statusbar/StatusBarIcon;
+Lcom/android/internal/telecom/IConnectionService;
+Lcom/android/internal/telecom/IConnectionServiceAdapter;
+Lcom/android/internal/telecom/IConnectionServiceAdapter$Stub;
+Lcom/android/internal/telecom/IConnectionService$Stub;
+Lcom/android/internal/telecom/IConnectionService$Stub$Proxy;
+Lcom/android/internal/telecom/IInCallAdapter;
+Lcom/android/internal/telecom/IInCallAdapter$Stub;
+Lcom/android/internal/telecom/IInCallService;
+Lcom/android/internal/telecom/IInCallService$Stub;
+Lcom/android/internal/telecom/IInCallService$Stub$Proxy;
+Lcom/android/internal/telecom/ITelecomService;
+Lcom/android/internal/telecom/ITelecomService$Stub;
+Lcom/android/internal/telecom/IVideoProvider;
+Lcom/android/internal/telecom/IVideoProvider$Stub;
+Lcom/android/internal/telecom/RemoteServiceCallback;
+Lcom/android/internal/telecom/RemoteServiceCallback$Stub;
+Lcom/android/internal/telecom/RemoteServiceCallback$Stub$Proxy;
+Lcom/android/internal/telephony/CallerInfo;
+Lcom/android/internal/telephony/CallerInfoAsyncQuery;
+Lcom/android/internal/telephony/CallerInfoAsyncQuery$CallerInfoAsyncQueryHandler;
+Lcom/android/internal/telephony/CallerInfoAsyncQuery$CallerInfoAsyncQueryHandler$CallerInfoWorkerHandler;
+Lcom/android/internal/telephony/CallerInfoAsyncQuery$CookieWrapper;
+Lcom/android/internal/telephony/CallerInfoAsyncQuery$OnQueryCompleteListener;
+Lcom/android/internal/telephony/CarrierAppUtils;
+Lcom/android/internal/telephony/DefaultPhoneNotifier;
+Lcom/android/internal/telephony/ICarrierConfigLoader;
+Lcom/android/internal/telephony/ICarrierConfigLoader$Stub;
+Lcom/android/internal/telephony/ICarrierConfigLoader$Stub$Proxy;
+Lcom/android/internal/telephony/IccCardConstants$State;
+Lcom/android/internal/telephony/IMms;
+Lcom/android/internal/telephony/IMms$Stub;
+Lcom/android/internal/telephony/IOnSubscriptionsChangedListener;
+Lcom/android/internal/telephony/IOnSubscriptionsChangedListener$Stub;
+Lcom/android/internal/telephony/IOnSubscriptionsChangedListener$Stub$Proxy;
+Lcom/android/internal/telephony/IPhoneStateListener;
+Lcom/android/internal/telephony/IPhoneStateListener$Stub;
+Lcom/android/internal/telephony/IPhoneStateListener$Stub$Proxy;
+Lcom/android/internal/telephony/IPhoneSubInfo;
+Lcom/android/internal/telephony/IPhoneSubInfo$Stub;
+Lcom/android/internal/telephony/IPhoneSubInfo$Stub$Proxy;
+Lcom/android/internal/telephony/ISub;
+Lcom/android/internal/telephony/ISub$Stub;
+Lcom/android/internal/telephony/ISub$Stub$Proxy;
+Lcom/android/internal/telephony/ITelephony;
+Lcom/android/internal/telephony/ITelephonyRegistry;
+Lcom/android/internal/telephony/ITelephonyRegistry$Stub;
+Lcom/android/internal/telephony/ITelephony$Stub;
+Lcom/android/internal/telephony/ITelephony$Stub$Proxy;
+Lcom/android/internal/telephony/PhoneConstants$DataState;
+Lcom/android/internal/telephony/PhoneConstants$State;
+Lcom/android/internal/telephony/PhoneNotifier;
+Lcom/android/internal/telephony/SmsApplication;
+Lcom/android/internal/textservice/ISpellCheckerService;
+Lcom/android/internal/textservice/ISpellCheckerService$Stub;
+Lcom/android/internal/textservice/ISpellCheckerService$Stub$Proxy;
+Lcom/android/internal/textservice/ISpellCheckerSession;
+Lcom/android/internal/textservice/ISpellCheckerSessionListener;
+Lcom/android/internal/textservice/ISpellCheckerSessionListener$Stub;
+Lcom/android/internal/textservice/ISpellCheckerSessionListener$Stub$Proxy;
+Lcom/android/internal/textservice/ISpellCheckerSession$Stub;
+Lcom/android/internal/textservice/ISpellCheckerSession$Stub$Proxy;
+Lcom/android/internal/textservice/ITextServicesManager;
+Lcom/android/internal/textservice/ITextServicesManager$Stub;
+Lcom/android/internal/textservice/ITextServicesSessionListener;
+Lcom/android/internal/textservice/ITextServicesSessionListener$Stub;
+Lcom/android/internal/textservice/ITextServicesSessionListener$Stub$Proxy;
+Lcom/android/internal/util/ArrayUtils;
+Lcom/android/internal/util/AsyncChannel;
+Lcom/android/internal/util/AsyncChannel$AsyncChannelConnection;
+Lcom/android/internal/util/AsyncChannel$DeathMonitor;
+Lcom/android/internal/util/AsyncChannel$SyncMessenger;
+Lcom/android/internal/util/AsyncChannel$SyncMessenger$SyncHandler;
+Lcom/android/internal/util/ConcurrentUtils;
+Lcom/android/internal/util/ConcurrentUtils$1;
+Lcom/android/internal/util/ConcurrentUtils$1$1;
+Lcom/android/internal/util/DumpUtils$Dump;
+Lcom/android/internal/util/FastPrintWriter;
+Lcom/android/internal/util/FastPrintWriter$DummyWriter;
+Lcom/android/internal/util/FastXmlSerializer;
+Lcom/android/internal/util/FileRotator;
+Lcom/android/internal/util/FileRotator$FileInfo;
+Lcom/android/internal/util/FileRotator$Reader;
+Lcom/android/internal/util/FileRotator$Rewriter;
+Lcom/android/internal/util/FileRotator$Writer;
+Lcom/android/internal/util/GrowingArrayUtils;
+Lcom/android/internal/util/HexDump;
+Lcom/android/internal/util/IndentingPrintWriter;
+Lcom/android/internal/util/IState;
+Lcom/android/internal/util/JournaledFile;
+Lcom/android/internal/util/LineBreakBufferedWriter;
+Lcom/android/internal/util/LocalLog;
+Lcom/android/internal/util/MemInfoReader;
+Lcom/android/internal/util/MessageUtils;
+Lcom/android/internal/util/Preconditions;
+Lcom/android/internal/util/ProcFileReader;
+Lcom/android/internal/util/ProgressReporter;
+Lcom/android/internal/util/RingBufferIndices;
+Lcom/android/internal/util/ScreenShapeHelper;
+Lcom/android/internal/util/State;
+Lcom/android/internal/util/StateMachine;
+Lcom/android/internal/util/StateMachine$LogRec;
+Lcom/android/internal/util/StateMachine$LogRecords;
+Lcom/android/internal/util/StateMachine$SmHandler;
+Lcom/android/internal/util/StateMachine$SmHandler$HaltingState;
+Lcom/android/internal/util/StateMachine$SmHandler$QuittingState;
+Lcom/android/internal/util/StateMachine$SmHandler$StateInfo;
+Lcom/android/internal/util/ToBooleanFunction;
+Lcom/android/internal/util/TokenBucket;
+Lcom/android/internal/util/VirtualRefBasePtr;
+Lcom/android/internal/util/WakeupMessage;
+Lcom/android/internal/util/XmlUtils;
+Lcom/android/internal/util/XmlUtils$ReadMapCallback;
+Lcom/android/internal/util/XmlUtils$WriteMapCallback;
+Lcom/android/internal/view/animation/NativeInterpolatorFactory;
+Lcom/android/internal/view/animation/NativeInterpolatorFactoryHelper;
+Lcom/android/internal/view/BaseIWindow;
+Lcom/android/internal/view/IInputConnectionWrapper;
+Lcom/android/internal/view/IInputConnectionWrapper$MyHandler;
+Lcom/android/internal/view/IInputContext;
+Lcom/android/internal/view/IInputContext$Stub;
+Lcom/android/internal/view/IInputContext$Stub$Proxy;
+Lcom/android/internal/view/IInputMethod;
+Lcom/android/internal/view/IInputMethodClient;
+Lcom/android/internal/view/IInputMethodClient$Stub;
+Lcom/android/internal/view/IInputMethodClient$Stub$Proxy;
+Lcom/android/internal/view/IInputMethodManager;
+Lcom/android/internal/view/IInputMethodManager$Stub;
+Lcom/android/internal/view/IInputMethodSession;
+Lcom/android/internal/view/IInputMethodSession$Stub;
+Lcom/android/internal/view/IInputMethodSession$Stub$Proxy;
+Lcom/android/internal/view/IInputMethod$Stub;
+Lcom/android/internal/view/IInputMethod$Stub$Proxy;
+Lcom/android/internal/view/IInputSessionCallback;
+Lcom/android/internal/view/IInputSessionCallback$Stub;
+Lcom/android/internal/view/InputBindResult;
+Lcom/android/internal/view/InputBindResult$1;
+Lcom/android/internal/view/menu/ActionMenuItem;
+Lcom/android/internal/view/menu/MenuBuilder$Callback;
+Lcom/android/internal/view/menu/MenuPresenter$Callback;
+Lcom/android/internal/view/RootViewSurfaceTaker;
+Lcom/android/internal/view/WindowManagerPolicyThread;
+Lcom/android/internal/widget/AbsActionBarView;
+Lcom/android/internal/widget/AbsActionBarView$VisibilityAnimListener;
+Lcom/android/internal/widget/ActionBarContainer;
+Lcom/android/internal/widget/ActionBarContainer$ActionBarBackgroundDrawable;
+Lcom/android/internal/widget/ActionBarContextView;
+Lcom/android/internal/widget/ActionBarOverlayLayout;
+Lcom/android/internal/widget/ActionBarOverlayLayout$1;
+Lcom/android/internal/widget/ActionBarOverlayLayout$2;
+Lcom/android/internal/widget/ActionBarOverlayLayout$3;
+Lcom/android/internal/widget/ActionBarOverlayLayout$4;
+Lcom/android/internal/widget/ActionBarOverlayLayout$5;
+Lcom/android/internal/widget/ActionBarOverlayLayout$LayoutParams;
+Lcom/android/internal/widget/BackgroundFallback;
+Lcom/android/internal/widget/DecorContentParent;
+Lcom/android/internal/widget/DecorToolbar;
+Lcom/android/internal/widget/ICheckCredentialProgressCallback;
+Lcom/android/internal/widget/ILockSettings;
+Lcom/android/internal/widget/ILockSettings$Stub;
+Lcom/android/internal/widget/LockPatternUtils;
+Lcom/android/internal/widget/LockPatternUtils$StrongAuthTracker;
+Lcom/android/internal/widget/LockPatternUtils$StrongAuthTracker$1;
+Lcom/android/internal/widget/LockPatternUtils$StrongAuthTracker$H;
+Lcom/android/internal/widget/ToolbarWidgetWrapper;
+Lcom/android/internal/widget/ToolbarWidgetWrapper$1;
+Lcom/android/internal/widget/VerifyCredentialResponse;
+Lcom/android/location/fused/FusedLocationProvider;
+Lcom/android/location/fused/FusedLocationProvider$1;
+Lcom/android/location/fused/FusedLocationProvider$2;
+Lcom/android/location/fused/FusedLocationService;
+Lcom/android/location/fused/FusionEngine;
+Lcom/android/location/fused/FusionEngine$Callback;
+Lcom/android/location/fused/FusionEngine$ProviderStats;
+Lcom/android/location/provider/LocationProviderBase;
+Lcom/android/location/provider/LocationProviderBase$Service;
+Lcom/android/location/provider/ProviderPropertiesUnbundled;
+Lcom/android/okhttp/Address;
+Lcom/android/okhttp/Authenticator;
+Lcom/android/okhttp/CacheControl;
+Lcom/android/okhttp/CacheControl$Builder;
+Lcom/android/okhttp/CertificatePinner;
+Lcom/android/okhttp/CertificatePinner$Builder;
+Lcom/android/okhttp/CipherSuite;
+Lcom/android/okhttp/ConfigAwareConnectionPool;
+Lcom/android/okhttp/Connection;
+Lcom/android/okhttp/ConnectionPool;
+Lcom/android/okhttp/ConnectionPool$1;
+Lcom/android/okhttp/ConnectionSpec;
+Lcom/android/okhttp/ConnectionSpec$Builder;
+Lcom/android/okhttp/Dispatcher;
+Lcom/android/okhttp/Dns;
+Lcom/android/okhttp/Handshake;
+Lcom/android/okhttp/Headers;
+Lcom/android/okhttp/Headers$Builder;
+Lcom/android/okhttp/HttpHandler;
+Lcom/android/okhttp/HttpHandler$CleartextURLFilter;
+Lcom/android/okhttp/HttpsHandler;
+Lcom/android/okhttp/HttpUrl;
+Lcom/android/okhttp/HttpUrl$Builder;
+Lcom/android/okhttp/HttpUrl$Builder$ParseResult;
+Lcom/android/okhttp/internal/ConnectionSpecSelector;
+Lcom/android/okhttp/internal/http/AuthenticatorAdapter;
+Lcom/android/okhttp/internal/http/CacheStrategy;
+Lcom/android/okhttp/internal/http/CacheStrategy$Factory;
+Lcom/android/okhttp/internal/http/Http1xStream;
+Lcom/android/okhttp/internal/http/Http1xStream$AbstractSource;
+Lcom/android/okhttp/internal/http/Http1xStream$FixedLengthSource;
+Lcom/android/okhttp/internal/http/HttpEngine;
+Lcom/android/okhttp/internal/http/HttpEngine$1;
+Lcom/android/okhttp/internal/http/HttpMethod;
+Lcom/android/okhttp/internal/http/HttpStream;
+Lcom/android/okhttp/internal/http/OkHeaders;
+Lcom/android/okhttp/internal/http/OkHeaders$1;
+Lcom/android/okhttp/internal/http/RealResponseBody;
+Lcom/android/okhttp/internal/http/RequestException;
+Lcom/android/okhttp/internal/http/RequestLine;
+Lcom/android/okhttp/internal/http/RetryableSink;
+Lcom/android/okhttp/internal/http/RouteException;
+Lcom/android/okhttp/internal/http/RouteSelector;
+Lcom/android/okhttp/internal/http/StatusLine;
+Lcom/android/okhttp/internal/http/StreamAllocation;
+Lcom/android/okhttp/internal/huc/DelegatingHttpsURLConnection;
+Lcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;
+Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+Lcom/android/okhttp/internal/Internal;
+Lcom/android/okhttp/internal/io/RealConnection;
+Lcom/android/okhttp/internal/OptionalMethod;
+Lcom/android/okhttp/internal/Platform;
+Lcom/android/okhttp/internal/RouteDatabase;
+Lcom/android/okhttp/internal/tls/OkHostnameVerifier;
+Lcom/android/okhttp/internal/URLFilter;
+Lcom/android/okhttp/internal/Util;
+Lcom/android/okhttp/internal/Util$1;
+Lcom/android/okhttp/OkHttpClient;
+Lcom/android/okhttp/OkHttpClient$1;
+Lcom/android/okhttp/okio/AsyncTimeout;
+Lcom/android/okhttp/okio/AsyncTimeout$1;
+Lcom/android/okhttp/okio/AsyncTimeout$2;
+Lcom/android/okhttp/okio/AsyncTimeout$Watchdog;
+Lcom/android/okhttp/okio/Buffer;
+Lcom/android/okhttp/okio/BufferedSink;
+Lcom/android/okhttp/okio/BufferedSource;
+Lcom/android/okhttp/okio/ForwardingTimeout;
+Lcom/android/okhttp/okio/Okio;
+Lcom/android/okhttp/okio/Okio$1;
+Lcom/android/okhttp/okio/Okio$2;
+Lcom/android/okhttp/okio/Okio$3;
+Lcom/android/okhttp/okio/RealBufferedSink;
+Lcom/android/okhttp/okio/RealBufferedSource;
+Lcom/android/okhttp/okio/Segment;
+Lcom/android/okhttp/okio/SegmentPool;
+Lcom/android/okhttp/okio/Sink;
+Lcom/android/okhttp/okio/Source;
+Lcom/android/okhttp/okio/Timeout;
+Lcom/android/okhttp/okio/Timeout$1;
+Lcom/android/okhttp/okio/Util;
+Lcom/android/okhttp/OkUrlFactory;
+Lcom/android/okhttp/Protocol;
+Lcom/android/okhttp/Request;
+Lcom/android/okhttp/RequestBody;
+Lcom/android/okhttp/RequestBody$2;
+Lcom/android/okhttp/Request$Builder;
+Lcom/android/okhttp/Response;
+Lcom/android/okhttp/ResponseBody;
+Lcom/android/okhttp/Response$Builder;
+Lcom/android/okhttp/Route;
+Lcom/android/okhttp/TlsVersion;
+Lcom/android/org/bouncycastle/asn1/ASN1Encodable;
+Lcom/android/org/bouncycastle/asn1/ASN1Object;
+Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;
+Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier$OidHandle;
+Lcom/android/org/bouncycastle/asn1/ASN1Primitive;
+Lcom/android/org/bouncycastle/asn1/bc/BCObjectIdentifiers;
+Lcom/android/org/bouncycastle/asn1/iana/IANAObjectIdentifiers;
+Lcom/android/org/bouncycastle/asn1/misc/MiscObjectIdentifiers;
+Lcom/android/org/bouncycastle/asn1/nist/NISTObjectIdentifiers;
+Lcom/android/org/bouncycastle/asn1/OIDTokenizer;
+Lcom/android/org/bouncycastle/asn1/oiw/OIWObjectIdentifiers;
+Lcom/android/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers;
+Lcom/android/org/bouncycastle/asn1/x509/X509ObjectIdentifiers;
+Lcom/android/org/bouncycastle/asn1/x9/X9ObjectIdentifiers;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyFactorySpi;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/DH$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSAUtil;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/dsa/KeyFactorySpi;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/DSA$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyFactorySpi;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyFactorySpi$EC;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/EC$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/rsa/KeyFactorySpi;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/RSA$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/util/BaseKeyFactorySpi;
+Lcom/android/org/bouncycastle/jcajce/provider/asymmetric/X509$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/config/ConfigurableProvider;
+Lcom/android/org/bouncycastle/jcajce/provider/config/ProviderConfiguration;
+Lcom/android/org/bouncycastle/jcajce/provider/config/ProviderConfigurationPermission;
+Lcom/android/org/bouncycastle/jcajce/provider/digest/DigestAlgorithmProvider;
+Lcom/android/org/bouncycastle/jcajce/provider/digest/MD5;
+Lcom/android/org/bouncycastle/jcajce/provider/digest/MD5$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/digest/SHA1;
+Lcom/android/org/bouncycastle/jcajce/provider/digest/SHA1$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/digest/SHA224;
+Lcom/android/org/bouncycastle/jcajce/provider/digest/SHA224$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/digest/SHA256;
+Lcom/android/org/bouncycastle/jcajce/provider/digest/SHA256$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/digest/SHA384;
+Lcom/android/org/bouncycastle/jcajce/provider/digest/SHA384$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/digest/SHA512;
+Lcom/android/org/bouncycastle/jcajce/provider/digest/SHA512$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi;
+Lcom/android/org/bouncycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi$Std;
+Lcom/android/org/bouncycastle/jcajce/provider/keystore/BC$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/keystore/PKCS12$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/AES;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/AES$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/ARC4;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/ARC4$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/Blowfish;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/Blowfish$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/DES;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/DESede;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/DESede$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/DES$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/PBEPBKDF2;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/PBEPBKDF2$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/PBEPKCS12;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/PBEPKCS12$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/PBES2AlgorithmParameters;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/PBES2AlgorithmParameters$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/RC2;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/RC2$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/SymmetricAlgorithmProvider;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/Twofish;
+Lcom/android/org/bouncycastle/jcajce/provider/symmetric/Twofish$Mappings;
+Lcom/android/org/bouncycastle/jcajce/provider/util/AlgorithmProvider;
+Lcom/android/org/bouncycastle/jcajce/provider/util/AsymmetricAlgorithmProvider;
+Lcom/android/org/bouncycastle/jcajce/provider/util/AsymmetricKeyInfoConverter;
+Lcom/android/org/bouncycastle/jcajce/util/BCJcaJceHelper;
+Lcom/android/org/bouncycastle/jcajce/util/JcaJceHelper;
+Lcom/android/org/bouncycastle/jcajce/util/ProviderJcaJceHelper;
+Lcom/android/org/bouncycastle/jce/interfaces/BCKeyStore;
+Lcom/android/org/bouncycastle/jce/provider/BouncyCastleProvider;
+Lcom/android/org/bouncycastle/jce/provider/BouncyCastleProvider$1;
+Lcom/android/org/bouncycastle/jce/provider/BouncyCastleProviderConfiguration;
+Lcom/android/org/bouncycastle/util/Arrays;
+Lcom/android/org/bouncycastle/util/Encodable;
+Lcom/android/org/bouncycastle/util/Strings;
+Lcom/android/org/bouncycastle/util/Strings$1;
+Lcom/android/org/conscrypt/AbstractOpenSSLSession;
+Lcom/android/org/conscrypt/AbstractSessionContext;
+Lcom/android/org/conscrypt/AbstractSessionContext$1;
+Lcom/android/org/conscrypt/AddressUtils;
+Lcom/android/org/conscrypt/ByteArray;
+Lcom/android/org/conscrypt/CertBlacklist;
+Lcom/android/org/conscrypt/CertificatePriorityComparator;
+Lcom/android/org/conscrypt/ChainStrengthAnalyzer;
+Lcom/android/org/conscrypt/ClientSessionContext;
+Lcom/android/org/conscrypt/ClientSessionContext$HostAndPort;
+Lcom/android/org/conscrypt/CryptoUpcalls;
+Lcom/android/org/conscrypt/ct/CTLogInfo;
+Lcom/android/org/conscrypt/ct/CTLogStore;
+Lcom/android/org/conscrypt/ct/CTLogStoreImpl;
+Lcom/android/org/conscrypt/ct/CTLogStoreImpl$InvalidLogFileException;
+Lcom/android/org/conscrypt/ct/CTPolicy;
+Lcom/android/org/conscrypt/ct/CTPolicyImpl;
+Lcom/android/org/conscrypt/ct/CTVerifier;
+Lcom/android/org/conscrypt/ct/KnownLogs;
+Lcom/android/org/conscrypt/ct/SerializationException;
+Lcom/android/org/conscrypt/EvpMdRef$MD5;
+Lcom/android/org/conscrypt/EvpMdRef$SHA1;
+Lcom/android/org/conscrypt/EvpMdRef$SHA256;
+Lcom/android/org/conscrypt/Hex;
+Lcom/android/org/conscrypt/JSSEProvider;
+Lcom/android/org/conscrypt/KeyManagerFactoryImpl;
+Lcom/android/org/conscrypt/KeyManagerImpl;
+Lcom/android/org/conscrypt/NativeCrypto;
+Lcom/android/org/conscrypt/NativeCryptoJni;
+Lcom/android/org/conscrypt/NativeCrypto$SSLHandshakeCallbacks;
+Lcom/android/org/conscrypt/NativeRef;
+Lcom/android/org/conscrypt/NativeRef$EC_GROUP;
+Lcom/android/org/conscrypt/NativeRef$EVP_MD_CTX;
+Lcom/android/org/conscrypt/NativeRef$EVP_PKEY;
+Lcom/android/org/conscrypt/OpenSSLBIOInputStream;
+Lcom/android/org/conscrypt/OpenSSLContextImpl;
+Lcom/android/org/conscrypt/OpenSSLContextImpl$TLSv12;
+Lcom/android/org/conscrypt/OpenSSLECGroupContext;
+Lcom/android/org/conscrypt/OpenSSLECPublicKey;
+Lcom/android/org/conscrypt/OpenSSLExtendedSessionImpl;
+Lcom/android/org/conscrypt/OpenSSLKey;
+Lcom/android/org/conscrypt/OpenSSLKeyHolder;
+Lcom/android/org/conscrypt/OpenSSLMessageDigestJDK;
+Lcom/android/org/conscrypt/OpenSSLMessageDigestJDK$MD5;
+Lcom/android/org/conscrypt/OpenSSLMessageDigestJDK$SHA1;
+Lcom/android/org/conscrypt/OpenSSLMessageDigestJDK$SHA256;
+Lcom/android/org/conscrypt/OpenSSLProvider;
+Lcom/android/org/conscrypt/OpenSSLRandom;
+Lcom/android/org/conscrypt/OpenSSLRSAKeyFactory;
+Lcom/android/org/conscrypt/OpenSSLRSAPublicKey;
+Lcom/android/org/conscrypt/OpenSSLSessionImpl;
+Lcom/android/org/conscrypt/OpenSSLSignature;
+Lcom/android/org/conscrypt/OpenSSLSignature$EngineType;
+Lcom/android/org/conscrypt/OpenSSLSignature$RSAPKCS1Padding;
+Lcom/android/org/conscrypt/OpenSSLSignature$SHA256RSA;
+Lcom/android/org/conscrypt/OpenSSLSocketFactoryImpl;
+Lcom/android/org/conscrypt/OpenSSLSocketImpl;
+Lcom/android/org/conscrypt/OpenSSLSocketImpl$SSLInputStream;
+Lcom/android/org/conscrypt/OpenSSLSocketImpl$SSLOutputStream;
+Lcom/android/org/conscrypt/OpenSSLSocketImplWrapper;
+Lcom/android/org/conscrypt/OpenSSLX509Certificate;
+Lcom/android/org/conscrypt/OpenSSLX509CertificateFactory;
+Lcom/android/org/conscrypt/OpenSSLX509CertificateFactory$1;
+Lcom/android/org/conscrypt/OpenSSLX509CertificateFactory$2;
+Lcom/android/org/conscrypt/OpenSSLX509CertificateFactory$Parser;
+Lcom/android/org/conscrypt/OpenSSLX509CertificateFactory$ParsingException;
+Lcom/android/org/conscrypt/OpenSSLX509CertPath;
+Lcom/android/org/conscrypt/OpenSSLX509CertPath$Encoding;
+Lcom/android/org/conscrypt/Platform;
+Lcom/android/org/conscrypt/Platform$NoPreloadHolder;
+Lcom/android/org/conscrypt/ServerSessionContext;
+Lcom/android/org/conscrypt/SSLParametersImpl;
+Lcom/android/org/conscrypt/SSLParametersImpl$AliasChooser;
+Lcom/android/org/conscrypt/SSLParametersImpl$PSKCallbacks;
+Lcom/android/org/conscrypt/TrustedCertificateIndex;
+Lcom/android/org/conscrypt/TrustedCertificateKeyStoreSpi;
+Lcom/android/org/conscrypt/TrustedCertificateStore;
+Lcom/android/org/conscrypt/TrustedCertificateStore$1;
+Lcom/android/org/conscrypt/TrustedCertificateStore$2;
+Lcom/android/org/conscrypt/TrustedCertificateStore$4;
+Lcom/android/org/conscrypt/TrustedCertificateStore$5;
+Lcom/android/org/conscrypt/TrustedCertificateStore$CertSelector;
+Lcom/android/org/conscrypt/TrustManagerFactoryImpl;
+Lcom/android/org/conscrypt/TrustManagerImpl;
+Lcom/android/org/conscrypt/TrustManagerImpl$ExtendedKeyUsagePKIXCertPathChecker;
+Lcom/android/org/conscrypt/TrustManagerImpl$TrustAnchorComparator;
+Lcom/android/org/conscrypt/util/ArrayUtils;
+Lcom/android/providers/settings/GenerationRegistry;
+Lcom/android/providers/settings/SettingsProvider;
+Lcom/android/providers/settings/SettingsProvider$1;
+Lcom/android/providers/settings/SettingsProvider$2;
+Lcom/android/providers/settings/SettingsProvider$SettingsRegistry;
+Lcom/android/providers/settings/SettingsProvider$SettingsRegistry$MyHandler;
+Lcom/android/providers/settings/SettingsProvider$SettingsRegistry$UpgradeController;
+Lcom/android/providers/settings/SettingsService;
+Lcom/android/providers/settings/SettingsService$MyShellCommand;
+Lcom/android/providers/settings/SettingsService$MyShellCommand$CommandVerb;
+Lcom/android/providers/settings/SettingsState;
+Lcom/android/providers/settings/SettingsState$1;
+Lcom/android/providers/settings/SettingsState$HistoricalOperation;
+Lcom/android/providers/settings/SettingsState$MyHandler;
+Lcom/android/providers/settings/SettingsState$Setting;
+Lcom/android/server/accessibility/AccessibilityManagerService;
+Lcom/android/server/accessibility/AccessibilityManagerService$1;
+Lcom/android/server/accessibility/AccessibilityManagerService$2;
+Lcom/android/server/accessibility/AccessibilityManagerService$AccessibilityContentObserver;
+Lcom/android/server/accessibility/AccessibilityManagerService$MainHandler;
+Lcom/android/server/accessibility/AccessibilityManagerService$SecurityPolicy;
+Lcom/android/server/accessibility/AccessibilityManagerService$Service;
+Lcom/android/server/accessibility/AccessibilityManagerService$UserState;
+Lcom/android/server/accessibility/AccessibilityManagerService$UserState$1;
+Lcom/android/server/accessibility/DisplayAdjustmentUtils;
+Lcom/android/server/accessibility/FingerprintGestureDispatcher$FingerprintGestureClient;
+Lcom/android/server/accessibility/KeyEventDispatcher$KeyEventFilter;
+Lcom/android/server/accounts/AccountAuthenticatorCache;
+Lcom/android/server/accounts/AccountAuthenticatorCache$MySerializer;
+Lcom/android/server/accounts/AccountManagerService;
+Lcom/android/server/accounts/AccountManagerService$1;
+Lcom/android/server/accounts/AccountManagerService$2;
+Lcom/android/server/accounts/AccountManagerService$3;
+Lcom/android/server/accounts/AccountManagerService$4;
+Lcom/android/server/accounts/AccountManagerService$8;
+Lcom/android/server/accounts/AccountManagerService$AccountManagerInternalImpl;
+Lcom/android/server/accounts/AccountManagerService$GetAccountsByTypeAndFeatureSession;
+Lcom/android/server/accounts/AccountManagerService$Injector;
+Lcom/android/server/accounts/AccountManagerService$Lifecycle;
+Lcom/android/server/accounts/AccountManagerService$MessageHandler;
+Lcom/android/server/accounts/AccountManagerService$Session;
+Lcom/android/server/accounts/AccountManagerService$TestFeaturesSession;
+Lcom/android/server/accounts/AccountManagerService$UserAccounts;
+Lcom/android/server/accounts/AccountsDb;
+Lcom/android/server/accounts/AccountsDb$CeDatabaseHelper;
+Lcom/android/server/accounts/AccountsDb$DeDatabaseHelper;
+Lcom/android/server/accounts/IAccountAuthenticatorCache;
+Lcom/android/server/accounts/TokenCache;
+Lcom/android/server/accounts/TokenCache$Key;
+Lcom/android/server/accounts/TokenCache$TokenLruCache;
+Lcom/android/server/accounts/TokenCache$TokenLruCache$Evictor;
+Lcom/android/server/accounts/TokenCache$Value;
+Lcom/android/server/AlarmManagerService;
+Lcom/android/server/AlarmManagerService$1;
+Lcom/android/server/AlarmManagerService$2;
+Lcom/android/server/AlarmManagerService$Alarm;
+Lcom/android/server/AlarmManagerService$AlarmHandler;
+Lcom/android/server/AlarmManagerService$AlarmThread;
+Lcom/android/server/AlarmManagerService$Batch;
+Lcom/android/server/AlarmManagerService$BatchTimeOrder;
+Lcom/android/server/AlarmManagerService$BroadcastStats;
+Lcom/android/server/AlarmManagerService$ClockReceiver;
+Lcom/android/server/AlarmManagerService$Constants;
+Lcom/android/server/AlarmManagerService$DeliveryTracker;
+Lcom/android/server/AlarmManagerService$FilterStats;
+Lcom/android/server/AlarmManagerService$IncreasingTimeOrder;
+Lcom/android/server/AlarmManagerService$InFlight;
+Lcom/android/server/AlarmManagerService$InteractiveStateReceiver;
+Lcom/android/server/AlarmManagerService$LocalService;
+Lcom/android/server/AlarmManagerService$PriorityClass;
+Lcom/android/server/AlarmManagerService$UidObserver;
+Lcom/android/server/AlarmManagerService$UninstallReceiver;
+Lcom/android/server/am/ActiveServices;
+Lcom/android/server/am/ActiveServices$1;
+Lcom/android/server/am/ActiveServices$ServiceLookupResult;
+Lcom/android/server/am/ActiveServices$ServiceMap;
+Lcom/android/server/am/ActiveServices$ServiceRestarter;
+Lcom/android/server/am/ActivityManagerConstants;
+Lcom/android/server/am/ActivityManagerDebugConfig;
+Lcom/android/server/am/ActivityManagerService;
+Lcom/android/server/am/ActivityManagerService$1;
+Lcom/android/server/am/ActivityManagerService$10;
+Lcom/android/server/am/ActivityManagerService$11;
+Lcom/android/server/am/ActivityManagerService$12;
+Lcom/android/server/am/ActivityManagerService$13;
+Lcom/android/server/am/ActivityManagerService$2;
+Lcom/android/server/am/ActivityManagerService$20;
+Lcom/android/server/am/ActivityManagerService$21;
+Lcom/android/server/am/ActivityManagerService$22;
+Lcom/android/server/am/ActivityManagerService$24;
+Lcom/android/server/am/ActivityManagerService$3;
+Lcom/android/server/am/ActivityManagerService$30;
+Lcom/android/server/am/ActivityManagerService$4;
+Lcom/android/server/am/ActivityManagerService$5;
+Lcom/android/server/am/ActivityManagerService$6;
+Lcom/android/server/am/ActivityManagerService$AppDeathRecipient;
+Lcom/android/server/am/ActivityManagerService$AppTaskImpl;
+Lcom/android/server/am/ActivityManagerService$CpuBinder;
+Lcom/android/server/am/ActivityManagerService$DbBinder;
+Lcom/android/server/am/ActivityManagerService$FontScaleSettingObserver;
+Lcom/android/server/am/ActivityManagerService$ForegroundToken;
+Lcom/android/server/am/ActivityManagerService$GrantUri;
+Lcom/android/server/am/ActivityManagerService$GraphicsBinder;
+Lcom/android/server/am/ActivityManagerService$Identity;
+Lcom/android/server/am/ActivityManagerService$IntentFirewallInterface;
+Lcom/android/server/am/ActivityManagerService$KillHandler;
+Lcom/android/server/am/ActivityManagerService$Lifecycle;
+Lcom/android/server/am/ActivityManagerService$LocalService;
+Lcom/android/server/am/ActivityManagerService$MainHandler;
+Lcom/android/server/am/ActivityManagerService$MemBinder;
+Lcom/android/server/am/ActivityManagerService$PendingAssistExtras;
+Lcom/android/server/am/ActivityManagerService$PermissionController;
+Lcom/android/server/am/ActivityManagerService$PriorityState;
+Lcom/android/server/am/ActivityManagerService$ProcessChangeItem;
+Lcom/android/server/am/ActivityManagerService$ProcessInfoService;
+Lcom/android/server/am/ActivityManagerService$SleepTokenImpl;
+Lcom/android/server/am/ActivityManagerService$UidObserverRegistration;
+Lcom/android/server/am/ActivityManagerService$UiHandler;
+Lcom/android/server/am/ActivityManagerService$UpdateConfigurationResult;
+Lcom/android/server/am/ActivityMetricsLogger;
+Lcom/android/server/am/ActivityRecord;
+Lcom/android/server/am/ActivityRecord$Token;
+Lcom/android/server/am/ActivityResult;
+Lcom/android/server/am/ActivityStack;
+Lcom/android/server/am/ActivityStack$ActivityStackHandler;
+Lcom/android/server/am/ActivityStack$ActivityState;
+Lcom/android/server/am/ActivityStackSupervisor;
+Lcom/android/server/am/ActivityStackSupervisor$ActivityContainer;
+Lcom/android/server/am/ActivityStackSupervisor$ActivityDisplay;
+Lcom/android/server/am/ActivityStackSupervisor$ActivityStackSupervisorHandler;
+Lcom/android/server/am/ActivityStackSupervisor$FindTaskResult;
+Lcom/android/server/am/ActivityStarter;
+Lcom/android/server/am/ActivityStartInterceptor;
+Lcom/android/server/am/AppBindRecord;
+Lcom/android/server/am/AppErrors;
+Lcom/android/server/am/BatteryStatsService;
+Lcom/android/server/am/BatteryStatsService$1;
+Lcom/android/server/am/BatteryStatsService$BatteryStatsHandler;
+Lcom/android/server/am/BatteryStatsService$WakeupReasonThread;
+Lcom/android/server/am/BroadcastFilter;
+Lcom/android/server/am/BroadcastQueue;
+Lcom/android/server/am/BroadcastQueue$AppNotResponding;
+Lcom/android/server/am/BroadcastQueue$BroadcastHandler;
+Lcom/android/server/am/BroadcastRecord;
+Lcom/android/server/am/BroadcastStats;
+Lcom/android/server/am/BroadcastStats$1;
+Lcom/android/server/am/BroadcastStats$ActionEntry;
+Lcom/android/server/am/BroadcastStats$PackageEntry;
+Lcom/android/server/am/CompatModePackages;
+Lcom/android/server/am/CompatModePackages$CompatHandler;
+Lcom/android/server/am/ConfigurationContainer;
+Lcom/android/server/am/ConnectionRecord;
+Lcom/android/server/am/ContentProviderConnection;
+Lcom/android/server/am/ContentProviderRecord;
+Lcom/android/server/am/CoreSettingsObserver;
+Lcom/android/server/am/DumpHeapProvider;
+Lcom/android/server/am/EventLogTags;
+Lcom/android/server/am/InstrumentationReporter;
+Lcom/android/server/am/IntentBindRecord;
+Lcom/android/server/am/KeyguardController;
+Lcom/android/server/am/NativeCrashListener;
+Lcom/android/server/am/PendingIntentRecord;
+Lcom/android/server/am/PendingIntentRecord$Key;
+Lcom/android/server/am/ProcessList;
+Lcom/android/server/am/ProcessRecord;
+Lcom/android/server/am/ProcessStatsService;
+Lcom/android/server/am/ProcessStatsService$1;
+Lcom/android/server/am/ProcessStatsService$2;
+Lcom/android/server/am/ProcessStatsService$3;
+Lcom/android/server/am/ProviderMap;
+Lcom/android/server/am/ReceiverList;
+Lcom/android/server/am/RecentTasks;
+Lcom/android/server/am/RecentTasks$1;
+Lcom/android/server/am/ServiceRecord;
+Lcom/android/server/am/ServiceRecord$1;
+Lcom/android/server/am/ServiceRecord$2;
+Lcom/android/server/am/ServiceRecord$3;
+Lcom/android/server/am/ServiceRecord$StartItem;
+Lcom/android/server/am/TaskChangeNotificationController;
+Lcom/android/server/am/TaskChangeNotificationController$MainHandler;
+Lcom/android/server/am/TaskChangeNotificationController$TaskStackConsumer;
+Lcom/android/server/am/TaskPersister;
+Lcom/android/server/am/TaskPersister$1;
+Lcom/android/server/am/TaskPersister$ImageWriteQueueItem;
+Lcom/android/server/am/TaskPersister$LazyTaskWriterThread;
+Lcom/android/server/am/TaskPersister$TaskWriteQueueItem;
+Lcom/android/server/am/TaskPersister$WriteQueueItem;
+Lcom/android/server/am/TaskRecord;
+Lcom/android/server/am/UidRecord;
+Lcom/android/server/am/UidRecord$ChangeItem;
+Lcom/android/server/am/UriPermission;
+Lcom/android/server/am/UriPermissionOwner;
+Lcom/android/server/am/UriPermissionOwner$ExternalToken;
+Lcom/android/server/am/UserController;
+Lcom/android/server/am/UserController$Injector;
+Lcom/android/server/am/UserState;
+Lcom/android/server/AnyMotionDetector;
+Lcom/android/server/AnyMotionDetector$1;
+Lcom/android/server/AnyMotionDetector$2;
+Lcom/android/server/AnyMotionDetector$3;
+Lcom/android/server/AnyMotionDetector$4;
+Lcom/android/server/AnyMotionDetector$DeviceIdleCallback;
+Lcom/android/server/AnyMotionDetector$RunningSignalStats;
+Lcom/android/server/AnyMotionDetector$Vector3;
+Lcom/android/server/AppOpsService;
+Lcom/android/server/AppOpsService$1;
+Lcom/android/server/AppOpsService$1$1;
+Lcom/android/server/AppOpsService$2;
+Lcom/android/server/AppOpsService$3;
+Lcom/android/server/AppOpsService$Callback;
+Lcom/android/server/AppOpsService$ClientRestrictionState;
+Lcom/android/server/AppOpsService$ClientState;
+Lcom/android/server/AppOpsService$Op;
+Lcom/android/server/AppOpsService$Ops;
+Lcom/android/server/AppOpsService$Restriction;
+Lcom/android/server/AppOpsService$UidState;
+Lcom/android/server/appwidget/AppWidgetService;
+Lcom/android/server/appwidget/AppWidgetServiceImpl;
+Lcom/android/server/appwidget/AppWidgetServiceImpl$1;
+Lcom/android/server/appwidget/AppWidgetServiceImpl$BackupRestoreController;
+Lcom/android/server/appwidget/AppWidgetServiceImpl$CallbackHandler;
+Lcom/android/server/appwidget/AppWidgetServiceImpl$Host;
+Lcom/android/server/appwidget/AppWidgetServiceImpl$HostId;
+Lcom/android/server/appwidget/AppWidgetServiceImpl$LoadedWidgetState;
+Lcom/android/server/appwidget/AppWidgetServiceImpl$Provider;
+Lcom/android/server/appwidget/AppWidgetServiceImpl$ProviderId;
+Lcom/android/server/appwidget/AppWidgetServiceImpl$SaveStateRunnable;
+Lcom/android/server/appwidget/AppWidgetServiceImpl$SecurityPolicy;
+Lcom/android/server/appwidget/AppWidgetServiceImpl$Widget;
+Lcom/android/server/AppWidgetBackupBridge;
+Lcom/android/server/AttributeCache;
+Lcom/android/server/AttributeCache$Entry;
+Lcom/android/server/AttributeCache$Package;
+Lcom/android/server/audio/AudioService;
+Lcom/android/server/audio/AudioService$1;
+Lcom/android/server/audio/AudioService$2;
+Lcom/android/server/audio/AudioService$3;
+Lcom/android/server/audio/AudioService$4;
+Lcom/android/server/audio/AudioService$AudioHandler;
+Lcom/android/server/audio/AudioService$AudioServiceBroadcastReceiver;
+Lcom/android/server/audio/AudioService$AudioServiceInternal;
+Lcom/android/server/audio/AudioService$AudioServiceUserRestrictionsListener;
+Lcom/android/server/audio/AudioService$AudioSystemThread;
+Lcom/android/server/audio/AudioService$ForceControlStreamClient;
+Lcom/android/server/audio/AudioService$Lifecycle;
+Lcom/android/server/audio/AudioService$MyDisplayStatusCallback;
+Lcom/android/server/audio/AudioService$SetModeDeathHandler;
+Lcom/android/server/audio/AudioService$SettingsObserver;
+Lcom/android/server/audio/AudioService$SoundPoolCallback;
+Lcom/android/server/audio/AudioService$SoundPoolListenerThread;
+Lcom/android/server/audio/AudioService$VolumeController;
+Lcom/android/server/audio/AudioService$VolumeStreamState;
+Lcom/android/server/audio/FocusRequester;
+Lcom/android/server/audio/MediaFocusControl;
+Lcom/android/server/audio/MediaFocusControl$AudioFocusDeathHandler;
+Lcom/android/server/audio/PlaybackActivityMonitor;
+Lcom/android/server/audio/PlaybackActivityMonitor$PlayMonitorClient;
+Lcom/android/server/audio/RecordingActivityMonitor;
+Lcom/android/server/audio/RecordingActivityMonitor$RecMonitorClient;
+Lcom/android/server/autofill/AutoFillManagerService;
+Lcom/android/server/autofill/AutoFillManagerService$1;
+Lcom/android/server/autofill/AutoFillManagerService$AutoFillManagerServiceStub;
+Lcom/android/server/autofill/AutoFillManagerServiceImpl;
+Lcom/android/server/autofill/AutoFillManagerService$SettingsObserver;
+Lcom/android/server/BackgroundDexOptJobService;
+Lcom/android/server/BackgroundDexOptJobService$1;
+Lcom/android/server/backup/AccountSyncSettingsBackupHelper;
+Lcom/android/server/backup/BackupManagerService;
+Lcom/android/server/backup/BackupManagerService$1;
+Lcom/android/server/backup/BackupManagerService$2;
+Lcom/android/server/backup/BackupManagerService$3;
+Lcom/android/server/backup/BackupManagerService$4;
+Lcom/android/server/backup/BackupManagerService$6;
+Lcom/android/server/backup/BackupManagerService$BackupHandler;
+Lcom/android/server/backup/BackupManagerService$BackupRequest;
+Lcom/android/server/backup/BackupManagerService$FullBackupEntry;
+Lcom/android/server/backup/BackupManagerService$Lifecycle;
+Lcom/android/server/backup/BackupManagerService$ProvisionedObserver;
+Lcom/android/server/backup/BackupManagerService$RunBackupReceiver;
+Lcom/android/server/backup/BackupManagerService$RunInitializeReceiver;
+Lcom/android/server/backup/FullBackupJob;
+Lcom/android/server/backup/KeyValueBackupJob;
+Lcom/android/server/backup/PackageManagerBackupAgent;
+Lcom/android/server/backup/Trampoline;
+Lcom/android/server/backup/TransportManager;
+Lcom/android/server/backup/TransportManager$TransportBoundListener;
+Lcom/android/server/backup/TransportManager$TransportConnection;
+Lcom/android/server/BatteryService;
+Lcom/android/server/BatteryService$2;
+Lcom/android/server/BatteryService$9;
+Lcom/android/server/BatteryService$BatteryListener;
+Lcom/android/server/BatteryService$BinderService;
+Lcom/android/server/BatteryService$Led;
+Lcom/android/server/BatteryService$LocalService;
+Lcom/android/server/BluetoothManagerService;
+Lcom/android/server/BluetoothManagerService$1;
+Lcom/android/server/BluetoothManagerService$2;
+Lcom/android/server/BluetoothManagerService$3;
+Lcom/android/server/BluetoothManagerService$4;
+Lcom/android/server/BluetoothManagerService$ActiveLog;
+Lcom/android/server/BluetoothManagerService$BluetoothHandler;
+Lcom/android/server/BluetoothManagerService$BluetoothServiceConnection;
+Lcom/android/server/BluetoothManagerService$ProfileServiceConnections;
+Lcom/android/server/BluetoothService;
+Lcom/android/server/BootReceiver;
+Lcom/android/server/BootReceiver$1;
+Lcom/android/server/camera/CameraService;
+Lcom/android/server/camera/CameraService$1;
+Lcom/android/server/camera/CameraService$2;
+Lcom/android/server/CertBlacklister;
+Lcom/android/server/CertBlacklister$BlacklistObserver;
+Lcom/android/server/clipboard/ClipboardService;
+Lcom/android/server/clipboard/ClipboardService$ClipboardImpl;
+Lcom/android/server/clipboard/ClipboardService$ListenerInfo;
+Lcom/android/server/clipboard/ClipboardService$PerUserClipboard;
+Lcom/android/server/CommonTimeManagementService;
+Lcom/android/server/CommonTimeManagementService$1;
+Lcom/android/server/CommonTimeManagementService$2;
+Lcom/android/server/CommonTimeManagementService$3;
+Lcom/android/server/CommonTimeManagementService$4;
+Lcom/android/server/CommonTimeManagementService$5;
+Lcom/android/server/CommonTimeManagementService$InterfaceScoreRule;
+Lcom/android/server/connectivity/DataConnectionStats;
+Lcom/android/server/connectivity/DataConnectionStats$1;
+Lcom/android/server/connectivity/IpConnectivityMetrics;
+Lcom/android/server/connectivity/IpConnectivityMetrics$Impl;
+Lcom/android/server/connectivity/KeepalivePacketData;
+Lcom/android/server/connectivity/KeepalivePacketData$InvalidPacketException;
+Lcom/android/server/connectivity/KeepaliveTracker;
+Lcom/android/server/connectivity/LingerMonitor;
+Lcom/android/server/connectivity/MetricsLoggerService;
+Lcom/android/server/connectivity/MetricsLoggerService$MetricsLoggerImpl;
+Lcom/android/server/connectivity/MockableSystemProperties;
+Lcom/android/server/connectivity/Nat464Xlat;
+Lcom/android/server/connectivity/NetdEventListenerService;
+Lcom/android/server/connectivity/NetdEventListenerService$1;
+Lcom/android/server/connectivity/NetdEventListenerService$DnsEventBatch;
+Lcom/android/server/connectivity/NetworkAgentInfo;
+Lcom/android/server/connectivity/NetworkAgentInfo$LingerTimer;
+Lcom/android/server/connectivity/NetworkMonitor;
+Lcom/android/server/connectivity/NetworkMonitor$1ProbeThread;
+Lcom/android/server/connectivity/NetworkMonitor$CaptivePortalProbeResult;
+Lcom/android/server/connectivity/NetworkMonitor$CaptivePortalState;
+Lcom/android/server/connectivity/NetworkMonitor$DefaultState;
+Lcom/android/server/connectivity/NetworkMonitor$EvaluatingState;
+Lcom/android/server/connectivity/NetworkMonitor$EvaluationResult;
+Lcom/android/server/connectivity/NetworkMonitor$MaybeNotifyState;
+Lcom/android/server/connectivity/NetworkMonitor$ValidatedState;
+Lcom/android/server/connectivity/NetworkMonitor$ValidationStage;
+Lcom/android/server/connectivity/NetworkNotificationManager;
+Lcom/android/server/connectivity/PacManager;
+Lcom/android/server/connectivity/PacManager$1;
+Lcom/android/server/connectivity/PacManager$PacRefreshIntentReceiver;
+Lcom/android/server/connectivity/PermissionMonitor;
+Lcom/android/server/connectivity/PermissionMonitor$1;
+Lcom/android/server/ConnectivityService;
+Lcom/android/server/ConnectivityService$1;
+Lcom/android/server/ConnectivityService$2;
+Lcom/android/server/ConnectivityService$3;
+Lcom/android/server/ConnectivityService$InternalHandler;
+Lcom/android/server/ConnectivityService$LegacyTypeTracker;
+Lcom/android/server/ConnectivityService$NetworkFactoryInfo;
+Lcom/android/server/ConnectivityService$NetworkRequestInfo;
+Lcom/android/server/ConnectivityService$NetworkStateTrackerHandler;
+Lcom/android/server/ConnectivityService$ReapUnvalidatedNetworks;
+Lcom/android/server/ConnectivityService$SettingsObserver;
+Lcom/android/server/ConnectivityService$UnneededFor;
+Lcom/android/server/ConnectivityService$ValidationLog;
+Lcom/android/server/connectivity/Tethering;
+Lcom/android/server/connectivity/tethering/IControlsTethering;
+Lcom/android/server/connectivity/tethering/IPv6TetheringCoordinator;
+Lcom/android/server/connectivity/tethering/IPv6TetheringInterfaceServices;
+Lcom/android/server/connectivity/Tethering$StateReceiver;
+Lcom/android/server/connectivity/tethering/TetheringConfiguration;
+Lcom/android/server/connectivity/tethering/TetherInterfaceStateMachine;
+Lcom/android/server/connectivity/tethering/TetherInterfaceStateMachine$InitialState;
+Lcom/android/server/connectivity/tethering/TetherInterfaceStateMachine$TetheredState;
+Lcom/android/server/connectivity/tethering/TetherInterfaceStateMachine$UnavailableState;
+Lcom/android/server/connectivity/Tethering$TetherMasterSM;
+Lcom/android/server/connectivity/Tethering$TetherMasterSM$ErrorState;
+Lcom/android/server/connectivity/Tethering$TetherMasterSM$InitialState;
+Lcom/android/server/connectivity/Tethering$TetherMasterSM$SetDnsForwardersErrorState;
+Lcom/android/server/connectivity/Tethering$TetherMasterSM$SetIpForwardingDisabledErrorState;
+Lcom/android/server/connectivity/Tethering$TetherMasterSM$SetIpForwardingEnabledErrorState;
+Lcom/android/server/connectivity/Tethering$TetherMasterSM$SimChangeListener;
+Lcom/android/server/connectivity/Tethering$TetherMasterSM$StartTetheringErrorState;
+Lcom/android/server/connectivity/Tethering$TetherMasterSM$StopTetheringErrorState;
+Lcom/android/server/connectivity/Tethering$TetherMasterSM$TetherMasterUtilState;
+Lcom/android/server/connectivity/Tethering$TetherMasterSM$TetherModeAliveState;
+Lcom/android/server/connectivity/Tethering$TetherState;
+Lcom/android/server/connectivity/tethering/UpstreamNetworkMonitor;
+Lcom/android/server/connectivity/Vpn;
+Lcom/android/server/connectivity/Vpn$1;
+Lcom/android/server/connectivity/Vpn$2;
+Lcom/android/server/ConsumerIrService;
+Lcom/android/server/content/ContentService;
+Lcom/android/server/content/ContentService$1;
+Lcom/android/server/content/ContentService$3;
+Lcom/android/server/content/ContentService$Lifecycle;
+Lcom/android/server/content/ContentService$ObserverCall;
+Lcom/android/server/content/ContentService$ObserverNode;
+Lcom/android/server/content/ContentService$ObserverNode$ObserverEntry;
+Lcom/android/server/content/SyncJobService;
+Lcom/android/server/content/SyncManager;
+Lcom/android/server/content/SyncManager$1;
+Lcom/android/server/content/SyncManager$10;
+Lcom/android/server/content/SyncManager$11;
+Lcom/android/server/content/SyncManager$13;
+Lcom/android/server/content/SyncManager$2;
+Lcom/android/server/content/SyncManager$3;
+Lcom/android/server/content/SyncManager$4;
+Lcom/android/server/content/SyncManager$5;
+Lcom/android/server/content/SyncManager$6;
+Lcom/android/server/content/SyncManager$7;
+Lcom/android/server/content/SyncManager$8;
+Lcom/android/server/content/SyncManager$9;
+Lcom/android/server/content/SyncManager$ActiveSyncContext;
+Lcom/android/server/content/SyncManager$ScheduleSyncMessagePayload;
+Lcom/android/server/content/SyncManager$ServiceConnectionData;
+Lcom/android/server/content/SyncManager$SyncFinishedOrCancelledMessagePayload;
+Lcom/android/server/content/SyncManager$SyncHandler;
+Lcom/android/server/content/SyncManager$SyncTimeTracker;
+Lcom/android/server/content/SyncManager$UpdatePeriodicSyncMessagePayload;
+Lcom/android/server/content/SyncOperation;
+Lcom/android/server/content/SyncStorageEngine;
+Lcom/android/server/content/SyncStorageEngine$AccountInfo;
+Lcom/android/server/content/SyncStorageEngine$AuthorityInfo;
+Lcom/android/server/content/SyncStorageEngine$DayStats;
+Lcom/android/server/content/SyncStorageEngine$EndPoint;
+Lcom/android/server/content/SyncStorageEngine$OnAuthorityRemovedListener;
+Lcom/android/server/content/SyncStorageEngine$OnSyncRequestListener;
+Lcom/android/server/content/SyncStorageEngine$PeriodicSyncAddedListener;
+Lcom/android/server/content/SyncStorageEngine$SyncHistoryItem;
+Lcom/android/server/ContextHubSystemService;
+Lcom/android/server/CountryDetectorService;
+Lcom/android/server/CountryDetectorService$1;
+Lcom/android/server/CountryDetectorService$1$1;
+Lcom/android/server/CountryDetectorService$2;
+Lcom/android/server/CountryDetectorService$Receiver;
+Lcom/android/server/coverage/CoverageService;
+Lcom/android/server/DeviceIdleController;
+Lcom/android/server/DeviceIdleController$1;
+Lcom/android/server/DeviceIdleController$2;
+Lcom/android/server/DeviceIdleController$3;
+Lcom/android/server/DeviceIdleController$4;
+Lcom/android/server/DeviceIdleController$5;
+Lcom/android/server/DeviceIdleController$6;
+Lcom/android/server/DeviceIdleController$7;
+Lcom/android/server/DeviceIdleController$8;
+Lcom/android/server/DeviceIdleController$BinderService;
+Lcom/android/server/DeviceIdleController$Constants;
+Lcom/android/server/DeviceIdleController$LocalService;
+Lcom/android/server/DeviceIdleController$MotionListener;
+Lcom/android/server/DeviceIdleController$MyHandler;
+Lcom/android/server/devicepolicy/DevicePolicyManagerService;
+Lcom/android/server/devicepolicy/DevicePolicyManagerService$1;
+Lcom/android/server/devicepolicy/DevicePolicyManagerService$2;
+Lcom/android/server/devicepolicy/DevicePolicyManagerService$3;
+Lcom/android/server/devicepolicy/DevicePolicyManagerService$4;
+Lcom/android/server/devicepolicy/DevicePolicyManagerService$4$1;
+Lcom/android/server/devicepolicy/DevicePolicyManagerService$9;
+Lcom/android/server/devicepolicy/DevicePolicyManagerService$ActiveAdmin;
+Lcom/android/server/devicepolicy/DevicePolicyManagerService$DevicePolicyData;
+Lcom/android/server/devicepolicy/DevicePolicyManagerService$Injector;
+Lcom/android/server/devicepolicy/DevicePolicyManagerService$Lifecycle;
+Lcom/android/server/devicepolicy/DevicePolicyManagerService$LocalService;
+Lcom/android/server/devicepolicy/DevicePolicyManagerService$MonitoringCertNotificationTask;
+Lcom/android/server/devicepolicy/DevicePolicyManagerService$SetupContentObserver;
+Lcom/android/server/devicepolicy/Owners;
+Lcom/android/server/devicepolicy/Owners$DeviceOwnerReadWriter;
+Lcom/android/server/devicepolicy/Owners$FileReadWriter;
+Lcom/android/server/devicepolicy/Owners$OwnerInfo;
+Lcom/android/server/devicepolicy/Owners$ProfileOwnerReadWriter;
+Lcom/android/server/devicepolicy/SecurityLogMonitor;
+Lcom/android/server/DiskStatsService;
+Lcom/android/server/display/AutomaticBrightnessController;
+Lcom/android/server/display/AutomaticBrightnessController$1;
+Lcom/android/server/display/AutomaticBrightnessController$2;
+Lcom/android/server/display/AutomaticBrightnessController$AmbientLightRingBuffer;
+Lcom/android/server/display/AutomaticBrightnessController$AutomaticBrightnessHandler;
+Lcom/android/server/display/AutomaticBrightnessController$Callbacks;
+Lcom/android/server/display/ColorFade;
+Lcom/android/server/display/ColorFade$NaturalSurfaceLayout;
+Lcom/android/server/display/DisplayAdapter;
+Lcom/android/server/display/DisplayAdapter$1;
+Lcom/android/server/display/DisplayAdapter$2;
+Lcom/android/server/display/DisplayAdapter$Listener;
+Lcom/android/server/display/DisplayBlanker;
+Lcom/android/server/display/DisplayDevice;
+Lcom/android/server/display/DisplayDeviceInfo;
+Lcom/android/server/display/DisplayManagerService;
+Lcom/android/server/display/DisplayManagerService$BinderService;
+Lcom/android/server/display/DisplayManagerService$CallbackRecord;
+Lcom/android/server/display/DisplayManagerService$DisplayAdapterListener;
+Lcom/android/server/display/DisplayManagerService$DisplayManagerHandler;
+Lcom/android/server/display/DisplayManagerService$LocalService;
+Lcom/android/server/display/DisplayManagerService$LocalService$1;
+Lcom/android/server/display/DisplayManagerService$SyncRoot;
+Lcom/android/server/display/DisplayPowerController;
+Lcom/android/server/display/DisplayPowerController$1;
+Lcom/android/server/display/DisplayPowerController$2;
+Lcom/android/server/display/DisplayPowerController$3;
+Lcom/android/server/display/DisplayPowerController$4;
+Lcom/android/server/display/DisplayPowerController$5;
+Lcom/android/server/display/DisplayPowerController$6;
+Lcom/android/server/display/DisplayPowerController$7;
+Lcom/android/server/display/DisplayPowerController$DisplayControllerHandler;
+Lcom/android/server/display/DisplayPowerController$ScreenOnUnblocker;
+Lcom/android/server/display/DisplayPowerState;
+Lcom/android/server/display/DisplayPowerState$1;
+Lcom/android/server/display/DisplayPowerState$2;
+Lcom/android/server/display/DisplayPowerState$3;
+Lcom/android/server/display/DisplayPowerState$4;
+Lcom/android/server/display/DisplayPowerState$PhotonicModulator;
+Lcom/android/server/display/DisplayTransformManager;
+Lcom/android/server/display/HysteresisLevels;
+Lcom/android/server/display/LocalDisplayAdapter;
+Lcom/android/server/display/LocalDisplayAdapter$DisplayModeRecord;
+Lcom/android/server/display/LocalDisplayAdapter$HotplugDisplayEventReceiver;
+Lcom/android/server/display/LocalDisplayAdapter$LocalDisplayDevice;
+Lcom/android/server/display/LocalDisplayAdapter$LocalDisplayDevice$1;
+Lcom/android/server/display/LogicalDisplay;
+Lcom/android/server/display/NightDisplayService;
+Lcom/android/server/display/NightDisplayService$1;
+Lcom/android/server/display/NightDisplayService$3;
+Lcom/android/server/display/NightDisplayService$4;
+Lcom/android/server/display/NightDisplayService$ColorMatrixEvaluator;
+Lcom/android/server/display/OverlayDisplayAdapter;
+Lcom/android/server/display/OverlayDisplayAdapter$1;
+Lcom/android/server/display/OverlayDisplayAdapter$1$1;
+Lcom/android/server/display/PersistentDataStore;
+Lcom/android/server/display/PersistentDataStore$DisplayState;
+Lcom/android/server/display/RampAnimator;
+Lcom/android/server/display/RampAnimator$1;
+Lcom/android/server/display/RampAnimator$Listener;
+Lcom/android/server/DisplayThread;
+Lcom/android/server/display/VirtualDisplayAdapter;
+Lcom/android/server/DockObserver;
+Lcom/android/server/DockObserver$1;
+Lcom/android/server/DockObserver$2;
+Lcom/android/server/DockObserver$BinderService;
+Lcom/android/server/dreams/DreamController;
+Lcom/android/server/dreams/DreamController$1;
+Lcom/android/server/dreams/DreamController$2;
+Lcom/android/server/dreams/DreamController$3;
+Lcom/android/server/dreams/DreamController$DreamRecord;
+Lcom/android/server/dreams/DreamController$DreamRecord$1;
+Lcom/android/server/dreams/DreamController$DreamRecord$3;
+Lcom/android/server/dreams/DreamController$Listener;
+Lcom/android/server/dreams/DreamManagerService;
+Lcom/android/server/dreams/DreamManagerService$1;
+Lcom/android/server/dreams/DreamManagerService$2;
+Lcom/android/server/dreams/DreamManagerService$3;
+Lcom/android/server/dreams/DreamManagerService$4;
+Lcom/android/server/dreams/DreamManagerService$6;
+Lcom/android/server/dreams/DreamManagerService$BinderService;
+Lcom/android/server/dreams/DreamManagerService$DreamHandler;
+Lcom/android/server/dreams/DreamManagerService$LocalService;
+Lcom/android/server/DropBoxManagerService;
+Lcom/android/server/DropBoxManagerService$1;
+Lcom/android/server/DropBoxManagerService$1$1;
+Lcom/android/server/DropBoxManagerService$2;
+Lcom/android/server/DropBoxManagerService$3;
+Lcom/android/server/DropBoxManagerService$4;
+Lcom/android/server/DropBoxManagerService$EntryFile;
+Lcom/android/server/DropBoxManagerService$FileList;
+Lcom/android/server/emergency/EmergencyAffordanceService;
+Lcom/android/server/emergency/EmergencyAffordanceService$1;
+Lcom/android/server/emergency/EmergencyAffordanceService$2;
+Lcom/android/server/emergency/EmergencyAffordanceService$3;
+Lcom/android/server/emergency/EmergencyAffordanceService$MyHandler;
+Lcom/android/server/EntropyMixer;
+Lcom/android/server/EntropyMixer$1;
+Lcom/android/server/EntropyMixer$2;
+Lcom/android/server/ethernet/EthernetConfigStore;
+Lcom/android/server/ethernet/EthernetNetworkFactory;
+Lcom/android/server/ethernet/EthernetNetworkFactory$InterfaceObserver;
+Lcom/android/server/ethernet/EthernetNetworkFactory$LocalNetworkFactory;
+Lcom/android/server/ethernet/EthernetService;
+Lcom/android/server/ethernet/EthernetServiceImpl;
+Lcom/android/server/EventLogTags;
+Lcom/android/server/FgThread;
+Lcom/android/server/fingerprint/FingerprintService;
+Lcom/android/server/fingerprint/FingerprintService$1;
+Lcom/android/server/fingerprint/FingerprintService$10;
+Lcom/android/server/fingerprint/FingerprintService$2;
+Lcom/android/server/fingerprint/FingerprintService$3;
+Lcom/android/server/fingerprint/FingerprintService$4;
+Lcom/android/server/fingerprint/FingerprintService$5;
+Lcom/android/server/fingerprint/FingerprintService$FingerprintServiceLockoutResetMonitor;
+Lcom/android/server/fingerprint/FingerprintService$FingerprintServiceLockoutResetMonitor$1;
+Lcom/android/server/fingerprint/FingerprintService$FingerprintServiceWrapper;
+Lcom/android/server/fingerprint/FingerprintService$FingerprintServiceWrapper$9;
+Lcom/android/server/fingerprint/FingerprintService$PerformanceStats;
+Lcom/android/server/fingerprint/FingerprintsUserState;
+Lcom/android/server/fingerprint/FingerprintsUserState$1;
+Lcom/android/server/fingerprint/FingerprintUtils;
+Lcom/android/server/firewall/AndFilter;
+Lcom/android/server/firewall/AndFilter$1;
+Lcom/android/server/firewall/CategoryFilter;
+Lcom/android/server/firewall/CategoryFilter$1;
+Lcom/android/server/firewall/Filter;
+Lcom/android/server/firewall/FilterFactory;
+Lcom/android/server/firewall/FilterList;
+Lcom/android/server/firewall/IntentFirewall;
+Lcom/android/server/firewall/IntentFirewall$AMSInterface;
+Lcom/android/server/firewall/IntentFirewall$FirewallHandler;
+Lcom/android/server/firewall/IntentFirewall$FirewallIntentResolver;
+Lcom/android/server/firewall/IntentFirewall$Rule;
+Lcom/android/server/firewall/IntentFirewall$RuleObserver;
+Lcom/android/server/firewall/NotFilter;
+Lcom/android/server/firewall/NotFilter$1;
+Lcom/android/server/firewall/OrFilter;
+Lcom/android/server/firewall/OrFilter$1;
+Lcom/android/server/firewall/PortFilter;
+Lcom/android/server/firewall/PortFilter$1;
+Lcom/android/server/firewall/SenderFilter;
+Lcom/android/server/firewall/SenderFilter$1;
+Lcom/android/server/firewall/SenderFilter$2;
+Lcom/android/server/firewall/SenderFilter$3;
+Lcom/android/server/firewall/SenderFilter$4;
+Lcom/android/server/firewall/SenderFilter$5;
+Lcom/android/server/firewall/SenderPackageFilter;
+Lcom/android/server/firewall/SenderPackageFilter$1;
+Lcom/android/server/firewall/SenderPermissionFilter;
+Lcom/android/server/firewall/SenderPermissionFilter$1;
+Lcom/android/server/firewall/StringFilter;
+Lcom/android/server/firewall/StringFilter$1;
+Lcom/android/server/firewall/StringFilter$10;
+Lcom/android/server/firewall/StringFilter$2;
+Lcom/android/server/firewall/StringFilter$3;
+Lcom/android/server/firewall/StringFilter$4;
+Lcom/android/server/firewall/StringFilter$5;
+Lcom/android/server/firewall/StringFilter$6;
+Lcom/android/server/firewall/StringFilter$7;
+Lcom/android/server/firewall/StringFilter$8;
+Lcom/android/server/firewall/StringFilter$9;
+Lcom/android/server/firewall/StringFilter$ValueProvider;
+Lcom/android/server/FontManagerService;
+Lcom/android/server/FontManagerService$Lifecycle;
+Lcom/android/server/GestureLauncherService;
+Lcom/android/server/GestureLauncherService$1;
+Lcom/android/server/GestureLauncherService$2;
+Lcom/android/server/GestureLauncherService$GestureEventListener;
+Lcom/android/server/GraphicsStatsService;
+Lcom/android/server/GraphicsStatsService$ActiveBuffer;
+Lcom/android/server/GraphicsStatsService$HistoricalData;
+Lcom/android/server/HardwarePropertiesManagerService;
+Lcom/android/server/hdmi/HdmiCecController;
+Lcom/android/server/INativeDaemonConnectorCallbacks;
+Lcom/android/server/input/InputApplicationHandle;
+Lcom/android/server/input/InputManagerService;
+Lcom/android/server/input/InputManagerService$1;
+Lcom/android/server/input/InputManagerService$10;
+Lcom/android/server/input/InputManagerService$11;
+Lcom/android/server/input/InputManagerService$12;
+Lcom/android/server/input/InputManagerService$2;
+Lcom/android/server/input/InputManagerService$3;
+Lcom/android/server/input/InputManagerService$5;
+Lcom/android/server/input/InputManagerService$InputDevicesChangedListenerRecord;
+Lcom/android/server/input/InputManagerService$InputManagerHandler;
+Lcom/android/server/input/InputManagerService$KeyboardLayoutDescriptor;
+Lcom/android/server/input/InputManagerService$KeyboardLayoutVisitor;
+Lcom/android/server/input/InputManagerService$LocalService;
+Lcom/android/server/input/InputManagerService$WindowManagerCallbacks;
+Lcom/android/server/input/InputManagerService$WiredAccessoryCallbacks;
+Lcom/android/server/input/InputWindowHandle;
+Lcom/android/server/InputMethodManagerService;
+Lcom/android/server/InputMethodManagerService$1;
+Lcom/android/server/InputMethodManagerService$2;
+Lcom/android/server/InputMethodManagerService$ClientState;
+Lcom/android/server/InputMethodManagerService$HardKeyboardListener;
+Lcom/android/server/InputMethodManagerService$ImmsBroadcastReceiver;
+Lcom/android/server/InputMethodManagerService$InputMethodFileManager;
+Lcom/android/server/InputMethodManagerService$Lifecycle;
+Lcom/android/server/InputMethodManagerService$LocalServiceImpl;
+Lcom/android/server/InputMethodManagerService$MethodCallback;
+Lcom/android/server/InputMethodManagerService$MyPackageMonitor;
+Lcom/android/server/InputMethodManagerService$SessionState;
+Lcom/android/server/InputMethodManagerService$SettingsObserver;
+Lcom/android/server/input/PersistentDataStore;
+Lcom/android/server/input/PersistentDataStore$InputDeviceState;
+Lcom/android/server/IntentResolver;
+Lcom/android/server/IntentResolver$1;
+Lcom/android/server/IntentResolver$IteratorWrapper;
+Lcom/android/server/IoThread;
+Lcom/android/server/job/controllers/AppIdleController;
+Lcom/android/server/job/controllers/AppIdleController$AppIdleStateChangeListener;
+Lcom/android/server/job/controllers/AppIdleController$GlobalUpdateFunc;
+Lcom/android/server/job/controllers/AppIdleController$PackageUpdateFunc;
+Lcom/android/server/job/controllers/BatteryController;
+Lcom/android/server/job/controllers/BatteryController$ChargingTracker;
+Lcom/android/server/job/controllers/ConnectivityController;
+Lcom/android/server/job/controllers/ConnectivityController$1;
+Lcom/android/server/job/controllers/ConnectivityController$2;
+Lcom/android/server/job/controllers/ContentObserverController;
+Lcom/android/server/job/controllers/ContentObserverController$JobInstance;
+Lcom/android/server/job/controllers/ContentObserverController$ObserverInstance;
+Lcom/android/server/job/controllers/ContentObserverController$TriggerRunnable;
+Lcom/android/server/job/controllers/DeviceIdleJobsController;
+Lcom/android/server/job/controllers/DeviceIdleJobsController$1;
+Lcom/android/server/job/controllers/DeviceIdleJobsController$2;
+Lcom/android/server/job/controllers/IdleController;
+Lcom/android/server/job/controllers/IdleController$IdlenessTracker;
+Lcom/android/server/job/controllers/JobStatus;
+Lcom/android/server/job/controllers/StateController;
+Lcom/android/server/job/controllers/TimeController;
+Lcom/android/server/job/controllers/TimeController$1;
+Lcom/android/server/job/controllers/TimeController$2;
+Lcom/android/server/job/JobCompletedListener;
+Lcom/android/server/job/JobPackageTracker;
+Lcom/android/server/job/JobPackageTracker$DataSet;
+Lcom/android/server/job/JobPackageTracker$PackageEntry;
+Lcom/android/server/job/JobSchedulerInternal;
+Lcom/android/server/job/JobSchedulerService;
+Lcom/android/server/job/JobSchedulerService$1;
+Lcom/android/server/job/JobSchedulerService$2;
+Lcom/android/server/job/JobSchedulerService$3;
+Lcom/android/server/job/JobSchedulerService$Constants;
+Lcom/android/server/job/JobSchedulerService$JobHandler;
+Lcom/android/server/job/JobSchedulerService$JobHandler$MaybeReadyJobQueueFunctor;
+Lcom/android/server/job/JobSchedulerService$JobHandler$ReadyJobQueueFunctor;
+Lcom/android/server/job/JobSchedulerService$JobSchedulerStub;
+Lcom/android/server/job/JobSchedulerService$LocalService;
+Lcom/android/server/job/JobSchedulerService$LocalService$1;
+Lcom/android/server/job/JobServiceContext;
+Lcom/android/server/job/JobServiceContext$JobServiceHandler;
+Lcom/android/server/job/JobStore;
+Lcom/android/server/job/JobStore$JobSet;
+Lcom/android/server/job/JobStore$JobStatusFunctor;
+Lcom/android/server/job/JobStore$ReadJobMapFromDiskRunnable;
+Lcom/android/server/job/JobStore$WriteJobsMapToDiskRunnable;
+Lcom/android/server/job/JobStore$WriteJobsMapToDiskRunnable$1;
+Lcom/android/server/job/StateChangedListener;
+Lcom/android/server/lights/Light;
+Lcom/android/server/lights/LightsManager;
+Lcom/android/server/lights/LightsService;
+Lcom/android/server/lights/LightsService$1;
+Lcom/android/server/lights/LightsService$2;
+Lcom/android/server/lights/LightsService$LightImpl;
+Lcom/android/server/LocalServices;
+Lcom/android/server/location/ActivityRecognitionProxy;
+Lcom/android/server/location/ActivityRecognitionProxy$1;
+Lcom/android/server/location/ComprehensiveCountryDetector;
+Lcom/android/server/location/ComprehensiveCountryDetector$1;
+Lcom/android/server/location/ComprehensiveCountryDetector$2;
+Lcom/android/server/location/ComprehensiveCountryDetector$3;
+Lcom/android/server/location/ComprehensiveCountryDetector$4;
+Lcom/android/server/location/ContextHubService;
+Lcom/android/server/location/CountryDetectorBase;
+Lcom/android/server/location/FlpHardwareProvider;
+Lcom/android/server/location/GeocoderProxy;
+Lcom/android/server/location/GeofenceManager;
+Lcom/android/server/location/GeofenceManager$GeofenceHandler;
+Lcom/android/server/location/GeofenceProxy;
+Lcom/android/server/location/GeofenceProxy$1;
+Lcom/android/server/location/GeofenceProxy$2;
+Lcom/android/server/location/GeofenceProxy$3;
+Lcom/android/server/location/GnssLocationProvider;
+Lcom/android/server/location/GnssLocationProvider$1;
+Lcom/android/server/location/GnssLocationProvider$10;
+Lcom/android/server/location/GnssLocationProvider$11;
+Lcom/android/server/location/GnssLocationProvider$12;
+Lcom/android/server/location/GnssLocationProvider$14;
+Lcom/android/server/location/GnssLocationProvider$2;
+Lcom/android/server/location/GnssLocationProvider$3;
+Lcom/android/server/location/GnssLocationProvider$4;
+Lcom/android/server/location/GnssLocationProvider$5;
+Lcom/android/server/location/GnssLocationProvider$6;
+Lcom/android/server/location/GnssLocationProvider$7;
+Lcom/android/server/location/GnssLocationProvider$8;
+Lcom/android/server/location/GnssLocationProvider$9;
+Lcom/android/server/location/GnssLocationProvider$BackOff;
+Lcom/android/server/location/GnssLocationProvider$GnssSystemInfoProvider;
+Lcom/android/server/location/GnssLocationProvider$GpsRequest;
+Lcom/android/server/location/GnssLocationProvider$NetworkLocationListener;
+Lcom/android/server/location/GnssLocationProvider$ProviderHandler;
+Lcom/android/server/location/GnssLocationProvider$SetCarrierProperty;
+Lcom/android/server/location/GnssMeasurementsProvider;
+Lcom/android/server/location/GnssNavigationMessageProvider;
+Lcom/android/server/location/GnssNavigationMessageProvider$StatusChangedOperation;
+Lcom/android/server/location/GnssStatusListenerHelper;
+Lcom/android/server/location/GnssStatusListenerHelper$1;
+Lcom/android/server/location/GnssStatusListenerHelper$2;
+Lcom/android/server/location/GnssStatusListenerHelper$3;
+Lcom/android/server/location/GnssStatusListenerHelper$4;
+Lcom/android/server/location/GnssStatusListenerHelper$5;
+Lcom/android/server/location/GnssStatusListenerHelper$Operation;
+Lcom/android/server/location/LocationBasedCountryDetector;
+Lcom/android/server/location/LocationBasedCountryDetector$1;
+Lcom/android/server/location/LocationBasedCountryDetector$2;
+Lcom/android/server/location/LocationBasedCountryDetector$3;
+Lcom/android/server/location/LocationBlacklist;
+Lcom/android/server/location/LocationFudger;
+Lcom/android/server/location/LocationFudger$1;
+Lcom/android/server/location/LocationProviderInterface;
+Lcom/android/server/location/LocationProviderProxy;
+Lcom/android/server/location/LocationProviderProxy$1;
+Lcom/android/server/location/LocationRequestStatistics;
+Lcom/android/server/location/LocationRequestStatistics$PackageProviderKey;
+Lcom/android/server/location/LocationRequestStatistics$PackageStatistics;
+Lcom/android/server/LocationManagerService;
+Lcom/android/server/LocationManagerService$1;
+Lcom/android/server/LocationManagerService$2;
+Lcom/android/server/LocationManagerService$3;
+Lcom/android/server/LocationManagerService$4;
+Lcom/android/server/LocationManagerService$5;
+Lcom/android/server/LocationManagerService$6;
+Lcom/android/server/LocationManagerService$7;
+Lcom/android/server/LocationManagerService$8;
+Lcom/android/server/LocationManagerService$9;
+Lcom/android/server/LocationManagerService$LocationWorkerHandler;
+Lcom/android/server/LocationManagerService$Receiver;
+Lcom/android/server/LocationManagerService$UpdateRecord;
+Lcom/android/server/location/PassiveProvider;
+Lcom/android/server/location/RemoteListenerHelper;
+Lcom/android/server/location/RemoteListenerHelper$HandlerRunnable;
+Lcom/android/server/location/RemoteListenerHelper$LinkedListener;
+Lcom/android/server/location/RemoteListenerHelper$ListenerOperation;
+Lcom/android/server/LockSettingsService;
+Lcom/android/server/LockSettingsService$1;
+Lcom/android/server/LockSettingsService$GateKeeperDiedRecipient;
+Lcom/android/server/LockSettingsService$Injector;
+Lcom/android/server/LockSettingsService$Injector$1;
+Lcom/android/server/LockSettingsService$Lifecycle;
+Lcom/android/server/LockSettingsService$SynchronizedStrongAuthTracker;
+Lcom/android/server/LockSettingsStorage;
+Lcom/android/server/LockSettingsStorage$Cache;
+Lcom/android/server/LockSettingsStorage$Cache$CacheKey;
+Lcom/android/server/LockSettingsStorage$Callback;
+Lcom/android/server/LockSettingsStorage$CredentialHash;
+Lcom/android/server/LockSettingsStorage$DatabaseHelper;
+Lcom/android/server/LockSettingsStrongAuth;
+Lcom/android/server/LockSettingsStrongAuth$1;
+Lcom/android/server/media/MediaResourceMonitorService;
+Lcom/android/server/media/MediaResourceMonitorService$MediaResourceMonitorImpl;
+Lcom/android/server/media/MediaRouterService;
+Lcom/android/server/media/MediaRouterService$1;
+Lcom/android/server/media/MediaRouterService$ClientRecord;
+Lcom/android/server/media/MediaRouterService$UserHandler;
+Lcom/android/server/media/MediaRouterService$UserHandler$ProviderRecord;
+Lcom/android/server/media/MediaRouterService$UserRecord;
+Lcom/android/server/media/MediaSessionRecord;
+Lcom/android/server/media/MediaSessionRecord$1;
+Lcom/android/server/media/MediaSessionRecord$ControllerStub;
+Lcom/android/server/media/MediaSessionRecord$MessageHandler;
+Lcom/android/server/media/MediaSessionRecord$SessionCb;
+Lcom/android/server/media/MediaSessionRecord$SessionStub;
+Lcom/android/server/media/MediaSessionService;
+Lcom/android/server/media/MediaSessionService$MessageHandler;
+Lcom/android/server/media/MediaSessionService$SessionManagerImpl;
+Lcom/android/server/media/MediaSessionService$SessionManagerImpl$1;
+Lcom/android/server/media/MediaSessionService$SessionManagerImpl$4;
+Lcom/android/server/media/MediaSessionService$SessionManagerImpl$KeyEventWakeLockReceiver;
+Lcom/android/server/media/MediaSessionService$SessionsListenerRecord;
+Lcom/android/server/media/MediaSessionService$SettingsObserver;
+Lcom/android/server/media/MediaSessionService$UserRecord;
+Lcom/android/server/media/MediaSessionStack;
+Lcom/android/server/media/projection/MediaProjectionManagerService;
+Lcom/android/server/media/projection/MediaProjectionManagerService$1;
+Lcom/android/server/media/projection/MediaProjectionManagerService$BinderService;
+Lcom/android/server/media/projection/MediaProjectionManagerService$CallbackDelegate;
+Lcom/android/server/media/projection/MediaProjectionManagerService$MediaRouterCallback;
+Lcom/android/server/media/RemoteDisplayProviderProxy;
+Lcom/android/server/media/RemoteDisplayProviderProxy$1;
+Lcom/android/server/media/RemoteDisplayProviderProxy$Callback;
+Lcom/android/server/media/RemoteDisplayProviderWatcher;
+Lcom/android/server/media/RemoteDisplayProviderWatcher$1;
+Lcom/android/server/media/RemoteDisplayProviderWatcher$2;
+Lcom/android/server/media/RemoteDisplayProviderWatcher$Callback;
+Lcom/android/server/midi/MidiService;
+Lcom/android/server/midi/MidiService$1;
+Lcom/android/server/midi/MidiService$Lifecycle;
+Lcom/android/server/MmsServiceBroker;
+Lcom/android/server/MmsServiceBroker$1;
+Lcom/android/server/MmsServiceBroker$2;
+Lcom/android/server/MmsServiceBroker$3;
+Lcom/android/server/MmsServiceBroker$BinderService;
+Lcom/android/server/MountServiceIdler;
+Lcom/android/server/NativeDaemonConnector;
+Lcom/android/server/NativeDaemonConnector$Command;
+Lcom/android/server/NativeDaemonConnectorException;
+Lcom/android/server/NativeDaemonConnector$NativeDaemonFailureException;
+Lcom/android/server/NativeDaemonConnector$ResponseQueue;
+Lcom/android/server/NativeDaemonConnector$ResponseQueue$PendingCmd;
+Lcom/android/server/NativeDaemonConnector$SensitiveArg;
+Lcom/android/server/NativeDaemonEvent;
+Lcom/android/server/NativeDaemonTimeoutException;
+Lcom/android/server/net/BaseNetworkObserver;
+Lcom/android/server/net/DelayedDiskWrite;
+Lcom/android/server/net/DelayedDiskWrite$Writer;
+Lcom/android/server/net/DnsServerEntry;
+Lcom/android/server/net/DnsServerRepository;
+Lcom/android/server/net/IpConfigStore;
+Lcom/android/server/net/LockdownVpnTracker;
+Lcom/android/server/net/NetlinkTracker;
+Lcom/android/server/net/NetlinkTracker$Callback;
+Lcom/android/server/net/NetworkIdentitySet;
+Lcom/android/server/net/NetworkPolicyManagerInternal;
+Lcom/android/server/net/NetworkPolicyManagerService;
+Lcom/android/server/net/NetworkPolicyManagerService$1;
+Lcom/android/server/net/NetworkPolicyManagerService$10;
+Lcom/android/server/net/NetworkPolicyManagerService$11;
+Lcom/android/server/net/NetworkPolicyManagerService$12;
+Lcom/android/server/net/NetworkPolicyManagerService$13;
+Lcom/android/server/net/NetworkPolicyManagerService$14;
+Lcom/android/server/net/NetworkPolicyManagerService$15;
+Lcom/android/server/net/NetworkPolicyManagerService$2;
+Lcom/android/server/net/NetworkPolicyManagerService$3;
+Lcom/android/server/net/NetworkPolicyManagerService$4;
+Lcom/android/server/net/NetworkPolicyManagerService$5;
+Lcom/android/server/net/NetworkPolicyManagerService$6;
+Lcom/android/server/net/NetworkPolicyManagerService$7;
+Lcom/android/server/net/NetworkPolicyManagerService$8;
+Lcom/android/server/net/NetworkPolicyManagerService$9;
+Lcom/android/server/net/NetworkPolicyManagerService$AppIdleStateChangeListener;
+Lcom/android/server/net/NetworkPolicyManagerService$NetworkPolicyManagerInternalImpl;
+Lcom/android/server/net/NetworkStatsAccess;
+Lcom/android/server/net/NetworkStatsCollection;
+Lcom/android/server/net/NetworkStatsCollection$Key;
+Lcom/android/server/net/NetworkStatsObservers;
+Lcom/android/server/net/NetworkStatsObservers$1;
+Lcom/android/server/net/NetworkStatsObservers$StatsContext;
+Lcom/android/server/net/NetworkStatsRecorder;
+Lcom/android/server/net/NetworkStatsRecorder$CombiningRewriter;
+Lcom/android/server/net/NetworkStatsService;
+Lcom/android/server/net/NetworkStatsService$1;
+Lcom/android/server/net/NetworkStatsService$2;
+Lcom/android/server/net/NetworkStatsService$3;
+Lcom/android/server/net/NetworkStatsService$4;
+Lcom/android/server/net/NetworkStatsService$5;
+Lcom/android/server/net/NetworkStatsService$6;
+Lcom/android/server/net/NetworkStatsService$7;
+Lcom/android/server/net/NetworkStatsService$DefaultNetworkStatsSettings;
+Lcom/android/server/net/NetworkStatsService$DropBoxNonMonotonicObserver;
+Lcom/android/server/net/NetworkStatsService$HandlerCallback;
+Lcom/android/server/net/NetworkStatsService$NetworkStatsSettings;
+Lcom/android/server/net/NetworkStatsService$NetworkStatsSettings$Config;
+Lcom/android/server/NetworkManagementService;
+Lcom/android/server/NetworkManagementService$1;
+Lcom/android/server/NetworkManagementService$IdleTimerParams;
+Lcom/android/server/NetworkManagementService$NetdCallbackReceiver;
+Lcom/android/server/NetworkManagementService$NetworkManagementEventCallback;
+Lcom/android/server/NetworkManagementSocketTagger;
+Lcom/android/server/NetworkManagementSocketTagger$1;
+Lcom/android/server/NetworkManagementSocketTagger$SocketTags;
+Lcom/android/server/NetworkScoreService;
+Lcom/android/server/NetworkScoreService$1;
+Lcom/android/server/NetworkScoreService$2;
+Lcom/android/server/NetworkScoreService$DispatchingContentObserver;
+Lcom/android/server/NetworkScoreService$NetworkScorerPackageMonitor;
+Lcom/android/server/NetworkScoreService$RequestRecommendationCaller;
+Lcom/android/server/NetworkScoreService$RequestRecommendationCaller$1;
+Lcom/android/server/NetworkScoreService$ServiceHandler;
+Lcom/android/server/NetworkTimeUpdateService;
+Lcom/android/server/NetworkTimeUpdateService$1;
+Lcom/android/server/NetworkTimeUpdateService$2;
+Lcom/android/server/NetworkTimeUpdateService$3;
+Lcom/android/server/NetworkTimeUpdateService$MyHandler;
+Lcom/android/server/NetworkTimeUpdateService$SettingsObserver;
+Lcom/android/server/notification/BadgeExtractor;
+Lcom/android/server/notification/CalendarTracker;
+Lcom/android/server/notification/CalendarTracker$1;
+Lcom/android/server/notification/CalendarTracker$Callback;
+Lcom/android/server/notification/CalendarTracker$CheckEventResult;
+Lcom/android/server/notification/ConditionProviders;
+Lcom/android/server/notification/ConditionProviders$Callback;
+Lcom/android/server/notification/ConditionProviders$ConditionRecord;
+Lcom/android/server/notification/CountdownConditionProvider;
+Lcom/android/server/notification/CountdownConditionProvider$Receiver;
+Lcom/android/server/notification/EventConditionProvider;
+Lcom/android/server/notification/EventConditionProvider$1;
+Lcom/android/server/notification/EventConditionProvider$2;
+Lcom/android/server/notification/EventConditionProvider$3;
+Lcom/android/server/notification/EventConditionProvider$4;
+Lcom/android/server/notification/GlobalSortKeyComparator;
+Lcom/android/server/notification/GroupHelper;
+Lcom/android/server/notification/GroupHelper$Callback;
+Lcom/android/server/notification/ImportanceExtractor;
+Lcom/android/server/notification/ManagedServices;
+Lcom/android/server/notification/ManagedServices$1;
+Lcom/android/server/notification/ManagedServices$Config;
+Lcom/android/server/notification/ManagedServices$ManagedServiceInfo;
+Lcom/android/server/notification/ManagedServices$SettingRestoredReceiver;
+Lcom/android/server/notification/ManagedServices$SettingsObserver;
+Lcom/android/server/notification/ManagedServices$UserProfiles;
+Lcom/android/server/notification/NotificationComparator;
+Lcom/android/server/notification/NotificationComparator$1;
+Lcom/android/server/notification/NotificationComparator$2;
+Lcom/android/server/notification/NotificationDelegate;
+Lcom/android/server/notification/NotificationIntrusivenessExtractor;
+Lcom/android/server/notification/NotificationIntrusivenessExtractor$1;
+Lcom/android/server/notification/NotificationManagerInternal;
+Lcom/android/server/notification/NotificationManagerService;
+Lcom/android/server/notification/NotificationManagerService$1;
+Lcom/android/server/notification/NotificationManagerService$10;
+Lcom/android/server/notification/NotificationManagerService$11;
+Lcom/android/server/notification/NotificationManagerService$12;
+Lcom/android/server/notification/NotificationManagerService$13;
+Lcom/android/server/notification/NotificationManagerService$16;
+Lcom/android/server/notification/NotificationManagerService$2;
+Lcom/android/server/notification/NotificationManagerService$3;
+Lcom/android/server/notification/NotificationManagerService$4;
+Lcom/android/server/notification/NotificationManagerService$5;
+Lcom/android/server/notification/NotificationManagerService$6;
+Lcom/android/server/notification/NotificationManagerService$6$1;
+Lcom/android/server/notification/NotificationManagerService$7;
+Lcom/android/server/notification/NotificationManagerService$7$1;
+Lcom/android/server/notification/NotificationManagerService$8;
+Lcom/android/server/notification/NotificationManagerService$9;
+Lcom/android/server/notification/NotificationManagerService$Archive;
+Lcom/android/server/notification/NotificationManagerService$DumpFilter;
+Lcom/android/server/notification/NotificationManagerService$EnqueueNotificationRunnable;
+Lcom/android/server/notification/NotificationManagerService$FlagChecker;
+Lcom/android/server/notification/NotificationManagerService$NotificationAssistants;
+Lcom/android/server/notification/NotificationManagerService$NotificationListeners;
+Lcom/android/server/notification/NotificationManagerService$NotificationListeners$2;
+Lcom/android/server/notification/NotificationManagerService$NotificationListeners$3;
+Lcom/android/server/notification/NotificationManagerService$NotificationListeners$6;
+Lcom/android/server/notification/NotificationManagerService$PolicyAccess;
+Lcom/android/server/notification/NotificationManagerService$PostNotificationRunnable;
+Lcom/android/server/notification/NotificationManagerService$PostNotificationRunnable$1;
+Lcom/android/server/notification/NotificationManagerService$RankingHandlerWorker;
+Lcom/android/server/notification/NotificationManagerService$SettingsObserver;
+Lcom/android/server/notification/NotificationManagerService$StatusBarNotificationHolder;
+Lcom/android/server/notification/NotificationManagerService$ToastRecord;
+Lcom/android/server/notification/NotificationManagerService$TrimCache;
+Lcom/android/server/notification/NotificationManagerService$WorkerHandler;
+Lcom/android/server/notification/NotificationRecord;
+Lcom/android/server/notification/NotificationSignalExtractor;
+Lcom/android/server/notification/NotificationUsageStats;
+Lcom/android/server/notification/NotificationUsageStats$1;
+Lcom/android/server/notification/NotificationUsageStats$AggregatedStats;
+Lcom/android/server/notification/NotificationUsageStats$ImportanceHistogram;
+Lcom/android/server/notification/NotificationUsageStats$SingleNotificationStats;
+Lcom/android/server/notification/NotificationUsageStats$SQLiteLog;
+Lcom/android/server/notification/NotificationUsageStats$SQLiteLog$1;
+Lcom/android/server/notification/NotificationUsageStats$SQLiteLog$2;
+Lcom/android/server/notification/PriorityExtractor;
+Lcom/android/server/notification/PropConfig;
+Lcom/android/server/notification/RankingConfig;
+Lcom/android/server/notification/RankingHandler;
+Lcom/android/server/notification/RankingHelper;
+Lcom/android/server/notification/RankingHelper$Record;
+Lcom/android/server/notification/RankingReconsideration;
+Lcom/android/server/notification/RateEstimator;
+Lcom/android/server/notification/ScheduleCalendar;
+Lcom/android/server/notification/ScheduleConditionProvider;
+Lcom/android/server/notification/ScheduleConditionProvider$1;
+Lcom/android/server/notification/SnoozeHelper;
+Lcom/android/server/notification/SnoozeHelper$1;
+Lcom/android/server/notification/SnoozeHelper$Callback;
+Lcom/android/server/notification/SystemConditionProviderService;
+Lcom/android/server/notification/ValidateNotificationPeople;
+Lcom/android/server/notification/ValidateNotificationPeople$1;
+Lcom/android/server/notification/VisibilityExtractor;
+Lcom/android/server/notification/ZenLog;
+Lcom/android/server/notification/ZenModeConditions;
+Lcom/android/server/notification/ZenModeFiltering;
+Lcom/android/server/notification/ZenModeFiltering$RepeatCallers;
+Lcom/android/server/notification/ZenModeHelper;
+Lcom/android/server/notification/ZenModeHelper$Callback;
+Lcom/android/server/notification/ZenModeHelper$H;
+Lcom/android/server/notification/ZenModeHelper$H$ConfigMessageData;
+Lcom/android/server/notification/ZenModeHelper$Metrics;
+Lcom/android/server/notification/ZenModeHelper$RingerModeDelegate;
+Lcom/android/server/notification/ZenModeHelper$SettingsObserver;
+Lcom/android/server/NsdService;
+Lcom/android/server/NsdService$NativeCallbackReceiver;
+Lcom/android/server/NsdService$NsdStateMachine;
+Lcom/android/server/NsdService$NsdStateMachine$1;
+Lcom/android/server/NsdService$NsdStateMachine$DefaultState;
+Lcom/android/server/NsdService$NsdStateMachine$DisabledState;
+Lcom/android/server/NsdService$NsdStateMachine$EnabledState;
+Lcom/android/server/os/DeviceIdentifiersPolicyService;
+Lcom/android/server/os/DeviceIdentifiersPolicyService$DeviceIdentifiersPolicy;
+Lcom/android/server/os/SchedulingPolicyService;
+Lcom/android/server/PersistentDataBlockService;
+Lcom/android/server/PersistentDataBlockService$1;
+Lcom/android/server/PinnerService;
+Lcom/android/server/PinnerService$BinderService;
+Lcom/android/server/PinnerService$PinnedFile;
+Lcom/android/server/PinnerService$PinnerHandler;
+Lcom/android/server/pm/AbstractStatsBase;
+Lcom/android/server/pm/AbstractStatsBase$1;
+Lcom/android/server/pm/BasePermission;
+Lcom/android/server/pm/CompilerStats;
+Lcom/android/server/pm/CompilerStats$PackageStats;
+Lcom/android/server/pm/CrossProfileIntentResolver;
+Lcom/android/server/pm/DefaultPermissionGrantPolicy;
+Lcom/android/server/pm/DefaultPermissionGrantPolicy$1;
+Lcom/android/server/pm/DefaultPermissionGrantPolicy$DefaultPermissionGrant;
+Lcom/android/server/pm/dex/DexManager;
+Lcom/android/server/pm/dex/DexManager$DexSearchResult;
+Lcom/android/server/pm/dex/DexManager$PackageCodeLocations;
+Lcom/android/server/pm/dex/PackageDexUsage;
+Lcom/android/server/pm/dex/PackageDexUsage$DexUseInfo;
+Lcom/android/server/pm/dex/PackageDexUsage$PackageUseInfo;
+Lcom/android/server/pm/EphemeralResolverConnection;
+Lcom/android/server/pm/EphemeralResolverConnection$GetEphemeralResolveInfoCaller;
+Lcom/android/server/pm/EphemeralResolverConnection$GetEphemeralResolveInfoCaller$1;
+Lcom/android/server/pm/EphemeralResolverConnection$MyServiceConnection;
+Lcom/android/server/pm/Installer;
+Lcom/android/server/pm/Installer$1;
+Lcom/android/server/pm/Installer$InstallerException;
+Lcom/android/server/pm/InstantAppRegistry;
+Lcom/android/server/pm/InstantAppRegistry$CookiePersistence;
+Lcom/android/server/pm/InstructionSets;
+Lcom/android/server/pm/KeySetHandle;
+Lcom/android/server/pm/KeySetManagerService;
+Lcom/android/server/pm/KeySetManagerService$PublicKeyHandle;
+Lcom/android/server/pm/LauncherAppsService;
+Lcom/android/server/pm/LauncherAppsService$BroadcastCookie;
+Lcom/android/server/pm/LauncherAppsService$LauncherAppsImpl;
+Lcom/android/server/pm/LauncherAppsService$LauncherAppsImpl$MyPackageMonitor;
+Lcom/android/server/pm/LauncherAppsService$LauncherAppsImpl$PackageCallbackList;
+Lcom/android/server/pm/OtaDexoptService;
+Lcom/android/server/pm/PackageDexOptimizer;
+Lcom/android/server/pm/PackageInstallerService;
+Lcom/android/server/pm/PackageInstallerService$1;
+Lcom/android/server/pm/PackageInstallerService$Callbacks;
+Lcom/android/server/pm/PackageInstallerService$InternalCallback;
+Lcom/android/server/pm/PackageKeySetData;
+Lcom/android/server/pm/PackageManagerException;
+Lcom/android/server/pm/PackageManagerService;
+Lcom/android/server/pm/PackageManagerService$1;
+Lcom/android/server/pm/PackageManagerService$11;
+Lcom/android/server/pm/PackageManagerService$2;
+Lcom/android/server/pm/PackageManagerService$21;
+Lcom/android/server/pm/PackageManagerService$3;
+Lcom/android/server/pm/PackageManagerService$8;
+Lcom/android/server/pm/PackageManagerService$ActivityIntentResolver;
+Lcom/android/server/pm/PackageManagerService$ActivityIntentResolver$ActionIterGenerator;
+Lcom/android/server/pm/PackageManagerService$ActivityIntentResolver$AuthoritiesIterGenerator;
+Lcom/android/server/pm/PackageManagerService$ActivityIntentResolver$CategoriesIterGenerator;
+Lcom/android/server/pm/PackageManagerService$ActivityIntentResolver$IterGenerator;
+Lcom/android/server/pm/PackageManagerService$ActivityIntentResolver$SchemesIterGenerator;
+Lcom/android/server/pm/PackageManagerServiceCompilerMapping;
+Lcom/android/server/pm/PackageManagerService$DefaultContainerConnection;
+Lcom/android/server/pm/PackageManagerService$DumpState;
+Lcom/android/server/pm/PackageManagerService$HandlerParams;
+Lcom/android/server/pm/PackageManagerService$IntentFilterVerifier;
+Lcom/android/server/pm/PackageManagerService$IntentVerifierProxy;
+Lcom/android/server/pm/PackageManagerService$MeasureParams;
+Lcom/android/server/pm/PackageManagerService$MoveCallbacks;
+Lcom/android/server/pm/PackageManagerService$OnPermissionChangeListeners;
+Lcom/android/server/pm/PackageManagerService$PackageHandler;
+Lcom/android/server/pm/PackageManagerService$PackageManagerInternalImpl;
+Lcom/android/server/pm/PackageManagerService$PendingPackageBroadcasts;
+Lcom/android/server/pm/PackageManagerService$ProviderIntentResolver;
+Lcom/android/server/pm/PackageManagerService$ServiceIntentResolver;
+Lcom/android/server/pm/PackageManagerService$SharedLibraryEntry;
+Lcom/android/server/pm/PackageManagerServiceUtils;
+Lcom/android/server/pm/PackageSetting;
+Lcom/android/server/pm/PackageSettingBase;
+Lcom/android/server/pm/PackageSignatures;
+Lcom/android/server/pm/PackageUsage;
+Lcom/android/server/pm/ParallelPackageParser;
+Lcom/android/server/pm/ParallelPackageParser$ParseResult;
+Lcom/android/server/pm/PermissionsState;
+Lcom/android/server/pm/PermissionsState$PermissionData;
+Lcom/android/server/pm/PermissionsState$PermissionState;
+Lcom/android/server/pm/PersistentPreferredIntentResolver;
+Lcom/android/server/pm/Policy;
+Lcom/android/server/pm/PolicyComparator;
+Lcom/android/server/pm/Policy$PolicyBuilder;
+Lcom/android/server/pm/PreferredActivity;
+Lcom/android/server/pm/PreferredComponent;
+Lcom/android/server/pm/PreferredComponent$Callbacks;
+Lcom/android/server/pm/PreferredIntentResolver;
+Lcom/android/server/pm/ProcessLoggingHandler;
+Lcom/android/server/pm/ProtectedPackages;
+Lcom/android/server/pm/SELinuxMMAC;
+Lcom/android/server/pm/SettingBase;
+Lcom/android/server/pm/Settings;
+Lcom/android/server/pm/Settings$RuntimePermissionPersistence;
+Lcom/android/server/pm/Settings$RuntimePermissionPersistence$MyHandler;
+Lcom/android/server/pm/Settings$VersionInfo;
+Lcom/android/server/pm/SharedUserSetting;
+Lcom/android/server/pm/ShortcutLauncher;
+Lcom/android/server/pm/ShortcutPackage;
+Lcom/android/server/pm/ShortcutPackageInfo;
+Lcom/android/server/pm/ShortcutPackageItem;
+Lcom/android/server/pm/ShortcutParser;
+Lcom/android/server/pm/ShortcutRequestPinProcessor;
+Lcom/android/server/pm/ShortcutService;
+Lcom/android/server/pm/ShortcutService$1;
+Lcom/android/server/pm/ShortcutService$2;
+Lcom/android/server/pm/ShortcutService$3;
+Lcom/android/server/pm/ShortcutService$4;
+Lcom/android/server/pm/ShortcutService$5;
+Lcom/android/server/pm/ShortcutService$FileOutputStreamWithPath;
+Lcom/android/server/pm/ShortcutService$InvalidFileFormatException;
+Lcom/android/server/pm/ShortcutService$Lifecycle;
+Lcom/android/server/pm/ShortcutService$LocalService;
+Lcom/android/server/pm/ShortcutUser;
+Lcom/android/server/pm/ShortcutUser$PackageWithUser;
+Lcom/android/server/pm/UserDataPreparer;
+Lcom/android/server/pm/UserManagerService;
+Lcom/android/server/pm/UserManagerService$1;
+Lcom/android/server/pm/UserManagerService$2;
+Lcom/android/server/pm/UserManagerService$3;
+Lcom/android/server/pm/UserManagerService$LifeCycle;
+Lcom/android/server/pm/UserManagerService$LocalService;
+Lcom/android/server/pm/UserManagerService$MainHandler;
+Lcom/android/server/pm/UserManagerService$UserData;
+Lcom/android/server/pm/UserRestrictionsUtils;
+Lcom/android/server/policy/AccessibilityShortcutController;
+Lcom/android/server/policy/AccessibilityShortcutController$1;
+Lcom/android/server/policy/AccessibilityShortcutController$FrameworkObjectProvider;
+Lcom/android/server/policy/BarController;
+Lcom/android/server/policy/BarController$1;
+Lcom/android/server/policy/GlobalKeyManager;
+Lcom/android/server/policy/IconUtilities;
+Lcom/android/server/policy/ImmersiveModeConfirmation;
+Lcom/android/server/policy/ImmersiveModeConfirmation$1;
+Lcom/android/server/policy/ImmersiveModeConfirmation$2;
+Lcom/android/server/policy/ImmersiveModeConfirmation$ClingWindowView;
+Lcom/android/server/policy/ImmersiveModeConfirmation$ClingWindowView$1;
+Lcom/android/server/policy/ImmersiveModeConfirmation$ClingWindowView$2;
+Lcom/android/server/policy/ImmersiveModeConfirmation$ClingWindowView$3;
+Lcom/android/server/policy/ImmersiveModeConfirmation$ClingWindowView$4;
+Lcom/android/server/policy/ImmersiveModeConfirmation$ClingWindowView$5;
+Lcom/android/server/policy/ImmersiveModeConfirmation$ClingWindowView$5$1;
+Lcom/android/server/policy/ImmersiveModeConfirmation$H;
+Lcom/android/server/policy/keyguard/KeyguardServiceDelegate;
+Lcom/android/server/policy/keyguard/KeyguardServiceDelegate$1;
+Lcom/android/server/policy/keyguard/KeyguardServiceDelegate$DrawnListener;
+Lcom/android/server/policy/keyguard/KeyguardServiceDelegate$KeyguardShowDelegate;
+Lcom/android/server/policy/keyguard/KeyguardServiceDelegate$KeyguardState;
+Lcom/android/server/policy/keyguard/KeyguardServiceWrapper;
+Lcom/android/server/policy/keyguard/KeyguardStateMonitor;
+Lcom/android/server/policy/keyguard/KeyguardStateMonitor$StateCallback;
+Lcom/android/server/policy/LogDecelerateInterpolator;
+Lcom/android/server/policy/PhoneWindowManager;
+Lcom/android/server/policy/PhoneWindowManager$1;
+Lcom/android/server/policy/PhoneWindowManager$10;
+Lcom/android/server/policy/PhoneWindowManager$11;
+Lcom/android/server/policy/PhoneWindowManager$12;
+Lcom/android/server/policy/PhoneWindowManager$13;
+Lcom/android/server/policy/PhoneWindowManager$16;
+Lcom/android/server/policy/PhoneWindowManager$17;
+Lcom/android/server/policy/PhoneWindowManager$19;
+Lcom/android/server/policy/PhoneWindowManager$2;
+Lcom/android/server/policy/PhoneWindowManager$3;
+Lcom/android/server/policy/PhoneWindowManager$4;
+Lcom/android/server/policy/PhoneWindowManager$5;
+Lcom/android/server/policy/PhoneWindowManager$6;
+Lcom/android/server/policy/PhoneWindowManager$7;
+Lcom/android/server/policy/PhoneWindowManager$8;
+Lcom/android/server/policy/PhoneWindowManager$9;
+Lcom/android/server/policy/PhoneWindowManager$MyOrientationListener;
+Lcom/android/server/policy/PhoneWindowManager$MyOrientationListener$1;
+Lcom/android/server/policy/PhoneWindowManager$MyWakeGestureListener;
+Lcom/android/server/policy/PhoneWindowManager$PolicyHandler;
+Lcom/android/server/policy/PhoneWindowManager$ScreenLockTimeout;
+Lcom/android/server/policy/PhoneWindowManager$ScreenshotRunnable;
+Lcom/android/server/policy/PhoneWindowManager$SettingsObserver;
+Lcom/android/server/policy/PolicyControl;
+Lcom/android/server/policy/ShortcutManager;
+Lcom/android/server/policy/ShortcutManager$ShortcutInfo;
+Lcom/android/server/policy/SplashScreenSurface;
+Lcom/android/server/policy/StatusBarController;
+Lcom/android/server/policy/StatusBarController$1;
+Lcom/android/server/policy/StatusBarController$1$1;
+Lcom/android/server/policy/StatusBarController$1$2;
+Lcom/android/server/policy/StatusBarController$1$3;
+Lcom/android/server/policy/StatusBarController$1$4;
+Lcom/android/server/policy/SystemGesturesPointerEventListener;
+Lcom/android/server/policy/SystemGesturesPointerEventListener$Callbacks;
+Lcom/android/server/policy/SystemGesturesPointerEventListener$FlingGestureDetector;
+Lcom/android/server/policy/WakeGestureListener;
+Lcom/android/server/policy/WakeGestureListener$1;
+Lcom/android/server/policy/WakeGestureListener$2;
+Lcom/android/server/policy/WindowOrientationListener;
+Lcom/android/server/policy/WindowOrientationListener$OrientationJudge;
+Lcom/android/server/policy/WindowOrientationListener$OrientationSensorJudge;
+Lcom/android/server/policy/WindowOrientationListener$OrientationSensorJudge$1;
+Lcom/android/server/power/Notifier;
+Lcom/android/server/power/Notifier$1;
+Lcom/android/server/power/Notifier$2;
+Lcom/android/server/power/Notifier$3;
+Lcom/android/server/power/Notifier$4;
+Lcom/android/server/power/Notifier$5;
+Lcom/android/server/power/Notifier$6;
+Lcom/android/server/power/Notifier$7;
+Lcom/android/server/power/Notifier$8;
+Lcom/android/server/power/Notifier$NotifierHandler;
+Lcom/android/server/power/PowerManagerService;
+Lcom/android/server/power/PowerManagerService$1;
+Lcom/android/server/power/PowerManagerService$2;
+Lcom/android/server/power/PowerManagerService$BatteryReceiver;
+Lcom/android/server/power/PowerManagerService$BinderService;
+Lcom/android/server/power/PowerManagerService$Constants;
+Lcom/android/server/power/PowerManagerService$DockReceiver;
+Lcom/android/server/power/PowerManagerService$DreamReceiver;
+Lcom/android/server/power/PowerManagerService$LocalService;
+Lcom/android/server/power/PowerManagerService$PowerManagerHandler;
+Lcom/android/server/power/PowerManagerService$SettingsObserver;
+Lcom/android/server/power/PowerManagerService$SuspendBlockerImpl;
+Lcom/android/server/power/PowerManagerService$UidState;
+Lcom/android/server/power/PowerManagerService$UserSwitchedReceiver;
+Lcom/android/server/power/PowerManagerService$WakeLock;
+Lcom/android/server/power/SuspendBlocker;
+Lcom/android/server/power/WirelessChargerDetector;
+Lcom/android/server/power/WirelessChargerDetector$1;
+Lcom/android/server/power/WirelessChargerDetector$2;
+Lcom/android/server/print/PrintManagerService;
+Lcom/android/server/print/PrintManagerService$PrintManagerImpl;
+Lcom/android/server/print/PrintManagerService$PrintManagerImpl$1;
+Lcom/android/server/print/PrintManagerService$PrintManagerImpl$2;
+Lcom/android/server/print/PrintManagerService$PrintManagerImpl$3;
+Lcom/android/server/print/RemotePrintService;
+Lcom/android/server/print/RemotePrintService$MyHandler;
+Lcom/android/server/print/RemotePrintService$PrintServiceCallbacks;
+Lcom/android/server/print/RemotePrintServiceRecommendationService$RemotePrintServiceRecommendationServiceCallbacks;
+Lcom/android/server/print/RemotePrintService$RemotePrintServiceClient;
+Lcom/android/server/print/RemotePrintService$RemoteServiceConneciton;
+Lcom/android/server/print/RemotePrintSpooler;
+Lcom/android/server/print/RemotePrintSpooler$BasePrintSpoolerServiceCallbacks;
+Lcom/android/server/print/RemotePrintSpooler$ClearCustomPrinterIconCacheCaller;
+Lcom/android/server/print/RemotePrintSpooler$ClearCustomPrinterIconCacheCaller$1;
+Lcom/android/server/print/RemotePrintSpooler$GetCustomPrinterIconCaller;
+Lcom/android/server/print/RemotePrintSpooler$GetCustomPrinterIconCaller$1;
+Lcom/android/server/print/RemotePrintSpooler$GetPrintJobInfoCaller;
+Lcom/android/server/print/RemotePrintSpooler$GetPrintJobInfoCaller$1;
+Lcom/android/server/print/RemotePrintSpooler$GetPrintJobInfosCaller;
+Lcom/android/server/print/RemotePrintSpooler$GetPrintJobInfosCaller$1;
+Lcom/android/server/print/RemotePrintSpooler$MyServiceConnection;
+Lcom/android/server/print/RemotePrintSpooler$OnCustomPrinterIconLoadedCaller;
+Lcom/android/server/print/RemotePrintSpooler$OnCustomPrinterIconLoadedCaller$1;
+Lcom/android/server/print/RemotePrintSpooler$PrintSpoolerCallbacks;
+Lcom/android/server/print/RemotePrintSpooler$PrintSpoolerClient;
+Lcom/android/server/print/RemotePrintSpooler$SetPrintJobStateCaller;
+Lcom/android/server/print/RemotePrintSpooler$SetPrintJobStateCaller$1;
+Lcom/android/server/print/RemotePrintSpooler$SetPrintJobTagCaller;
+Lcom/android/server/print/RemotePrintSpooler$SetPrintJobTagCaller$1;
+Lcom/android/server/print/UserState;
+Lcom/android/server/print/UserState$4;
+Lcom/android/server/print/UserState$ListenerRecord;
+Lcom/android/server/print/UserState$PrintJobForAppCache;
+Lcom/android/server/print/UserState$UserStateHandler;
+Lcom/android/server/PruneInstantAppsJobService;
+Lcom/android/server/RandomBlock;
+Lcom/android/server/RecoverySystemService;
+Lcom/android/server/RecoverySystemService$BinderService;
+Lcom/android/server/RescueParty;
+Lcom/android/server/RescueParty$BootThreshold;
+Lcom/android/server/RescueParty$Threshold;
+Lcom/android/server/restrictions/RestrictionsManagerService;
+Lcom/android/server/restrictions/RestrictionsManagerService$RestrictionsManagerImpl;
+Lcom/android/server/retaildemo/RetailDemoModeService;
+Lcom/android/server/retaildemo/RetailDemoModeService$1;
+Lcom/android/server/retaildemo/RetailDemoModeService$Injector;
+Lcom/android/server/retaildemo/RetailDemoModeService$MainHandler;
+Lcom/android/server/retaildemo/RetailDemoModeService$SettingsObserver;
+Lcom/android/server/SamplingProfilerService;
+Lcom/android/server/SamplingProfilerService$1;
+Lcom/android/server/SamplingProfilerService$SamplingProfilerSettingsObserver;
+Lcom/android/server/search/Searchables;
+Lcom/android/server/search/Searchables$1;
+Lcom/android/server/search/SearchManagerService;
+Lcom/android/server/search/SearchManagerService$GlobalSearchProviderObserver;
+Lcom/android/server/search/SearchManagerService$Lifecycle;
+Lcom/android/server/search/SearchManagerService$Lifecycle$1;
+Lcom/android/server/search/SearchManagerService$MyPackageMonitor;
+Lcom/android/server/security/KeyAttestationApplicationIdProviderService;
+Lcom/android/server/SensorNotificationService;
+Lcom/android/server/SerialService;
+Lcom/android/server/ServiceThread;
+Lcom/android/server/ServiceWatcher;
+Lcom/android/server/ServiceWatcher$1;
+Lcom/android/server/ServiceWatcher$2;
+Lcom/android/server/soundtrigger/SoundTriggerDbHelper;
+Lcom/android/server/soundtrigger/SoundTriggerHelper;
+Lcom/android/server/soundtrigger/SoundTriggerHelper$MyCallStateListener;
+Lcom/android/server/soundtrigger/SoundTriggerInternal;
+Lcom/android/server/soundtrigger/SoundTriggerService;
+Lcom/android/server/soundtrigger/SoundTriggerService$LocalSoundTriggerService;
+Lcom/android/server/soundtrigger/SoundTriggerService$SoundTriggerServiceStub;
+Lcom/android/server/statusbar/StatusBarManagerInternal;
+Lcom/android/server/statusbar/StatusBarManagerService;
+Lcom/android/server/statusbar/StatusBarManagerService$1;
+Lcom/android/server/statusbar/StatusBarManagerService$2;
+Lcom/android/server/statusbar/StatusBarManagerService$3;
+Lcom/android/server/statusbar/StatusBarManagerService$4;
+Lcom/android/server/statusbar/StatusBarManagerService$5;
+Lcom/android/server/statusbar/StatusBarManagerService$DisableRecord;
+Lcom/android/server/storage/AppFuseBridge;
+Lcom/android/server/storage/DeviceStorageMonitorInternal;
+Lcom/android/server/storage/DeviceStorageMonitorService;
+Lcom/android/server/storage/DeviceStorageMonitorService$1;
+Lcom/android/server/storage/DeviceStorageMonitorService$2;
+Lcom/android/server/storage/DeviceStorageMonitorService$3;
+Lcom/android/server/storage/DeviceStorageMonitorService$CacheFileDeletedObserver;
+Lcom/android/server/storage/DiskStatsLoggingService;
+Lcom/android/server/StorageManagerService;
+Lcom/android/server/StorageManagerService$1;
+Lcom/android/server/StorageManagerService$Callbacks;
+Lcom/android/server/StorageManagerService$DefaultContainerConnection;
+Lcom/android/server/StorageManagerService$Lifecycle;
+Lcom/android/server/StorageManagerService$ObbActionHandler;
+Lcom/android/server/StorageManagerService$StorageManagerInternalImpl;
+Lcom/android/server/StorageManagerService$StorageManagerServiceHandler;
+Lcom/android/server/SystemConfig;
+Lcom/android/server/SystemConfig$PermissionEntry;
+Lcom/android/server/SystemServer;
+Lcom/android/server/SystemServerInitThreadPool;
+Lcom/android/server/SystemService;
+Lcom/android/server/SystemServiceManager;
+Lcom/android/server/telecom/Analytics;
+Lcom/android/server/telecom/Analytics$1;
+Lcom/android/server/telecom/Analytics$2;
+Lcom/android/server/telecom/Analytics$3;
+Lcom/android/server/telecom/Analytics$CallInfo;
+Lcom/android/server/telecom/Analytics$CallInfoImpl;
+Lcom/android/server/telecom/AsyncRingtonePlayer;
+Lcom/android/server/telecom/BluetoothAdapterProxy;
+Lcom/android/server/telecom/bluetooth/BluetoothDeviceManager;
+Lcom/android/server/telecom/bluetooth/BluetoothDeviceManager$1;
+Lcom/android/server/telecom/bluetooth/BluetoothDeviceManager$2;
+Lcom/android/server/telecom/bluetooth/BluetoothRouteManager;
+Lcom/android/server/telecom/bluetooth/BluetoothRouteManager$1;
+Lcom/android/server/telecom/bluetooth/BluetoothRouteManager$2;
+Lcom/android/server/telecom/bluetooth/BluetoothRouteManager$AudioOffState;
+Lcom/android/server/telecom/bluetooth/BluetoothRouteManager$BluetoothStateListener;
+Lcom/android/server/telecom/BluetoothHeadsetProxy;
+Lcom/android/server/telecom/BluetoothPhoneServiceImpl;
+Lcom/android/server/telecom/BluetoothPhoneServiceImpl$1;
+Lcom/android/server/telecom/BluetoothPhoneServiceImpl$2;
+Lcom/android/server/telecom/BluetoothPhoneServiceImpl$3;
+Lcom/android/server/telecom/BluetoothPhoneServiceImpl$4;
+Lcom/android/server/telecom/BluetoothPhoneServiceImpl$BluetoothPhoneServiceImplFactory;
+Lcom/android/server/telecom/Call;
+Lcom/android/server/telecom/Call$1;
+Lcom/android/server/telecom/CallAudioManager;
+Lcom/android/server/telecom/CallAudioManager$1;
+Lcom/android/server/telecom/CallAudioManager$AudioServiceFactory;
+Lcom/android/server/telecom/CallAudioModeStateMachine;
+Lcom/android/server/telecom/CallAudioModeStateMachine$1;
+Lcom/android/server/telecom/CallAudioModeStateMachine$BaseState;
+Lcom/android/server/telecom/CallAudioModeStateMachine$MessageArgs;
+Lcom/android/server/telecom/CallAudioModeStateMachine$OtherFocusState;
+Lcom/android/server/telecom/CallAudioModeStateMachine$RingingFocusState;
+Lcom/android/server/telecom/CallAudioModeStateMachine$SimCallFocusState;
+Lcom/android/server/telecom/CallAudioModeStateMachine$UnfocusedState;
+Lcom/android/server/telecom/CallAudioModeStateMachine$VoipCallFocusState;
+Lcom/android/server/telecom/CallAudioRoutePeripheralAdapter;
+Lcom/android/server/telecom/CallAudioRouteStateMachine;
+Lcom/android/server/telecom/CallAudioRouteStateMachine$1;
+Lcom/android/server/telecom/CallAudioRouteStateMachine$2;
+Lcom/android/server/telecom/CallAudioRouteStateMachine$3;
+Lcom/android/server/telecom/CallAudioRouteStateMachine$ActiveBluetoothRoute;
+Lcom/android/server/telecom/CallAudioRouteStateMachine$ActiveEarpieceRoute;
+Lcom/android/server/telecom/CallAudioRouteStateMachine$ActiveHeadsetRoute;
+Lcom/android/server/telecom/CallAudioRouteStateMachine$ActiveSpeakerRoute;
+Lcom/android/server/telecom/CallAudioRouteStateMachine$AudioState;
+Lcom/android/server/telecom/CallAudioRouteStateMachine$BluetoothRoute;
+Lcom/android/server/telecom/CallAudioRouteStateMachine$EarpieceRoute;
+Lcom/android/server/telecom/CallAudioRouteStateMachine$HeadsetRoute;
+Lcom/android/server/telecom/CallAudioRouteStateMachine$QuiescentBluetoothRoute;
+Lcom/android/server/telecom/CallAudioRouteStateMachine$QuiescentEarpieceRoute;
+Lcom/android/server/telecom/CallAudioRouteStateMachine$QuiescentHeadsetRoute;
+Lcom/android/server/telecom/CallAudioRouteStateMachine$QuiescentSpeakerRoute;
+Lcom/android/server/telecom/CallAudioRouteStateMachine$RingingBluetoothRoute;
+Lcom/android/server/telecom/CallAudioRouteStateMachine$SpeakerRoute;
+Lcom/android/server/telecom/CallerInfoAsyncQueryFactory;
+Lcom/android/server/telecom/CallerInfoLookupHelper;
+Lcom/android/server/telecom/CallerInfoLookupHelper$1;
+Lcom/android/server/telecom/CallerInfoLookupHelper$CallerInfoQueryInfo;
+Lcom/android/server/telecom/CallerInfoLookupHelper$OnQueryCompleteListener;
+Lcom/android/server/telecom/callfiltering/CallFilterResultCallback;
+Lcom/android/server/telecom/CallIdMapper;
+Lcom/android/server/telecom/CallIdMapper$BiMap;
+Lcom/android/server/telecom/CallIdMapper$ICallInfo;
+Lcom/android/server/telecom/CallIntentProcessor;
+Lcom/android/server/telecom/CallIntentProcessor$Adapter;
+Lcom/android/server/telecom/CallIntentProcessor$AdapterImpl;
+Lcom/android/server/telecom/Call$Listener;
+Lcom/android/server/telecom/Call$ListenerBase;
+Lcom/android/server/telecom/CallLogManager;
+Lcom/android/server/telecom/CallLogManager$AddCallArgs;
+Lcom/android/server/telecom/CallLogManager$LogCallAsyncTask;
+Lcom/android/server/telecom/CallLogManager$LogCallCompletedListener;
+Lcom/android/server/telecom/CallsManager;
+Lcom/android/server/telecom/CallsManager$CallsManagerListener;
+Lcom/android/server/telecom/CallsManagerListenerBase;
+Lcom/android/server/telecom/CallState;
+Lcom/android/server/telecom/components/BluetoothPhoneService;
+Lcom/android/server/telecom/components/PrimaryCallReceiver;
+Lcom/android/server/telecom/components/TelecomBroadcastReceiver;
+Lcom/android/server/telecom/components/TelecomService;
+Lcom/android/server/telecom/components/TelecomService$1;
+Lcom/android/server/telecom/components/TelecomService$2;
+Lcom/android/server/telecom/components/TelecomService$3;
+Lcom/android/server/telecom/components/TelecomService$4;
+Lcom/android/server/telecom/components/TelecomService$5;
+Lcom/android/server/telecom/components/TelecomService$6;
+Lcom/android/server/telecom/components/TelecomService$7;
+Lcom/android/server/telecom/components/TelecomService$8;
+Lcom/android/server/telecom/components/UserCallIntentProcessor;
+Lcom/android/server/telecom/components/UserCallIntentProcessorFactory;
+Lcom/android/server/telecom/ConnectionServiceRepository;
+Lcom/android/server/telecom/ConnectionServiceRepository$1;
+Lcom/android/server/telecom/ConnectionServiceWrapper;
+Lcom/android/server/telecom/ConnectionServiceWrapper$1;
+Lcom/android/server/telecom/ConnectionServiceWrapper$2;
+Lcom/android/server/telecom/ConnectionServiceWrapper$Adapter;
+Lcom/android/server/telecom/ContactsAsyncHelper;
+Lcom/android/server/telecom/ContactsAsyncHelper$ContentResolverAdapter;
+Lcom/android/server/telecom/CreateConnectionProcessor;
+Lcom/android/server/telecom/CreateConnectionProcessor$CallAttemptRecord;
+Lcom/android/server/telecom/CreateConnectionResponse;
+Lcom/android/server/telecom/CreateConnectionTimeout;
+Lcom/android/server/telecom/CurrentUserProxy;
+Lcom/android/server/telecom/DefaultDialerCache;
+Lcom/android/server/telecom/DefaultDialerCache$1;
+Lcom/android/server/telecom/DefaultDialerCache$2;
+Lcom/android/server/telecom/DefaultDialerCache$DefaultDialerManagerAdapter;
+Lcom/android/server/telecom/DefaultDialerCache$DefaultDialerManagerAdapterImpl;
+Lcom/android/server/telecom/DialerCodeReceiver;
+Lcom/android/server/telecom/DockManager;
+Lcom/android/server/telecom/DockManager$DockBroadcastReceiver;
+Lcom/android/server/telecom/DockManager$Listener;
+Lcom/android/server/telecom/DtmfLocalTonePlayer;
+Lcom/android/server/telecom/DtmfLocalTonePlayer$1;
+Lcom/android/server/telecom/EmergencyCallHelper;
+Lcom/android/server/telecom/HeadsetMediaButton;
+Lcom/android/server/telecom/HeadsetMediaButton$1;
+Lcom/android/server/telecom/HeadsetMediaButton$2;
+Lcom/android/server/telecom/HeadsetMediaButtonFactory;
+Lcom/android/server/telecom/InCallAdapter;
+Lcom/android/server/telecom/InCallController;
+Lcom/android/server/telecom/InCallController$1;
+Lcom/android/server/telecom/InCallController$2;
+Lcom/android/server/telecom/InCallController$3;
+Lcom/android/server/telecom/InCallController$CarSwappingInCallServiceConnection;
+Lcom/android/server/telecom/InCallController$EmergencyInCallServiceConnection;
+Lcom/android/server/telecom/InCallController$EmergencyInCallServiceConnection$1;
+Lcom/android/server/telecom/InCallController$InCallServiceBindingConnection;
+Lcom/android/server/telecom/InCallController$InCallServiceBindingConnection$1;
+Lcom/android/server/telecom/InCallController$InCallServiceConnection;
+Lcom/android/server/telecom/InCallController$InCallServiceConnection$Listener;
+Lcom/android/server/telecom/InCallController$InCallServiceInfo;
+Lcom/android/server/telecom/InCallController$NonUIInCallServiceConnectionCollection;
+Lcom/android/server/telecom/InCallTonePlayer$Factory;
+Lcom/android/server/telecom/InCallWakeLockController;
+Lcom/android/server/telecom/InCallWakeLockControllerFactory;
+Lcom/android/server/telecom/InterruptionFilterProxy;
+Lcom/android/server/telecom/LogUtils;
+Lcom/android/server/telecom/LogUtils$Events$Timings;
+Lcom/android/server/telecom/MissedCallNotifier;
+Lcom/android/server/telecom/MissedCallNotifier$CallInfoFactory;
+Lcom/android/server/telecom/nano/TelecomLogClass$InCallServiceInfo;
+Lcom/android/server/telecom/NewOutgoingCallIntentBroadcaster;
+Lcom/android/server/telecom/NewOutgoingCallIntentBroadcaster$NewOutgoingCallBroadcastIntentReceiver;
+Lcom/android/server/telecom/ParcelableCallUtils;
+Lcom/android/server/telecom/PhoneAccountRegistrar;
+Lcom/android/server/telecom/PhoneAccountRegistrar$1;
+Lcom/android/server/telecom/PhoneAccountRegistrar$2;
+Lcom/android/server/telecom/PhoneAccountRegistrar$3;
+Lcom/android/server/telecom/PhoneAccountRegistrar$4;
+Lcom/android/server/telecom/PhoneAccountRegistrar$5;
+Lcom/android/server/telecom/PhoneAccountRegistrar$AsyncXmlWriter;
+Lcom/android/server/telecom/PhoneAccountRegistrar$DefaultPhoneAccountHandle;
+Lcom/android/server/telecom/PhoneAccountRegistrar$Listener;
+Lcom/android/server/telecom/PhoneAccountRegistrar$PhoneAccountRegistrarWriteLock;
+Lcom/android/server/telecom/PhoneAccountRegistrar$State;
+Lcom/android/server/telecom/PhoneAccountRegistrar$XmlSerialization;
+Lcom/android/server/telecom/PhoneNumberUtilsAdapter;
+Lcom/android/server/telecom/PhoneNumberUtilsAdapterImpl;
+Lcom/android/server/telecom/PhoneStateBroadcaster;
+Lcom/android/server/telecom/ProximitySensorManager;
+Lcom/android/server/telecom/ProximitySensorManagerFactory;
+Lcom/android/server/telecom/RespondViaSmsManager;
+Lcom/android/server/telecom/RespondViaSmsManager$1;
+Lcom/android/server/telecom/RingbackPlayer;
+Lcom/android/server/telecom/Ringer;
+Lcom/android/server/telecom/RingtoneFactory;
+Lcom/android/server/telecom/ServiceBinder;
+Lcom/android/server/telecom/ServiceBinder$BindCallback;
+Lcom/android/server/telecom/ServiceBinder$Binder2;
+Lcom/android/server/telecom/ServiceBinder$Listener;
+Lcom/android/server/telecom/ServiceBinder$ServiceBinderConnection;
+Lcom/android/server/telecom/StatusBarNotifier;
+Lcom/android/server/telecom/SystemSettingsUtil;
+Lcom/android/server/telecom/SystemStateProvider;
+Lcom/android/server/telecom/SystemStateProvider$1;
+Lcom/android/server/telecom/SystemStateProvider$SystemStateListener;
+Lcom/android/server/telecom/TelecomBroadcastIntentProcessor;
+Lcom/android/server/telecom/TelecomLoaderService;
+Lcom/android/server/telecom/TelecomLoaderService$1;
+Lcom/android/server/telecom/TelecomLoaderService$2;
+Lcom/android/server/telecom/TelecomLoaderService$3;
+Lcom/android/server/telecom/TelecomLoaderService$4;
+Lcom/android/server/telecom/TelecomLoaderService$5;
+Lcom/android/server/telecom/TelecomLoaderService$TelecomServiceConnection;
+Lcom/android/server/telecom/TelecomLoaderService$TelecomServiceConnection$1;
+Lcom/android/server/telecom/TelecomServiceImpl;
+Lcom/android/server/telecom/TelecomServiceImpl$1;
+Lcom/android/server/telecom/TelecomServiceImpl$SubscriptionManagerAdapter;
+Lcom/android/server/telecom/TelecomServiceImpl$SubscriptionManagerAdapterImpl;
+Lcom/android/server/telecom/TelecomSystem;
+Lcom/android/server/telecom/TelecomSystem$1;
+Lcom/android/server/telecom/TelecomSystem$2;
+Lcom/android/server/telecom/TelecomSystem$3;
+Lcom/android/server/telecom/TelecomSystem$4;
+Lcom/android/server/telecom/TelecomSystem$5;
+Lcom/android/server/telecom/TelecomSystem$6;
+Lcom/android/server/telecom/TelecomSystem$SyncRoot;
+Lcom/android/server/telecom/TelecomWakeLock;
+Lcom/android/server/telecom/TelecomWakeLock$WakeLockAdapter;
+Lcom/android/server/telecom/TelephonyUtil;
+Lcom/android/server/telecom/Timeouts;
+Lcom/android/server/telecom/Timeouts$Adapter;
+Lcom/android/server/telecom/TtyManager;
+Lcom/android/server/telecom/TtyManager$TtyBroadcastReceiver;
+Lcom/android/server/telecom/ui/MissedCallNotifierImpl;
+Lcom/android/server/telecom/ui/MissedCallNotifierImpl$2;
+Lcom/android/server/telecom/ui/MissedCallNotifierImpl$DefaultNotificationBuilderFactory;
+Lcom/android/server/telecom/ui/MissedCallNotifierImpl$MissedCallNotifierImplFactory;
+Lcom/android/server/telecom/ui/MissedCallNotifierImpl$NotificationBuilderFactory;
+Lcom/android/server/telecom/UserUtil;
+Lcom/android/server/telecom/VideoProviderProxy$Listener;
+Lcom/android/server/telecom/WiredHeadsetManager;
+Lcom/android/server/telecom/WiredHeadsetManager$Listener;
+Lcom/android/server/telecom/WiredHeadsetManager$WiredHeadsetCallback;
+Lcom/android/server/TelephonyRegistry;
+Lcom/android/server/TelephonyRegistry$1;
+Lcom/android/server/TelephonyRegistry$2;
+Lcom/android/server/TelephonyRegistry$LogSSC;
+Lcom/android/server/TelephonyRegistry$Record;
+Lcom/android/server/TextServicesManagerService;
+Lcom/android/server/TextServicesManagerService$InternalDeathRecipient;
+Lcom/android/server/TextServicesManagerService$InternalServiceConnection;
+Lcom/android/server/TextServicesManagerService$Lifecycle;
+Lcom/android/server/TextServicesManagerService$SpellCheckerBindGroup;
+Lcom/android/server/TextServicesManagerService$TextServicesBroadcastReceiver;
+Lcom/android/server/TextServicesManagerService$TextServicesMonitor;
+Lcom/android/server/TextServicesManagerService$TextServicesSettings;
+Lcom/android/server/text/TextClassificationService;
+Lcom/android/server/text/TextClassificationService$Lifecycle;
+Lcom/android/server/trust/TrustArchive;
+Lcom/android/server/trust/TrustManagerService;
+Lcom/android/server/trust/TrustManagerService$1;
+Lcom/android/server/trust/TrustManagerService$2;
+Lcom/android/server/trust/TrustManagerService$3;
+Lcom/android/server/trust/TrustManagerService$Receiver;
+Lcom/android/server/trust/TrustManagerService$StrongAuthTracker;
+Lcom/android/server/tv/TvInputHal;
+Lcom/android/server/tv/UinputBridge;
+Lcom/android/server/twilight/TwilightListener;
+Lcom/android/server/twilight/TwilightManager;
+Lcom/android/server/twilight/TwilightService;
+Lcom/android/server/twilight/TwilightService$1;
+Lcom/android/server/UiModeManagerService;
+Lcom/android/server/UiModeManagerService$1;
+Lcom/android/server/UiModeManagerService$2;
+Lcom/android/server/UiModeManagerService$3;
+Lcom/android/server/UiModeManagerService$4;
+Lcom/android/server/UiModeManagerService$5;
+Lcom/android/server/UiModeManagerService$6;
+Lcom/android/server/UiThread;
+Lcom/android/server/UpdateLockService;
+Lcom/android/server/UpdateLockService$LockWatcher;
+Lcom/android/server/usage/AppIdleHistory;
+Lcom/android/server/usage/AppIdleHistory$PackageHistory;
+Lcom/android/server/usage/IntervalStats;
+Lcom/android/server/usage/StorageStatsService;
+Lcom/android/server/usage/StorageStatsService$1;
+Lcom/android/server/usage/StorageStatsService$Lifecycle;
+Lcom/android/server/usage/UnixCalendar;
+Lcom/android/server/usage/UsageStatsDatabase;
+Lcom/android/server/usage/UsageStatsDatabase$1;
+Lcom/android/server/usage/UsageStatsDatabase$StatCombiner;
+Lcom/android/server/usage/UsageStatsService;
+Lcom/android/server/usage/UsageStatsService$1;
+Lcom/android/server/usage/UsageStatsService$2;
+Lcom/android/server/usage/UsageStatsService$BinderService;
+Lcom/android/server/usage/UsageStatsService$DeviceStateReceiver;
+Lcom/android/server/usage/UsageStatsService$H;
+Lcom/android/server/usage/UsageStatsService$LocalService;
+Lcom/android/server/usage/UsageStatsService$PackageReceiver;
+Lcom/android/server/usage/UsageStatsService$SettingsObserver;
+Lcom/android/server/usage/UsageStatsService$UserActionsReceiver;
+Lcom/android/server/usage/UsageStatsXml;
+Lcom/android/server/usage/UsageStatsXmlV1;
+Lcom/android/server/usage/UserUsageStatsService;
+Lcom/android/server/usage/UserUsageStatsService$1;
+Lcom/android/server/usage/UserUsageStatsService$2;
+Lcom/android/server/usage/UserUsageStatsService$3;
+Lcom/android/server/usage/UserUsageStatsService$StatsUpdatedListener;
+Lcom/android/server/usb/MtpNotificationManager;
+Lcom/android/server/usb/MtpNotificationManager$OnOpenInAppListener;
+Lcom/android/server/usb/MtpNotificationManager$Receiver;
+Lcom/android/server/usb/UsbAlsaManager;
+Lcom/android/server/usb/UsbAlsaManager$1;
+Lcom/android/server/usb/UsbAlsaManager$AlsaDevice;
+Lcom/android/server/usb/UsbDebuggingManager;
+Lcom/android/server/usb/UsbDebuggingManager$UsbDebuggingHandler;
+Lcom/android/server/usb/UsbDebuggingManager$UsbDebuggingThread;
+Lcom/android/server/usb/UsbDeviceManager;
+Lcom/android/server/usb/UsbDeviceManager$1;
+Lcom/android/server/usb/UsbDeviceManager$2;
+Lcom/android/server/usb/UsbDeviceManager$AdbSettingsObserver;
+Lcom/android/server/usb/UsbDeviceManager$UsbHandler;
+Lcom/android/server/usb/UsbHostManager;
+Lcom/android/server/usb/UsbHostManager$1;
+Lcom/android/server/usb/UsbMidiDevice;
+Lcom/android/server/usb/UsbPortManager;
+Lcom/android/server/usb/UsbPortManager$1;
+Lcom/android/server/usb/UsbPortManager$2;
+Lcom/android/server/usb/UsbPortManager$DeathRecipient;
+Lcom/android/server/usb/UsbPortManager$HALCallback;
+Lcom/android/server/usb/UsbPortManager$PortInfo;
+Lcom/android/server/usb/UsbPortManager$RawPortInfo;
+Lcom/android/server/usb/UsbPortManager$RawPortInfo$1;
+Lcom/android/server/usb/UsbPortManager$ServiceNotification;
+Lcom/android/server/usb/UsbProfileGroupSettingsManager;
+Lcom/android/server/usb/UsbProfileGroupSettingsManager$1;
+Lcom/android/server/usb/UsbProfileGroupSettingsManager$AccessoryFilter;
+Lcom/android/server/usb/UsbProfileGroupSettingsManager$MyPackageMonitor;
+Lcom/android/server/usb/UsbProfileGroupSettingsManager$UserPackage;
+Lcom/android/server/usb/UsbService;
+Lcom/android/server/usb/UsbService$1;
+Lcom/android/server/usb/UsbService$Lifecycle;
+Lcom/android/server/usb/UsbSettingsManager;
+Lcom/android/server/utils/ManagedApplicationService$BinderChecker;
+Lcom/android/server/VibratorService;
+Lcom/android/server/VibratorService$1;
+Lcom/android/server/VibratorService$2;
+Lcom/android/server/VibratorService$3;
+Lcom/android/server/VibratorService$4;
+Lcom/android/server/VibratorService$SettingsObserver;
+Lcom/android/server/VibratorService$VibrateThread;
+Lcom/android/server/VibratorService$Vibration;
+Lcom/android/server/VibratorService$VibrationInfo;
+Lcom/android/server/voiceinteraction/DatabaseHelper;
+Lcom/android/server/voiceinteraction/VoiceInteractionManagerService;
+Lcom/android/server/voiceinteraction/VoiceInteractionManagerService$1;
+Lcom/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl;
+Lcom/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl$1;
+Lcom/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl$2;
+Lcom/android/server/voiceinteraction/VoiceInteractionManagerService$LocalService;
+Lcom/android/server/voiceinteraction/VoiceInteractionManagerService$VoiceInteractionManagerServiceStub;
+Lcom/android/server/voiceinteraction/VoiceInteractionManagerService$VoiceInteractionManagerServiceStub$1;
+Lcom/android/server/voiceinteraction/VoiceInteractionManagerService$VoiceInteractionManagerServiceStub$SettingsObserver;
+Lcom/android/server/voiceinteraction/VoiceInteractionSessionConnection;
+Lcom/android/server/voiceinteraction/VoiceInteractionSessionConnection$1;
+Lcom/android/server/voiceinteraction/VoiceInteractionSessionConnection$2;
+Lcom/android/server/voiceinteraction/VoiceInteractionSessionConnection$3;
+Lcom/android/server/voiceinteraction/VoiceInteractionSessionConnection$4;
+Lcom/android/server/voiceinteraction/VoiceInteractionSessionConnection$5;
+Lcom/android/server/voiceinteraction/VoiceInteractionSessionConnection$AssistDataForActivity;
+Lcom/android/server/voiceinteraction/VoiceInteractionSessionConnection$Callback;
+Lcom/android/server/vr/CompatibilityDisplay;
+Lcom/android/server/vr/CompatibilityDisplay$1;
+Lcom/android/server/vr/EnabledComponentsObserver;
+Lcom/android/server/vr/EnabledComponentsObserver$1;
+Lcom/android/server/vr/EnabledComponentsObserver$EnabledComponentChangeListener;
+Lcom/android/server/vr/SettingsObserver;
+Lcom/android/server/vr/SettingsObserver$1;
+Lcom/android/server/vr/SettingsObserver$2;
+Lcom/android/server/vr/SettingsObserver$SettingChangeListener;
+Lcom/android/server/vr/VrManagerInternal;
+Lcom/android/server/vr/VrManagerService;
+Lcom/android/server/vr/VrManagerService$1;
+Lcom/android/server/vr/VrManagerService$2;
+Lcom/android/server/vr/VrManagerService$3;
+Lcom/android/server/vr/VrManagerService$LocalService;
+Lcom/android/server/vr/VrManagerService$NotificationAccessManager;
+Lcom/android/server/vr/VrManagerService$VrState;
+Lcom/android/server/wallpaper/WallpaperManagerService;
+Lcom/android/server/wallpaper/WallpaperManagerService$1;
+Lcom/android/server/wallpaper/WallpaperManagerService$2;
+Lcom/android/server/wallpaper/WallpaperManagerService$3;
+Lcom/android/server/wallpaper/WallpaperManagerService$4;
+Lcom/android/server/wallpaper/WallpaperManagerService$Lifecycle;
+Lcom/android/server/wallpaper/WallpaperManagerService$MyPackageMonitor;
+Lcom/android/server/wallpaper/WallpaperManagerService$WallpaperConnection;
+Lcom/android/server/wallpaper/WallpaperManagerService$WallpaperData;
+Lcom/android/server/wallpaper/WallpaperManagerService$WallpaperObserver;
+Lcom/android/server/Watchdog;
+Lcom/android/server/Watchdog$BinderThreadMonitor;
+Lcom/android/server/Watchdog$HandlerChecker;
+Lcom/android/server/Watchdog$Monitor;
+Lcom/android/server/Watchdog$RebootRequestReceiver;
+Lcom/android/server/webkit/SystemImpl;
+Lcom/android/server/webkit/SystemImpl$LazyHolder;
+Lcom/android/server/webkit/SystemInterface;
+Lcom/android/server/webkit/WebViewUpdateService;
+Lcom/android/server/webkit/WebViewUpdateService$1;
+Lcom/android/server/webkit/WebViewUpdateService$BinderService;
+Lcom/android/server/webkit/WebViewUpdateServiceImpl;
+Lcom/android/server/webkit/WebViewUpdateServiceImpl$WebViewUpdater;
+Lcom/android/server/webkit/WebViewUpdateServiceImpl$WebViewUpdater$ProviderAndPackageInfo;
+Lcom/android/server/webkit/WebViewUpdateServiceImpl$WebViewUpdater$WebViewPackageMissingException;
+Lcom/android/server/WidgetBackupProvider;
+Lcom/android/server/wifi/BackupManagerProxy;
+Lcom/android/server/wifi/BaseWifiDiagnostics;
+Lcom/android/server/wifi/BuildProperties;
+Lcom/android/server/wifi/Clock;
+Lcom/android/server/wifi/ConfigurationMap;
+Lcom/android/server/wifi/ExternalScoreEvaluator;
+Lcom/android/server/wifi/FrameworkFacade;
+Lcom/android/server/wifi/HalDeviceManager;
+Lcom/android/server/wifi/HalDeviceManager$ManagerStatusListener;
+Lcom/android/server/wifi/HalDeviceManager$WifiEventCallback;
+Lcom/android/server/wifi/hotspot2/AnqpCache;
+Lcom/android/server/wifi/hotspot2/anqp/Constants$ANQPElementType;
+Lcom/android/server/wifi/hotspot2/ANQPRequestManager;
+Lcom/android/server/wifi/hotspot2/NetworkDetail;
+Lcom/android/server/wifi/hotspot2/NetworkDetail$Ant;
+Lcom/android/server/wifi/hotspot2/NetworkDetail$HSRelease;
+Lcom/android/server/wifi/hotspot2/PasspointEventHandler;
+Lcom/android/server/wifi/hotspot2/PasspointEventHandler$Callbacks;
+Lcom/android/server/wifi/hotspot2/PasspointManager;
+Lcom/android/server/wifi/hotspot2/PasspointManager$CallbackHandler;
+Lcom/android/server/wifi/hotspot2/PasspointNetworkEvaluator;
+Lcom/android/server/wifi/hotspot2/PasspointObjectFactory;
+Lcom/android/server/wifi/hotspot2/Utils;
+Lcom/android/server/wifi/LastMileLogger;
+Lcom/android/server/wifi/LogcatLog;
+Lcom/android/server/wifi/LogcatLog$RealLogMessage;
+Lcom/android/server/wifi/nano/WifiMetricsProto$AlertReasonCount;
+Lcom/android/server/wifi/nano/WifiMetricsProto$ConnectionEvent;
+Lcom/android/server/wifi/nano/WifiMetricsProto$RouterFingerPrint;
+Lcom/android/server/wifi/nano/WifiMetricsProto$RssiPollCount;
+Lcom/android/server/wifi/nano/WifiMetricsProto$SoftApDurationBucket;
+Lcom/android/server/wifi/nano/WifiMetricsProto$SoftApReturnCodeCount;
+Lcom/android/server/wifi/nano/WifiMetricsProto$WifiLog;
+Lcom/android/server/wifi/nano/WifiMetricsProto$WifiLog$ScanReturnEntry;
+Lcom/android/server/wifi/nano/WifiMetricsProto$WifiLog$WifiSystemStateEntry;
+Lcom/android/server/wifi/nano/WifiMetricsProto$WifiScoreCount;
+Lcom/android/server/wifi/p2p/WifiP2pService;
+Lcom/android/server/wifi/p2p/WifiP2pServiceImpl;
+Lcom/android/server/wifi/p2p/WifiP2pServiceImpl$1;
+Lcom/android/server/wifi/p2p/WifiP2pServiceImpl$ClientHandler;
+Lcom/android/server/wifi/p2p/WifiP2pServiceImpl$P2pStateMachine;
+Lcom/android/server/wifi/p2p/WifiP2pServiceImpl$P2pStateMachine$1;
+Lcom/android/server/wifi/p2p/WifiP2pServiceImpl$P2pStateMachine$DefaultState;
+Lcom/android/server/wifi/p2p/WifiP2pServiceImpl$P2pStateMachine$FrequencyConflictState;
+Lcom/android/server/wifi/p2p/WifiP2pServiceImpl$P2pStateMachine$GroupCreatedState;
+Lcom/android/server/wifi/p2p/WifiP2pServiceImpl$P2pStateMachine$GroupCreatingState;
+Lcom/android/server/wifi/p2p/WifiP2pServiceImpl$P2pStateMachine$GroupNegotiationState;
+Lcom/android/server/wifi/p2p/WifiP2pServiceImpl$P2pStateMachine$InactiveState;
+Lcom/android/server/wifi/p2p/WifiP2pServiceImpl$P2pStateMachine$OngoingGroupRemovalState;
+Lcom/android/server/wifi/p2p/WifiP2pServiceImpl$P2pStateMachine$P2pDisabledState;
+Lcom/android/server/wifi/p2p/WifiP2pServiceImpl$P2pStateMachine$P2pDisablingState;
+Lcom/android/server/wifi/p2p/WifiP2pServiceImpl$P2pStateMachine$P2pEnabledState;
+Lcom/android/server/wifi/p2p/WifiP2pServiceImpl$P2pStateMachine$P2pEnablingState;
+Lcom/android/server/wifi/p2p/WifiP2pServiceImpl$P2pStateMachine$P2pNotSupportedState;
+Lcom/android/server/wifi/p2p/WifiP2pServiceImpl$P2pStateMachine$ProvisionDiscoveryState;
+Lcom/android/server/wifi/p2p/WifiP2pServiceImpl$P2pStateMachine$UserAuthorizingInviteRequestState;
+Lcom/android/server/wifi/p2p/WifiP2pServiceImpl$P2pStateMachine$UserAuthorizingJoinState;
+Lcom/android/server/wifi/p2p/WifiP2pServiceImpl$P2pStateMachine$UserAuthorizingNegotiationRequestState;
+Lcom/android/server/wifi/PropertyService;
+Lcom/android/server/wifi/RecommendedNetworkEvaluator;
+Lcom/android/server/wifi/RecommendedNetworkEvaluator$1;
+Lcom/android/server/wifi/RttService;
+Lcom/android/server/wifi/RttService$RttServiceImpl;
+Lcom/android/server/wifi/RttService$RttServiceImpl$1;
+Lcom/android/server/wifi/RttService$RttServiceImpl$2;
+Lcom/android/server/wifi/RttService$RttServiceImpl$ClientHandler;
+Lcom/android/server/wifi/RttService$RttServiceImpl$ClientInfo;
+Lcom/android/server/wifi/RttService$RttServiceImpl$InterfaceEventHandler;
+Lcom/android/server/wifi/RttService$RttServiceImpl$RttStateMachine;
+Lcom/android/server/wifi/RttService$RttServiceImpl$RttStateMachine$DefaultState;
+Lcom/android/server/wifi/RttService$RttServiceImpl$RttStateMachine$EnabledState;
+Lcom/android/server/wifi/RttService$RttServiceImpl$RttStateMachine$InitiatorEnabledState;
+Lcom/android/server/wifi/RttService$RttServiceImpl$RttStateMachine$ResponderEnabledState;
+Lcom/android/server/wifi/SavedNetworkEvaluator;
+Lcom/android/server/wifi/SavedNetworkEvaluator$1;
+Lcom/android/server/wifi/ScanDetail;
+Lcom/android/server/wifi/ScanDetailCache;
+Lcom/android/server/wifi/scanner/BackgroundScanScheduler;
+Lcom/android/server/wifi/scanner/BackgroundScanScheduler$Bucket;
+Lcom/android/server/wifi/scanner/BackgroundScanScheduler$BucketList;
+Lcom/android/server/wifi/scanner/BackgroundScanScheduler$BucketList$1;
+Lcom/android/server/wifi/scanner/ChannelHelper;
+Lcom/android/server/wifi/scanner/ChannelHelper$ChannelCollection;
+Lcom/android/server/wifi/scanner/HalChannelHelper;
+Lcom/android/server/wifi/scanner/HalWifiScannerImpl;
+Lcom/android/server/wifi/scanner/KnownBandsChannelHelper;
+Lcom/android/server/wifi/scanner/KnownBandsChannelHelper$KnownBandsChannelCollection;
+Lcom/android/server/wifi/scanner/ScanScheduleUtil;
+Lcom/android/server/wifi/scanner/SupplicantWifiScannerImpl;
+Lcom/android/server/wifi/scanner/SupplicantWifiScannerImpl$1;
+Lcom/android/server/wifi/scanner/SupplicantWifiScannerImpl$2;
+Lcom/android/server/wifi/scanner/SupplicantWifiScannerImpl$3;
+Lcom/android/server/wifi/scanner/SupplicantWifiScannerImpl$ChangeBuffer;
+Lcom/android/server/wifi/scanner/SupplicantWifiScannerImpl$HwPnoDebouncer;
+Lcom/android/server/wifi/scanner/SupplicantWifiScannerImpl$HwPnoDebouncer$1;
+Lcom/android/server/wifi/scanner/SupplicantWifiScannerImpl$HwPnoDebouncer$Listener;
+Lcom/android/server/wifi/scanner/SupplicantWifiScannerImpl$LastScanSettings;
+Lcom/android/server/wifi/scanner/SupplicantWifiScannerImpl$ScanBuffer;
+Lcom/android/server/wifi/scanner/WifiScannerImpl;
+Lcom/android/server/wifi/scanner/WifiScannerImpl$1;
+Lcom/android/server/wifi/scanner/WifiScannerImpl$2;
+Lcom/android/server/wifi/scanner/WifiScannerImpl$WifiScannerImplFactory;
+Lcom/android/server/wifi/scanner/WifiScanningService;
+Lcom/android/server/wifi/scanner/WifiScanningServiceImpl;
+Lcom/android/server/wifi/scanner/WifiScanningServiceImpl$1;
+Lcom/android/server/wifi/scanner/WifiScanningServiceImpl$ClientHandler;
+Lcom/android/server/wifi/scanner/WifiScanningServiceImpl$ClientInfo;
+Lcom/android/server/wifi/scanner/WifiScanningServiceImpl$ExternalClientInfo;
+Lcom/android/server/wifi/scanner/WifiScanningServiceImpl$RequestInfo;
+Lcom/android/server/wifi/scanner/WifiScanningServiceImpl$RequestList;
+Lcom/android/server/wifi/scanner/WifiScanningServiceImpl$WifiBackgroundScanStateMachine;
+Lcom/android/server/wifi/scanner/WifiScanningServiceImpl$WifiBackgroundScanStateMachine$DefaultState;
+Lcom/android/server/wifi/scanner/WifiScanningServiceImpl$WifiBackgroundScanStateMachine$PausedState;
+Lcom/android/server/wifi/scanner/WifiScanningServiceImpl$WifiBackgroundScanStateMachine$StartedState;
+Lcom/android/server/wifi/scanner/WifiScanningServiceImpl$WifiChangeStateMachine;
+Lcom/android/server/wifi/scanner/WifiScanningServiceImpl$WifiChangeStateMachine$DefaultState;
+Lcom/android/server/wifi/scanner/WifiScanningServiceImpl$WifiChangeStateMachine$MovingState;
+Lcom/android/server/wifi/scanner/WifiScanningServiceImpl$WifiChangeStateMachine$StationaryState;
+Lcom/android/server/wifi/scanner/WifiScanningServiceImpl$WifiPnoScanStateMachine;
+Lcom/android/server/wifi/scanner/WifiScanningServiceImpl$WifiPnoScanStateMachine$DefaultState;
+Lcom/android/server/wifi/scanner/WifiScanningServiceImpl$WifiPnoScanStateMachine$HwPnoScanState;
+Lcom/android/server/wifi/scanner/WifiScanningServiceImpl$WifiPnoScanStateMachine$SingleScanState;
+Lcom/android/server/wifi/scanner/WifiScanningServiceImpl$WifiPnoScanStateMachine$StartedState;
+Lcom/android/server/wifi/scanner/WifiScanningServiceImpl$WifiPnoScanStateMachine$SwPnoScanState;
+Lcom/android/server/wifi/scanner/WifiScanningServiceImpl$WifiSingleScanStateMachine;
+Lcom/android/server/wifi/scanner/WifiScanningServiceImpl$WifiSingleScanStateMachine$DefaultState;
+Lcom/android/server/wifi/scanner/WifiScanningServiceImpl$WifiSingleScanStateMachine$DriverStartedState;
+Lcom/android/server/wifi/scanner/WifiScanningServiceImpl$WifiSingleScanStateMachine$IdleState;
+Lcom/android/server/wifi/scanner/WifiScanningServiceImpl$WifiSingleScanStateMachine$ScanningState;
+Lcom/android/server/wifi/SIMAccessor;
+Lcom/android/server/wifi/StateChangeResult;
+Lcom/android/server/wifi/StateMachineDeathRecipient;
+Lcom/android/server/wifi/SupplicantStateTracker;
+Lcom/android/server/wifi/SupplicantStateTracker$CompletedState;
+Lcom/android/server/wifi/SupplicantStateTracker$ConnectionActiveState;
+Lcom/android/server/wifi/SupplicantStateTracker$DefaultState;
+Lcom/android/server/wifi/SupplicantStateTracker$DisconnectedState;
+Lcom/android/server/wifi/SupplicantStateTracker$DormantState;
+Lcom/android/server/wifi/SupplicantStateTracker$HandshakeState;
+Lcom/android/server/wifi/SupplicantStateTracker$InactiveState;
+Lcom/android/server/wifi/SupplicantStateTracker$ScanState;
+Lcom/android/server/wifi/SupplicantStateTracker$UninitializedState;
+Lcom/android/server/wifi/SystemBuildProperties;
+Lcom/android/server/wifi/SystemPropertyService;
+Lcom/android/server/wifi/util/ByteArrayRingBuffer;
+Lcom/android/server/wifi/util/InformationElementUtil;
+Lcom/android/server/wifi/util/InformationElementUtil$BssLoad;
+Lcom/android/server/wifi/util/InformationElementUtil$Capabilities;
+Lcom/android/server/wifi/util/InformationElementUtil$ExtendedCapabilities;
+Lcom/android/server/wifi/util/InformationElementUtil$HtOperation;
+Lcom/android/server/wifi/util/InformationElementUtil$Interworking;
+Lcom/android/server/wifi/util/InformationElementUtil$RoamingConsortium;
+Lcom/android/server/wifi/util/InformationElementUtil$SupportedRates;
+Lcom/android/server/wifi/util/InformationElementUtil$TrafficIndicationMap;
+Lcom/android/server/wifi/util/InformationElementUtil$VhtOperation;
+Lcom/android/server/wifi/util/InformationElementUtil$Vsa;
+Lcom/android/server/wifi/util/InformationElementUtil$WifiMode;
+Lcom/android/server/wifi/util/ScanResultUtil;
+Lcom/android/server/wifi/util/TelephonyUtil;
+Lcom/android/server/wifi/util/TelephonyUtil$SimAuthRequestData;
+Lcom/android/server/wifi/util/TelephonyUtil$SimAuthResponseData;
+Lcom/android/server/wifi/util/WifiAsyncChannel;
+Lcom/android/server/wifi/util/WifiHandler;
+Lcom/android/server/wifi/util/WifiPermissionsUtil;
+Lcom/android/server/wifi/util/WifiPermissionsWrapper;
+Lcom/android/server/wifi/util/XmlUtil;
+Lcom/android/server/wifi/util/XmlUtil$IpConfigurationXmlUtil;
+Lcom/android/server/wifi/util/XmlUtil$NetworkSelectionStatusXmlUtil;
+Lcom/android/server/wifi/util/XmlUtil$WifiConfigurationXmlUtil;
+Lcom/android/server/wifi/WifiApConfigStore;
+Lcom/android/server/wifi/WifiBackupRestore;
+Lcom/android/server/wifi/WifiCertManager;
+Lcom/android/server/wifi/WifiCertManager$1;
+Lcom/android/server/wifi/WifiConfigManager;
+Lcom/android/server/wifi/WifiConfigManager$1;
+Lcom/android/server/wifi/WifiConfigStore;
+Lcom/android/server/wifi/WifiConfigStore$1;
+Lcom/android/server/wifi/WifiConfigStoreData;
+Lcom/android/server/wifi/WifiConfigStoreData$SharedData;
+Lcom/android/server/wifi/WifiConfigStoreData$UserData;
+Lcom/android/server/wifi/WifiConfigStoreLegacy;
+Lcom/android/server/wifi/WifiConfigStore$StoreFile;
+Lcom/android/server/wifi/WifiConfigurationUtil;
+Lcom/android/server/wifi/WifiConfigurationUtil$WifiConfigurationComparator;
+Lcom/android/server/wifi/WifiConnectivityManager;
+Lcom/android/server/wifi/WifiConnectivityManager$1;
+Lcom/android/server/wifi/WifiConnectivityManager$2;
+Lcom/android/server/wifi/WifiConnectivityManager$3;
+Lcom/android/server/wifi/WifiConnectivityManager$AllSingleScanListener;
+Lcom/android/server/wifi/WifiConnectivityManager$PnoScanListener;
+Lcom/android/server/wifi/WifiConnectivityManager$SingleScanListener;
+Lcom/android/server/wifi/WifiController;
+Lcom/android/server/wifi/WifiController$1;
+Lcom/android/server/wifi/WifiController$2;
+Lcom/android/server/wifi/WifiController$3;
+Lcom/android/server/wifi/WifiController$4;
+Lcom/android/server/wifi/WifiController$ApEnabledState;
+Lcom/android/server/wifi/WifiController$ApStaDisabledState;
+Lcom/android/server/wifi/WifiController$DefaultState;
+Lcom/android/server/wifi/WifiController$DeviceActiveState;
+Lcom/android/server/wifi/WifiController$DeviceInactiveState;
+Lcom/android/server/wifi/WifiController$EcmState;
+Lcom/android/server/wifi/WifiController$FullHighPerfLockHeldState;
+Lcom/android/server/wifi/WifiController$FullLockHeldState;
+Lcom/android/server/wifi/WifiController$NoLockHeldState;
+Lcom/android/server/wifi/WifiController$ScanOnlyLockHeldState;
+Lcom/android/server/wifi/WifiController$StaDisabledWithScanState;
+Lcom/android/server/wifi/WifiController$StaEnabledState;
+Lcom/android/server/wifi/WifiCountryCode;
+Lcom/android/server/wifi/WifiDiagnostics;
+Lcom/android/server/wifi/WifiDiagnostics$1;
+Lcom/android/server/wifi/WifiDiagnostics$LimitedCircularArray;
+Lcom/android/server/wifi/WifiInjector;
+Lcom/android/server/wifi/WifiKeyStore;
+Lcom/android/server/wifi/WifiLastResortWatchdog;
+Lcom/android/server/wifi/WifiLastResortWatchdog$AvailableNetworkFailureCount;
+Lcom/android/server/wifi/WifiLockManager;
+Lcom/android/server/wifi/WifiLockManager$WifiLock;
+Lcom/android/server/wifi/WifiLog;
+Lcom/android/server/wifi/WifiLog$LogMessage;
+Lcom/android/server/wifi/WifiMetrics;
+Lcom/android/server/wifi/WifiMetrics$ConnectionEvent;
+Lcom/android/server/wifi/WifiMetrics$RouterFingerPrint;
+Lcom/android/server/wifi/WifiMonitor;
+Lcom/android/server/wifi/WifiMonitor$1;
+Lcom/android/server/wifi/WifiMonitor$MonitorThread;
+Lcom/android/server/wifi/WifiMulticastLockManager;
+Lcom/android/server/wifi/WifiMulticastLockManager$FilterController;
+Lcom/android/server/wifi/WifiMulticastLockManager$Multicaster;
+Lcom/android/server/wifi/WifiNative;
+Lcom/android/server/wifi/WifiNative$BucketSettings;
+Lcom/android/server/wifi/WifiNative$ChannelSettings;
+Lcom/android/server/wifi/WifiNative$HotlistEventHandler;
+Lcom/android/server/wifi/WifiNative$MonitorThread;
+Lcom/android/server/wifi/WifiNative$PnoEventHandler;
+Lcom/android/server/wifi/WifiNative$RingBufferStatus;
+Lcom/android/server/wifi/WifiNative$RttEventHandler;
+Lcom/android/server/wifi/WifiNative$ScanCapabilities;
+Lcom/android/server/wifi/WifiNative$ScanEventHandler;
+Lcom/android/server/wifi/WifiNative$ScanSettings;
+Lcom/android/server/wifi/WifiNative$SignificantWifiChangeEventHandler;
+Lcom/android/server/wifi/WifiNative$WifiLoggerEventHandler;
+Lcom/android/server/wifi/WifiNative$WifiRssiEventHandler;
+Lcom/android/server/wifi/WifiNetworkHistory;
+Lcom/android/server/wifi/WifiNetworkHistory$1;
+Lcom/android/server/wifi/WifiNetworkSelector;
+Lcom/android/server/wifi/WifiNetworkSelector$BssidBlacklistStatus;
+Lcom/android/server/wifi/WifiNetworkSelector$NetworkEvaluator;
+Lcom/android/server/wifi/WifiScoreReport;
+Lcom/android/server/wifi/WifiService;
+Lcom/android/server/wifi/WifiServiceImpl;
+Lcom/android/server/wifi/WifiServiceImpl$1;
+Lcom/android/server/wifi/WifiServiceImpl$2;
+Lcom/android/server/wifi/WifiServiceImpl$3;
+Lcom/android/server/wifi/WifiServiceImpl$4;
+Lcom/android/server/wifi/WifiServiceImpl$5;
+Lcom/android/server/wifi/WifiServiceImpl$ClientHandler;
+Lcom/android/server/wifi/WifiServiceImpl$WifiStateMachineHandler;
+Lcom/android/server/wifi/WifiSettingsStore;
+Lcom/android/server/wifi/WifiStateMachine;
+Lcom/android/server/wifi/WifiStateMachine$1;
+Lcom/android/server/wifi/WifiStateMachine$2;
+Lcom/android/server/wifi/WifiStateMachine$3;
+Lcom/android/server/wifi/WifiStateMachine$4;
+Lcom/android/server/wifi/WifiStateMachine$ConnectedState;
+Lcom/android/server/wifi/WifiStateMachine$ConnectModeState;
+Lcom/android/server/wifi/WifiStateMachine$DefaultState;
+Lcom/android/server/wifi/WifiStateMachine$DisconnectedState;
+Lcom/android/server/wifi/WifiStateMachine$DisconnectingState;
+Lcom/android/server/wifi/WifiStateMachine$InitialState;
+Lcom/android/server/wifi/WifiStateMachine$IpManagerCallback;
+Lcom/android/server/wifi/WifiStateMachine$L2ConnectedState;
+Lcom/android/server/wifi/WifiStateMachine$ObtainingIpState;
+Lcom/android/server/wifi/WifiStateMachine$RoamingState;
+Lcom/android/server/wifi/WifiStateMachine$ScanModeState;
+Lcom/android/server/wifi/WifiStateMachine$SoftApState;
+Lcom/android/server/wifi/WifiStateMachine$SupplicantStartedState;
+Lcom/android/server/wifi/WifiStateMachine$SupplicantStartingState;
+Lcom/android/server/wifi/WifiStateMachine$SupplicantStoppingState;
+Lcom/android/server/wifi/WifiStateMachine$UntrustedWifiNetworkFactory;
+Lcom/android/server/wifi/WifiStateMachine$WaitForP2pDisableState;
+Lcom/android/server/wifi/WifiStateMachine$WifiNetworkAgent;
+Lcom/android/server/wifi/WifiStateMachine$WifiNetworkFactory;
+Lcom/android/server/wifi/WifiStateMachine$WpsRunningState;
+Lcom/android/server/wifi/WifiSupplicantControl;
+Lcom/android/server/wifi/WifiSupplicantControl$WpaConfigFileObserver;
+Lcom/android/server/wifi/WifiSupplicantHal;
+Lcom/android/server/wifi/WifiSupplicantHal$HalDeviceManagerStatusListener;
+Lcom/android/server/wifi/WifiTrafficPoller;
+Lcom/android/server/wifi/WifiTrafficPoller$1;
+Lcom/android/server/wifi/WifiTrafficPoller$TrafficHandler;
+Lcom/android/server/wifi/WifiVendorHal;
+Lcom/android/server/wifi/WifiVendorHal$HalDeviceManagerStatusListener;
+Lcom/android/server/WiredAccessoryManager;
+Lcom/android/server/WiredAccessoryManager$1;
+Lcom/android/server/WiredAccessoryManager$WiredAccessoryObserver;
+Lcom/android/server/WiredAccessoryManager$WiredAccessoryObserver$UEventInfo;
+Lcom/android/server/wm/animation/ClipRectLRAnimation;
+Lcom/android/server/wm/animation/ClipRectTBAnimation;
+Lcom/android/server/wm/AppTokenList;
+Lcom/android/server/wm/AppTransition;
+Lcom/android/server/wm/AppTransition$1;
+Lcom/android/server/wm/AppTransition$2;
+Lcom/android/server/wm/AppTransition$4;
+Lcom/android/server/wm/AppWindowAnimator;
+Lcom/android/server/wm/AppWindowAnimator$DummyAnimation;
+Lcom/android/server/wm/AppWindowContainerController;
+Lcom/android/server/wm/AppWindowContainerListener;
+Lcom/android/server/wm/AppWindowToken;
+Lcom/android/server/wm/BlackFrame;
+Lcom/android/server/wm/BlackFrame$BlackSurface;
+Lcom/android/server/wm/BoundsAnimationController;
+Lcom/android/server/wm/BoundsAnimationController$AnimateBoundsUser;
+Lcom/android/server/wm/BoundsAnimationController$AppTransitionNotifier;
+Lcom/android/server/wm/DimLayer;
+Lcom/android/server/wm/DimLayerController;
+Lcom/android/server/wm/DimLayerController$DimLayerState;
+Lcom/android/server/wm/DimLayer$DimLayerUser;
+Lcom/android/server/wm/DisplayContent;
+Lcom/android/server/wm/DisplayContent$ApplySurfaceChangesTransactionState;
+Lcom/android/server/wm/DisplayContent$DisplayChildWindowContainer;
+Lcom/android/server/wm/DisplayContent$NonAppWindowContainers;
+Lcom/android/server/wm/DisplayContent$ScreenshotApplicationState;
+Lcom/android/server/wm/DisplayContent$Screenshoter;
+Lcom/android/server/wm/DisplayContent$TaskForResizePointSearchResult;
+Lcom/android/server/wm/DisplayContent$TaskStackContainers;
+Lcom/android/server/wm/DisplaySettings;
+Lcom/android/server/wm/DisplaySettings$Entry;
+Lcom/android/server/wm/DockedStackDividerController;
+Lcom/android/server/wm/InputConsumerImpl;
+Lcom/android/server/wm/InputMonitor;
+Lcom/android/server/wm/InputMonitor$UpdateInputForAllWindowsConsumer;
+Lcom/android/server/wm/KeyguardDisableHandler;
+Lcom/android/server/wm/nano/WindowManagerProtos$TaskSnapshotProto;
+Lcom/android/server/wm/PinnedStackController;
+Lcom/android/server/wm/PinnedStackController$PinnedStackControllerCallback;
+Lcom/android/server/wm/PinnedStackController$PinnedStackListenerDeathHandler;
+Lcom/android/server/wm/PointerEventDispatcher;
+Lcom/android/server/wm/RootWindowContainer;
+Lcom/android/server/wm/ScreenRotationAnimation;
+Lcom/android/server/wm/Session;
+Lcom/android/server/wm/SnapshotStartingData;
+Lcom/android/server/wm/SplashScreenStartingData;
+Lcom/android/server/wm/StackWindowController;
+Lcom/android/server/wm/StackWindowController$H;
+Lcom/android/server/wm/StackWindowListener;
+Lcom/android/server/wm/StartingData;
+Lcom/android/server/wm/Task;
+Lcom/android/server/wm/TaskSnapshotCache;
+Lcom/android/server/wm/TaskSnapshotCache$CacheEntry;
+Lcom/android/server/wm/TaskSnapshotController;
+Lcom/android/server/wm/TaskSnapshotLoader;
+Lcom/android/server/wm/TaskSnapshotPersister;
+Lcom/android/server/wm/TaskSnapshotPersister$1;
+Lcom/android/server/wm/TaskSnapshotPersister$DeleteWriteQueueItem;
+Lcom/android/server/wm/TaskSnapshotPersister$DirectoryResolver;
+Lcom/android/server/wm/TaskSnapshotPersister$RemoveObsoleteFilesQueueItem;
+Lcom/android/server/wm/TaskSnapshotPersister$StoreWriteQueueItem;
+Lcom/android/server/wm/TaskSnapshotPersister$WriteQueueItem;
+Lcom/android/server/wm/TaskSnapshotSurface;
+Lcom/android/server/wm/TaskSnapshotSurface$1;
+Lcom/android/server/wm/TaskSnapshotSurface$Window;
+Lcom/android/server/wm/TaskStack;
+Lcom/android/server/wm/TaskTapPointerEventListener;
+Lcom/android/server/wm/TaskWindowContainerController;
+Lcom/android/server/wm/TaskWindowContainerController$H;
+Lcom/android/server/wm/TaskWindowContainerListener;
+Lcom/android/server/wm/UnknownAppVisibilityController;
+Lcom/android/server/wm/WallpaperController;
+Lcom/android/server/wm/WallpaperController$FindWallpaperTargetResult;
+Lcom/android/server/wm/WallpaperWindowToken;
+Lcom/android/server/wm/WindowAnimator;
+Lcom/android/server/wm/WindowAnimator$1;
+Lcom/android/server/wm/WindowAnimator$DisplayContentsAnimator;
+Lcom/android/server/wm/WindowContainer;
+Lcom/android/server/wm/WindowContainerController;
+Lcom/android/server/wm/WindowContainer$ForAllWindowsConsumerWrapper;
+Lcom/android/server/wm/WindowContainerListener;
+Lcom/android/server/wm/WindowLayersController;
+Lcom/android/server/wm/WindowManagerService;
+Lcom/android/server/wm/WindowManagerService$1;
+Lcom/android/server/wm/WindowManagerService$2;
+Lcom/android/server/wm/WindowManagerService$3;
+Lcom/android/server/wm/WindowManagerService$4;
+Lcom/android/server/wm/WindowManagerService$6;
+Lcom/android/server/wm/WindowManagerService$AppFreezeListener;
+Lcom/android/server/wm/WindowManagerService$H;
+Lcom/android/server/wm/WindowManagerService$LocalService;
+Lcom/android/server/wm/WindowManagerService$MousePositionTracker;
+Lcom/android/server/wm/WindowManagerService$RotationWatcher;
+Lcom/android/server/wm/WindowManagerService$SettingsObserver;
+Lcom/android/server/wm/WindowState;
+Lcom/android/server/wm/WindowState$1;
+Lcom/android/server/wm/WindowState$2;
+Lcom/android/server/wm/WindowState$3;
+Lcom/android/server/wm/WindowStateAnimator;
+Lcom/android/server/wm/WindowState$DeathRecipient;
+Lcom/android/server/wm/WindowState$UpdateReportedVisibilityResults;
+Lcom/android/server/wm/WindowSurfaceController;
+Lcom/android/server/wm/WindowSurfaceController$SurfaceControlWithBackground;
+Lcom/android/server/wm/WindowSurfacePlacer;
+Lcom/android/server/wm/WindowSurfacePlacer$LayerAndToken;
+Lcom/android/server/wm/WindowToken;
+Lcom/google/android/collect/Lists;
+Lcom/google/android/collect/Maps;
+Lcom/google/android/collect/Sets;
+Lcom/google/android/gles_jni/EGLImpl;
+Lcom/google/android/gles_jni/GLImpl;
+Lcom/google/protobuf/nano/InvalidProtocolBufferNanoException;
+Lcom/google/protobuf/nano/MessageNano;
+LD;
+Ldalvik/annotation/optimization/CriticalNative;
+Ldalvik/annotation/optimization/FastNative;
+Ldalvik/system/BaseDexClassLoader;
+Ldalvik/system/BaseDexClassLoader$Reporter;
+Ldalvik/system/BlockGuard;
+Ldalvik/system/BlockGuard$1;
+Ldalvik/system/BlockGuard$2;
+Ldalvik/system/BlockGuard$BlockGuardPolicyException;
+Ldalvik/system/BlockGuard$Policy;
+Ldalvik/system/ClassExt;
+Ldalvik/system/CloseGuard;
+Ldalvik/system/CloseGuard$DefaultReporter;
+Ldalvik/system/CloseGuard$DefaultTracker;
+Ldalvik/system/CloseGuard$Reporter;
+Ldalvik/system/CloseGuard$Tracker;
+Ldalvik/system/DalvikLogHandler;
+Ldalvik/system/DexClassLoader;
+Ldalvik/system/DexFile;
+Ldalvik/system/DexFile$DFEnum;
+Ldalvik/system/DexPathList;
+Ldalvik/system/DexPathList$Element;
+Ldalvik/system/DexPathList$NativeLibraryElement;
+Ldalvik/system/EmulatedStackFrame;
+Ldalvik/system/EmulatedStackFrame$Range;
+Ldalvik/system/InMemoryDexClassLoader$DexData;
+Ldalvik/system/PathClassLoader;
+Ldalvik/system/SocketTagger;
+Ldalvik/system/SocketTagger$1;
+Ldalvik/system/VMDebug;
+Ldalvik/system/VMRuntime;
+Ldalvik/system/VMStack;
+Ldalvik/system/ZygoteHooks;
+LF;
+LI;
+LJ;
+Ljava/io/Bits;
+Ljava/io/BufferedInputStream;
+Ljava/io/BufferedOutputStream;
+Ljava/io/BufferedReader;
+Ljava/io/BufferedWriter;
+Ljava/io/ByteArrayInputStream;
+Ljava/io/ByteArrayOutputStream;
+Ljava/io/CharArrayWriter;
+Ljava/io/Closeable;
+Ljava/io/Console;
+Ljava/io/DataInput;
+Ljava/io/DataInputStream;
+Ljava/io/DataOutput;
+Ljava/io/DataOutputStream;
+Ljava/io/DefaultFileSystem;
+Ljava/io/EOFException;
+Ljava/io/ExpiringCache;
+Ljava/io/ExpiringCache$1;
+Ljava/io/ExpiringCache$Entry;
+Ljava/io/Externalizable;
+Ljava/io/File;
+Ljava/io/FileDescriptor;
+Ljava/io/FileDescriptor$1;
+Ljava/io/FileInputStream;
+Ljava/io/FileInputStream$UseManualSkipException;
+Ljava/io/FilenameFilter;
+Ljava/io/FileNotFoundException;
+Ljava/io/FileOutputStream;
+Ljava/io/File$PathStatus;
+Ljava/io/FileReader;
+Ljava/io/FileSystem;
+Ljava/io/File$TempDirectory;
+Ljava/io/FileWriter;
+Ljava/io/FilterInputStream;
+Ljava/io/FilterOutputStream;
+Ljava/io/Flushable;
+Ljava/io/InputStream;
+Ljava/io/InputStreamReader;
+Ljava/io/InterruptedIOException;
+Ljava/io/InvalidObjectException;
+Ljava/io/IOException;
+Ljava/io/ObjectInput;
+Ljava/io/ObjectInputStream;
+Ljava/io/ObjectInputStream$BlockDataInputStream;
+Ljava/io/ObjectInputStream$HandleTable;
+Ljava/io/ObjectInputStream$HandleTable$HandleList;
+Ljava/io/ObjectInputStream$PeekInputStream;
+Ljava/io/ObjectInputStream$ValidationList;
+Ljava/io/ObjectOutput;
+Ljava/io/ObjectOutputStream;
+Ljava/io/ObjectOutputStream$PutField;
+Ljava/io/ObjectStreamClass;
+Ljava/io/ObjectStreamConstants;
+Ljava/io/ObjectStreamException;
+Ljava/io/ObjectStreamField;
+Ljava/io/OutputStream;
+Ljava/io/OutputStreamWriter;
+Ljava/io/PrintStream;
+Ljava/io/PrintWriter;
+Ljava/io/PushbackInputStream;
+Ljava/io/RandomAccessFile;
+Ljava/io/Reader;
+Ljava/io/Serializable;
+Ljava/io/SerializablePermission;
+Ljava/io/StringWriter;
+Ljava/io/UnixFileSystem;
+Ljava/io/UnsupportedEncodingException;
+Ljava/io/UTFDataFormatException;
+Ljava/io/Writer;
+Ljava/lang/AbstractMethodError;
+Ljava/lang/AbstractStringBuilder;
+Ljava/lang/AndroidHardcodedSystemProperties;
+Ljava/lang/annotation/Annotation;
+Ljava/lang/annotation/AnnotationTypeMismatchException;
+Ljava/lang/annotation/IncompleteAnnotationException;
+Ljava/lang/annotation/Inherited;
+Ljava/lang/Appendable;
+Ljava/lang/ArithmeticException;
+Ljava/lang/ArrayIndexOutOfBoundsException;
+Ljava/lang/ArrayStoreException;
+Ljava/lang/AssertionError;
+Ljava/lang/AutoCloseable;
+Ljava/lang/Boolean;
+Ljava/lang/BootClassLoader;
+Ljava/lang/Byte;
+Ljava/lang/Byte$ByteCache;
+Ljava/lang/CaseMapper;
+Ljava/lang/CaseMapper$1;
+Ljava/lang/Character;
+Ljava/lang/Character$CharacterCache;
+Ljava/lang/Character$Subset;
+Ljava/lang/Character$UnicodeBlock;
+Ljava/lang/CharSequence;
+Ljava/lang/CharSequence$1CharIterator;
+Ljava/lang/CharSequence$1CodePointIterator;
+Ljava/lang/Class;
+Ljava/lang/Class$Caches;
+Ljava/lang/ClassCastException;
+Ljava/lang/ClassLoader;
+Ljava/lang/ClassLoader$SystemClassLoader;
+Ljava/lang/ClassNotFoundException;
+Ljava/lang/Cloneable;
+Ljava/lang/CloneNotSupportedException;
+Ljava/lang/Comparable;
+Ljava/lang/Daemons;
+Ljava/lang/Daemons$Daemon;
+Ljava/lang/Daemons$FinalizerDaemon;
+Ljava/lang/Daemons$FinalizerWatchdogDaemon;
+Ljava/lang/Daemons$HeapTaskDaemon;
+Ljava/lang/Daemons$ReferenceQueueDaemon;
+Ljava/lang/DexCache;
+Ljava/lang/Double;
+Ljava/lang/Enum;
+Ljava/lang/Enum$1;
+Ljava/lang/EnumConstantNotPresentException;
+Ljava/lang/Error;
+Ljava/lang/Exception;
+Ljava/lang/ExceptionInInitializerError;
+Ljava/lang/Float;
+Ljava/lang/IllegalAccessError;
+Ljava/lang/IllegalAccessException;
+Ljava/lang/IllegalArgumentException;
+Ljava/lang/IllegalStateException;
+Ljava/lang/IllegalThreadStateException;
+Ljava/lang/IncompatibleClassChangeError;
+Ljava/lang/IndexOutOfBoundsException;
+Ljava/lang/InheritableThreadLocal;
+Ljava/lang/InstantiationException;
+Ljava/lang/Integer;
+Ljava/lang/Integer$IntegerCache;
+Ljava/lang/InternalError;
+Ljava/lang/InterruptedException;
+Ljava/lang/invoke/MethodHandle;
+Ljava/lang/invoke/MethodHandleImpl;
+Ljava/lang/invoke/MethodHandleImpl$HandleInfo;
+Ljava/lang/invoke/MethodHandleInfo;
+Ljava/lang/invoke/MethodHandles;
+Ljava/lang/invoke/MethodHandleStatics;
+Ljava/lang/invoke/MethodType;
+Ljava/lang/invoke/MethodType$ConcurrentWeakInternSet;
+Ljava/lang/invoke/MethodType$ConcurrentWeakInternSet$WeakEntry;
+Ljava/lang/invoke/MethodTypeForm;
+Ljava/lang/invoke/Transformers$BindTo;
+Ljava/lang/invoke/Transformers$Collector;
+Ljava/lang/invoke/Transformers$Spreader;
+Ljava/lang/invoke/Transformers$Transformer;
+Ljava/lang/invoke/Transformers$VarargsCollector;
+Ljava/lang/invoke/WrongMethodTypeException;
+Ljava/lang/Iterable;
+Ljava/lang/JavaLangAccess;
+Ljava/lang/LinkageError;
+Ljava/lang/Long;
+Ljava/lang/Long$LongCache;
+Ljava/lang/Math;
+Ljava/lang/Math$RandomNumberGeneratorHolder;
+Ljava/lang/NoClassDefFoundError;
+Ljava/lang/NoSuchFieldError;
+Ljava/lang/NoSuchFieldException;
+Ljava/lang/NoSuchMethodError;
+Ljava/lang/NoSuchMethodException;
+Ljava/lang/NullPointerException;
+Ljava/lang/Number;
+Ljava/lang/NumberFormatException;
+Ljava/lang/Object;
+Ljava/lang/OutOfMemoryError;
+Ljava/lang/Package;
+Ljava/lang/Process;
+Ljava/lang/ProcessBuilder;
+Ljava/lang/ProcessEnvironment;
+Ljava/lang/Readable;
+Ljava/lang/ref/FinalizerReference;
+Ljava/lang/ref/FinalizerReference$Sentinel;
+Ljava/lang/reflect/AccessibleObject;
+Ljava/lang/reflect/AnnotatedElement;
+Ljava/lang/reflect/Array;
+Ljava/lang/reflect/Constructor;
+Ljava/lang/reflect/Executable;
+Ljava/lang/reflect/Executable$GenericInfo;
+Ljava/lang/reflect/Field;
+Ljava/lang/reflect/GenericDeclaration;
+Ljava/lang/reflect/InvocationHandler;
+Ljava/lang/reflect/InvocationTargetException;
+Ljava/lang/ReflectiveOperationException;
+Ljava/lang/reflect/MalformedParametersException;
+Ljava/lang/reflect/Member;
+Ljava/lang/reflect/Method;
+Ljava/lang/reflect/Method$1;
+Ljava/lang/reflect/Modifier;
+Ljava/lang/reflect/Parameter;
+Ljava/lang/reflect/ParameterizedType;
+Ljava/lang/reflect/Proxy;
+Ljava/lang/reflect/Proxy$1;
+Ljava/lang/reflect/Proxy$Key1;
+Ljava/lang/reflect/Proxy$Key2;
+Ljava/lang/reflect/Proxy$KeyFactory;
+Ljava/lang/reflect/Proxy$KeyX;
+Ljava/lang/reflect/Proxy$ProxyClassFactory;
+Ljava/lang/reflect/Type;
+Ljava/lang/reflect/TypeVariable;
+Ljava/lang/reflect/WeakCache;
+Ljava/lang/reflect/WeakCache$CacheKey;
+Ljava/lang/reflect/WeakCache$Factory;
+Ljava/lang/reflect/WeakCache$LookupValue;
+Ljava/lang/reflect/WeakCache$Value;
+Ljava/lang/ref/PhantomReference;
+Ljava/lang/ref/Reference;
+Ljava/lang/ref/ReferenceQueue;
+Ljava/lang/ref/SoftReference;
+Ljava/lang/ref/WeakReference;
+Ljava/lang/Runnable;
+Ljava/lang/Runtime;
+Ljava/lang/RuntimeException;
+Ljava/lang/RuntimePermission;
+Ljava/lang/SecurityException;
+Ljava/lang/Short;
+Ljava/lang/Short$ShortCache;
+Ljava/lang/StackOverflowError;
+Ljava/lang/StackTraceElement;
+Ljava/lang/StrictMath;
+Ljava/lang/String;
+Ljava/lang/StringBuffer;
+Ljava/lang/StringBuilder;
+Ljava/lang/String$CaseInsensitiveComparator;
+Ljava/lang/StringFactory;
+Ljava/lang/StringIndexOutOfBoundsException;
+Ljava/lang/System;
+Ljava/lang/System$PropertiesWithNonOverrideableDefaults;
+Ljava/lang/Thread;
+Ljava/lang/Thread$1;
+Ljava/lang/Thread$Caches;
+Ljava/lang/ThreadDeath;
+Ljava/lang/ThreadGroup;
+Ljava/lang/ThreadLocal;
+Ljava/lang/ThreadLocal$ThreadLocalMap;
+Ljava/lang/ThreadLocal$ThreadLocalMap$Entry;
+Ljava/lang/Thread$State;
+Ljava/lang/Thread$UncaughtExceptionHandler;
+Ljava/lang/Thread$WeakClassKey;
+Ljava/lang/Throwable;
+Ljava/lang/Throwable$PrintStreamOrWriter;
+Ljava/lang/Throwable$SentinelHolder;
+Ljava/lang/Throwable$WrappedPrintStream;
+Ljava/lang/Throwable$WrappedPrintWriter;
+Ljava/lang/TypeNotPresentException;
+Ljava/lang/UNIXProcess;
+Ljava/lang/UnsatisfiedLinkError;
+Ljava/lang/UnsupportedOperationException;
+Ljava/lang/VirtualMachineError;
+Ljava/lang/VMClassLoader;
+Ljava/lang/Void;
+Ljava/math/BigInt;
+Ljava/math/BigInteger;
+Ljava/math/NativeBN;
+Ljava/math/RoundingMode;
+Ljava/net/AbstractPlainDatagramSocketImpl;
+Ljava/net/AbstractPlainSocketImpl;
+Ljava/net/AddressCache;
+Ljava/net/AddressCache$AddressCacheEntry;
+Ljava/net/AddressCache$AddressCacheKey;
+Ljava/net/ConnectException;
+Ljava/net/CookieHandler;
+Ljava/net/DatagramPacket;
+Ljava/net/DatagramSocket;
+Ljava/net/DatagramSocket$1;
+Ljava/net/DatagramSocketImpl;
+Ljava/net/DefaultDatagramSocketImplFactory;
+Ljava/net/DefaultInterface;
+Ljava/net/HttpURLConnection;
+Ljava/net/IDN;
+Ljava/net/Inet4Address;
+Ljava/net/Inet6Address;
+Ljava/net/Inet6AddressImpl;
+Ljava/net/Inet6Address$Inet6AddressHolder;
+Ljava/net/InetAddress;
+Ljava/net/InetAddress$1;
+Ljava/net/InetAddressImpl;
+Ljava/net/InetAddress$InetAddressHolder;
+Ljava/net/InetSocketAddress;
+Ljava/net/InetSocketAddress$InetSocketAddressHolder;
+Ljava/net/InterfaceAddress;
+Ljava/net/JarURLConnection;
+Ljava/net/MalformedURLException;
+Ljava/net/MulticastSocket;
+Ljava/net/NetworkInterface;
+Ljava/net/Parts;
+Ljava/net/PlainDatagramSocketImpl;
+Ljava/net/PlainSocketImpl;
+Ljava/net/ProtocolException;
+Ljava/net/Proxy;
+Ljava/net/ProxySelector;
+Ljava/net/Proxy$Type;
+Ljava/net/ResponseCache;
+Ljava/net/ServerSocket;
+Ljava/net/Socket;
+Ljava/net/Socket$2;
+Ljava/net/Socket$3;
+Ljava/net/SocketAddress;
+Ljava/net/SocketException;
+Ljava/net/SocketImpl;
+Ljava/net/SocketInputStream;
+Ljava/net/SocketOptions;
+Ljava/net/SocketOutputStream;
+Ljava/net/SocketTimeoutException;
+Ljava/net/SocksConsts;
+Ljava/net/SocksSocketImpl;
+Ljava/net/UnknownHostException;
+Ljava/net/URI;
+Ljava/net/URI$Parser;
+Ljava/net/URISyntaxException;
+Ljava/net/URL;
+Ljava/net/URLConnection;
+Ljava/net/URLEncoder;
+Ljava/net/URLStreamHandler;
+Ljava/net/URLStreamHandlerFactory;
+Ljava/nio/Bits;
+Ljava/nio/Buffer;
+Ljava/nio/BufferOverflowException;
+Ljava/nio/BufferUnderflowException;
+Ljava/nio/ByteBuffer;
+Ljava/nio/ByteBufferAsCharBuffer;
+Ljava/nio/ByteBufferAsDoubleBuffer;
+Ljava/nio/ByteBufferAsFloatBuffer;
+Ljava/nio/ByteBufferAsIntBuffer;
+Ljava/nio/ByteBufferAsLongBuffer;
+Ljava/nio/ByteBufferAsShortBuffer;
+Ljava/nio/ByteOrder;
+Ljava/nio/channels/AsynchronousCloseException;
+Ljava/nio/channels/ByteChannel;
+Ljava/nio/channels/Channel;
+Ljava/nio/channels/Channels;
+Ljava/nio/channels/ClosedByInterruptException;
+Ljava/nio/channels/ClosedChannelException;
+Ljava/nio/channels/DatagramChannel;
+Ljava/nio/channels/FileChannel;
+Ljava/nio/channels/FileChannel$MapMode;
+Ljava/nio/channels/GatheringByteChannel;
+Ljava/nio/channels/InterruptibleChannel;
+Ljava/nio/channels/MulticastChannel;
+Ljava/nio/channels/NetworkChannel;
+Ljava/nio/channels/ReadableByteChannel;
+Ljava/nio/channels/ScatteringByteChannel;
+Ljava/nio/channels/SeekableByteChannel;
+Ljava/nio/channels/SelectableChannel;
+Ljava/nio/channels/ServerSocketChannel;
+Ljava/nio/channels/SocketChannel;
+Ljava/nio/channels/spi/AbstractInterruptibleChannel;
+Ljava/nio/channels/spi/AbstractInterruptibleChannel$1;
+Ljava/nio/channels/spi/AbstractSelectableChannel;
+Ljava/nio/channels/WritableByteChannel;
+Ljava/nio/CharBuffer;
+Ljava/nio/charset/CharacterCodingException;
+Ljava/nio/charset/Charset;
+Ljava/nio/charset/CharsetDecoder;
+Ljava/nio/charset/CharsetDecoderICU;
+Ljava/nio/charset/CharsetEncoder;
+Ljava/nio/charset/CharsetEncoderICU;
+Ljava/nio/charset/CharsetICU;
+Ljava/nio/charset/CoderResult;
+Ljava/nio/charset/CoderResult$1;
+Ljava/nio/charset/CoderResult$2;
+Ljava/nio/charset/CoderResult$Cache;
+Ljava/nio/charset/CodingErrorAction;
+Ljava/nio/charset/IllegalCharsetNameException;
+Ljava/nio/charset/StandardCharsets;
+Ljava/nio/charset/UnsupportedCharsetException;
+Ljava/nio/DirectByteBuffer;
+Ljava/nio/DirectByteBuffer$MemoryRef;
+Ljava/nio/DoubleBuffer;
+Ljava/nio/file/attribute/BasicFileAttributes;
+Ljava/nio/file/attribute/FileAttribute;
+Ljava/nio/file/attribute/PosixFileAttributes;
+Ljava/nio/file/FileAlreadyExistsException;
+Ljava/nio/file/Files;
+Ljava/nio/file/FileSystem;
+Ljava/nio/file/FileSystemException;
+Ljava/nio/file/FileSystems;
+Ljava/nio/file/FileSystems$DefaultFileSystemHolder;
+Ljava/nio/file/FileSystems$DefaultFileSystemHolder$1;
+Ljava/nio/file/NoSuchFileException;
+Ljava/nio/file/OpenOption;
+Ljava/nio/file/Path;
+Ljava/nio/file/spi/FileSystemProvider;
+Ljava/nio/file/Watchable;
+Ljava/nio/FloatBuffer;
+Ljava/nio/HeapByteBuffer;
+Ljava/nio/HeapCharBuffer;
+Ljava/nio/IntBuffer;
+Ljava/nio/InvalidMarkException;
+Ljava/nio/LongBuffer;
+Ljava/nio/MappedByteBuffer;
+Ljava/nio/NIOAccess;
+Ljava/nio/NioUtils;
+Ljava/nio/ReadOnlyBufferException;
+Ljava/nio/ShortBuffer;
+Ljava/nio/StringCharBuffer;
+Ljava/security/AccessControlContext;
+Ljava/security/AccessControlException;
+Ljava/security/AccessController;
+Ljava/security/AlgorithmConstraints;
+Ljava/security/BasicPermission;
+Ljava/security/cert/Certificate;
+Ljava/security/cert/CertificateEncodingException;
+Ljava/security/cert/CertificateException;
+Ljava/security/cert/CertificateExpiredException;
+Ljava/security/cert/CertificateFactory;
+Ljava/security/cert/CertificateFactorySpi;
+Ljava/security/cert/CertificateNotYetValidException;
+Ljava/security/cert/CertificateParsingException;
+Ljava/security/cert/CertPath;
+Ljava/security/cert/CertPathChecker;
+Ljava/security/cert/CertPathHelperImpl;
+Ljava/security/cert/CertPathParameters;
+Ljava/security/cert/CertPathValidator;
+Ljava/security/cert/CertPathValidatorException;
+Ljava/security/cert/CertPathValidatorResult;
+Ljava/security/cert/CertPathValidatorSpi;
+Ljava/security/cert/CertSelector;
+Ljava/security/cert/CRLException;
+Ljava/security/cert/Extension;
+Ljava/security/cert/PKIXCertPathChecker;
+Ljava/security/cert/PKIXCertPathValidatorResult;
+Ljava/security/cert/PKIXParameters;
+Ljava/security/cert/PKIXRevocationChecker;
+Ljava/security/cert/PolicyNode;
+Ljava/security/cert/TrustAnchor;
+Ljava/security/cert/X509Certificate;
+Ljava/security/cert/X509CertSelector;
+Ljava/security/cert/X509Extension;
+Ljava/security/CryptoPrimitive;
+Ljava/security/DigestException;
+Ljava/security/GeneralSecurityException;
+Ljava/security/Guard;
+Ljava/security/interfaces/DSAKey;
+Ljava/security/interfaces/DSAPublicKey;
+Ljava/security/interfaces/ECKey;
+Ljava/security/interfaces/ECPrivateKey;
+Ljava/security/interfaces/ECPublicKey;
+Ljava/security/interfaces/RSAKey;
+Ljava/security/interfaces/RSAPrivateKey;
+Ljava/security/interfaces/RSAPublicKey;
+Ljava/security/InvalidAlgorithmParameterException;
+Ljava/security/InvalidKeyException;
+Ljava/security/Key;
+Ljava/security/KeyException;
+Ljava/security/KeyFactory;
+Ljava/security/KeyFactorySpi;
+Ljava/security/KeyManagementException;
+Ljava/security/KeyStore;
+Ljava/security/KeyStore$1;
+Ljava/security/KeyStoreException;
+Ljava/security/KeyStoreSpi;
+Ljava/security/MessageDigest;
+Ljava/security/MessageDigest$Delegate;
+Ljava/security/MessageDigestSpi;
+Ljava/security/NoSuchAlgorithmException;
+Ljava/security/NoSuchProviderException;
+Ljava/security/Permission;
+Ljava/security/PermissionCollection;
+Ljava/security/Permissions;
+Ljava/security/Principal;
+Ljava/security/PrivateKey;
+Ljava/security/PrivilegedAction;
+Ljava/security/PrivilegedActionException;
+Ljava/security/PrivilegedExceptionAction;
+Ljava/security/ProtectionDomain;
+Ljava/security/Provider;
+Ljava/security/Provider$EngineDescription;
+Ljava/security/Provider$Service;
+Ljava/security/Provider$ServiceKey;
+Ljava/security/Provider$UString;
+Ljava/security/PublicKey;
+Ljava/security/SecureRandom;
+Ljava/security/SecureRandomSpi;
+Ljava/security/Security;
+Ljava/security/Signature;
+Ljava/security/Signature$Delegate;
+Ljava/security/SignatureException;
+Ljava/security/SignatureSpi;
+Ljava/security/spec/AlgorithmParameterSpec;
+Ljava/security/spec/EncodedKeySpec;
+Ljava/security/spec/InvalidKeySpecException;
+Ljava/security/spec/KeySpec;
+Ljava/security/spec/RSAPublicKeySpec;
+Ljava/security/spec/X509EncodedKeySpec;
+Ljava/security/UnrecoverableEntryException;
+Ljava/security/UnrecoverableKeyException;
+Ljava/text/AttributedCharacterIterator$Attribute;
+Ljava/text/DateFormat;
+Ljava/text/DateFormat$Field;
+Ljava/text/DateFormatSymbols;
+Ljava/text/DecimalFormat;
+Ljava/text/DecimalFormatSymbols;
+Ljava/text/DontCareFieldPosition;
+Ljava/text/DontCareFieldPosition$1;
+Ljava/text/FieldPosition;
+Ljava/text/FieldPosition$Delegate;
+Ljava/text/Format;
+Ljava/text/Format$Field;
+Ljava/text/Format$FieldDelegate;
+Ljava/text/Normalizer;
+Ljava/text/Normalizer$Form;
+Ljava/text/NumberFormat;
+Ljava/text/ParseException;
+Ljava/text/SimpleDateFormat;
+Ljava/time/DateTimeException;
+Ljava/util/AbstractCollection;
+Ljava/util/AbstractList;
+Ljava/util/AbstractList$Itr;
+Ljava/util/AbstractList$ListItr;
+Ljava/util/AbstractMap;
+Ljava/util/AbstractMap$1;
+Ljava/util/AbstractMap$2;
+Ljava/util/AbstractMap$SimpleImmutableEntry;
+Ljava/util/AbstractQueue;
+Ljava/util/AbstractSequentialList;
+Ljava/util/AbstractSet;
+Ljava/util/ArrayDeque;
+Ljava/util/ArrayDeque$DeqIterator;
+Ljava/util/ArrayList;
+Ljava/util/ArrayList$ArrayListSpliterator;
+Ljava/util/ArrayList$Itr;
+Ljava/util/ArrayList$ListItr;
+Ljava/util/ArrayList$SubList;
+Ljava/util/ArrayList$SubList$1;
+Ljava/util/ArrayPrefixHelpers$CumulateTask;
+Ljava/util/ArrayPrefixHelpers$DoubleCumulateTask;
+Ljava/util/ArrayPrefixHelpers$IntCumulateTask;
+Ljava/util/ArrayPrefixHelpers$LongCumulateTask;
+Ljava/util/Arrays;
+Ljava/util/Arrays$ArrayList;
+Ljava/util/Arrays$NaturalOrder;
+Ljava/util/ArraysParallelSortHelpers$FJByte$Sorter;
+Ljava/util/ArraysParallelSortHelpers$FJChar$Sorter;
+Ljava/util/ArraysParallelSortHelpers$FJDouble$Sorter;
+Ljava/util/ArraysParallelSortHelpers$FJFloat$Sorter;
+Ljava/util/ArraysParallelSortHelpers$FJInt$Sorter;
+Ljava/util/ArraysParallelSortHelpers$FJLong$Sorter;
+Ljava/util/ArraysParallelSortHelpers$FJObject$Sorter;
+Ljava/util/ArraysParallelSortHelpers$FJShort$Sorter;
+Ljava/util/Base64;
+Ljava/util/Base64$Decoder;
+Ljava/util/Base64$Encoder;
+Ljava/util/BitSet;
+Ljava/util/Calendar;
+Ljava/util/Collection;
+Ljava/util/Collections;
+Ljava/util/Collections$1;
+Ljava/util/Collections$2;
+Ljava/util/Collections$3;
+Ljava/util/Collections$AsLIFOQueue;
+Ljava/util/Collections$CheckedCollection;
+Ljava/util/Collections$CheckedList;
+Ljava/util/Collections$CheckedMap;
+Ljava/util/Collections$CheckedNavigableMap;
+Ljava/util/Collections$CheckedNavigableSet;
+Ljava/util/Collections$CheckedQueue;
+Ljava/util/Collections$CheckedRandomAccessList;
+Ljava/util/Collections$CheckedSet;
+Ljava/util/Collections$CheckedSortedMap;
+Ljava/util/Collections$CheckedSortedSet;
+Ljava/util/Collections$CopiesList;
+Ljava/util/Collections$EmptyEnumeration;
+Ljava/util/Collections$EmptyIterator;
+Ljava/util/Collections$EmptyList;
+Ljava/util/Collections$EmptyListIterator;
+Ljava/util/Collections$EmptyMap;
+Ljava/util/Collections$EmptySet;
+Ljava/util/Collections$ReverseComparator;
+Ljava/util/Collections$ReverseComparator2;
+Ljava/util/Collections$SetFromMap;
+Ljava/util/Collections$SingletonList;
+Ljava/util/Collections$SingletonMap;
+Ljava/util/Collections$SingletonSet;
+Ljava/util/Collections$SynchronizedCollection;
+Ljava/util/Collections$SynchronizedList;
+Ljava/util/Collections$SynchronizedMap;
+Ljava/util/Collections$SynchronizedNavigableMap;
+Ljava/util/Collections$SynchronizedNavigableSet;
+Ljava/util/Collections$SynchronizedRandomAccessList;
+Ljava/util/Collections$SynchronizedSet;
+Ljava/util/Collections$SynchronizedSortedMap;
+Ljava/util/Collections$SynchronizedSortedSet;
+Ljava/util/Collections$UnmodifiableCollection;
+Ljava/util/Collections$UnmodifiableCollection$1;
+Ljava/util/Collections$UnmodifiableList;
+Ljava/util/Collections$UnmodifiableList$1;
+Ljava/util/Collections$UnmodifiableMap;
+Ljava/util/Collections$UnmodifiableMap$UnmodifiableEntrySet;
+Ljava/util/Collections$UnmodifiableMap$UnmodifiableEntrySet$1;
+Ljava/util/Collections$UnmodifiableMap$UnmodifiableEntrySet$UnmodifiableEntry;
+Ljava/util/Collections$UnmodifiableNavigableMap;
+Ljava/util/Collections$UnmodifiableNavigableMap$EmptyNavigableMap;
+Ljava/util/Collections$UnmodifiableNavigableSet;
+Ljava/util/Collections$UnmodifiableNavigableSet$EmptyNavigableSet;
+Ljava/util/Collections$UnmodifiableRandomAccessList;
+Ljava/util/Collections$UnmodifiableSet;
+Ljava/util/Collections$UnmodifiableSortedMap;
+Ljava/util/Collections$UnmodifiableSortedSet;
+Ljava/util/ComparableTimSort;
+Ljava/util/Comparator;
+Ljava/util/Comparators$NaturalOrderComparator;
+Ljava/util/Comparators$NullComparator;
+Ljava/util/concurrent/AbstractExecutorService;
+Ljava/util/concurrent/ArrayBlockingQueue;
+Ljava/util/concurrent/atomic/AtomicBoolean;
+Ljava/util/concurrent/atomic/AtomicInteger;
+Ljava/util/concurrent/atomic/AtomicLong;
+Ljava/util/concurrent/atomic/AtomicReference;
+Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater;
+Ljava/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl;
+Ljava/util/concurrent/BlockingQueue;
+Ljava/util/concurrent/Callable;
+Ljava/util/concurrent/CancellationException;
+Ljava/util/concurrent/CompletableFuture;
+Ljava/util/concurrent/CompletableFuture$AltResult;
+Ljava/util/concurrent/CompletableFuture$AsynchronousCompletionTask;
+Ljava/util/concurrent/CompletableFuture$Completion;
+Ljava/util/concurrent/CompletableFuture$Signaller;
+Ljava/util/concurrent/CompletionStage;
+Ljava/util/concurrent/ConcurrentHashMap;
+Ljava/util/concurrent/ConcurrentHashMap$BaseIterator;
+Ljava/util/concurrent/ConcurrentHashMap$BulkTask;
+Ljava/util/concurrent/ConcurrentHashMap$CollectionView;
+Ljava/util/concurrent/ConcurrentHashMap$CounterCell;
+Ljava/util/concurrent/ConcurrentHashMap$EntryIterator;
+Ljava/util/concurrent/ConcurrentHashMap$EntrySetView;
+Ljava/util/concurrent/ConcurrentHashMap$ForEachEntryTask;
+Ljava/util/concurrent/ConcurrentHashMap$ForEachKeyTask;
+Ljava/util/concurrent/ConcurrentHashMap$ForEachMappingTask;
+Ljava/util/concurrent/ConcurrentHashMap$ForEachTransformedEntryTask;
+Ljava/util/concurrent/ConcurrentHashMap$ForEachTransformedKeyTask;
+Ljava/util/concurrent/ConcurrentHashMap$ForEachTransformedMappingTask;
+Ljava/util/concurrent/ConcurrentHashMap$ForEachTransformedValueTask;
+Ljava/util/concurrent/ConcurrentHashMap$ForEachValueTask;
+Ljava/util/concurrent/ConcurrentHashMap$ForwardingNode;
+Ljava/util/concurrent/ConcurrentHashMap$KeyIterator;
+Ljava/util/concurrent/ConcurrentHashMap$KeySetView;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToDoubleTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToIntTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceEntriesToLongTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToDoubleTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToIntTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceKeysToLongTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToDoubleTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToIntTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceMappingsToLongTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToDoubleTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToIntTask;
+Ljava/util/concurrent/ConcurrentHashMap$MapReduceValuesToLongTask;
+Ljava/util/concurrent/ConcurrentHashMap$Node;
+Ljava/util/concurrent/ConcurrentHashMap$ReduceEntriesTask;
+Ljava/util/concurrent/ConcurrentHashMap$ReduceKeysTask;
+Ljava/util/concurrent/ConcurrentHashMap$ReduceValuesTask;
+Ljava/util/concurrent/ConcurrentHashMap$ReservationNode;
+Ljava/util/concurrent/ConcurrentHashMap$SearchEntriesTask;
+Ljava/util/concurrent/ConcurrentHashMap$SearchKeysTask;
+Ljava/util/concurrent/ConcurrentHashMap$SearchMappingsTask;
+Ljava/util/concurrent/ConcurrentHashMap$SearchValuesTask;
+Ljava/util/concurrent/ConcurrentHashMap$Segment;
+Ljava/util/concurrent/ConcurrentHashMap$Traverser;
+Ljava/util/concurrent/ConcurrentHashMap$TreeBin;
+Ljava/util/concurrent/ConcurrentHashMap$TreeNode;
+Ljava/util/concurrent/ConcurrentHashMap$ValueIterator;
+Ljava/util/concurrent/ConcurrentHashMap$ValuesView;
+Ljava/util/concurrent/ConcurrentLinkedQueue;
+Ljava/util/concurrent/ConcurrentLinkedQueue$Node;
+Ljava/util/concurrent/ConcurrentMap;
+Ljava/util/concurrent/CopyOnWriteArrayList;
+Ljava/util/concurrent/CopyOnWriteArrayList$COWIterator;
+Ljava/util/concurrent/CopyOnWriteArraySet;
+Ljava/util/concurrent/CountDownLatch;
+Ljava/util/concurrent/CountDownLatch$Sync;
+Ljava/util/concurrent/CountedCompleter;
+Ljava/util/concurrent/ExecutionException;
+Ljava/util/concurrent/Executor;
+Ljava/util/concurrent/Executors;
+Ljava/util/concurrent/Executors$DefaultThreadFactory;
+Ljava/util/concurrent/Executors$DelegatedExecutorService;
+Ljava/util/concurrent/ExecutorService;
+Ljava/util/concurrent/Executors$FinalizableDelegatedExecutorService;
+Ljava/util/concurrent/Executors$RunnableAdapter;
+Ljava/util/concurrent/ForkJoinPool;
+Ljava/util/concurrent/ForkJoinPool$1;
+Ljava/util/concurrent/ForkJoinPool$DefaultForkJoinWorkerThreadFactory;
+Ljava/util/concurrent/ForkJoinPool$ForkJoinWorkerThreadFactory;
+Ljava/util/concurrent/ForkJoinPool$ManagedBlocker;
+Ljava/util/concurrent/ForkJoinTask;
+Ljava/util/concurrent/ForkJoinTask$ExceptionNode;
+Ljava/util/concurrent/ForkJoinWorkerThread;
+Ljava/util/concurrent/Future;
+Ljava/util/concurrent/FutureTask;
+Ljava/util/concurrent/FutureTask$WaitNode;
+Ljava/util/concurrent/LinkedBlockingQueue;
+Ljava/util/concurrent/LinkedBlockingQueue$Node;
+Ljava/util/concurrent/locks/AbstractOwnableSynchronizer;
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer;
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject;
+Ljava/util/concurrent/locks/AbstractQueuedSynchronizer$Node;
+Ljava/util/concurrent/locks/Condition;
+Ljava/util/concurrent/locks/Lock;
+Ljava/util/concurrent/locks/LockSupport;
+Ljava/util/concurrent/locks/ReadWriteLock;
+Ljava/util/concurrent/locks/ReentrantLock;
+Ljava/util/concurrent/locks/ReentrantLock$NonfairSync;
+Ljava/util/concurrent/locks/ReentrantLock$Sync;
+Ljava/util/concurrent/locks/ReentrantReadWriteLock;
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$NonfairSync;
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$ReadLock;
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync;
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$Sync$ThreadLocalHoldCounter;
+Ljava/util/concurrent/locks/ReentrantReadWriteLock$WriteLock;
+Ljava/util/ConcurrentModificationException;
+Ljava/util/concurrent/RejectedExecutionHandler;
+Ljava/util/concurrent/RunnableFuture;
+Ljava/util/concurrent/ThreadFactory;
+Ljava/util/concurrent/ThreadLocalRandom;
+Ljava/util/concurrent/ThreadPoolExecutor;
+Ljava/util/concurrent/ThreadPoolExecutor$AbortPolicy;
+Ljava/util/concurrent/ThreadPoolExecutor$Worker;
+Ljava/util/concurrent/TimeoutException;
+Ljava/util/concurrent/TimeUnit;
+Ljava/util/concurrent/TimeUnit$1;
+Ljava/util/concurrent/TimeUnit$2;
+Ljava/util/concurrent/TimeUnit$3;
+Ljava/util/concurrent/TimeUnit$4;
+Ljava/util/concurrent/TimeUnit$5;
+Ljava/util/concurrent/TimeUnit$6;
+Ljava/util/concurrent/TimeUnit$7;
+Ljava/util/Currency;
+Ljava/util/Date;
+Ljava/util/Deque;
+Ljava/util/Dictionary;
+Ljava/util/DualPivotQuicksort;
+Ljava/util/Enumeration;
+Ljava/util/EnumMap;
+Ljava/util/EnumMap$1;
+Ljava/util/EnumSet;
+Ljava/util/Formattable;
+Ljava/util/Formatter;
+Ljava/util/Formatter$Conversion;
+Ljava/util/Formatter$DateTime;
+Ljava/util/Formatter$FixedString;
+Ljava/util/Formatter$Flags;
+Ljava/util/Formatter$FormatSpecifier;
+Ljava/util/Formatter$FormatSpecifierParser;
+Ljava/util/Formatter$FormatString;
+Ljava/util/function/BiConsumer;
+Ljava/util/function/BiFunction;
+Ljava/util/function/BinaryOperator;
+Ljava/util/function/Consumer;
+Ljava/util/function/DoubleBinaryOperator;
+Ljava/util/function/Function;
+Ljava/util/function/IntBinaryOperator;
+Ljava/util/function/IntConsumer;
+Ljava/util/function/IntFunction;
+Ljava/util/function/IntToDoubleFunction;
+Ljava/util/function/IntToLongFunction;
+Ljava/util/function/IntUnaryOperator;
+Ljava/util/function/LongBinaryOperator;
+Ljava/util/function/LongUnaryOperator;
+Ljava/util/function/Predicate;
+Ljava/util/function/Supplier;
+Ljava/util/function/ToDoubleBiFunction;
+Ljava/util/function/ToDoubleFunction;
+Ljava/util/function/ToIntBiFunction;
+Ljava/util/function/ToIntFunction;
+Ljava/util/function/ToLongBiFunction;
+Ljava/util/function/ToLongFunction;
+Ljava/util/function/UnaryOperator;
+Ljava/util/GregorianCalendar;
+Ljava/util/HashMap;
+Ljava/util/HashMap$EntryIterator;
+Ljava/util/HashMap$EntrySet;
+Ljava/util/HashMap$HashIterator;
+Ljava/util/HashMap$KeyIterator;
+Ljava/util/HashMap$KeySet;
+Ljava/util/HashMap$Node;
+Ljava/util/HashMap$TreeNode;
+Ljava/util/HashMap$ValueIterator;
+Ljava/util/HashMap$Values;
+Ljava/util/HashSet;
+Ljava/util/Hashtable;
+Ljava/util/Hashtable$Enumerator;
+Ljava/util/Hashtable$HashtableEntry;
+Ljava/util/Hashtable$KeySet;
+Ljava/util/Hashtable$ValueCollection;
+Ljava/util/IdentityHashMap;
+Ljava/util/IdentityHashMap$KeySet;
+Ljava/util/IllegalFormatException;
+Ljava/util/IllformedLocaleException;
+Ljava/util/Iterator;
+Ljava/util/jar/JarEntry;
+Ljava/util/jar/JarFile;
+Ljava/util/jar/JarFile$JarEntryIterator;
+Ljava/util/jar/JarFile$JarFileEntry;
+Ljava/util/LinkedHashMap;
+Ljava/util/LinkedHashMap$LinkedEntryIterator;
+Ljava/util/LinkedHashMap$LinkedEntrySet;
+Ljava/util/LinkedHashMap$LinkedHashIterator;
+Ljava/util/LinkedHashMap$LinkedHashMapEntry;
+Ljava/util/LinkedHashMap$LinkedKeyIterator;
+Ljava/util/LinkedHashMap$LinkedKeySet;
+Ljava/util/LinkedHashMap$LinkedValueIterator;
+Ljava/util/LinkedHashMap$LinkedValues;
+Ljava/util/LinkedHashSet;
+Ljava/util/LinkedList;
+Ljava/util/LinkedList$ListItr;
+Ljava/util/LinkedList$Node;
+Ljava/util/List;
+Ljava/util/ListIterator;
+Ljava/util/Locale;
+Ljava/util/Locale$Builder;
+Ljava/util/Locale$Cache;
+Ljava/util/Locale$Category;
+Ljava/util/Locale$FilteringMode;
+Ljava/util/Locale$LanguageRange;
+Ljava/util/Locale$LocaleKey;
+Ljava/util/logging/ErrorManager;
+Ljava/util/logging/Formatter;
+Ljava/util/logging/Handler;
+Ljava/util/logging/Level;
+Ljava/util/logging/Level$KnownLevel;
+Ljava/util/logging/Logger;
+Ljava/util/logging/Logger$LoggerBundle;
+Ljava/util/logging/LoggingPermission;
+Ljava/util/logging/LoggingProxyImpl;
+Ljava/util/logging/LogManager;
+Ljava/util/logging/LogManager$1;
+Ljava/util/logging/LogManager$2;
+Ljava/util/logging/LogManager$3;
+Ljava/util/logging/LogManager$5;
+Ljava/util/logging/LogManager$Cleaner;
+Ljava/util/logging/LogManager$LoggerContext;
+Ljava/util/logging/LogManager$LoggerContext$1;
+Ljava/util/logging/LogManager$LoggerWeakRef;
+Ljava/util/logging/LogManager$LogNode;
+Ljava/util/logging/LogManager$RootLogger;
+Ljava/util/logging/LogManager$SystemLoggerContext;
+Ljava/util/Map;
+Ljava/util/Map$Entry;
+Ljava/util/MissingResourceException;
+Ljava/util/NavigableMap;
+Ljava/util/NavigableSet;
+Ljava/util/NoSuchElementException;
+Ljava/util/Objects;
+Ljava/util/prefs/AbstractPreferences;
+Ljava/util/prefs/FileSystemPreferences;
+Ljava/util/prefs/Preferences;
+Ljava/util/PrimitiveIterator;
+Ljava/util/PrimitiveIterator$OfInt;
+Ljava/util/Properties;
+Ljava/util/Properties$LineReader;
+Ljava/util/Queue;
+Ljava/util/Random;
+Ljava/util/RandomAccess;
+Ljava/util/RandomAccessSubList;
+Ljava/util/regex/Matcher;
+Ljava/util/regex/MatchResult;
+Ljava/util/regex/Pattern;
+Ljava/util/regex/PatternSyntaxException;
+Ljava/util/RegularEnumSet;
+Ljava/util/ResourceBundle;
+Ljava/util/ResourceBundle$1;
+Ljava/util/Set;
+Ljava/util/SimpleTimeZone;
+Ljava/util/SortedMap;
+Ljava/util/SortedSet;
+Ljava/util/Spliterator;
+Ljava/util/Spliterator$OfDouble;
+Ljava/util/Spliterator$OfInt;
+Ljava/util/Spliterator$OfLong;
+Ljava/util/Spliterator$OfPrimitive;
+Ljava/util/Spliterators;
+Ljava/util/Spliterators$EmptySpliterator;
+Ljava/util/Spliterators$EmptySpliterator$OfDouble;
+Ljava/util/Spliterators$EmptySpliterator$OfInt;
+Ljava/util/Spliterators$EmptySpliterator$OfLong;
+Ljava/util/Spliterators$EmptySpliterator$OfRef;
+Ljava/util/Stack;
+Ljava/util/stream/BaseStream;
+Ljava/util/stream/DoubleStream;
+Ljava/util/stream/IntStream;
+Ljava/util/stream/LongStream;
+Ljava/util/stream/Stream;
+Ljava/util/stream/StreamSupport;
+Ljava/util/StringJoiner;
+Ljava/util/StringTokenizer;
+Ljava/util/SubList;
+Ljava/util/TaskQueue;
+Ljava/util/Timer;
+Ljava/util/Timer$1;
+Ljava/util/TimerTask;
+Ljava/util/TimerThread;
+Ljava/util/TimeZone;
+Ljava/util/TimSort;
+Ljava/util/TreeMap;
+Ljava/util/TreeMap$AscendingSubMap;
+Ljava/util/TreeMap$AscendingSubMap$AscendingEntrySetView;
+Ljava/util/TreeMap$EntryIterator;
+Ljava/util/TreeMap$EntrySet;
+Ljava/util/TreeMap$KeyIterator;
+Ljava/util/TreeMap$KeySet;
+Ljava/util/TreeMap$NavigableSubMap;
+Ljava/util/TreeMap$NavigableSubMap$EntrySetView;
+Ljava/util/TreeMap$NavigableSubMap$SubMapIterator;
+Ljava/util/TreeMap$NavigableSubMap$SubMapKeyIterator;
+Ljava/util/TreeMap$PrivateEntryIterator;
+Ljava/util/TreeMap$TreeMapEntry;
+Ljava/util/TreeMap$ValueIterator;
+Ljava/util/TreeMap$Values;
+Ljava/util/TreeSet;
+Ljava/util/UUID;
+Ljava/util/UUID$Holder;
+Ljava/util/Vector;
+Ljava/util/Vector$Itr;
+Ljava/util/WeakHashMap;
+Ljava/util/WeakHashMap$Entry;
+Ljava/util/WeakHashMap$EntrySet;
+Ljava/util/WeakHashMap$KeySet;
+Ljava/util/WeakHashMap$Values;
+Ljava/util/zip/Adler32;
+Ljava/util/zip/Checksum;
+Ljava/util/zip/CRC32;
+Ljava/util/zip/DataFormatException;
+Ljava/util/zip/Deflater;
+Ljava/util/zip/DeflaterOutputStream;
+Ljava/util/zip/GZIPOutputStream;
+Ljava/util/zip/Inflater;
+Ljava/util/zip/InflaterInputStream;
+Ljava/util/zip/ZipCoder;
+Ljava/util/zip/ZipConstants;
+Ljava/util/zip/ZipEntry;
+Ljava/util/zip/ZipFile;
+Ljava/util/zip/ZipFile$ZipEntryIterator;
+Ljava/util/zip/ZipFile$ZipFileInflaterInputStream;
+Ljava/util/zip/ZipFile$ZipFileInputStream;
+Ljava/util/zip/ZipUtils;
+Ljava/util/zip/ZStreamRef;
+Ljavax/crypto/BadPaddingException;
+Ljavax/crypto/IllegalBlockSizeException;
+Ljavax/crypto/NoSuchPaddingException;
+Ljavax/crypto/SecretKey;
+Ljavax/microedition/khronos/egl/EGL;
+Ljavax/microedition/khronos/egl/EGL10;
+Ljavax/microedition/khronos/opengles/GL;
+Ljavax/microedition/khronos/opengles/GL10;
+Ljavax/microedition/khronos/opengles/GL10Ext;
+Ljavax/microedition/khronos/opengles/GL11;
+Ljavax/microedition/khronos/opengles/GL11Ext;
+Ljavax/microedition/khronos/opengles/GL11ExtensionPack;
+Ljavax/net/SocketFactory;
+Ljavax/net/ssl/ExtendedSSLSession;
+Ljavax/net/ssl/HostnameVerifier;
+Ljavax/net/ssl/HttpsURLConnection;
+Ljavax/net/ssl/HttpsURLConnection$NoPreloadHolder;
+Ljavax/net/ssl/KeyManager;
+Ljavax/net/ssl/KeyManagerFactory;
+Ljavax/net/ssl/KeyManagerFactory$1;
+Ljavax/net/ssl/KeyManagerFactorySpi;
+Ljavax/net/ssl/SNIHostName;
+Ljavax/net/ssl/SNIServerName;
+Ljavax/net/ssl/SSLContext;
+Ljavax/net/ssl/SSLContextSpi;
+Ljavax/net/ssl/SSLException;
+Ljavax/net/ssl/SSLParameters;
+Ljavax/net/ssl/SSLPeerUnverifiedException;
+Ljavax/net/ssl/SSLProtocolException;
+Ljavax/net/ssl/SSLSession;
+Ljavax/net/ssl/SSLSessionContext;
+Ljavax/net/ssl/SSLSocket;
+Ljavax/net/ssl/SSLSocketFactory;
+Ljavax/net/ssl/SSLSocketFactory$1;
+Ljavax/net/ssl/TrustManager;
+Ljavax/net/ssl/TrustManagerFactory;
+Ljavax/net/ssl/TrustManagerFactory$1;
+Ljavax/net/ssl/TrustManagerFactorySpi;
+Ljavax/net/ssl/X509ExtendedKeyManager;
+Ljavax/net/ssl/X509ExtendedTrustManager;
+Ljavax/net/ssl/X509KeyManager;
+Ljavax/net/ssl/X509TrustManager;
+Ljavax/security/auth/callback/UnsupportedCallbackException;
+Ljavax/security/auth/Destroyable;
+Ljavax/security/auth/x500/X500Principal;
+Ljavax/security/cert/CertificateException;
+Llibcore/icu/ICU;
+Llibcore/icu/LocaleData;
+Llibcore/icu/NativeConverter;
+Llibcore/icu/TimeZoneNames;
+Llibcore/icu/TimeZoneNames$1;
+Llibcore/icu/TimeZoneNames$ZoneStringsCache;
+Llibcore/internal/StringPool;
+Llibcore/io/AsynchronousCloseMonitor;
+Llibcore/io/BlockGuardOs;
+Llibcore/io/BufferIterator;
+Llibcore/io/ClassPathURLStreamHandler;
+Llibcore/io/ClassPathURLStreamHandler$ClassPathURLConnection;
+Llibcore/io/ClassPathURLStreamHandler$ClassPathURLConnection$1;
+Llibcore/io/DropBox;
+Llibcore/io/DropBox$DefaultReporter;
+Llibcore/io/DropBox$Reporter;
+Llibcore/io/ForwardingOs;
+Llibcore/io/IoBridge;
+Llibcore/io/IoTracker;
+Llibcore/io/IoTracker$Mode;
+Llibcore/io/IoUtils;
+Llibcore/io/IoUtils$FileReader;
+Llibcore/io/Libcore;
+Llibcore/io/Memory;
+Llibcore/io/MemoryMappedFile;
+Llibcore/io/NioBufferIterator;
+Llibcore/io/Os;
+Llibcore/io/Posix;
+Llibcore/io/Streams;
+Llibcore/net/event/NetworkEventDispatcher;
+Llibcore/net/NetworkSecurityPolicy;
+Llibcore/net/NetworkSecurityPolicy$DefaultNetworkSecurityPolicy;
+Llibcore/net/UriCodec;
+Llibcore/reflect/AnnotatedElements;
+Llibcore/reflect/AnnotationFactory;
+Llibcore/reflect/AnnotationMember;
+Llibcore/reflect/AnnotationMember$DefaultValues;
+Llibcore/reflect/GenericSignatureParser;
+Llibcore/reflect/InternalNames;
+Llibcore/reflect/ListOfTypes;
+Llibcore/reflect/Types;
+Llibcore/util/BasicLruCache;
+Llibcore/util/CharsetUtils;
+Llibcore/util/CollectionUtils;
+Llibcore/util/EmptyArray;
+Llibcore/util/HexEncoding;
+Llibcore/util/NativeAllocationRegistry;
+Llibcore/util/NativeAllocationRegistry$CleanerRunner;
+Llibcore/util/NativeAllocationRegistry$CleanerThunk;
+Llibcore/util/Objects;
+Llibcore/util/ZoneInfo;
+Llibcore/util/ZoneInfo$CheckedArithmeticException;
+Llibcore/util/ZoneInfoDB;
+Llibcore/util/ZoneInfoDB$TzData;
+Llibcore/util/ZoneInfoDB$TzData$1;
+Llibcore/util/ZoneInfo$WallTime;
+Lorg/apache/harmony/dalvik/ddmc/Chunk;
+Lorg/apache/harmony/dalvik/ddmc/ChunkHandler;
+Lorg/apache/harmony/dalvik/ddmc/DdmServer;
+Lorg/apache/harmony/dalvik/ddmc/DdmVmInternal;
+Lorg/apache/harmony/dalvik/NativeTestTarget;
+Lorg/apache/harmony/luni/internal/util/TimezoneGetter;
+Lorg/apache/harmony/xml/ExpatAttributes;
+Lorg/apache/harmony/xml/ExpatParser;
+Lorg/json/JSON;
+Lorg/json/JSONArray;
+Lorg/json/JSONException;
+Lorg/json/JSONObject;
+Lorg/json/JSONObject$1;
+Lorg/json/JSONStringer;
+Lorg/json/JSONStringer$Scope;
+Lorg/json/JSONTokener;
+Lorg/kxml2/io/KXmlParser;
+Lorg/kxml2/io/KXmlParser$ValueContext;
+Lorg/kxml2/io/KXmlSerializer;
+Lorg/xmlpull/v1/XmlPullParser;
+Lorg/xmlpull/v1/XmlPullParserException;
+Lorg/xmlpull/v1/XmlPullParserFactory;
+Lorg/xmlpull/v1/XmlSerializer;
+Lorg/xml/sax/Attributes;
+LS;
+Lsun/invoke/util/BytecodeDescriptor;
+Lsun/invoke/util/Wrapper;
+Lsun/misc/Cleaner;
+Lsun/misc/CompoundEnumeration;
+Lsun/misc/FDBigInteger;
+Lsun/misc/FloatingDecimal;
+Lsun/misc/FloatingDecimal$1;
+Lsun/misc/FloatingDecimal$ASCIIToBinaryBuffer;
+Lsun/misc/FloatingDecimal$ASCIIToBinaryConverter;
+Lsun/misc/FloatingDecimal$BinaryToASCIIBuffer;
+Lsun/misc/FloatingDecimal$BinaryToASCIIConverter;
+Lsun/misc/FloatingDecimal$ExceptionalBinaryToASCIIBuffer;
+Lsun/misc/FloatingDecimal$PreparedASCIIToBinaryBuffer;
+Lsun/misc/FormattedFloatingDecimal;
+Lsun/misc/FormattedFloatingDecimal$1;
+Lsun/misc/FormattedFloatingDecimal$Form;
+Lsun/misc/IOUtils;
+Lsun/misc/JavaIOFileDescriptorAccess;
+Lsun/misc/SharedSecrets;
+Lsun/misc/Unsafe;
+Lsun/misc/Version;
+Lsun/misc/VM;
+Lsun/net/ConnectionResetException;
+Lsun/net/NetHooks;
+Lsun/net/ResourceManager;
+Lsun/net/spi/DefaultProxySelector;
+Lsun/net/spi/nameservice/NameService;
+Lsun/net/util/IPAddressUtil;
+Lsun/net/www/ParseUtil;
+Lsun/net/www/protocol/file/Handler;
+Lsun/net/www/protocol/jar/Handler;
+Lsun/nio/ch/ChannelInputStream;
+Lsun/nio/ch/DatagramChannelImpl;
+Lsun/nio/ch/DatagramDispatcher;
+Lsun/nio/ch/DirectBuffer;
+Lsun/nio/ch/EPollArrayWrapper;
+Lsun/nio/ch/FileChannelImpl;
+Lsun/nio/ch/FileChannelImpl$Unmapper;
+Lsun/nio/ch/FileDispatcher;
+Lsun/nio/ch/FileDispatcherImpl;
+Lsun/nio/ch/FileKey;
+Lsun/nio/ch/Interruptible;
+Lsun/nio/ch/IOStatus;
+Lsun/nio/ch/IOUtil;
+Lsun/nio/ch/NativeDispatcher;
+Lsun/nio/ch/NativeThread;
+Lsun/nio/ch/NativeThreadSet;
+Lsun/nio/ch/Net;
+Lsun/nio/ch/SelChImpl;
+Lsun/nio/ch/ServerSocketChannelImpl;
+Lsun/nio/ch/SocketChannelImpl;
+Lsun/nio/ch/Util;
+Lsun/nio/ch/Util$1;
+Lsun/nio/ch/Util$BufferCache;
+Lsun/nio/cs/ArrayEncoder;
+Lsun/nio/cs/StreamDecoder;
+Lsun/nio/cs/StreamEncoder;
+Lsun/nio/fs/AbstractFileSystemProvider;
+Lsun/nio/fs/AbstractPath;
+Lsun/nio/fs/DefaultFileSystemProvider;
+Lsun/nio/fs/LinuxFileSystem;
+Lsun/nio/fs/LinuxFileSystemProvider;
+Lsun/nio/fs/NativeBuffer;
+Lsun/nio/fs/NativeBuffer$Deallocator;
+Lsun/nio/fs/NativeBuffers;
+Lsun/nio/fs/UnixChannelFactory;
+Lsun/nio/fs/UnixChannelFactory$Flags;
+Lsun/nio/fs/UnixConstants;
+Lsun/nio/fs/UnixException;
+Lsun/nio/fs/UnixFileAttributes;
+Lsun/nio/fs/UnixFileModeAttribute;
+Lsun/nio/fs/UnixFileStoreAttributes;
+Lsun/nio/fs/UnixFileSystem;
+Lsun/nio/fs/UnixFileSystemProvider;
+Lsun/nio/fs/UnixMountEntry;
+Lsun/nio/fs/UnixNativeDispatcher;
+Lsun/nio/fs/UnixPath;
+Lsun/nio/fs/Util;
+Lsun/security/action/GetBooleanAction;
+Lsun/security/action/GetPropertyAction;
+Lsun/security/jca/GetInstance;
+Lsun/security/jca/GetInstance$Instance;
+Lsun/security/jca/ProviderConfig;
+Lsun/security/jca/ProviderConfig$2;
+Lsun/security/jca/ProviderList;
+Lsun/security/jca/ProviderList$1;
+Lsun/security/jca/ProviderList$2;
+Lsun/security/jca/ProviderList$3;
+Lsun/security/jca/ProviderList$ServiceList;
+Lsun/security/jca/ProviderList$ServiceList$1;
+Lsun/security/jca/Providers;
+Lsun/security/jca/ServiceId;
+Lsun/security/pkcs/PKCS9Attribute;
+Lsun/security/pkcs/SignerInfo;
+Lsun/security/provider/certpath/AdaptableX509CertSelector;
+Lsun/security/provider/certpath/AlgorithmChecker;
+Lsun/security/provider/certpath/BasicChecker;
+Lsun/security/provider/certpath/CertPathHelper;
+Lsun/security/provider/certpath/ConstraintsChecker;
+Lsun/security/provider/certpath/KeyChecker;
+Lsun/security/provider/certpath/PKIX;
+Lsun/security/provider/certpath/PKIXCertPathValidator;
+Lsun/security/provider/certpath/PKIXMasterCertPathValidator;
+Lsun/security/provider/certpath/PKIX$ValidatorParams;
+Lsun/security/provider/certpath/PolicyChecker;
+Lsun/security/provider/certpath/PolicyNodeImpl;
+Lsun/security/provider/CertPathProvider;
+Lsun/security/provider/X509Factory;
+Lsun/security/util/AbstractAlgorithmConstraints;
+Lsun/security/util/AlgorithmDecomposer;
+Lsun/security/util/BitArray;
+Lsun/security/util/ByteArrayLexOrder;
+Lsun/security/util/ByteArrayTagOrder;
+Lsun/security/util/Cache;
+Lsun/security/util/Cache$EqualByteArray;
+Lsun/security/util/Debug;
+Lsun/security/util/DerEncoder;
+Lsun/security/util/DerIndefLenConverter;
+Lsun/security/util/DerInputBuffer;
+Lsun/security/util/DerInputStream;
+Lsun/security/util/DerOutputStream;
+Lsun/security/util/DerValue;
+Lsun/security/util/DisabledAlgorithmConstraints;
+Lsun/security/util/DisabledAlgorithmConstraints$KeySizeConstraint;
+Lsun/security/util/DisabledAlgorithmConstraints$KeySizeConstraint$Operator;
+Lsun/security/util/DisabledAlgorithmConstraints$KeySizeConstraints;
+Lsun/security/util/KeyUtil;
+Lsun/security/util/Length;
+Lsun/security/util/MemoryCache;
+Lsun/security/util/MemoryCache$CacheEntry;
+Lsun/security/util/MemoryCache$SoftCacheEntry;
+Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AccessDescription;
+Lsun/security/x509/AlgorithmId;
+Lsun/security/x509/AuthorityInfoAccessExtension;
+Lsun/security/x509/AuthorityKeyIdentifierExtension;
+Lsun/security/x509/AVA;
+Lsun/security/x509/AVAKeyword;
+Lsun/security/x509/BasicConstraintsExtension;
+Lsun/security/x509/CertAttrSet;
+Lsun/security/x509/CertificateAlgorithmId;
+Lsun/security/x509/CertificateExtensions;
+Lsun/security/x509/CertificateIssuerExtension;
+Lsun/security/x509/CertificatePoliciesExtension;
+Lsun/security/x509/CertificatePolicyId;
+Lsun/security/x509/CertificateSerialNumber;
+Lsun/security/x509/CertificateValidity;
+Lsun/security/x509/CertificateVersion;
+Lsun/security/x509/CertificateX509Key;
+Lsun/security/x509/CRLDistributionPointsExtension;
+Lsun/security/x509/CRLNumberExtension;
+Lsun/security/x509/CRLReasonCodeExtension;
+Lsun/security/x509/DeltaCRLIndicatorExtension;
+Lsun/security/x509/DistributionPoint;
+Lsun/security/x509/DNSName;
+Lsun/security/x509/ExtendedKeyUsageExtension;
+Lsun/security/x509/Extension;
+Lsun/security/x509/FreshestCRLExtension;
+Lsun/security/x509/GeneralName;
+Lsun/security/x509/GeneralNameInterface;
+Lsun/security/x509/GeneralNames;
+Lsun/security/x509/InhibitAnyPolicyExtension;
+Lsun/security/x509/IssuerAlternativeNameExtension;
+Lsun/security/x509/IssuingDistributionPointExtension;
+Lsun/security/x509/KeyIdentifier;
+Lsun/security/x509/KeyUsageExtension;
+Lsun/security/x509/NameConstraintsExtension;
+Lsun/security/x509/NetscapeCertTypeExtension;
+Lsun/security/x509/OCSPNoCheckExtension;
+Lsun/security/x509/OIDMap;
+Lsun/security/x509/OIDMap$OIDInfo;
+Lsun/security/x509/PKIXExtensions;
+Lsun/security/x509/PolicyConstraintsExtension;
+Lsun/security/x509/PolicyInformation;
+Lsun/security/x509/PolicyMappingsExtension;
+Lsun/security/x509/PrivateKeyUsageExtension;
+Lsun/security/x509/RDN;
+Lsun/security/x509/SerialNumber;
+Lsun/security/x509/SubjectAlternativeNameExtension;
+Lsun/security/x509/SubjectInfoAccessExtension;
+Lsun/security/x509/SubjectKeyIdentifierExtension;
+Lsun/security/x509/URIName;
+Lsun/security/x509/X500Name;
+Lsun/security/x509/X500Name$1;
+Lsun/security/x509/X509AttributeName;
+Lsun/security/x509/X509CertImpl;
+Lsun/security/x509/X509CertInfo;
+Lsun/security/x509/X509Key;
+Lsun/util/calendar/AbstractCalendar;
+Lsun/util/calendar/BaseCalendar;
+Lsun/util/calendar/BaseCalendar$Date;
+Lsun/util/calendar/CalendarDate;
+Lsun/util/calendar/CalendarSystem;
+Lsun/util/calendar/CalendarUtils;
+Lsun/util/calendar/Gregorian;
+Lsun/util/calendar/Gregorian$Date;
+Lsun/util/calendar/JulianCalendar;
+Lsun/util/calendar/LocalGregorianCalendar;
+Lsun/util/locale/BaseLocale;
+Lsun/util/locale/BaseLocale$Cache;
+Lsun/util/locale/BaseLocale$Key;
+Lsun/util/locale/InternalLocaleBuilder;
+Lsun/util/locale/InternalLocaleBuilder$CaseInsensitiveChar;
+Lsun/util/locale/LanguageTag;
+Lsun/util/locale/LocaleObjectCache;
+Lsun/util/locale/LocaleObjectCache$CacheEntry;
+Lsun/util/locale/LocaleSyntaxException;
+Lsun/util/locale/LocaleUtils;
+Lsun/util/locale/ParseStatus;
+Lsun/util/locale/StringTokenIterator;
+Lsun/util/logging/LoggingProxy;
+Lsun/util/logging/LoggingSupport;
+Lsun/util/logging/LoggingSupport$1;
+Lsun/util/logging/PlatformLogger;
+Lsun/util/logging/PlatformLogger$1;
+Lsun/util/logging/PlatformLogger$Level;
+LV;
+LZ;
diff --git a/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java b/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
index f943ee2c..472f984 100644
--- a/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
+++ b/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
@@ -61,6 +61,7 @@
 import android.text.TextUtils;
 import android.util.KeyValueListParser;
 import android.util.Slog;
+import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
@@ -818,7 +819,7 @@
         }
 
         Notification createResetNotification() {
-            return new Notification.Builder(getContext())
+            return new Notification.Builder(getContext(), SystemNotificationChannels.RETAIL_MODE)
                     .setContentTitle(getContext().getString(R.string.reset_retail_demo_mode_title))
                     .setContentText(getContext().getString(R.string.reset_retail_demo_mode_text))
                     .setOngoing(true)
diff --git a/services/tests/notification/AndroidManifest.xml b/services/tests/notification/AndroidManifest.xml
index 92f155f..cf050a8 100644
--- a/services/tests/notification/AndroidManifest.xml
+++ b/services/tests/notification/AndroidManifest.xml
@@ -23,6 +23,7 @@
     <uses-permission android:name="android.permission.MANAGE_USERS" />
     <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
     <uses-permission android:name="android.permission.ACCESS_NOTIFICATIONS" />
+    <uses-permission android:name="android.permission.READ_CONTACTS" />
 
     <application>
         <uses-library android:name="android.test.runner" />
diff --git a/services/tests/notification/src/com/android/server/notification/BadgeExtractorTest.java b/services/tests/notification/src/com/android/server/notification/BadgeExtractorTest.java
index b26bac3..0cf4994 100644
--- a/services/tests/notification/src/com/android/server/notification/BadgeExtractorTest.java
+++ b/services/tests/notification/src/com/android/server/notification/BadgeExtractorTest.java
@@ -89,6 +89,7 @@
         when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true);
         NotificationChannel channel =
                 new NotificationChannel("a", "a", NotificationManager.IMPORTANCE_UNSPECIFIED);
+        when(mConfig.getNotificationChannel(mPkg, mUid, "a", false)).thenReturn(channel);
         channel.setShowBadge(false);
 
         NotificationRecord r = getNotificationRecord(channel);
@@ -107,6 +108,7 @@
         NotificationChannel channel =
                 new NotificationChannel("a", "a", NotificationManager.IMPORTANCE_HIGH);
         channel.setShowBadge(true);
+        when(mConfig.getNotificationChannel(mPkg, mUid, "a", false)).thenReturn(channel);
 
         NotificationRecord r = getNotificationRecord(channel);
 
@@ -124,6 +126,7 @@
         NotificationChannel channel =
                 new NotificationChannel("a", "a", NotificationManager.IMPORTANCE_UNSPECIFIED);
         channel.setShowBadge(true);
+        when(mConfig.getNotificationChannel(mPkg, mUid, "a", false)).thenReturn(channel);
 
         NotificationRecord r = getNotificationRecord(channel);
 
@@ -141,6 +144,7 @@
         NotificationChannel channel =
                 new NotificationChannel("a", "a", NotificationManager.IMPORTANCE_UNSPECIFIED);
         channel.setShowBadge(false);
+        when(mConfig.getNotificationChannel(mPkg, mUid, "a", false)).thenReturn(channel);
 
         NotificationRecord r = getNotificationRecord(channel);
 
diff --git a/services/tests/notification/src/com/android/server/notification/GroupHelperTest.java b/services/tests/notification/src/com/android/server/notification/GroupHelperTest.java
index 936531b..05c33a4 100644
--- a/services/tests/notification/src/com/android/server/notification/GroupHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/GroupHelperTest.java
@@ -64,7 +64,7 @@
 
     private StatusBarNotification getSbn(String pkg, int id, String tag,
             UserHandle user, String groupKey) {
-        Notification.Builder nb = new Notification.Builder(getContext())
+        Notification.Builder nb = new Notification.Builder(getContext(), "test_channel_id")
                 .setContentTitle("A")
                 .setWhen(1205);
         if (groupKey != null) {
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java b/services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java
index 064ab0a..176342b 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java
@@ -63,6 +63,7 @@
     private final int smsUid = 11;
     private final String pkg2 = "pkg2";
     private final int uid2 = 1111111;
+    private static final String TEST_CHANNEL_ID = "test_channel_id";
 
     private NotificationRecord mRecordMinCall;
     private NotificationRecord mRecordHighCall;
@@ -100,7 +101,7 @@
         smsPkg = Settings.Secure.getString(mContext.getContentResolver(),
                 Settings.Secure.SMS_DEFAULT_APPLICATION);
 
-        Notification n1 = new Notification.Builder(mContext)
+        Notification n1 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
                 .setCategory(Notification.CATEGORY_CALL)
                 .setFlag(Notification.FLAG_FOREGROUND_SERVICE, true)
                 .build();
@@ -109,7 +110,7 @@
                 new UserHandle(userId), "", 2000), getDefaultChannel());
         mRecordMinCall.setUserImportance(NotificationManager.IMPORTANCE_MIN);
 
-        Notification n2 = new Notification.Builder(mContext)
+        Notification n2 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
                 .setCategory(Notification.CATEGORY_CALL)
                 .setFlag(Notification.FLAG_FOREGROUND_SERVICE, true)
                 .setColorized(true /* colorized */)
@@ -119,7 +120,7 @@
                 new UserHandle(userId), "", 1999), getDefaultChannel());
         mRecordHighCall.setUserImportance(NotificationManager.IMPORTANCE_HIGH);
 
-        Notification n3 = new Notification.Builder(mContext)
+        Notification n3 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
                 .setStyle(new Notification.MediaStyle()
                         .setMediaSession(new MediaSession.Token(null)))
                 .setFlag(Notification.FLAG_FOREGROUND_SERVICE, true)
@@ -129,7 +130,7 @@
                 "", 1499), getDefaultChannel());
         mRecordDefaultMedia.setUserImportance(NotificationManager.IMPORTANCE_DEFAULT);
 
-        Notification n4 = new Notification.Builder(mContext)
+        Notification n4 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
                 .setStyle(new Notification.MessagingStyle("sender!")).build();
         mRecordInlineReply = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
                 pkg2, 1, "inlinereply", uid2, uid2, n4, new UserHandle(userId),
@@ -137,34 +138,34 @@
         mRecordInlineReply.setUserImportance(NotificationManager.IMPORTANCE_HIGH);
         mRecordInlineReply.setPackagePriority(Notification.PRIORITY_MAX);
 
-        Notification n5 = new Notification.Builder(mContext)
+        Notification n5 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
                 .setCategory(Notification.CATEGORY_MESSAGE).build();
         mRecordSms = new NotificationRecord(mContext, new StatusBarNotification(smsPkg,
                 smsPkg, 1, "sms", smsUid, smsUid, n5, new UserHandle(userId),
                 "", 1299), getDefaultChannel());
         mRecordSms.setUserImportance(NotificationManager.IMPORTANCE_DEFAULT);
 
-        Notification n6 = new Notification.Builder(mContext).build();
+        Notification n6 = new Notification.Builder(mContext, TEST_CHANNEL_ID).build();
         mRecordStarredContact = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
                 pkg2, 1, "starred", uid2, uid2, n6, new UserHandle(userId),
                 "", 1259), getDefaultChannel());
         mRecordStarredContact.setContactAffinity(ValidateNotificationPeople.STARRED_CONTACT);
         mRecordStarredContact.setUserImportance(NotificationManager.IMPORTANCE_DEFAULT);
 
-        Notification n7 = new Notification.Builder(mContext).build();
+        Notification n7 = new Notification.Builder(mContext, TEST_CHANNEL_ID).build();
         mRecordContact = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
                 pkg2, 1, "contact", uid2, uid2, n7, new UserHandle(userId),
                 "", 1259), getDefaultChannel());
         mRecordContact.setContactAffinity(ValidateNotificationPeople.VALID_CONTACT);
         mRecordContact.setUserImportance(NotificationManager.IMPORTANCE_DEFAULT);
 
-        Notification n8 = new Notification.Builder(mContext).build();
+        Notification n8 = new Notification.Builder(mContext, TEST_CHANNEL_ID).build();
         mRecordUrgent = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
                 pkg2, 1, "urgent", uid2, uid2, n8, new UserHandle(userId),
                 "", 1258), getDefaultChannel());
         mRecordUrgent.setUserImportance(NotificationManager.IMPORTANCE_HIGH);
 
-        Notification n9 = new Notification.Builder(mContext)
+        Notification n9 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
                 .setCategory(Notification.CATEGORY_MESSAGE)
                 .setFlag(Notification.FLAG_ONGOING_EVENT
                         |Notification.FLAG_FOREGROUND_SERVICE, true)
@@ -174,7 +175,7 @@
                 "", 9258), getDefaultChannel());
         mRecordCheater.setUserImportance(NotificationManager.IMPORTANCE_LOW);
 
-        Notification n10 = new Notification.Builder(mContext)
+        Notification n10 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
                 .setStyle(new Notification.InboxStyle().setSummaryText("message!")).build();
         mRecordEmail = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
                 pkg2, 1, "email", uid2, uid2, n10, new UserHandle(userId),
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
index 88f1a53..b7b3617 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -129,11 +129,9 @@
         if (channel == null) {
             channel = new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_DEFAULT);
         }
-        Notification.Builder nb = new Notification.Builder(mContext)
+        Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
                 .setContentTitle("foo")
-                .setSmallIcon(android.R.drawable.sym_def_app_icon)
-                .setChannel(channel.getId())
-                .setPriority(Notification.PRIORITY_HIGH);
+                .setSmallIcon(android.R.drawable.sym_def_app_icon);
         if (extender != null) {
             nb.extend(extender);
         }
diff --git a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
index 9ea9ce9..450f9b6 100644
--- a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
@@ -15,11 +15,15 @@
  */
 package com.android.server.notification;
 
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
 import static android.app.NotificationManager.IMPORTANCE_LOW;
 
 import static junit.framework.Assert.assertNull;
 import static junit.framework.Assert.fail;
 
+import org.json.JSONArray;
+import org.json.JSONObject;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -47,6 +51,7 @@
 import android.support.test.InstrumentationRegistry;
 import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
+import android.util.ArrayMap;
 import android.util.Xml;
 
 import java.io.BufferedInputStream;
@@ -59,12 +64,14 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.concurrent.ThreadLocalRandom;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.when;
 
@@ -93,6 +100,7 @@
     private final int uid = 0;
     private final String pkg2 = "pkg2";
     private final int uid2 = 1111111;
+    private static final String TEST_CHANNEL_ID = "test_channel_id";
     private AudioAttributes mAudioAttributes;
 
     private Context getContext() {
@@ -107,7 +115,7 @@
         mHelper = new RankingHelper(getContext(), mPm, handler, mUsageStats,
                 new String[]{ImportanceExtractor.class.getName()});
 
-        mNotiGroupGSortA = new Notification.Builder(getContext())
+        mNotiGroupGSortA = new Notification.Builder(getContext(), TEST_CHANNEL_ID)
                 .setContentTitle("A")
                 .setGroup("G")
                 .setSortKey("A")
@@ -117,7 +125,7 @@
                 "package", "package", 1, null, 0, 0, mNotiGroupGSortA, user,
                 null, System.currentTimeMillis()), getDefaultChannel());
 
-        mNotiGroupGSortB = new Notification.Builder(getContext())
+        mNotiGroupGSortB = new Notification.Builder(getContext(), TEST_CHANNEL_ID)
                 .setContentTitle("B")
                 .setGroup("G")
                 .setSortKey("B")
@@ -127,7 +135,7 @@
                 "package", "package", 1, null, 0, 0, mNotiGroupGSortB, user,
                 null, System.currentTimeMillis()), getDefaultChannel());
 
-        mNotiNoGroup = new Notification.Builder(getContext())
+        mNotiNoGroup = new Notification.Builder(getContext(), TEST_CHANNEL_ID)
                 .setContentTitle("C")
                 .setWhen(1201)
                 .build();
@@ -135,7 +143,7 @@
                 "package", "package", 1, null, 0, 0, mNotiNoGroup, user,
                 null, System.currentTimeMillis()), getDefaultChannel());
 
-        mNotiNoGroup2 = new Notification.Builder(getContext())
+        mNotiNoGroup2 = new Notification.Builder(getContext(), TEST_CHANNEL_ID)
                 .setContentTitle("D")
                 .setWhen(1202)
                 .build();
@@ -143,7 +151,7 @@
                 "package", "package", 1, null, 0, 0, mNotiNoGroup2, user,
                 null, System.currentTimeMillis()), getDefaultChannel());
 
-        mNotiNoGroupSortA = new Notification.Builder(getContext())
+        mNotiNoGroupSortA = new Notification.Builder(getContext(), TEST_CHANNEL_ID)
                 .setContentTitle("E")
                 .setWhen(1201)
                 .setSortKey("A")
@@ -195,6 +203,7 @@
     private void compareChannels(NotificationChannel expected, NotificationChannel actual) {
         assertEquals(expected.getId(), actual.getId());
         assertEquals(expected.getName(), actual.getName());
+        assertEquals(expected.getNameResId(), actual.getNameResId());
         assertEquals(expected.shouldVibrate(), actual.shouldVibrate());
         assertEquals(expected.shouldShowLights(), actual.shouldShowLights());
         assertEquals(expected.getImportance(), actual.getImportance());
@@ -207,6 +216,12 @@
         assertEquals(expected.getLightColor(), actual.getLightColor());
     }
 
+    private void compareGroups(NotificationChannelGroup expected, NotificationChannelGroup actual) {
+        assertEquals(expected.getId(), actual.getId());
+        assertEquals(expected.getName(), actual.getName());
+        assertEquals(expected.getNameResId(), actual.getNameResId());
+    }
+
     @Test
     public void testFindAfterRankingWithASplitGroup() throws Exception {
         ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(3);
@@ -259,11 +274,15 @@
 
     @Test
     public void testChannelXml() throws Exception {
-        NotificationChannelGroup ncg = new NotificationChannelGroup("1", "2");
+        int nameResId = 924896;
+        int groupNameResId = 426272;
+
+        NotificationChannelGroup ncg = new NotificationChannelGroup("1", groupNameResId);
+        NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello");
         NotificationChannel channel1 =
                 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
         NotificationChannel channel2 =
-                new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
+                new NotificationChannel("id2", nameResId, IMPORTANCE_LOW);
         channel2.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
         channel2.enableLights(true);
         channel2.setBypassDnd(true);
@@ -274,6 +293,7 @@
         channel2.setLightColor(Color.BLUE);
 
         mHelper.createNotificationChannelGroup(pkg, uid, ncg, true);
+        mHelper.createNotificationChannelGroup(pkg, uid, ncg2, true);
         mHelper.createNotificationChannel(pkg, uid, channel1, true);
         mHelper.createNotificationChannel(pkg, uid, channel2, false);
 
@@ -304,7 +324,9 @@
         for (NotificationChannelGroup actual : actualGroups) {
             if (ncg.getId().equals(actual.getId())) {
                 foundNcg = true;
-                 break;
+                compareGroups(ncg, actual);
+            } else if (ncg2.getId().equals(actual.getId())) {
+                compareGroups(ncg2, actual);
             }
         }
         assertTrue(foundNcg);
@@ -756,6 +778,17 @@
     }
 
     @Test
+    public void testCreateChannel_defaultChannelId() throws Exception {
+        try {
+            mHelper.createNotificationChannel(pkg2, uid2, new NotificationChannel(
+                    NotificationChannel.DEFAULT_CHANNEL_ID, "ha", IMPORTANCE_HIGH), true);
+            fail("Allowed to create default channel");
+        } catch (IllegalArgumentException e) {
+            // pass
+        }
+    }
+
+    @Test
     public void testCreateChannel_alreadyExists() throws Exception {
         long[] vibration = new long[]{100, 67, 145, 156};
         NotificationChannel channel =
@@ -776,6 +809,26 @@
     }
 
     @Test
+    public void testCreateChannel_addMissingSound() throws Exception {
+        final NotificationChannel channel =
+                new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
+        mHelper.createNotificationChannel(pkg, uid, channel, true);
+        assertNotNull(mHelper.getNotificationChannel(
+                pkg, uid, channel.getId(), false).getSound());
+    }
+
+    @Test
+    public void testCreateChannel_noOverrideSound() throws Exception {
+        Uri sound = new Uri.Builder().scheme("test").build();
+        final NotificationChannel channel = new NotificationChannel("id2", "name2",
+                 NotificationManager.IMPORTANCE_DEFAULT);
+        channel.setSound(sound, mAudioAttributes);
+        mHelper.createNotificationChannel(pkg, uid, channel, true);
+        assertEquals(sound, mHelper.getNotificationChannel(
+                pkg, uid, channel.getId(), false).getSound());
+    }
+
+    @Test
     public void testPermanentlyDeleteChannels() throws Exception {
         NotificationChannel channel1 =
                 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
@@ -939,9 +992,58 @@
 
         assertEquals(2, actual.size());
         for (NotificationChannelGroup group : actual) {
-            if (Objects.equals(group.getId(),ncg.getId())) {
+            if (Objects.equals(group.getId(), ncg.getId())) {
                 assertEquals(1, group.getChannels().size());
             }
         }
     }
+
+    @Test
+    public void testCreateChannel_updateNameResId() throws Exception {
+        NotificationChannel nc = new NotificationChannel("id", 1, IMPORTANCE_DEFAULT);
+        mHelper.createNotificationChannel(pkg, uid, nc, true);
+
+        nc = new NotificationChannel("id", 2, IMPORTANCE_DEFAULT);
+        mHelper.createNotificationChannel(pkg, uid, nc, true);
+
+        assertEquals(2, mHelper.getNotificationChannel(pkg, uid, "id", false).getNameResId());
+    }
+
+    @Test
+    public void testDumpChannelsJson() throws Exception {
+        final ApplicationInfo upgrade = new ApplicationInfo();
+        upgrade.targetSdkVersion = Build.VERSION_CODES.O;
+        try {
+            when(mPm.getApplicationInfoAsUser(
+                    anyString(), anyInt(), anyInt())).thenReturn(upgrade);
+        } catch (PackageManager.NameNotFoundException e) {
+        }
+        ArrayMap<String, Integer> expectedChannels = new ArrayMap<>();
+        int numPackages = ThreadLocalRandom.current().nextInt(1, 5);
+        for (int i = 0; i < numPackages; i++) {
+            String pkgName = "pkg" + i;
+            int numChannels = ThreadLocalRandom.current().nextInt(1, 10);
+            for (int j = 0; j < numChannels; j++) {
+                mHelper.createNotificationChannel(pkgName, uid,
+                        new NotificationChannel("" + j, "a", IMPORTANCE_HIGH), true);
+            }
+            expectedChannels.put(pkgName, numChannels);
+        }
+
+        // delete the first channel of the first package
+        String pkg = expectedChannels.keyAt(0);
+        mHelper.deleteNotificationChannel("pkg" + 0, uid, "0");
+        // dump should not include deleted channels
+        int count = expectedChannels.get(pkg);
+        expectedChannels.put(pkg, count - 1);
+
+        JSONArray actual = mHelper.dumpChannelsJson(new NotificationManagerService.DumpFilter());
+        assertEquals(numPackages, actual.length());
+        for (int i = 0; i < numPackages; i++) {
+            JSONObject object = actual.getJSONObject(i);
+            assertTrue(expectedChannels.containsKey(object.get("packageName")));
+            assertEquals(expectedChannels.get(object.get("packageName")).intValue() + 1,
+                    object.getInt("channelCount"));
+        }
+    }
 }
diff --git a/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java b/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java
index 69724f4..9575d32 100644
--- a/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java
@@ -18,6 +18,7 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -27,6 +28,7 @@
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.Context;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.service.notification.StatusBarNotification;
 import android.support.test.InstrumentationRegistry;
@@ -49,6 +51,8 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class SnoozeHelperTest {
+    private static final String TEST_CHANNEL_ID = "test_channel_id";
+
     @Mock SnoozeHelper.Callback mCallback;
     @Mock AlarmManager mAm;
     @Mock ManagedServices.UserProfiles mUserProfiles;
@@ -71,8 +75,11 @@
     public void testSnoozeForTime() throws Exception {
         NotificationRecord r = getNotificationRecord("pkg", 1, "one", UserHandle.SYSTEM);
         mSnoozeHelper.snooze(r, 1000);
+        ArgumentCaptor<Long> captor = ArgumentCaptor.forClass(Long.class);
         verify(mAm, times(1)).setExactAndAllowWhileIdle(
-                anyInt(), eq((long) 1000), any(PendingIntent.class));
+                anyInt(), captor.capture(), any(PendingIntent.class));
+        long actualSnoozedUntilDuration = captor.getValue() - SystemClock.elapsedRealtime();
+        assertTrue(Math.abs(actualSnoozedUntilDuration - 1000) < 25);
         assertTrue(mSnoozeHelper.isSnoozed(
                 UserHandle.USER_SYSTEM, r.sbn.getPackageName(), r.getKey()));
     }
@@ -227,20 +234,16 @@
 
     private NotificationRecord getNotificationRecord(String pkg, int id, String tag,
             UserHandle user) {
-        Notification n = new Notification.Builder(getContext())
+        Notification n = new Notification.Builder(getContext(), TEST_CHANNEL_ID)
                 .setContentTitle("A")
                 .setGroup("G")
                 .setSortKey("A")
                 .setWhen(1205)
                 .build();
+        final NotificationChannel notificationChannel = new NotificationChannel(
+                TEST_CHANNEL_ID, "name", NotificationManager.IMPORTANCE_LOW);
         return new NotificationRecord(getContext(), new StatusBarNotification(
                 pkg, pkg, id, tag, 0, 0, n, user, null,
-                System.currentTimeMillis()), getDefaultChannel());
+                System.currentTimeMillis()), notificationChannel);
     }
-
-    private NotificationChannel getDefaultChannel() {
-        return new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "name",
-                NotificationManager.IMPORTANCE_LOW);
-    }
-
 }
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
index c0b79be..38c6b0d 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
@@ -56,8 +56,7 @@
 import android.net.INetworkScoreCache;
 import android.net.NetworkKey;
 import android.net.NetworkScoreManager;
-import android.net.NetworkScorerAppManager;
-import android.net.NetworkScorerAppManager.NetworkScorerAppData;
+import android.net.NetworkScorerAppData;
 import android.net.RecommendationRequest;
 import android.net.RecommendationResult;
 import android.net.ScoredNetwork;
@@ -120,14 +119,18 @@
     private static final String INVALID_BSSID = "invalid_bssid";
     private static final ComponentName RECOMMENDATION_SERVICE_COMP =
             new ComponentName("newPackageName", "newScoringServiceClass");
+    private static final String RECOMMENDATION_SERVICE_LABEL = "Test Recommendation Service";
+    private static final ComponentName USE_WIFI_ENABLE_ACTIVITY_COMP =
+            new ComponentName("useWifiPackageName", "enableUseWifiActivityClass");
     private static final ScoredNetwork SCORED_NETWORK =
             new ScoredNetwork(new NetworkKey(new WifiKey(quote(SSID), "00:00:00:00:00:00")),
                     null /* rssiCurve*/);
     private static final ScoredNetwork SCORED_NETWORK_2 =
             new ScoredNetwork(new NetworkKey(new WifiKey(quote(SSID_2), "00:00:00:00:00:00")),
                     null /* rssiCurve*/);
-    private static final NetworkScorerAppData NEW_SCORER =
-        new NetworkScorerAppData(1, RECOMMENDATION_SERVICE_COMP);
+    private static final NetworkScorerAppData NEW_SCORER = new NetworkScorerAppData(
+            1, RECOMMENDATION_SERVICE_COMP, RECOMMENDATION_SERVICE_LABEL,
+            USE_WIFI_ENABLE_ACTIVITY_COMP);
 
     @Mock private NetworkScorerAppManager mNetworkScorerAppManager;
     @Mock private Context mContext;
@@ -199,10 +202,10 @@
     }
 
     @Test
-    public void testSystemRunning() {
+    public void testOnUserUnlocked() {
         when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
 
-        mNetworkScoreService.systemRunning();
+        mNetworkScoreService.onUserUnlocked(0);
 
         verify(mContext).bindServiceAsUser(MockUtils.checkIntent(
                 new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS)
@@ -547,9 +550,9 @@
     }
 
     @Test
-    public void testSetActiveScorer_noScoreNetworksPermission() {
-        doThrow(new SecurityException()).when(mContext)
-                .enforceCallingOrSelfPermission(eq(permission.SCORE_NETWORKS), anyString());
+    public void testSetActiveScorer_noRequestNetworkScoresPermission() {
+        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
+                .thenReturn(PackageManager.PERMISSION_DENIED);
 
         try {
             mNetworkScoreService.setActiveScorer(null);
@@ -628,7 +631,7 @@
 
     @Test
     public void testIsCallerActiveScorer_noBoundService() throws Exception {
-        mNetworkScoreService.systemRunning();
+        mNetworkScoreService.onUserUnlocked(0);
 
         assertFalse(mNetworkScoreService.isCallerActiveScorer(Binder.getCallingUid()));
     }
@@ -649,7 +652,7 @@
 
     @Test
     public void testGetActiveScorerPackage_notActive() throws Exception {
-        mNetworkScoreService.systemRunning();
+        mNetworkScoreService.onUserUnlocked(0);
 
         assertNull(mNetworkScoreService.getActiveScorerPackage());
     }
@@ -657,10 +660,12 @@
     @Test
     public void testGetActiveScorerPackage_active() throws Exception {
         when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
-        mNetworkScoreService.systemRunning();
+        mNetworkScoreService.onUserUnlocked(0);
 
         assertEquals(NEW_SCORER.getRecommendationServicePackageName(),
                 mNetworkScoreService.getActiveScorerPackage());
+        assertEquals(NEW_SCORER.getEnableUseOpenWifiActivity(),
+                mNetworkScoreService.getActiveScorer().getEnableUseOpenWifiActivity());
     }
 
     @Test
@@ -920,8 +925,9 @@
             throws Exception {
         when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
                 .thenReturn(PackageManager.PERMISSION_GRANTED);
-        NetworkScorerAppData expectedAppData =
-                new NetworkScorerAppData(Binder.getCallingUid(), RECOMMENDATION_SERVICE_COMP);
+        NetworkScorerAppData expectedAppData = new NetworkScorerAppData(Binder.getCallingUid(),
+                RECOMMENDATION_SERVICE_COMP, RECOMMENDATION_SERVICE_LABEL,
+                USE_WIFI_ENABLE_ACTIVITY_COMP);
         bindToScorer(expectedAppData);
         assertEquals(expectedAppData, mNetworkScoreService.getActiveScorer());
     }
@@ -956,13 +962,14 @@
                 return true;
             }
         });
-        mNetworkScoreService.systemRunning();
+        mNetworkScoreService.onUserUnlocked(0);
     }
 
     private void bindToScorer(boolean callerIsScorer) {
         final int callingUid = callerIsScorer ? Binder.getCallingUid() : Binder.getCallingUid() + 1;
-        NetworkScorerAppData appData =
-                new NetworkScorerAppData(callingUid, RECOMMENDATION_SERVICE_COMP);
+        NetworkScorerAppData appData = new NetworkScorerAppData(callingUid,
+                RECOMMENDATION_SERVICE_COMP, RECOMMENDATION_SERVICE_LABEL,
+                USE_WIFI_ENABLE_ACTIVITY_COMP);
         bindToScorer(appData);
     }
 
@@ -970,7 +977,7 @@
         when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(appData);
         when(mContext.bindServiceAsUser(isA(Intent.class), isA(ServiceConnection.class), anyInt(),
                 isA(UserHandle.class))).thenReturn(true);
-        mNetworkScoreService.systemRunning();
+        mNetworkScoreService.onUserUnlocked(0);
     }
 
     private static class OnResultListener implements RemoteCallback.OnResultListener {
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java b/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java
new file mode 100644
index 0000000..64f176a
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java
@@ -0,0 +1,426 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+
+import static org.junit.Assert.assertFalse;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.Manifest.permission;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.content.res.Resources;
+import android.net.NetworkScoreManager;
+import android.net.NetworkScorerAppData;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.internal.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentMatcher;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class NetworkScorerAppManagerTest {
+    private static String MOCK_SERVICE_LABEL = "Mock Service";
+    private static String MOCK_OVERRIDEN_SERVICE_LABEL = "Mock Service Label Override";
+
+    @Mock private Context mMockContext;
+    @Mock private PackageManager mMockPm;
+    @Mock private Resources mResources;
+    @Mock private NetworkScorerAppManager.SettingsFacade mSettingsFacade;
+    private NetworkScorerAppManager mNetworkScorerAppManager;
+    private List<ResolveInfo> mAvailableServices;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mAvailableServices = new ArrayList<>();
+        when(mMockContext.getPackageManager()).thenReturn(mMockPm);
+        when(mMockPm.queryIntentServices(Mockito.argThat(new ArgumentMatcher<Intent>() {
+            @Override
+            public boolean matches(Object object) {
+                Intent intent = (Intent) object;
+                return NetworkScoreManager.ACTION_RECOMMEND_NETWORKS.equals(intent.getAction());
+            }
+        }), eq(PackageManager.GET_META_DATA))).thenReturn(mAvailableServices);
+        when(mMockContext.getResources()).thenReturn(mResources);
+
+        mNetworkScorerAppManager = new NetworkScorerAppManager(mMockContext, mSettingsFacade);
+    }
+
+    @Test
+    public void testGetActiveScorer_providerAvailable() throws Exception {
+        final ComponentName recoComponent = new ComponentName("package1", "class1");
+        setNetworkRecoPackageSetting(recoComponent.getPackageName());
+        mockScoreNetworksGranted(recoComponent.getPackageName());
+        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */);
+
+        final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
+        assertNotNull(activeScorer);
+        assertEquals(recoComponent, activeScorer.getRecommendationServiceComponent());
+        assertEquals(924, activeScorer.packageUid);
+        assertEquals(MOCK_SERVICE_LABEL, activeScorer.getRecommendationServiceLabel());
+    }
+
+    @Test
+    public void testGetActiveScorer_providerAvailable_serviceLabelOverride() throws Exception {
+        final ComponentName recoComponent = new ComponentName("package1", "class1");
+        setNetworkRecoPackageSetting(recoComponent.getPackageName());
+        mockScoreNetworksGranted(recoComponent.getPackageName());
+        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
+                null /* enableUseOpenWifiPackageActivityPackage*/, true /* serviceLabelOverride */);
+
+        final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
+        assertNotNull(activeScorer);
+        assertEquals(recoComponent, activeScorer.getRecommendationServiceComponent());
+        assertEquals(924, activeScorer.packageUid);
+        assertEquals(MOCK_OVERRIDEN_SERVICE_LABEL, activeScorer.getRecommendationServiceLabel());
+    }
+
+    @Test
+    public void testGetActiveScorer_permissionMissing() throws Exception {
+        final ComponentName recoComponent = new ComponentName("package1", "class1");
+        setNetworkRecoPackageSetting(recoComponent.getPackageName());
+        mockScoreNetworksDenied(recoComponent.getPackageName());
+        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */);
+
+        final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
+        assertNull(activeScorer);
+    }
+
+    @Test
+    public void testGetActiveScorer_providerAvailable_enableUseOpenWifiActivityNotSet()
+            throws Exception {
+        final ComponentName recoComponent = new ComponentName("package1", "class1");
+        setNetworkRecoPackageSetting(recoComponent.getPackageName());
+        mockScoreNetworksGranted(recoComponent.getPackageName());
+        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
+                null /* enableUseOpenWifiPackageActivityPackage*/);
+
+        final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
+        assertNotNull(activeScorer);
+        assertEquals(recoComponent, activeScorer.getRecommendationServiceComponent());
+        assertEquals(924, activeScorer.packageUid);
+        assertNull(activeScorer.getEnableUseOpenWifiActivity());
+    }
+
+    @Test
+    public void testGetActiveScorer_providerAvailable_enableUseOpenWifiActivityNotResolved()
+            throws Exception {
+        final ComponentName recoComponent = new ComponentName("package1", "class1");
+        setNetworkRecoPackageSetting(recoComponent.getPackageName());
+        mockScoreNetworksGranted(recoComponent.getPackageName());
+        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
+                "package2" /* enableUseOpenWifiPackageActivityPackage*/);
+
+        final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
+        assertNotNull(activeScorer);
+        assertEquals(recoComponent, activeScorer.getRecommendationServiceComponent());
+        assertEquals(924, activeScorer.packageUid);
+        assertNull(activeScorer.getEnableUseOpenWifiActivity());
+    }
+
+    @Test
+    public void testGetActiveScorer_providerAvailable_enableUseOpenWifiActivityResolved()
+            throws Exception {
+        final ComponentName recoComponent = new ComponentName("package1", "class1");
+        final ComponentName enableUseOpenWifiComponent = new ComponentName("package2", "class2");
+        setNetworkRecoPackageSetting(recoComponent.getPackageName());
+        mockScoreNetworksGranted(recoComponent.getPackageName());
+        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
+                enableUseOpenWifiComponent.getPackageName());
+        mockEnableUseOpenWifiActivity(enableUseOpenWifiComponent);
+
+        final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
+        assertNotNull(activeScorer);
+        assertEquals(recoComponent, activeScorer.getRecommendationServiceComponent());
+        assertEquals(924, activeScorer.packageUid);
+        assertEquals(enableUseOpenWifiComponent, activeScorer.getEnableUseOpenWifiActivity());
+    }
+
+    @Test
+    public void testGetActiveScorer_packageSettingIsNull()
+            throws Exception {
+        // NETWORK_RECOMMENDATIONS_PACKAGE is null
+
+        final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
+        assertNull(activeScorer);
+    }
+
+    @Test
+    public void testGetActiveScorer_packageSettingIsInvalid() throws Exception {
+        final ComponentName recoComponent = new ComponentName("package1", "class1");
+        setDefaultNetworkRecommendationPackage(recoComponent.getPackageName());
+        mockScoreNetworksGranted(recoComponent.getPackageName());
+        // NETWORK_RECOMMENDATIONS_PACKAGE is set to a package that isn't a recommender.
+
+        final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
+        assertNull(activeScorer);
+    }
+
+    @Test
+    public void testSetActiveScorer_noChange() throws Exception {
+        String packageName = "package";
+        setNetworkRecoPackageSetting(packageName);
+
+        assertTrue(mNetworkScorerAppManager.setActiveScorer(packageName));
+        verify(mSettingsFacade, never()).putString(any(), any(), any());
+    }
+
+    @Test
+    public void testSetActiveScorer_nullPackage_validDefault() throws Exception {
+        String packageName = "package";
+        String defaultPackage = "defaultPackage";
+        setNetworkRecoPackageSetting(packageName);
+        setDefaultNetworkRecommendationPackage(defaultPackage);
+        final ComponentName recoComponent = new ComponentName(defaultPackage, "class1");
+        mockScoreNetworksGranted(recoComponent.getPackageName());
+        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */, null);
+
+        assertTrue(mNetworkScorerAppManager.setActiveScorer(null));
+        verify(mSettingsFacade).putString(mMockContext,
+                Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, defaultPackage);
+    }
+
+    @Test
+    public void testSetActiveScorer_nullPackage_invalidDefault() throws Exception {
+        String packageName = "package";
+        String defaultPackage = "defaultPackage";
+        setNetworkRecoPackageSetting(packageName);
+        setDefaultNetworkRecommendationPackage(defaultPackage);
+
+        assertFalse(mNetworkScorerAppManager.setActiveScorer(null));
+        verify(mSettingsFacade, never()).putString(any(),
+                eq(Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE), any());
+    }
+
+    @Test
+    public void testSetActiveScorer_validPackage() throws Exception {
+        String packageName = "package";
+        String newPackage = "newPackage";
+        setNetworkRecoPackageSetting(packageName);
+        final ComponentName recoComponent = new ComponentName(newPackage, "class1");
+        mockScoreNetworksGranted(recoComponent.getPackageName());
+        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */, null);
+
+        assertTrue(mNetworkScorerAppManager.setActiveScorer(newPackage));
+        verify(mSettingsFacade).putString(mMockContext,
+                Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, newPackage);
+    }
+
+    @Test
+    public void testSetActiveScorer_invalidPackage() throws Exception {
+        String packageName = "package";
+        String newPackage = "newPackage";
+        setNetworkRecoPackageSetting(packageName);
+        // newPackage doesn't resolve to a valid recommender
+
+        assertFalse(mNetworkScorerAppManager.setActiveScorer(newPackage));
+        verify(mSettingsFacade, never()).putString(any(), any(), any());
+    }
+
+    @Test
+    public void testUpdateState_recommendationsForcedOff() throws Exception {
+        setRecommendationsEnabledSetting(NetworkScoreManager.RECOMMENDATIONS_ENABLED_FORCED_OFF);
+
+        mNetworkScorerAppManager.updateState();
+
+        verify(mSettingsFacade, never()).getString(any(),
+                eq(Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE));
+        verify(mSettingsFacade, never()).putInt(any(),
+                eq(Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED), anyInt());
+    }
+
+    @Test
+    public void testUpdateState_currentPackageValid() throws Exception {
+        String packageName = "package";
+        setNetworkRecoPackageSetting(packageName);
+        final ComponentName recoComponent = new ComponentName(packageName, "class1");
+        mockScoreNetworksGranted(recoComponent.getPackageName());
+        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */, null);
+
+        mNetworkScorerAppManager.updateState();
+
+        verify(mSettingsFacade, never()).putString(any(),
+                eq(Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE), any());
+        verify(mSettingsFacade).putInt(mMockContext,
+                Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED,
+                NetworkScoreManager.RECOMMENDATIONS_ENABLED_ON);
+    }
+
+    @Test
+    public void testUpdateState_currentPackageNotValid_validDefault() throws Exception {
+        String defaultPackage = "defaultPackage";
+        setDefaultNetworkRecommendationPackage(defaultPackage);
+        final ComponentName recoComponent = new ComponentName(defaultPackage, "class1");
+        mockScoreNetworksGranted(recoComponent.getPackageName());
+        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */, null);
+
+        mNetworkScorerAppManager.updateState();
+
+        verify(mSettingsFacade).putString(mMockContext,
+                Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, defaultPackage);
+        verify(mSettingsFacade).putInt(mMockContext,
+                Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED,
+                NetworkScoreManager.RECOMMENDATIONS_ENABLED_ON);
+    }
+
+    @Test
+    public void testUpdateState_currentPackageNotValid_invalidDefault() throws Exception {
+        String defaultPackage = "defaultPackage";
+        setDefaultNetworkRecommendationPackage(defaultPackage);
+        setNetworkRecoPackageSetting("currentPackage");
+
+        mNetworkScorerAppManager.updateState();
+
+        verify(mSettingsFacade).putString(mMockContext,
+                Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, defaultPackage);
+        verify(mSettingsFacade).putInt(mMockContext,
+                Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED,
+                NetworkScoreManager.RECOMMENDATIONS_ENABLED_OFF);
+    }
+
+    @Test
+    public void testUpdateState_currentPackageNotValid_sameAsDefault() throws Exception {
+        String defaultPackage = "defaultPackage";
+        setDefaultNetworkRecommendationPackage(defaultPackage);
+        setNetworkRecoPackageSetting(defaultPackage);
+
+        mNetworkScorerAppManager.updateState();
+
+        verify(mSettingsFacade, never()).putString(any(),
+                eq(Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE), any());
+    }
+
+    private void setRecommendationsEnabledSetting(int value) {
+        when(mSettingsFacade.getInt(eq(mMockContext),
+                eq(Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED), anyInt())).thenReturn(value);
+    }
+
+    private void setNetworkRecoPackageSetting(String packageName) {
+        when(mSettingsFacade.getString(mMockContext,
+                Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE)).thenReturn(packageName);
+    }
+
+    private void setDefaultNetworkRecommendationPackage(String name) {
+        when(mResources.getString(R.string.config_defaultNetworkRecommendationProviderPackage))
+                .thenReturn(name);
+    }
+
+    private void mockScoreNetworksGranted(String packageName) {
+        when(mMockPm.checkPermission(permission.SCORE_NETWORKS, packageName))
+                .thenReturn(PackageManager.PERMISSION_GRANTED);
+    }
+
+    private void mockScoreNetworksDenied(String packageName) {
+        when(mMockPm.checkPermission(permission.SCORE_NETWORKS, packageName))
+                .thenReturn(PackageManager.PERMISSION_DENIED);
+    }
+
+    private void mockRecommendationServiceAvailable(final ComponentName compName, int packageUid) {
+        mockRecommendationServiceAvailable(compName, packageUid, null, false);
+    }
+
+    private void mockRecommendationServiceAvailable(final ComponentName compName, int packageUid,
+            String enableUseOpenWifiActivityPackage) {
+        mockRecommendationServiceAvailable(
+                compName, packageUid, enableUseOpenWifiActivityPackage, false);
+    }
+
+    private void mockRecommendationServiceAvailable(final ComponentName compName, int packageUid,
+            String enableUseOpenWifiActivityPackage, boolean serviceLabelOverride) {
+        final ResolveInfo serviceInfo = new ResolveInfo();
+        serviceInfo.serviceInfo = new ServiceInfo();
+        serviceInfo.serviceInfo.name = compName.getClassName();
+        serviceInfo.serviceInfo.packageName = compName.getPackageName();
+        serviceInfo.serviceInfo.applicationInfo = new ApplicationInfo();
+        serviceInfo.serviceInfo.applicationInfo.uid = packageUid;
+        if (enableUseOpenWifiActivityPackage != null) {
+            serviceInfo.serviceInfo.metaData = new Bundle();
+            serviceInfo.serviceInfo.metaData.putString(
+                    NetworkScoreManager.USE_OPEN_WIFI_PACKAGE_META_DATA,
+                    enableUseOpenWifiActivityPackage);
+        }
+        if (serviceLabelOverride) {
+            if (serviceInfo.serviceInfo.metaData == null) {
+                serviceInfo.serviceInfo.metaData = new Bundle();
+            }
+            serviceInfo.serviceInfo.metaData.putString(
+                    NetworkScoreManager.RECOMMENDATION_SERVICE_LABEL_META_DATA,
+                    MOCK_OVERRIDEN_SERVICE_LABEL);
+        } else {
+            serviceInfo.serviceInfo.nonLocalizedLabel = MOCK_SERVICE_LABEL;
+        }
+
+        final int flags = PackageManager.GET_META_DATA;
+        when(mMockPm.resolveService(
+                Mockito.argThat(new ArgumentMatcher<Intent>() {
+                    @Override
+                    public boolean matches(Object object) {
+                        Intent intent = (Intent) object;
+                        return NetworkScoreManager.ACTION_RECOMMEND_NETWORKS
+                                .equals(intent.getAction())
+                                && compName.getPackageName().equals(intent.getPackage());
+                    }
+                }), Mockito.eq(flags))).thenReturn(serviceInfo);
+
+        mAvailableServices.add(serviceInfo);
+    }
+
+    private void mockEnableUseOpenWifiActivity(final ComponentName useOpenWifiComp) {
+        final ResolveInfo resolveActivityInfo = new ResolveInfo();
+        resolveActivityInfo.activityInfo = new ActivityInfo();
+        resolveActivityInfo.activityInfo.name = useOpenWifiComp.getClassName();
+        resolveActivityInfo.activityInfo.packageName = useOpenWifiComp.getPackageName();
+
+        final int flags = 0;
+        when(mMockPm.resolveActivity(
+                Mockito.argThat(new ArgumentMatcher<Intent>() {
+                    @Override
+                    public boolean matches(Object object) {
+                        Intent intent = (Intent) object;
+                        return NetworkScoreManager.ACTION_CUSTOM_ENABLE.equals(intent.getAction())
+                                && useOpenWifiComp.getPackageName().equals(intent.getPackage());
+                    }
+                }), Mockito.eq(flags))).thenReturn(resolveActivityInfo);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
new file mode 100644
index 0000000..cc2f7d5
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
@@ -0,0 +1,148 @@
+/*
+ * 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.am;
+
+import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
+import static android.app.ActivityManager.PROCESS_STATE_CACHED_EMPTY;
+import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
+import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
+import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
+import static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
+import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
+import static android.app.ActivityManager.PROCESS_STATE_RECEIVER;
+import static android.app.ActivityManager.PROCESS_STATE_SERVICE;
+import static android.app.ActivityManager.PROCESS_STATE_TOP;
+import static android.util.DebugUtils.valueToString;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.app.ActivityManager;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.function.Function;
+
+/**
+ * Test class for {@link ActivityManagerService}.
+ *
+ * To run the tests, use
+ *
+ * runtest -c com.android.server.am.ActivityManagerServiceTest frameworks-services
+ *
+ * or the following steps:
+ *
+ * Build: m FrameworksServicesTests
+ * Install: adb install -r \
+ *     ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
+ * Run: adb shell am instrument -e class com.android.server.am.ActivityManagerServiceTest -w \
+ *     com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ActivityManagerServiceTest {
+    private static final int TEST_UID = 111;
+
+    @Test
+    public void testIncrementProcStateSeqIfNeeded() {
+        final ActivityManagerService ams = new ActivityManagerService();
+        final UidRecord uidRec = new UidRecord(TEST_UID);
+
+        assertEquals("Initially global seq counter should be 0", 0, ams.mProcStateSeqCounter);
+        assertEquals("Initially seq counter in uidRecord should be 0", 0, uidRec.curProcStateSeq);
+
+        // Uid state is not moving from background to foreground or vice versa.
+        uidRec.setProcState = PROCESS_STATE_TOP;
+        uidRec.curProcState = PROCESS_STATE_TOP;
+        ams.incrementProcStateSeqIfNeeded(uidRec);
+        assertEquals(0, ams.mProcStateSeqCounter);
+        assertEquals(0, uidRec.curProcStateSeq);
+
+        // Uid state is moving from foreground to background.
+        uidRec.curProcState = PROCESS_STATE_FOREGROUND_SERVICE;
+        uidRec.setProcState = PROCESS_STATE_SERVICE;
+        ams.incrementProcStateSeqIfNeeded(uidRec);
+        assertEquals(1, ams.mProcStateSeqCounter);
+        assertEquals(1, uidRec.curProcStateSeq);
+
+        // Explicitly setting the seq counter for more verification.
+        ams.mProcStateSeqCounter = 42;
+
+        // Uid state is not moving from background to foreground or vice versa.
+        uidRec.setProcState = PROCESS_STATE_IMPORTANT_BACKGROUND;
+        uidRec.curProcState = PROCESS_STATE_IMPORTANT_FOREGROUND;
+        ams.incrementProcStateSeqIfNeeded(uidRec);
+        assertEquals(42, ams.mProcStateSeqCounter);
+        assertEquals(1, uidRec.curProcStateSeq);
+
+        // Uid state is moving from background to foreground.
+        uidRec.setProcState = PROCESS_STATE_LAST_ACTIVITY;
+        uidRec.curProcState = PROCESS_STATE_TOP;
+        ams.incrementProcStateSeqIfNeeded(uidRec);
+        assertEquals(43, ams.mProcStateSeqCounter);
+        assertEquals(43, uidRec.curProcStateSeq);
+    }
+
+    @Test
+    public void testShouldIncrementProcStateSeq() {
+        final ActivityManagerService ams = new ActivityManagerService();
+        final UidRecord uidRec = new UidRecord(TEST_UID);
+
+        final String error1 = "Seq should be incremented: prevState: %s, curState: %s";
+        final String error2 = "Seq should not be incremented: prevState: %s, curState: %s";
+        Function<String, String> errorMsg = errorTemplate -> {
+            return String.format(errorTemplate,
+                    valueToString(ActivityManager.class, "PROCESS_STATE_", uidRec.setProcState),
+                    valueToString(ActivityManager.class, "PROCESS_STATE_", uidRec.curProcState));
+        };
+
+        // No change in uid state
+        uidRec.setProcState = PROCESS_STATE_RECEIVER;
+        uidRec.curProcState = PROCESS_STATE_RECEIVER;
+        assertFalse(errorMsg.apply(error2), ams.shouldIncrementProcStateSeq(uidRec));
+
+        // Foreground to foreground
+        uidRec.setProcState = PROCESS_STATE_FOREGROUND_SERVICE;
+        uidRec.curProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+        assertFalse(errorMsg.apply(error2), ams.shouldIncrementProcStateSeq(uidRec));
+
+        // Background to background
+        uidRec.setProcState = PROCESS_STATE_CACHED_ACTIVITY;
+        uidRec.curProcState = PROCESS_STATE_CACHED_EMPTY;
+        assertFalse(errorMsg.apply(error2), ams.shouldIncrementProcStateSeq(uidRec));
+
+        // Background to background
+        uidRec.setProcState = PROCESS_STATE_NONEXISTENT;
+        uidRec.curProcState = PROCESS_STATE_CACHED_ACTIVITY;
+        assertFalse(errorMsg.apply(error2), ams.shouldIncrementProcStateSeq(uidRec));
+
+        // Background to foreground
+        uidRec.setProcState = PROCESS_STATE_SERVICE;
+        uidRec.curProcState = PROCESS_STATE_FOREGROUND_SERVICE;
+        assertTrue(errorMsg.apply(error1), ams.shouldIncrementProcStateSeq(uidRec));
+
+        // Foreground to background
+        uidRec.setProcState = PROCESS_STATE_TOP;
+        uidRec.curProcState = PROCESS_STATE_LAST_ACTIVITY;
+        assertTrue(errorMsg.apply(error1), ams.shouldIncrementProcStateSeq(uidRec));
+    }
+}
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java b/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
index d7bfc44..f3f68ff 100644
--- a/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
@@ -38,6 +38,7 @@
 import android.content.IntentSender;
 import android.content.pm.LauncherApps;
 import android.content.pm.ShortcutServiceInternal;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.UserHandle;
 import android.test.InstrumentationTestCase;
@@ -104,21 +105,21 @@
         if (otherProvider == null) {
             // No other provider found. Ignore this test.
         }
-        assertFalse(mManager.requestPinAppWidget(otherProvider, null));
+        assertFalse(mManager.requestPinAppWidget(otherProvider, null, null));
     }
 
     public void testRequestPinAppWidget() {
         ComponentName provider = new ComponentName(mTestContext, DummyAppWidget.class);
         // Set up users.
         when(mMockShortcutService.requestPinAppWidget(anyString(),
-                any(AppWidgetProviderInfo.class), any(IntentSender.class), anyInt()))
+                any(AppWidgetProviderInfo.class), any(Bundle.class), any(IntentSender.class), anyInt()))
                 .thenReturn(true);
-        assertTrue(mManager.requestPinAppWidget(provider, null));
+        assertTrue(mManager.requestPinAppWidget(provider, null, null));
 
         final ArgumentCaptor<AppWidgetProviderInfo> providerCaptor =
                 ArgumentCaptor.forClass(AppWidgetProviderInfo.class);
         verify(mMockShortcutService, times(1)).requestPinAppWidget(anyString(),
-                providerCaptor.capture(), eq(null), anyInt());
+                providerCaptor.capture(), any(null), eq(null), anyInt());
         assertEquals(provider, providerCaptor.getValue().provider);
     }
 
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 d65a9bf..f969e80 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -34,7 +34,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.ParceledListSlice;
+import android.content.pm.StringParceledListSlice;
 import android.content.res.Resources;
 import android.graphics.Color;
 import android.net.IIpConnectivityMetrics;
@@ -49,6 +49,8 @@
 import android.os.UserManager;
 import android.os.UserManagerInternal;
 import android.provider.Settings;
+import android.security.IKeyChainService;
+import android.security.KeyChain;
 import android.telephony.TelephonyManager;
 import android.test.MoreAsserts;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -56,7 +58,6 @@
 import android.util.Pair;
 
 import com.android.internal.R;
-import com.android.internal.util.ParcelableString;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
@@ -123,6 +124,34 @@
     public DevicePolicyManager dpm;
     public DevicePolicyManagerServiceTestable dpms;
 
+    /*
+     * The CA cert below is the content of cacert.pem as generated by:
+     *
+     * openssl req -new -x509 -days 3650 -extensions v3_ca -keyout cakey.pem -out cacert.pem
+     */
+    private static final String TEST_CA =
+            "-----BEGIN CERTIFICATE-----\n" +
+            "MIIDXTCCAkWgAwIBAgIJAK9Tl/F9V8kSMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV\n" +
+            "BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX\n" +
+            "aWRnaXRzIFB0eSBMdGQwHhcNMTUwMzA2MTczMjExWhcNMjUwMzAzMTczMjExWjBF\n" +
+            "MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50\n" +
+            "ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\n" +
+            "CgKCAQEAvItOutsE75WBTgTyNAHt4JXQ3JoseaGqcC3WQij6vhrleWi5KJ0jh1/M\n" +
+            "Rpry7Fajtwwb4t8VZa0NuM2h2YALv52w1xivql88zce/HU1y7XzbXhxis9o6SCI+\n" +
+            "oVQSbPeXRgBPppFzBEh3ZqYTVhAqw451XhwdA4Aqs3wts7ddjwlUzyMdU44osCUg\n" +
+            "kVg7lfPf9sTm5IoHVcfLSCWH5n6Nr9sH3o2ksyTwxuOAvsN11F/a0mmUoPciYPp+\n" +
+            "q7DzQzdi7akRG601DZ4YVOwo6UITGvDyuAAdxl5isovUXqe6Jmz2/myTSpAKxGFs\n" +
+            "jk9oRoG6WXWB1kni490GIPjJ1OceyQIDAQABo1AwTjAdBgNVHQ4EFgQUH1QIlPKL\n" +
+            "p2OQ/AoLOjKvBW4zK3AwHwYDVR0jBBgwFoAUH1QIlPKLp2OQ/AoLOjKvBW4zK3Aw\n" +
+            "DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAcMi4voMMJHeQLjtq8Oky\n" +
+            "Azpyk8moDwgCd4llcGj7izOkIIFqq/lyqKdtykVKUWz2bSHO5cLrtaOCiBWVlaCV\n" +
+            "DYAnnVLM8aqaA6hJDIfaGs4zmwz0dY8hVMFCuCBiLWuPfiYtbEmjHGSmpQTG6Qxn\n" +
+            "ZJlaK5CZyt5pgh5EdNdvQmDEbKGmu0wpCq9qjZImwdyAul1t/B0DrsWApZMgZpeI\n" +
+            "d2od0VBrCICB1K4p+C51D93xyQiva7xQcCne+TAnGNy9+gjQ/MyR8MRpwRLv5ikD\n" +
+            "u0anJCN8pXo6IMglfMAsoton1J6o5/ae5uhC6caQU8bNUsCK570gpNfjkzo6rbP0\n" +
+            "wQ==\n" +
+            "-----END CERTIFICATE-----\n";
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
@@ -1220,8 +1249,8 @@
         mContext.userContexts.put(user, mContext);
         when(mContext.resources.getColor(anyInt(), anyObject())).thenReturn(Color.WHITE);
 
-        ParceledListSlice<ParcelableString> oneCert = asSlice(new String[] {"1"});
-        ParceledListSlice<ParcelableString> fourCerts = asSlice(new String[] {"1", "2", "3", "4"});
+        StringParceledListSlice oneCert = asSlice(new String[] {"1"});
+        StringParceledListSlice fourCerts = asSlice(new String[] {"1", "2", "3", "4"});
 
         final String TEST_STRING = "Test for exactly 2 certs out of 4";
         doReturn(TEST_STRING).when(mContext.resources).getQuantityText(anyInt(), eq(2));
@@ -1229,7 +1258,7 @@
         // Given that we have exactly one certificate installed,
         when(mContext.keyChainConnection.getService().getUserCaAliases()).thenReturn(oneCert);
         // when that certificate is approved,
-        dpms.approveCaCert(oneCert.getList().get(0).string, userId, true);
+        dpms.approveCaCert(oneCert.getList().get(0), userId, true);
         // a notification should not be shown.
         verify(mContext.notificationManager, timeout(1000))
                 .cancelAsUser(anyString(), anyInt(), eq(user));
@@ -1237,8 +1266,8 @@
         // Given that we have four certificates installed,
         when(mContext.keyChainConnection.getService().getUserCaAliases()).thenReturn(fourCerts);
         // when two of them are approved (one of them approved twice hence no action),
-        dpms.approveCaCert(fourCerts.getList().get(0).string, userId, true);
-        dpms.approveCaCert(fourCerts.getList().get(1).string, userId, true);
+        dpms.approveCaCert(fourCerts.getList().get(0), userId, true);
+        dpms.approveCaCert(fourCerts.getList().get(1), userId, true);
         // a notification should be shown saying that there are two certificates left to approve.
         verify(mContext.notificationManager, timeout(1000))
                 .notifyAsUser(anyString(), anyInt(), argThat(
@@ -3777,144 +3806,281 @@
                 .thenReturn(true);
         assertTrue(dpm.clearResetPasswordToken(admin1));
     }
-  
-    public void testIsDefaultInputMethodSetByOwnerForDeviceOwner() throws Exception {
-        final String defaultIme = Settings.Secure.DEFAULT_INPUT_METHOD;
-        final Uri defaultImeUri = Settings.Secure.getUriFor(defaultIme);
-        final UserHandle firstUser = UserHandle.SYSTEM;
-        final UserHandle secondUser = UserHandle.of(DpmMockContext.CALLER_USER_HANDLE);
 
-        // Set up a Device Owner.
-        mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+    public void testIsCurrentInputMethodSetByOwnerForDeviceOwner() throws Exception {
+        final String currentIme = Settings.Secure.DEFAULT_INPUT_METHOD;
+        final Uri currentImeUri = Settings.Secure.getUriFor(currentIme);
+        final int deviceOwnerUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+        final int firstUserSystemUid = UserHandle.getUid(UserHandle.USER_SYSTEM,
+                DpmMockContext.SYSTEM_UID);
+        final int secondUserSystemUid = UserHandle.getUid(DpmMockContext.CALLER_USER_HANDLE,
+                DpmMockContext.SYSTEM_UID);
+
+        // Set up a device owner.
+        mContext.binder.callingUid = deviceOwnerUid;
         setupDeviceOwner();
 
-        // First and second user set default IMEs manually.
-        final long ident = mContext.binder.clearCallingIdentity();
-        assertFalse(dpm.isDefaultInputMethodSetByOwner(firstUser));
-        assertFalse(dpm.isDefaultInputMethodSetByOwner(secondUser));
-        mContext.binder.restoreCallingIdentity(ident);
+        // First and second user set IMEs manually.
+        mContext.binder.callingUid = firstUserSystemUid;
+        assertFalse(dpm.isCurrentInputMethodSetByOwner());
+        mContext.binder.callingUid = secondUserSystemUid;
+        assertFalse(dpm.isCurrentInputMethodSetByOwner());
 
-        // Device Owner changes default IME for first user.
-        when(mContext.settings.settingsSecureGetStringForUser(defaultIme, UserHandle.USER_SYSTEM))
+        // Device owner changes IME for first user.
+        mContext.binder.callingUid = deviceOwnerUid;
+        when(mContext.settings.settingsSecureGetStringForUser(currentIme, UserHandle.USER_SYSTEM))
                 .thenReturn("ime1");
-        dpm.setSecureSetting(admin1, defaultIme, "ime2");
-        verify(mContext.settings).settingsSecurePutStringForUser(defaultIme, "ime2",
+        dpm.setSecureSetting(admin1, currentIme, "ime2");
+        verify(mContext.settings).settingsSecurePutStringForUser(currentIme, "ime2",
                 UserHandle.USER_SYSTEM);
         reset(mContext.settings);
-        dpms.notifyChangeToContentObserver(defaultImeUri, UserHandle.USER_SYSTEM);
-        mContext.binder.clearCallingIdentity();
-        assertTrue(dpm.isDefaultInputMethodSetByOwner(firstUser));
-        assertFalse(dpm.isDefaultInputMethodSetByOwner(secondUser));
-        mContext.binder.restoreCallingIdentity(ident);
+        dpms.notifyChangeToContentObserver(currentImeUri, UserHandle.USER_SYSTEM);
+        mContext.binder.callingUid = firstUserSystemUid;
+        assertTrue(dpm.isCurrentInputMethodSetByOwner());
+        mContext.binder.callingUid = secondUserSystemUid;
+        assertFalse(dpm.isCurrentInputMethodSetByOwner());
 
-        // Second user changes default IME manually.
-        dpms.notifyChangeToContentObserver(defaultImeUri, DpmMockContext.CALLER_USER_HANDLE);
-        mContext.binder.clearCallingIdentity();
-        assertTrue(dpm.isDefaultInputMethodSetByOwner(firstUser));
-        assertFalse(dpm.isDefaultInputMethodSetByOwner(secondUser));
-        mContext.binder.restoreCallingIdentity(ident);
+        // Second user changes IME manually.
+        dpms.notifyChangeToContentObserver(currentImeUri, DpmMockContext.CALLER_USER_HANDLE);
+        mContext.binder.callingUid = firstUserSystemUid;
+        assertTrue(dpm.isCurrentInputMethodSetByOwner());
+        mContext.binder.callingUid = secondUserSystemUid;
+        assertFalse(dpm.isCurrentInputMethodSetByOwner());
 
-        // First user changes default IME manually.
-        dpms.notifyChangeToContentObserver(defaultImeUri, UserHandle.USER_SYSTEM);
-        mContext.binder.clearCallingIdentity();
-        assertFalse(dpm.isDefaultInputMethodSetByOwner(firstUser));
-        assertFalse(dpm.isDefaultInputMethodSetByOwner(secondUser));
-        mContext.binder.restoreCallingIdentity(ident);
+        // First user changes IME manually.
+        dpms.notifyChangeToContentObserver(currentImeUri, UserHandle.USER_SYSTEM);
+        mContext.binder.callingUid = firstUserSystemUid;
+        assertFalse(dpm.isCurrentInputMethodSetByOwner());
+        mContext.binder.callingUid = secondUserSystemUid;
+        assertFalse(dpm.isCurrentInputMethodSetByOwner());
 
-        // Device Owner changes default IME for first user again.
-        when(mContext.settings.settingsSecureGetStringForUser(defaultIme, UserHandle.USER_SYSTEM))
+        // Device owner changes IME for first user again.
+        mContext.binder.callingUid = deviceOwnerUid;
+        when(mContext.settings.settingsSecureGetStringForUser(currentIme, UserHandle.USER_SYSTEM))
                 .thenReturn("ime2");
-        dpm.setSecureSetting(admin1, defaultIme, "ime3");
-        verify(mContext.settings).settingsSecurePutStringForUser(defaultIme, "ime3",
+        dpm.setSecureSetting(admin1, currentIme, "ime3");
+        verify(mContext.settings).settingsSecurePutStringForUser(currentIme, "ime3",
                 UserHandle.USER_SYSTEM);
-        dpms.notifyChangeToContentObserver(defaultImeUri, UserHandle.USER_SYSTEM);
-        mContext.binder.clearCallingIdentity();
-        assertTrue(dpm.isDefaultInputMethodSetByOwner(firstUser));
-        assertFalse(dpm.isDefaultInputMethodSetByOwner(secondUser));
+        dpms.notifyChangeToContentObserver(currentImeUri, UserHandle.USER_SYSTEM);
+        mContext.binder.callingUid = firstUserSystemUid;
+        assertTrue(dpm.isCurrentInputMethodSetByOwner());
+        mContext.binder.callingUid = secondUserSystemUid;
+        assertFalse(dpm.isCurrentInputMethodSetByOwner());
 
         // Restarting the DPMS should not lose information.
         initializeDpms();
-        assertTrue(dpm.isDefaultInputMethodSetByOwner(firstUser));
-        assertFalse(dpm.isDefaultInputMethodSetByOwner(secondUser));
-        mContext.binder.restoreCallingIdentity(ident);
+        mContext.binder.callingUid = firstUserSystemUid;
+        assertTrue(dpm.isCurrentInputMethodSetByOwner());
+        mContext.binder.callingUid = secondUserSystemUid;
+        assertFalse(dpm.isCurrentInputMethodSetByOwner());
 
-        // Device Owner can find out whether it set the default IME itself.
-        assertTrue(dpm.isDefaultInputMethodSetByOwner(firstUser));
+        // Device owner can find out whether it set the current IME itself.
+        mContext.binder.callingUid = deviceOwnerUid;
+        assertTrue(dpm.isCurrentInputMethodSetByOwner());
 
-        // Removing the Device Owner should clear the information that it set the default IME.
+        // Removing the device owner should clear the information that it set the current IME.
         clearDeviceOwner();
-        mContext.binder.clearCallingIdentity();
-        assertFalse(dpm.isDefaultInputMethodSetByOwner(firstUser));
-        assertFalse(dpm.isDefaultInputMethodSetByOwner(secondUser));
+        mContext.binder.callingUid = firstUserSystemUid;
+        assertFalse(dpm.isCurrentInputMethodSetByOwner());
+        mContext.binder.callingUid = secondUserSystemUid;
+        assertFalse(dpm.isCurrentInputMethodSetByOwner());
     }
 
-    public void testIsDefaultInputMethodSetByOwnerForProfileOwner() throws Exception {
-        final String defaultIme = Settings.Secure.DEFAULT_INPUT_METHOD;
-        final Uri defaultImeUri = Settings.Secure.getUriFor(defaultIme);
-        final UserHandle firstUser = UserHandle.SYSTEM;
-        final UserHandle secondUser = UserHandle.of(DpmMockContext.CALLER_USER_HANDLE);
+    public void testIsCurrentInputMethodSetByOwnerForProfileOwner() throws Exception {
+        final String currentIme = Settings.Secure.DEFAULT_INPUT_METHOD;
+        final Uri currentImeUri = Settings.Secure.getUriFor(currentIme);
+        final int profileOwnerUid = DpmMockContext.CALLER_UID;
+        final int firstUserSystemUid = UserHandle.getUid(UserHandle.USER_SYSTEM,
+                DpmMockContext.SYSTEM_UID);
+        final int secondUserSystemUid = UserHandle.getUid(DpmMockContext.CALLER_USER_HANDLE,
+                DpmMockContext.SYSTEM_UID);
 
         // Set up a profile owner.
+        mContext.binder.callingUid = profileOwnerUid;
         setupProfileOwner();
 
-        // First and second user set default IMEs manually.
-        final long ident = mContext.binder.clearCallingIdentity();
-        assertFalse(dpm.isDefaultInputMethodSetByOwner(firstUser));
-        assertFalse(dpm.isDefaultInputMethodSetByOwner(secondUser));
-        mContext.binder.restoreCallingIdentity(ident);
+        // First and second user set IMEs manually.
+        mContext.binder.callingUid = firstUserSystemUid;
+        assertFalse(dpm.isCurrentInputMethodSetByOwner());
+        mContext.binder.callingUid = secondUserSystemUid;
+        assertFalse(dpm.isCurrentInputMethodSetByOwner());
 
-        // Profile Owner changes default IME for second user.
-        when(mContext.settings.settingsSecureGetStringForUser(defaultIme,
+        // Profile owner changes IME for second user.
+        mContext.binder.callingUid = profileOwnerUid;
+        when(mContext.settings.settingsSecureGetStringForUser(currentIme,
                 DpmMockContext.CALLER_USER_HANDLE)).thenReturn("ime1");
-        dpm.setSecureSetting(admin1, defaultIme, "ime2");
-        verify(mContext.settings).settingsSecurePutStringForUser(defaultIme, "ime2",
+        dpm.setSecureSetting(admin1, currentIme, "ime2");
+        verify(mContext.settings).settingsSecurePutStringForUser(currentIme, "ime2",
                 DpmMockContext.CALLER_USER_HANDLE);
         reset(mContext.settings);
-        dpms.notifyChangeToContentObserver(defaultImeUri, DpmMockContext.CALLER_USER_HANDLE);
-        mContext.binder.clearCallingIdentity();
-        assertFalse(dpm.isDefaultInputMethodSetByOwner(firstUser));
-        assertTrue(dpm.isDefaultInputMethodSetByOwner(secondUser));
-        mContext.binder.restoreCallingIdentity(ident);
+        dpms.notifyChangeToContentObserver(currentImeUri, DpmMockContext.CALLER_USER_HANDLE);
+        mContext.binder.callingUid = firstUserSystemUid;
+        assertFalse(dpm.isCurrentInputMethodSetByOwner());
+        mContext.binder.callingUid = secondUserSystemUid;
+        assertTrue(dpm.isCurrentInputMethodSetByOwner());
 
-        // First user changes default IME manually.
-        dpms.notifyChangeToContentObserver(defaultImeUri, UserHandle.USER_SYSTEM);
-        mContext.binder.clearCallingIdentity();
-        assertFalse(dpm.isDefaultInputMethodSetByOwner(firstUser));
-        assertTrue(dpm.isDefaultInputMethodSetByOwner(secondUser));
-        mContext.binder.restoreCallingIdentity(ident);
+        // First user changes IME manually.
+        dpms.notifyChangeToContentObserver(currentImeUri, UserHandle.USER_SYSTEM);
+        mContext.binder.callingUid = firstUserSystemUid;
+        assertFalse(dpm.isCurrentInputMethodSetByOwner());
+        mContext.binder.callingUid = secondUserSystemUid;
+        assertTrue(dpm.isCurrentInputMethodSetByOwner());
 
-        // Second user changes default IME manually.
-        dpms.notifyChangeToContentObserver(defaultImeUri, DpmMockContext.CALLER_USER_HANDLE);
-        mContext.binder.clearCallingIdentity();
-        assertFalse(dpm.isDefaultInputMethodSetByOwner(firstUser));
-        assertFalse(dpm.isDefaultInputMethodSetByOwner(secondUser));
-        mContext.binder.restoreCallingIdentity(ident);
+        // Second user changes IME manually.
+        dpms.notifyChangeToContentObserver(currentImeUri, DpmMockContext.CALLER_USER_HANDLE);
+        mContext.binder.callingUid = firstUserSystemUid;
+        assertFalse(dpm.isCurrentInputMethodSetByOwner());
+        mContext.binder.callingUid = secondUserSystemUid;
+        assertFalse(dpm.isCurrentInputMethodSetByOwner());
 
-        // Profile Owner changes default IME for second user again.
-        when(mContext.settings.settingsSecureGetStringForUser(defaultIme,
+        // Profile owner changes IME for second user again.
+        mContext.binder.callingUid = profileOwnerUid;
+        when(mContext.settings.settingsSecureGetStringForUser(currentIme,
                 DpmMockContext.CALLER_USER_HANDLE)).thenReturn("ime2");
-        dpm.setSecureSetting(admin1, defaultIme, "ime3");
-        verify(mContext.settings).settingsSecurePutStringForUser(defaultIme, "ime3",
+        dpm.setSecureSetting(admin1, currentIme, "ime3");
+        verify(mContext.settings).settingsSecurePutStringForUser(currentIme, "ime3",
                 DpmMockContext.CALLER_USER_HANDLE);
-        dpms.notifyChangeToContentObserver(defaultImeUri, DpmMockContext.CALLER_USER_HANDLE);
-        mContext.binder.clearCallingIdentity();
-        assertFalse(dpm.isDefaultInputMethodSetByOwner(firstUser));
-        assertTrue(dpm.isDefaultInputMethodSetByOwner(secondUser));
+        dpms.notifyChangeToContentObserver(currentImeUri, DpmMockContext.CALLER_USER_HANDLE);
+        mContext.binder.callingUid = firstUserSystemUid;
+        assertFalse(dpm.isCurrentInputMethodSetByOwner());
+        mContext.binder.callingUid = secondUserSystemUid;
+        assertTrue(dpm.isCurrentInputMethodSetByOwner());
 
         // Restarting the DPMS should not lose information.
         initializeDpms();
-        assertFalse(dpm.isDefaultInputMethodSetByOwner(firstUser));
-        assertTrue(dpm.isDefaultInputMethodSetByOwner(secondUser));
-        mContext.binder.restoreCallingIdentity(ident);
+        mContext.binder.callingUid = firstUserSystemUid;
+        assertFalse(dpm.isCurrentInputMethodSetByOwner());
+        mContext.binder.callingUid = secondUserSystemUid;
+        assertTrue(dpm.isCurrentInputMethodSetByOwner());
 
-        // Profile Owner can find out whether it set the default IME itself.
-        assertTrue(dpm.isDefaultInputMethodSetByOwner(secondUser));
+        // Profile owner can find out whether it set the current IME itself.
+        mContext.binder.callingUid = profileOwnerUid;
+        assertTrue(dpm.isCurrentInputMethodSetByOwner());
 
-        // Removing the Profile Owner should clear the information that it set the default IME.
+        // Removing the profile owner should clear the information that it set the current IME.
         dpm.clearProfileOwner(admin1);
+        mContext.binder.callingUid = firstUserSystemUid;
+        assertFalse(dpm.isCurrentInputMethodSetByOwner());
+        mContext.binder.callingUid = secondUserSystemUid;
+        assertFalse(dpm.isCurrentInputMethodSetByOwner());
+    }
+
+    public void testGetOwnerInstalledCaCertsForDeviceOwner() throws Exception {
+        setDeviceOwner();
+
+        mContext.packageName = admin1.getPackageName();
+        mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+        verifyCanGetOwnerInstalledCaCerts(admin1);
+    }
+
+    public void testGetOwnerInstalledCaCertsForProfileOwner() throws Exception {
+        setAsProfileOwner(admin1);
+
+        mContext.packageName = admin1.getPackageName();
+        verifyCanGetOwnerInstalledCaCerts(admin1);
+        verifyCantGetOwnerInstalledCaCertsProfileOwnerRemoval(admin1);
+    }
+
+    public void testGetOwnerInstalledCaCertsForDelegate() throws Exception {
+        setAsProfileOwner(admin1);
+
+        final String delegate = "com.example.delegate";
+        final int delegateUid = setupPackageInPackageManager(delegate, 20988);
+        dpm.setCertInstallerPackage(admin1, delegate);
+
+        mContext.packageName = delegate;
+        mContext.binder.callingUid = delegateUid;
+        verifyCanGetOwnerInstalledCaCerts(null);
+        verifyCantGetOwnerInstalledCaCertsProfileOwnerRemoval(null);
+    }
+
+    private void verifyCanGetOwnerInstalledCaCerts(ComponentName caller) throws Exception {
+        final UserHandle user = UserHandle.getUserHandleForUid(mContext.binder.callingUid);
+        final int ownerUid = user.equals(UserHandle.SYSTEM) ?
+                DpmMockContext.CALLER_SYSTEM_USER_UID : DpmMockContext.CALLER_UID;
+
+        mContext.applicationInfo = new ApplicationInfo();
+        mContext.userContexts.put(user, mContext);
+        when(mContext.resources.getColor(anyInt(), anyObject())).thenReturn(Color.WHITE);
+
+        // Install a CA cert.
+        final String alias = "cert";
+        final byte[] caCert = TEST_CA.getBytes();
+        when(mContext.keyChainConnection.getService().installCaCertificate(caCert))
+                .thenReturn(alias);
+        assertTrue(dpm.installCaCert(caller, caCert));
+        when(mContext.keyChainConnection.getService().getUserCaAliases())
+                .thenReturn(asSlice(new String[] {alias}));
+        mContext.injectBroadcast(new Intent(KeyChain.ACTION_TRUST_STORE_CHANGED));
+        flushTasks();
+
+        // Device Owner / Profile Owner can find out which CA certs were installed by itself.
+        final String packageName = mContext.packageName;
+        mContext.packageName = admin1.getPackageName();
+        final long callerIdentity = mContext.binder.clearCallingIdentity();
+        mContext.binder.callingUid = ownerUid;
+        List<String> ownerInstalledCaCerts = dpm.getOwnerInstalledCaCerts(user);
+        assertNotNull(ownerInstalledCaCerts);
+        assertEquals(1, ownerInstalledCaCerts.size());
+        assertTrue(ownerInstalledCaCerts.contains(alias));
+
+        // Restarting the DPMS should not lose information.
+        initializeDpms();
+        assertEquals(ownerInstalledCaCerts, dpm.getOwnerInstalledCaCerts(user));
+
+        // System can find out which CA certs were installed by the Device Owner / Profile Owner.
+        mContext.packageName = "com.android.frameworks.servicestests";
         mContext.binder.clearCallingIdentity();
-        assertFalse(dpm.isDefaultInputMethodSetByOwner(firstUser));
-        assertFalse(dpm.isDefaultInputMethodSetByOwner(secondUser));
+        assertEquals(ownerInstalledCaCerts, dpm.getOwnerInstalledCaCerts(user));
+
+        // Remove the CA cert.
+        mContext.packageName = packageName;
+        mContext.binder.restoreCallingIdentity(callerIdentity);
+        reset(mContext.keyChainConnection.getService());
+        mContext.injectBroadcast(new Intent(KeyChain.ACTION_TRUST_STORE_CHANGED));
+        flushTasks();
+
+        // Verify that the CA cert is no longer reported as installed by the Device Owner / Profile
+        // Owner.
+        mContext.packageName = admin1.getPackageName();
+        mContext.binder.callingUid = ownerUid;
+        ownerInstalledCaCerts = dpm.getOwnerInstalledCaCerts(user);
+        assertNotNull(ownerInstalledCaCerts);
+        assertTrue(ownerInstalledCaCerts.isEmpty());
+
+        mContext.packageName = packageName;
+        mContext.binder.restoreCallingIdentity(callerIdentity);
+    }
+
+    private void verifyCantGetOwnerInstalledCaCertsProfileOwnerRemoval(ComponentName caller)
+            throws Exception {
+        final UserHandle user = UserHandle.of(DpmMockContext.CALLER_USER_HANDLE);
+
+        mContext.applicationInfo = new ApplicationInfo();
+        mContext.userContexts.put(user, mContext);
+        when(mContext.resources.getColor(anyInt(), anyObject())).thenReturn(Color.WHITE);
+
+        // Install a CA cert.
+        final String alias = "cert";
+        final byte[] caCert = TEST_CA.getBytes();
+        when(mContext.keyChainConnection.getService().installCaCertificate(caCert))
+                .thenReturn(alias);
+        assertTrue(dpm.installCaCert(caller, caCert));
+        when(mContext.keyChainConnection.getService().getUserCaAliases())
+                .thenReturn(asSlice(new String[] {alias}));
+        mContext.injectBroadcast(new Intent(KeyChain.ACTION_TRUST_STORE_CHANGED));
+        flushTasks();
+
+        // Removing the Profile Owner should clear the information which CA certs were installed
+        // by it.
+        mContext.packageName = admin1.getPackageName();
+        mContext.binder.callingUid = DpmMockContext.CALLER_UID;
+        dpm.clearProfileOwner(admin1);
+        mContext.packageName = "com.android.frameworks.servicestests";
+        mContext.binder.clearCallingIdentity();
+        final List<String> ownerInstalledCaCerts = dpm.getOwnerInstalledCaCerts(user);
+        assertNotNull(ownerInstalledCaCerts);
+        assertTrue(ownerInstalledCaCerts.isEmpty());
     }
 
     private void setUserSetupCompleteForUser(boolean isUserSetupComplete, int userhandle) {
@@ -3974,18 +4140,36 @@
     }
 
     /**
-     * Convert String[] to ParceledListSlice&lt;ParcelableString&gt;.
-     * <p>
-     * TODO: This shouldn't be necessary. If ParcelableString does need to exist, it also needs
-     * a real constructor.
+     * Convert String[] to StringParceledListSlice.
      */
-    private static ParceledListSlice<ParcelableString> asSlice(String[] s) {
-        List<ParcelableString> list = new ArrayList<>(s.length);
-        for (int i = 0; i < s.length; i++) {
-            ParcelableString item = new ParcelableString();
-            item.string = s[i];
-            list.add(i, item);
+    private static StringParceledListSlice asSlice(String[] s) {
+        return new StringParceledListSlice(Arrays.asList(s));
+    }
+
+    private void flushTasks() throws Exception {
+        Boolean tasksFlushed[] = new Boolean[] {false};
+        final Runnable tasksFlushedNotifier = () -> {
+            synchronized (tasksFlushed) {
+                tasksFlushed[0] = true;
+                tasksFlushed.notify();
+            }
+        };
+
+        // Flush main thread handler.
+        dpms.mHandler.post(tasksFlushedNotifier);
+        synchronized (tasksFlushed) {
+            if (!tasksFlushed[0]) {
+                tasksFlushed.wait();
+            }
         }
-        return new ParceledListSlice<ParcelableString>(list);
+
+        // Flush background thread handler.
+        tasksFlushed[0] = false;
+        dpms.mBackgroundHandler.post(tasksFlushedNotifier);
+        synchronized (tasksFlushed) {
+            if (!tasksFlushed[0]) {
+                tasksFlushed.wait();
+            }
+        }
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
index 258b393..7d017c5 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -316,6 +316,41 @@
 
     public ApplicationInfo applicationInfo = null;
 
+    // We have to keep track of broadcast receivers registered for a given intent ourselves as the
+    // DPM unit tests mock out the package manager and PackageManager.queryBroadcastReceivers() does
+    // not work.
+    private class BroadcastReceiverRegistration {
+        public final BroadcastReceiver receiver;
+        public final IntentFilter filter;
+        public final Handler scheduler;
+
+        public BroadcastReceiverRegistration(BroadcastReceiver receiver, IntentFilter filter,
+                Handler scheduler) {
+            this.receiver = receiver;
+            this.filter = filter;
+            this.scheduler = scheduler;
+        }
+
+        public void sendBroadcastIfApplicable(int userId, Intent intent) {
+            final BroadcastReceiver.PendingResult result = new BroadcastReceiver.PendingResult(
+                    0 /* resultCode */, null /* resultData */, null /* resultExtras */,
+                    0 /* type */, false /* ordered */, false /* sticky */, null /* token */, userId,
+                    0 /* flags */);
+            if (filter.match(null, intent, false, "DpmMockContext") > 0) {
+                if (scheduler != null) {
+                    scheduler.post(() -> {
+                        receiver.setPendingResult(result);
+                        receiver.onReceive(DpmMockContext.this, intent);
+                    });
+                } else {
+                    receiver.setPendingResult(result);
+                    receiver.onReceive(DpmMockContext.this, intent);
+                }
+            }
+        }
+    }
+    private List<BroadcastReceiverRegistration> mBroadcastReceivers = new ArrayList<>();
+
     public DpmMockContext(Context context, File dataDir) {
         realTestContext = context;
 
@@ -476,6 +511,13 @@
                 .thenReturn(isRunning);
     }
 
+    public void injectBroadcast(Intent intent) {
+        final int userId = UserHandle.getUserId(binder.getCallingUid());
+        for (final BroadcastReceiverRegistration receiver : mBroadcastReceivers) {
+            receiver.sendBroadcastIfApplicable(userId, intent);
+        }
+    }
+
     @Override
     public Resources getResources() {
         return resources;
@@ -681,24 +723,28 @@
 
     @Override
     public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
+        mBroadcastReceivers.add(new BroadcastReceiverRegistration(receiver, filter, null));
         return spiedContext.registerReceiver(receiver, filter);
     }
 
     @Override
     public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
             String broadcastPermission, Handler scheduler) {
+        mBroadcastReceivers.add(new BroadcastReceiverRegistration(receiver, filter, scheduler));
         return spiedContext.registerReceiver(receiver, filter, broadcastPermission, scheduler);
     }
 
     @Override
     public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
             IntentFilter filter, String broadcastPermission, Handler scheduler) {
+        mBroadcastReceivers.add(new BroadcastReceiverRegistration(receiver, filter, scheduler));
         return spiedContext.registerReceiverAsUser(receiver, user, filter, broadcastPermission,
                 scheduler);
     }
 
     @Override
     public void unregisterReceiver(BroadcastReceiver receiver) {
+        mBroadcastReceivers.removeIf(r -> r.receiver == receiver);
         spiedContext.unregisterReceiver(receiver);
     }
 
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 f615bf3..33e1a16 100644
--- a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
@@ -10,7 +10,6 @@
 import android.test.AndroidTestCase;
 import android.test.RenamingDelegatingContext;
 import android.util.Log;
-import android.util.ArraySet;
 
 import com.android.server.job.JobStore.JobSet;
 import com.android.server.job.controllers.JobStatus;
@@ -278,6 +277,8 @@
 
         assertEquals("Invalid charging constraint.", first.isRequireCharging(),
                 second.isRequireCharging());
+        assertEquals("Invalid battery not low constraint.", first.isRequireBatteryNotLow(),
+                second.isRequireBatteryNotLow());
         assertEquals("Invalid idle constraint.", first.isRequireDeviceIdle(),
                 second.isRequireDeviceIdle());
         assertEquals("Invalid unmetered constraint.",
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 100338e..1b59d72 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -34,6 +34,7 @@
 import static org.mockito.Mockito.when;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.Activity;
 import android.app.ActivityManager;
@@ -1324,20 +1325,23 @@
     protected ShortcutInfo makeShortcut(String id) {
         return makeShortcut(
                 id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
-                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+                /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
     }
 
     @Deprecated // Title was renamed to short label.
     protected ShortcutInfo makeShortcutWithTitle(String id, String title) {
         return makeShortcut(
                 id, title, /* activity =*/ null, /* icon =*/ null,
-                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+                /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
     }
 
     protected ShortcutInfo makeShortcutWithShortLabel(String id, String shortLabel) {
         return makeShortcut(
                 id, shortLabel, /* activity =*/ null, /* icon =*/ null,
-                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+                /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
     }
 
     /**
@@ -1346,7 +1350,8 @@
     protected ShortcutInfo makeShortcutWithTimestamp(String id, long timestamp) {
         final ShortcutInfo s = makeShortcut(
                 id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
-                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+                /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
         s.setTimestamp(timestamp);
         return s;
     }
@@ -1358,7 +1363,8 @@
             ComponentName activity) {
         final ShortcutInfo s = makeShortcut(
                 id, "Title-" + id, activity, /* icon =*/ null,
-                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+                /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
         s.setTimestamp(timestamp);
         return s;
     }
@@ -1369,7 +1375,27 @@
     protected ShortcutInfo makeShortcutWithIcon(String id, Icon icon) {
         return makeShortcut(
                 id, "Title-" + id, /* activity =*/ null, icon,
-                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+                /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
+    }
+
+    protected ShortcutInfo makeChooserShortcut(String id, int i, boolean includeIntent) {
+        List<IntentFilter> filters = new ArrayList<>();
+        List<ComponentName> componentNames = new ArrayList<>();
+        for(int j = 0; j < i; j++) {
+            final IntentFilter filter = new IntentFilter();
+            filter.addAction("view");
+            filters.add(filter);
+
+            componentNames.add(new ComponentName("xxxx", "yy" + i));
+        }
+        Intent intent = null;
+        if (includeIntent) {
+            intent = makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class);
+        }
+        return makeShortcut(
+                id, "Title-" + id, /* activity =*/ null, /* icon */ null,
+                intent, /* rank =*/ 0, filters, componentNames);
     }
 
     protected ShortcutInfo makePackageShortcut(String packageName, String id) {
@@ -1378,7 +1404,8 @@
         setCaller(packageName);
         ShortcutInfo s = makeShortcut(
                 id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
-                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+                /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
         setCaller(origCaller); // restore the caller
 
         return s;
@@ -1402,39 +1429,52 @@
     protected ShortcutInfo makeShortcutWithActivity(String id, ComponentName activity) {
         return makeShortcut(
                 id, "Title-" + id, activity, /* icon =*/ null,
-                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+                /* chooserFilters =*/ null, /* chooserComponentNames =*/ null);
     }
 
     protected ShortcutInfo makeShortcutWithIntent(String id, Intent intent) {
         return makeShortcut(
                 id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
-                intent, /* rank =*/ 0);
+                intent, /* rank =*/ 0, /* chooserFilters =*/ null,
+                /* chooserComponentNames =*/ null);
+
     }
 
     protected ShortcutInfo makeShortcutWithActivityAndTitle(String id, ComponentName activity,
             String title) {
         return makeShortcut(
                 id, title, activity, /* icon =*/ null,
-                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+                /* chooserFilters =*/ null, /* chooserComponentNames =*/ null);
     }
 
     protected ShortcutInfo makeShortcutWithActivityAndRank(String id, ComponentName activity,
             int rank) {
         return makeShortcut(
                 id, "Title-" + id, activity, /* icon =*/ null,
-                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), rank);
+                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), rank,
+                /* chooserFilters =*/ null, /* chooserComponentNames =*/ null);
     }
 
     /**
      * Make a shortcut with details.
      */
     protected ShortcutInfo makeShortcut(String id, String title, ComponentName activity,
-            Icon icon, Intent intent, int rank) {
+            Icon icon, Intent intent, int rank, @Nullable List<IntentFilter> chooserFilters,
+            @Nullable List<ComponentName> chooserComponentNames) {
         final ShortcutInfo.Builder  b = new ShortcutInfo.Builder(mClientContext, id)
                 .setActivity(new ComponentName(mClientContext.getPackageName(), "main"))
                 .setShortLabel(title)
-                .setRank(rank)
-                .setIntent(intent);
+                .setRank(rank);
+        if (intent != null) {
+            b.setIntent(intent);
+        }
+        if (chooserFilters != null) {
+            for (int i = 0; i < chooserFilters.size(); i++) {
+                b.addChooserIntentFilter(chooserFilters.get(i), chooserComponentNames.get(i));
+            }
+        }
         if (icon != null) {
             b.setIcon(icon);
         }
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index 5591029..d8db331 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -140,6 +140,36 @@
         assertAllFieldsExist(deserialized);
     }
 
+    @Test
+    public void test_stringInterning() throws Exception {
+        PackageParser.Package pkg = new PackageParser.Package("foo");
+        setKnownFields(pkg);
+
+        Parcel p = Parcel.obtain();
+        pkg.writeToParcel(p, 0 /* flags */);
+
+        p.setDataPosition(0);
+        PackageParser.Package deserialized = new PackageParser.Package(p);
+
+        p.setDataPosition(0);
+        PackageParser.Package deserialized2 = new PackageParser.Package(p);
+
+        assertSame(deserialized.packageName, deserialized2.packageName);
+        assertSame(deserialized.applicationInfo.permission,
+                deserialized2.applicationInfo.permission);
+        assertSame(deserialized.requestedPermissions.get(0),
+                deserialized2.requestedPermissions.get(0));
+        assertSame(deserialized.protectedBroadcasts.get(0),
+                deserialized2.protectedBroadcasts.get(0));
+        assertSame(deserialized.usesLibraries.get(0),
+                deserialized2.usesLibraries.get(0));
+        assertSame(deserialized.usesOptionalLibraries.get(0),
+                deserialized2.usesOptionalLibraries.get(0));
+        assertSame(deserialized.mVersionName, deserialized2.mVersionName);
+        assertSame(deserialized.mSharedUserId, deserialized2.mSharedUserId);
+    }
+
+
     /**
      * A trivial subclass of package parser that only caches the package name, and throws away
      * all other information.
@@ -167,7 +197,6 @@
         assertEquals(a.installLocation, b.installLocation);
         assertEquals(a.coreApp, b.coreApp);
         assertEquals(a.mRequiredForAllUsers, b.mRequiredForAllUsers);
-        assertEquals(a.mOverlayPriority, b.mOverlayPriority);
         assertEquals(a.mTrustedOverlay, b.mTrustedOverlay);
         assertEquals(a.use32bitAbi, b.use32bitAbi);
         assertEquals(a.packageName, b.packageName);
@@ -384,9 +413,7 @@
         assertTrue(Arrays.equals(a.sharedLibraryFiles, that.sharedLibraryFiles));
         assertEquals(a.dataDir, that.dataDir);
         assertEquals(a.deviceProtectedDataDir, that.deviceProtectedDataDir);
-        assertEquals(a.deviceEncryptedDataDir, that.deviceEncryptedDataDir);
         assertEquals(a.credentialProtectedDataDir, that.credentialProtectedDataDir);
-        assertEquals(a.credentialEncryptedDataDir, that.credentialEncryptedDataDir);
         assertEquals(a.nativeLibraryDir, that.nativeLibraryDir);
         assertEquals(a.secondaryNativeLibraryDir, that.secondaryNativeLibraryDir);
         assertEquals(a.nativeLibraryRootDir, that.nativeLibraryRootDir);
@@ -403,15 +430,14 @@
         pkg.installLocation = 100;
         pkg.coreApp = true;
         pkg.mRequiredForAllUsers = true;
-        pkg.mOverlayPriority = 100;
         pkg.mTrustedOverlay = true;
         pkg.use32bitAbi = true;
         pkg.packageName = "foo";
-        pkg.splitNames = new String[] { "foo" };
-        pkg.volumeUuid = "foo";
-        pkg.codePath = "foo";
-        pkg.baseCodePath = "foo";
-        pkg.splitCodePaths = new String[] { "foo" };
+        pkg.splitNames = new String[] { "foo2" };
+        pkg.volumeUuid = "foo3";
+        pkg.codePath = "foo4";
+        pkg.baseCodePath = "foo5";
+        pkg.splitCodePaths = new String[] { "foo6" };
         pkg.splitRevisionCodes = new int[] { 100 };
         pkg.splitFlags = new int[] { 100 };
         pkg.splitPrivateFlags = new int[] { 100 };
@@ -428,48 +454,55 @@
         pkg.providers.add(new PackageParser.Provider(dummy, new ProviderInfo()));
         pkg.services.add(new PackageParser.Service(dummy, new ServiceInfo()));
         pkg.instrumentation.add(new PackageParser.Instrumentation(dummy, new InstrumentationInfo()));
-        pkg.requestedPermissions.add("foo");
+        pkg.requestedPermissions.add("foo7");
 
         pkg.protectedBroadcasts = new ArrayList<>();
-        pkg.protectedBroadcasts.add("foo");
+        pkg.protectedBroadcasts.add("foo8");
 
-        pkg.parentPackage = new PackageParser.Package("foo");
+        pkg.parentPackage = new PackageParser.Package("foo9");
 
         pkg.childPackages = new ArrayList<>();
         pkg.childPackages.add(new PackageParser.Package("bar"));
 
+        pkg.staticSharedLibName = "foo23";
+        pkg.staticSharedLibVersion = 100;
+        pkg.usesStaticLibraries = new ArrayList<>();
+        pkg.usesStaticLibraries.add("foo23");
+        pkg.usesStaticLibrariesCertDigests = new String[] { "digest" };
+        pkg.usesStaticLibrariesVersions = new int[] { 100 };
+
         pkg.libraryNames = new ArrayList<>();
-        pkg.libraryNames.add("foo");
+        pkg.libraryNames.add("foo10");
 
         pkg.usesLibraries = new ArrayList<>();
-        pkg.usesLibraries.add("foo");
+        pkg.usesLibraries.add("foo11");
 
         pkg.usesOptionalLibraries = new ArrayList<>();
-        pkg.usesOptionalLibraries.add("foo");
+        pkg.usesOptionalLibraries.add("foo12");
 
-        pkg.usesLibraryFiles = new String[] { "foo "};
+        pkg.usesLibraryFiles = new String[] { "foo13"};
 
         pkg.mOriginalPackages = new ArrayList<>();
-        pkg.mOriginalPackages.add("foo");
+        pkg.mOriginalPackages.add("foo14");
 
-        pkg.mRealPackage = "foo";
+        pkg.mRealPackage = "foo15";
 
         pkg.mAdoptPermissions = new ArrayList<>();
-        pkg.mAdoptPermissions.add("foo");
+        pkg.mAdoptPermissions.add("foo16");
 
         pkg.mAppMetaData = new Bundle();
-        pkg.mVersionName = "foo";
-        pkg.mSharedUserId = "foo";
+        pkg.mVersionName = "foo17";
+        pkg.mSharedUserId = "foo18";
         pkg.mSignatures = new Signature[] { new Signature(new byte[16]) };
         pkg.mCertificates = new Certificate[][] { new Certificate[] { null }};
         pkg.mExtras = new Bundle();
-        pkg.mRestrictedAccountType = "foo";
-        pkg.mRequiredAccountType = "foo";
-        pkg.mOverlayTarget = "foo";
+        pkg.mRestrictedAccountType = "foo19";
+        pkg.mRequiredAccountType = "foo20";
+        pkg.mOverlayTarget = "foo21";
         pkg.mSigningKeys = new ArraySet<>();
         pkg.mUpgradeKeySets = new ArraySet<>();
         pkg.mKeySetMapping = new ArrayMap<>();
-        pkg.cpuAbiOverride = "foo";
+        pkg.cpuAbiOverride = "foo22";
         pkg.restrictUpdateHash = new byte[16];
 
         pkg.preferredActivityFilters = new ArrayList<>();
@@ -504,7 +537,7 @@
                 // Sanity check for list fields: Assume they're non-null and contain precisely
                 // one element.
                 List<?> list = (List<?>) f.get(pkg);
-                assertNotNull(list);
+                assertNotNull("List was null: " + f, list);
                 assertEquals(1, list.size());
             } else if (fieldType.getComponentType() != null) {
                 // Sanity check for array fields: Assume they're non-null and contain precisely
@@ -514,15 +547,16 @@
             } else if (fieldType == String.class) {
                 // String fields: Check that they're set to "foo".
                 String value = (String) f.get(pkg);
-                assertEquals("foo", value);
+
+                assertTrue("Bad value for field: " + f, value != null && value.startsWith("foo"));
             } else if (fieldType == int.class) {
                 // int fields: Check that they're set to 100.
                 int value = (int) f.get(pkg);
-                assertEquals(100, value);
+                assertEquals("Bad value for field: " + f, 100, value);
             } else {
                 // All other fields: Check that they're set.
                 Object o = f.get(pkg);
-                assertNotNull("Field was null: " + f.getName(), o);
+                assertNotNull("Field was null: " + f, o);
             }
         }
     }
diff --git a/services/tests/servicestests/src/com/android/server/pm/ParallelPackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/ParallelPackageParserTest.java
index 6c6eb7e..d665094 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ParallelPackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ParallelPackageParserTest.java
@@ -69,7 +69,7 @@
     class TestParallelPackageParser extends ParallelPackageParser {
 
         TestParallelPackageParser() {
-            super(null, false, null, null);
+            super(null, false, null, null, null);
         }
 
         @Override
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 0c53167..4b3c2f8 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -15,6 +15,7 @@
  */
 package com.android.server.pm;
 
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllChooser;
 import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllDisabled;
 import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllDynamic;
 import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllDynamicOrPinned;
@@ -75,9 +76,9 @@
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.CompressFormat;
 import android.graphics.BitmapFactory;
+import android.graphics.drawable.AdaptiveIconDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
-import android.graphics.drawable.MaskableIconDrawable;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
@@ -246,7 +247,7 @@
         final Icon icon1 = Icon.createWithResource(getTestContext(), R.drawable.icon1);
         final Icon icon2 = Icon.createWithBitmap(BitmapFactory.decodeResource(
                 getTestContext().getResources(), R.drawable.icon2));
-        final Icon icon3 = Icon.createWithMaskableBitmap(BitmapFactory.decodeResource(
+        final Icon icon3 = Icon.createWithAdaptiveBitmap(BitmapFactory.decodeResource(
             getTestContext().getResources(), R.drawable.icon2));
 
         final ShortcutInfo si1 = makeShortcut(
@@ -256,7 +257,9 @@
                 icon1,
                 makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
                         "key1", "val1", "nest", makeBundle("key", 123)),
-                /* weight */ 10);
+                /* weight */ 10,
+                /* chooserFilter=*/ null,
+                /* chooserComponentNames=*/ null);
 
         final ShortcutInfo si2 = makeShortcut(
                 "shortcut2",
@@ -264,14 +267,18 @@
                 /* activity */ null,
                 icon2,
                 makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
-                /* weight */ 12);
+                /* weight */ 12,
+                /* chooserFilter=*/ null,
+                /* chooserComponentNames=*/ null);
         final ShortcutInfo si3 = makeShortcut(
                 "shortcut3",
                 "Title 3",
                 /* activity */ null,
                 icon3,
                 makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
-                /* weight */ 13);
+                /* weight */ 13,
+                /* chooserFilter=*/ null,
+                /* chooserComponentNames=*/ null);
 
         assertTrue(mManager.setDynamicShortcuts(list(si1, si2, si3)));
         assertShortcutIds(assertAllNotKeyFieldsOnly(
@@ -560,7 +567,7 @@
 
         final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource(
                 getTestContext().getResources(), R.drawable.black_32x32));
-        final Icon bmp64x64_maskable = Icon.createWithMaskableBitmap(BitmapFactory.decodeResource(
+        final Icon bmp64x64_maskable = Icon.createWithAdaptiveBitmap(BitmapFactory.decodeResource(
                 getTestContext().getResources(), R.drawable.black_64x64));
         final Icon bmp512x512 = Icon.createWithBitmap(BitmapFactory.decodeResource(
                 getTestContext().getResources(), R.drawable.black_512x512));
@@ -704,8 +711,8 @@
 
         Drawable dr = mLauncherApps.getShortcutIconDrawable(
             makeShortcutWithIcon("bmp64x64", bmp64x64_maskable), 0);
-        assertTrue(dr instanceof MaskableIconDrawable);
-        float viewportPercentage = 1 / (1 + 2 * MaskableIconDrawable.getExtraInsetPercentage());
+        assertTrue(dr instanceof AdaptiveIconDrawable);
+        float viewportPercentage = 1 / (1 + 2 * AdaptiveIconDrawable.getExtraInsetPercentage());
         assertEquals((int) (bmp64x64_maskable.getBitmap().getWidth() * viewportPercentage),
             dr.getIntrinsicWidth());
         assertEquals((int) (bmp64x64_maskable.getBitmap().getHeight() * viewportPercentage),
@@ -982,8 +989,10 @@
                     makeShortcut("s2"),
                     makeShortcut("s3"),
                     makeShortcut("s4"),
-                    makeShortcut("s5")
-            )));
+                    makeShortcut("s5"),
+                    makeChooserShortcut("s6", 2, true),
+                    makeChooserShortcut("s7", 2, true),
+                    makeChooserShortcut("s8", 1, true))));
         });
         runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
@@ -991,11 +1000,13 @@
                     makeShortcut("s2"),
                     makeShortcut("s3"),
                     makeShortcut("s4"),
-                    makeShortcut("s5")
-            )));
+                    makeShortcut("s5"),
+                    makeChooserShortcut("s6", 2, true),
+                    makeChooserShortcut("s7", 2, true),
+                    makeChooserShortcut("s8", 1, true))));
         });
         runWithCaller(LAUNCHER_1, UserHandle.USER_SYSTEM, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2", "s3"),
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2", "s3", "s6"),
                     getCallingUser());
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s4", "s5"),
                     getCallingUser());
@@ -1008,19 +1019,20 @@
             mManager.removeDynamicShortcuts(list("s1"));
             mManager.removeDynamicShortcuts(list("s3"));
             mManager.removeDynamicShortcuts(list("s5"));
+            mManager.removeDynamicShortcuts(list("s7"));
         });
         runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
             assertShortcutIds(assertAllDynamic(
                     mManager.getDynamicShortcuts()),
-                    "s3", "s4", "s5");
+                    "s3", "s4", "s5", "s6", "s7", "s8");
             assertShortcutIds(assertAllPinned(
                     mManager.getPinnedShortcuts()),
-                    "s2", "s3");
+                    "s2", "s3", "s6");
         });
         runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
             assertShortcutIds(assertAllDynamic(
                     mManager.getDynamicShortcuts()),
-                    "s2", "s4");
+                    "s2", "s4", "s6", "s8");
             assertShortcutIds(assertAllPinned(
                     mManager.getPinnedShortcuts()),
                     "s4", "s5");
@@ -1057,10 +1069,10 @@
         runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
             assertShortcutIds(assertAllDynamic(
                     mManager.getDynamicShortcuts()),
-                    "s3", "s4", "s5");
+                    "s3", "s4", "s5", "s6", "s7", "s8");
             assertShortcutIds(assertAllPinned(
                     mManager.getPinnedShortcuts()),
-                    "s2", "s3");
+                    "s2", "s3", "s6");
 
             ShortcutInfo s = getCallerShortcut("s2");
             assertTrue(s.hasIconResource());
@@ -1076,7 +1088,7 @@
         runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
             assertShortcutIds(assertAllDynamic(
                     mManager.getDynamicShortcuts()),
-                    "s2", "s4");
+                    "s2", "s4", "s6", "s8");
             assertShortcutIds(assertAllPinned(
                     mManager.getPinnedShortcuts()),
                     "s4", "s5");
@@ -1173,7 +1185,46 @@
         });
     }
 
-    // === Test for launcher side APIs ===
+    public void testUpdateShortcuts_chooser() {
+        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(
+                    makeShortcut("s1"),
+                    makeChooserShortcut("s2", 2, false),
+                    makeChooserShortcut("s3", 2, false)
+            )));
+
+            assertFalse(getCallerShortcut("s1").isChooser());
+            assertTrue(getCallerShortcut("s2").isChooser());
+            assertTrue(getCallerShortcut("s3").isChooser());
+
+            ShortcutInfo s = getCallerShortcut("s1");
+            assertNull(s.getChooserIntentFilters());
+            assertNull(s.getChooserComponentNames());
+
+            assertTrue(getCallerShortcut("s1").isDynamic());
+            assertFalse(getCallerShortcut("s2").isDynamic());
+            assertFalse(getCallerShortcut("s3").isDynamic());
+
+
+            // Replace 2 with a chooser shortcut
+            mManager.updateShortcuts(list(makeChooserShortcut("s1", 2, true)));
+
+            s = getCallerShortcut("s1");
+            assertEquals(2, s.getChooserIntentFilters().length);
+            assertEquals(2, s.getChooserComponentNames().length);
+
+            assertShortcutIds(assertAllChooser(
+                    mManager.getDynamicShortcuts()),
+                    "s1", "s2", "s3");
+
+            assertTrue(getCallerShortcut("s1").isDynamic());
+            assertFalse(getCallerShortcut("s2").isDynamic());
+            assertFalse(getCallerShortcut("s3").isDynamic());
+        });
+    }
+
+
+            // === Test for launcher side APIs ===
 
     public void testGetShortcuts() {
 
@@ -1484,15 +1535,17 @@
                 /* icon =*/ null,
                 makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
                         "key1", "val1", "nest", makeBundle("key", 123)),
-                /* weight */ 10);
+                        /* weight */ 10, /* chooserFilter=*/ null,
+                        /* chooserComponentNames=*/ null);
 
         final ShortcutInfo s1_2 = makeShortcut(
-                "s2",
-                "Title 2",
+                "s2", "Title 2",
                 /* activity */ null,
                 /* icon =*/ null,
                 makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
-                /* weight */ 12);
+                /* weight */ 12,
+                /* chooserFilter=*/ null,
+                /* chooserComponentNames=*/ null);
 
         assertTrue(mManager.setDynamicShortcuts(list(s1_1, s1_2)));
         dumpsysOnLogcat();
@@ -1505,7 +1558,9 @@
                 /* icon =*/ null,
                 makeIntent(Intent.ACTION_ANSWER, ShortcutActivity2.class,
                         "key1", "val1", "nest", makeBundle("key", 123)),
-                /* weight */ 10);
+                /* weight */ 10,
+                /* chooserFilter=*/ null,
+                /* chooserComponentNames=*/ null);
         assertTrue(mManager.setDynamicShortcuts(list(s2_1)));
         dumpsysOnLogcat();
 
@@ -2674,10 +2729,12 @@
             final ShortcutInfo s1_2 = makeShortcut(
                     "s2",
                     "Title 2",
-            /* activity */ null,
-            /* icon =*/ null,
+                    /* activity */ null,
+                    /* icon =*/ null,
                     makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
-            /* rank */ 12);
+                    /* rank */ 12,
+                    /* chooserFilter=*/ null,
+                    /* chooserComponentNames=*/ null);
 
             final ShortcutInfo s1_3 = makeShortcut("s3");
 
@@ -2692,7 +2749,9 @@
                     /* icon =*/ null,
                     makeIntent(Intent.ACTION_ANSWER, ShortcutActivity.class,
                             "key1", "val1", "nest", makeBundle("key", 123)),
-                    /* weight */ 10);
+                    /* weight */ 10,
+                    /* chooserFilter=*/ null,
+                    /* chooserComponentNames=*/ null);
             assertTrue(mManager.setDynamicShortcuts(list(s2_1)));
         });
 
@@ -3110,7 +3169,9 @@
                     icon1,
                     makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
                             "key1", "val1", "nest", makeBundle("key", 123)),
-                        /* weight */ 10);
+                        /* weight */ 10,
+                    /* chooserFilter=*/ null,
+                    /* chooserComponentNames=*/ null);
 
             final ShortcutInfo si2 = makeShortcut(
                     "s2",
@@ -3118,7 +3179,9 @@
                         /* activity */ null,
                     icon2,
                     makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
-                        /* weight */ 12);
+                        /* weight */ 12,
+                    /* chooserFilter=*/ null,
+                    /* chooserComponentNames=*/ null);
 
             assertTrue(mManager.setDynamicShortcuts(list(si1, si2)));
 
@@ -3136,8 +3199,8 @@
                     makeComponent(ShortcutActivity.class),
                     icon1,
                     makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
-                            "key1", "val1", "nest", makeBundle("key", 123)),
-                        /* weight */ 10);
+                            "key1", "val1", "nest", makeBundle("key", 123)), /* weight */ 10,
+                            /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
 
             final ShortcutInfo si2 = makeShortcut(
                     "s2",
@@ -3145,7 +3208,8 @@
                         /* activity */ null,
                     icon2,
                     makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
-                        /* weight */ 12);
+                        /* weight */ 12, /* chooserFilter=*/ null,
+                        /* chooserComponentNames=*/ null);
 
             assertTrue(mManager.setDynamicShortcuts(list(si1, si2)));
 
@@ -3167,7 +3231,8 @@
                     icon1,
                     makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
                             "key1", "val1", "nest", makeBundle("key", 123)),
-                        /* weight */ 10);
+                            /* weight */ 10, /* chooserFilter=*/ null,
+                            /* chooserComponentNames=*/ null);
 
             final ShortcutInfo si2 = makeShortcut(
                     "s2",
@@ -3175,7 +3240,8 @@
                         /* activity */ null,
                     icon2,
                     makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
-                        /* weight */ 12);
+                            /* weight */ 12, /* chooserFilter=*/ null,
+                            /* chooserComponentNames=*/ null);
 
             assertTrue(mManager.setDynamicShortcuts(list(si1, si2)));
 
@@ -6800,10 +6866,12 @@
             mManager.setDynamicShortcuts(list(
                     makeShortcut("ms1", "title1",
                             new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
-                    /* icon */ null, new Intent("action1"), /* rank */ 0),
+                            /* icon */ null, new Intent("action1"), /* rank */ 0,
+                            /* chooserFilter=*/ null, /* chooserComponentNames=*/ null),
                     makeShortcut("ms2", "title2",
                             new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
-                    /* icon */ null, new Intent("action1"), /* rank */ 0)));
+                            /* icon */ null, new Intent("action1"), /* rank */ 0, /* chooserFilter=*/ null,
+                            /* chooserComponentNames=*/ null)));
         });
 
         runWithCaller(LAUNCHER_1, USER_0, () -> {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index 28ec4fd..900da09 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -34,6 +34,7 @@
 import android.app.ActivityManager;
 import android.content.ComponentName;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.ShortcutInfo;
 import android.content.res.Resources;
 import android.graphics.BitmapFactory;
@@ -45,7 +46,6 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.frameworks.servicestests.R;
-import com.android.server.pm.ShortcutService.ConfigConstants;
 import com.android.server.pm.ShortcutUser.PackageWithUser;
 
 import java.io.File;
@@ -93,11 +93,6 @@
 
         assertExpectException(
                 RuntimeException.class,
-                "intents cannot contain null",
-                () -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(null));
-
-        assertExpectException(
-                RuntimeException.class,
                 "action must be set",
                 () -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(new Intent()));
 
@@ -142,6 +137,19 @@
                 "disabledMessage cannot be empty",
                 () -> new ShortcutInfo.Builder(getTestContext(), "id").setDisabledMessage(""));
 
+
+        assertExpectException(
+                RuntimeException.class,
+                "component name cannot be null",
+                () -> new ShortcutInfo.Builder(getTestContext(), "id")
+                        .addChooserIntentFilter(new IntentFilter(Intent.ACTION_SEND), null));
+
+        assertExpectException(
+                RuntimeException.class,
+                "intent filter cannot be null",
+                () -> new ShortcutInfo.Builder(getTestContext(), "id")
+                        .addChooserIntentFilter(null, new ComponentName("xxx", "s")));
+
         assertExpectException(NullPointerException.class, "action must be set",
                 () -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(new Intent()));
 
@@ -240,6 +248,10 @@
 
         PersistableBundle pb = new PersistableBundle();
         pb.putInt("k", 1);
+        IntentFilter chooserFilter = new IntentFilter();
+        chooserFilter.addAction(Intent.ACTION_VIEW);
+        PersistableBundle pb2 = new PersistableBundle();
+        pb2.putInt("l", 1);
 
         si = new ShortcutInfo.Builder(getTestContext())
                 .setId("id")
@@ -252,6 +264,8 @@
                 .setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
                 .setRank(123)
                 .setExtras(pb)
+                .addChooserIntentFilter(chooserFilter, new ComponentName("a", "b"))
+                .setChooserExtras(pb2)
                 .build();
         si.addFlags(ShortcutInfo.FLAG_PINNED);
         si.setBitmapPath("abc");
@@ -282,6 +296,12 @@
         assertEquals(null, si.getTextResName());
         assertEquals(0, si.getDisabledMessageResourceId());
         assertEquals(null, si.getDisabledMessageResName());
+
+        assertEquals(1, si.getChooserIntentFilters().length);
+        assertEquals(Intent.ACTION_VIEW, si.getChooserIntentFilters()[0].getAction(0));
+        assertEquals(1, si.getChooserComponentNames().length);
+        assertEquals(new ComponentName("a", "b"), si.getChooserComponentNames()[0]);
+        assertEquals(1, si.getChooserExtras().getInt("l"));
     }
 
     public void testShortcutInfoParcel_resId() {
@@ -290,6 +310,10 @@
 
         PersistableBundle pb = new PersistableBundle();
         pb.putInt("k", 1);
+        IntentFilter chooserFilter = new IntentFilter();
+        chooserFilter.addAction(Intent.ACTION_VIEW);
+        PersistableBundle pb2 = new PersistableBundle();
+        pb2.putInt("l", 1);
 
         si = new ShortcutInfo.Builder(getTestContext())
                 .setId("id")
@@ -302,6 +326,8 @@
                 .setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
                 .setRank(123)
                 .setExtras(pb)
+                .addChooserIntentFilter(chooserFilter, new ComponentName("a", "b"))
+                .setChooserExtras(pb2)
                 .build();
         si.addFlags(ShortcutInfo.FLAG_PINNED);
         si.setBitmapPath("abc");
@@ -338,6 +364,11 @@
 
         PersistableBundle pb = new PersistableBundle();
         pb.putInt("k", 1);
+        IntentFilter chooserFilter = new IntentFilter();
+        chooserFilter.addAction(Intent.ACTION_VIEW);
+        PersistableBundle pb2 = new PersistableBundle();
+        pb2.putInt("l", 1);
+
         ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext)
                 .setId("id")
                 .setActivity(new ComponentName("a", "b"))
@@ -349,6 +380,8 @@
                 .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
                 .setRank(123)
                 .setExtras(pb)
+                .addChooserIntentFilter(chooserFilter, new ComponentName("a", "b"))
+                .setChooserExtras(pb2)
                 .build();
         sorig.addFlags(ShortcutInfo.FLAG_PINNED);
         sorig.setBitmapPath("abc");
@@ -378,6 +411,12 @@
         assertEquals(456, si.getIconResourceId());
         assertEquals("string/r456", si.getIconResName());
 
+        assertEquals(1, si.getChooserIntentFilters().length);
+        assertEquals(Intent.ACTION_VIEW, si.getChooserIntentFilters()[0].getAction(0));
+        assertEquals(1, si.getChooserComponentNames().length);
+        assertEquals(new ComponentName("a", "b"), si.getChooserComponentNames()[0]);
+        assertEquals(1, si.getChooserExtras().getInt("l"));
+
         si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_CREATOR);
 
         assertEquals(mClientContext.getPackageName(), si.getPackage());
@@ -445,6 +484,10 @@
 
         PersistableBundle pb = new PersistableBundle();
         pb.putInt("k", 1);
+        IntentFilter chooserFilter = new IntentFilter();
+        chooserFilter.addAction(Intent.ACTION_VIEW);
+        PersistableBundle pb2 = new PersistableBundle();
+        pb2.putInt("l", 1);
         ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext)
                 .setId("id")
                 .setActivity(new ComponentName("a", "b"))
@@ -456,6 +499,8 @@
                 .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
                 .setRank(123)
                 .setExtras(pb)
+                .addChooserIntentFilter(chooserFilter, new ComponentName("a", "b"))
+                .setChooserExtras(pb2)
                 .build();
         sorig.addFlags(ShortcutInfo.FLAG_PINNED);
         sorig.setBitmapPath("abc");
@@ -488,6 +533,12 @@
         assertEquals(456, si.getIconResourceId());
         assertEquals("string/r456", si.getIconResName());
 
+        assertEquals(1, si.getChooserIntentFilters().length);
+        assertEquals(Intent.ACTION_VIEW, si.getChooserIntentFilters()[0].getAction(0));
+        assertEquals(1, si.getChooserComponentNames().length);
+        assertEquals(new ComponentName("a", "b"), si.getChooserComponentNames()[0]);
+        assertEquals(1, si.getChooserExtras().getInt("l"));
+
         si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_CREATOR);
 
         assertEquals(mClientContext.getPackageName(), si.getPackage());
@@ -603,6 +654,10 @@
     public void testShortcutInfoCopyNonNullFieldsFrom() throws InterruptedException {
         PersistableBundle pb = new PersistableBundle();
         pb.putInt("k", 1);
+        IntentFilter chooserFilter = new IntentFilter();
+        chooserFilter.addAction(Intent.ACTION_VIEW);
+        PersistableBundle pb2 = new PersistableBundle();
+        pb2.putInt("l", 1);
         ShortcutInfo sorig = new ShortcutInfo.Builder(getTestContext())
                 .setId("id")
                 .setActivity(new ComponentName("a", "b"))
@@ -714,12 +769,12 @@
         assertEquals(999, si.getRank());
 
 
-        PersistableBundle pb2 = new PersistableBundle();
-        pb2.putInt("x", 99);
+        PersistableBundle pb3 = new PersistableBundle();
+        pb3.putInt("x", 99);
 
         si = sorig.clone(/* flags=*/ 0);
         si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
-                .setExtras(pb2).build());
+                .setExtras(pb3).build());
         assertEquals("text", si.getText());
         assertEquals(99, si.getExtras().getInt("x"));
     }
@@ -937,7 +992,7 @@
 
         setCaller(CALLING_PACKAGE_1, USER_10);
 
-        final Icon bmp32x32 = Icon.createWithMaskableBitmap(BitmapFactory.decodeResource(
+        final Icon bmp32x32 = Icon.createWithAdaptiveBitmap(BitmapFactory.decodeResource(
             getTestContext().getResources(), R.drawable.black_32x32));
 
         PersistableBundle pb = new PersistableBundle();
@@ -991,7 +1046,7 @@
         assertEquals(1, si.getExtras().getInt("k"));
 
         assertEquals(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_HAS_ICON_FILE
-            | ShortcutInfo.FLAG_STRINGS_RESOLVED | ShortcutInfo.FLAG_MASKABLE_BITMAP,
+            | ShortcutInfo.FLAG_STRINGS_RESOLVED | ShortcutInfo.FLAG_ADAPTIVE_BITMAP,
             si.getFlags());
         assertNotNull(si.getBitmapPath()); // Something should be set.
         assertEquals(0, si.getIconResourceId());
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java
index 26033a3..012024f1 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java
@@ -95,7 +95,7 @@
 
             assertExpectException(IllegalStateException.class, "foreground activity", () -> {
                 mInternal.requestPinAppWidget(CALLING_PACKAGE_1, makeProviderInfo("dummy"),
-            /* resultIntent= */ null, USER_P0);
+                        null /* extras */, null /* resultIntent= */, USER_P0);
             });
 
             verify(mServiceContext, times(0)).sendIntentSender(any(IntentSender.class));
@@ -111,7 +111,7 @@
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             AppWidgetProviderInfo info = makeProviderInfo("c1");
 
-            assertTrue(mInternal.requestPinAppWidget(CALLING_PACKAGE_1, info,
+            assertTrue(mInternal.requestPinAppWidget(CALLING_PACKAGE_1, info, null,
                     resultIntent == null ? null : resultIntent.getIntentSender(), USER_P0));
 
             verify(mServiceContext, times(0)).sendIntentSender(any(IntentSender.class));
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
index 90a2ec0..fa0bd39 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
@@ -16,9 +16,10 @@
 
 package com.android.server.pm.dex;
 
-import android.os.Build;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
+import android.os.Build;
+import android.os.UserHandle;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
@@ -57,6 +58,7 @@
 
     private int mUser0;
     private int mUser1;
+
     @Before
     public void setup() {
 
@@ -243,6 +245,113 @@
         assertSecondaryUse(newPackage, pui, newSecondaries, /*isUsedByOtherApps*/false, mUser0);
     }
 
+    @Test
+    public void testNotifyPackageUpdated() {
+        // Foo loads Bar main apks.
+        notifyDexLoad(mFooUser0, mBarUser0.getBaseAndSplitDexPaths(), mUser0);
+
+        // Bar is used by others now and should be in our records.
+        PackageUseInfo pui = getPackageUseInfo(mBarUser0);
+        assertNotNull(pui);
+        assertTrue(pui.isUsedByOtherApps());
+        assertTrue(pui.getDexUseInfoMap().isEmpty());
+
+        // Notify that bar is updated.
+        mDexManager.notifyPackageUpdated(mBarUser0.getPackageName(),
+                mBarUser0.mPackageInfo.applicationInfo.sourceDir,
+                mBarUser0.mPackageInfo.applicationInfo.splitSourceDirs);
+
+        // The usedByOtherApps flag should be clear now.
+        pui = getPackageUseInfo(mBarUser0);
+        assertNotNull(pui);
+        assertFalse(pui.isUsedByOtherApps());
+    }
+
+    @Test
+    public void testNotifyPackageUpdatedCodeLocations() {
+        // Simulate a split update.
+        String newSplit = mBarUser0.replaceLastSplit();
+        List<String> newSplits = new ArrayList<>();
+        newSplits.add(newSplit);
+
+        // We shouldn't find yet the new split as we didn't notify the package update.
+        notifyDexLoad(mFooUser0, newSplits, mUser0);
+        PackageUseInfo pui = getPackageUseInfo(mBarUser0);
+        assertNull(pui);
+
+        // Notify that bar is updated. splitSourceDirs will contain the updated path.
+        mDexManager.notifyPackageUpdated(mBarUser0.getPackageName(),
+                mBarUser0.mPackageInfo.applicationInfo.sourceDir,
+                mBarUser0.mPackageInfo.applicationInfo.splitSourceDirs);
+
+        // Now, when the split is loaded we will find it and we should mark Bar as usedByOthers.
+        notifyDexLoad(mFooUser0, newSplits, mUser0);
+        pui = getPackageUseInfo(mBarUser0);
+        assertNotNull(pui);
+        assertTrue(pui.isUsedByOtherApps());
+    }
+
+    @Test
+    public void testNotifyPackageDataDestroyForOne() {
+        // Bar loads its own secondary files.
+        notifyDexLoad(mBarUser0, mBarUser0.getSecondaryDexPaths(), mUser0);
+        notifyDexLoad(mBarUser1, mBarUser1.getSecondaryDexPaths(), mUser1);
+
+        mDexManager.notifyPackageDataDestroyed(mBarUser0.getPackageName(), mUser0);
+
+        // Bar should not be around since it was removed for all users.
+        PackageUseInfo pui = getPackageUseInfo(mBarUser1);
+        assertNotNull(pui);
+        assertSecondaryUse(mBarUser1, pui, mBarUser1.getSecondaryDexPaths(),
+                /*isUsedByOtherApps*/false, mUser1);
+    }
+
+    @Test
+    public void testNotifyPackageDataDestroyForeignUse() {
+        // Foo loads its own secondary files.
+        List<String> fooSecondaries = mFooUser0.getSecondaryDexPaths();
+        notifyDexLoad(mFooUser0, fooSecondaries, mUser0);
+
+        // Bar loads Foo main apks.
+        notifyDexLoad(mBarUser0, mFooUser0.getBaseAndSplitDexPaths(), mUser0);
+
+        mDexManager.notifyPackageDataDestroyed(mFooUser0.getPackageName(), mUser0);
+
+        // Foo should still be around since it's used by other apps but with no
+        // secondary dex info.
+        PackageUseInfo pui = getPackageUseInfo(mFooUser0);
+        assertNotNull(pui);
+        assertTrue(pui.isUsedByOtherApps());
+        assertTrue(pui.getDexUseInfoMap().isEmpty());
+    }
+
+    @Test
+    public void testNotifyPackageDataDestroyComplete() {
+        // Foo loads its own secondary files.
+        List<String> fooSecondaries = mFooUser0.getSecondaryDexPaths();
+        notifyDexLoad(mFooUser0, fooSecondaries, mUser0);
+
+        mDexManager.notifyPackageDataDestroyed(mFooUser0.getPackageName(), mUser0);
+
+        // Foo should not be around since all its secondary dex info were deleted
+        // and it is not used by other apps.
+        PackageUseInfo pui = getPackageUseInfo(mFooUser0);
+        assertNull(pui);
+    }
+
+    @Test
+    public void testNotifyPackageDataDestroyForAll() {
+        // Foo loads its own secondary files.
+        notifyDexLoad(mBarUser0, mBarUser0.getSecondaryDexPaths(), mUser0);
+        notifyDexLoad(mBarUser1, mBarUser1.getSecondaryDexPaths(), mUser1);
+
+        mDexManager.notifyPackageDataDestroyed(mBarUser0.getPackageName(), UserHandle.USER_ALL);
+
+        // Bar should not be around since it was removed for all users.
+        PackageUseInfo pui = getPackageUseInfo(mBarUser0);
+        assertNull(pui);
+    }
+
     private void assertSecondaryUse(TestData testData, PackageUseInfo pui,
             List<String> secondaries, boolean isUsedByOtherApps, int ownerUserId) {
         for (String dex : secondaries) {
@@ -317,5 +426,12 @@
             }
             return paths;
         }
+
+        String replaceLastSplit() {
+            int length = mPackageInfo.applicationInfo.splitSourceDirs.length;
+            // Add an extra bogus dex extension to simulate a new split name.
+            mPackageInfo.applicationInfo.splitSourceDirs[length - 1] += ".dex";
+            return mPackageInfo.applicationInfo.splitSourceDirs[length - 1];
+        }
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java
index 19e0bcf..2e99433 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java
@@ -257,6 +257,30 @@
     }
 
     @Test
+    public void testRemovePackage() {
+        // Record Bar secondaries for two different users.
+        assertTrue(record(mBarSecondary1User0));
+        assertTrue(record(mBarSecondary2User1));
+
+        // Remove the package.
+        assertTrue(mPackageDexUsage.removePackage(mBarSecondary1User0.mPackageName));
+        // Assert that we can't find the package anymore.
+        assertNull(mPackageDexUsage.getPackageUseInfo(mBarSecondary1User0.mPackageName));
+    }
+
+    @Test
+    public void testRemoveNonexistentPackage() {
+        // Record Bar secondaries for two different users.
+        assertTrue(record(mBarSecondary1User0));
+
+        // Remove the package.
+        assertTrue(mPackageDexUsage.removePackage(mBarSecondary1User0.mPackageName));
+        // Remove the package again. It should return false because the package no longer
+        // has a record in the use info.
+        assertFalse(mPackageDexUsage.removePackage(mBarSecondary1User0.mPackageName));
+    }
+
+    @Test
     public void testRemoveUserPackage() {
         // Record Bar secondaries for two different users.
         assertTrue(record(mBarSecondary1User0));
@@ -282,6 +306,32 @@
         assertPackageDexUsage(null, mBarSecondary2User1);
     }
 
+    @Test
+    public void testClearUsedByOtherApps() {
+        // Write a package which is used by other apps.
+        assertTrue(record(mFooSplit2UsedByOtherApps0));
+        assertTrue(mPackageDexUsage.clearUsedByOtherApps(mFooSplit2UsedByOtherApps0.mPackageName));
+
+        // Check that the package is no longer used by other apps.
+        TestData noLongerUsedByOtherApps = new TestData(
+            mFooSplit2UsedByOtherApps0.mPackageName,
+            mFooSplit2UsedByOtherApps0.mDexFile,
+            mFooSplit2UsedByOtherApps0.mOwnerUserId,
+            mFooSplit2UsedByOtherApps0.mLoaderIsa,
+            /*mIsUsedByOtherApps*/false,
+            mFooSplit2UsedByOtherApps0.mPrimaryOrSplit);
+        assertPackageDexUsage(noLongerUsedByOtherApps);
+    }
+
+    @Test
+    public void testClearUsedByOtherAppsNonexistent() {
+        // Write a package which is used by other apps.
+        assertTrue(record(mFooSplit2UsedByOtherApps0));
+        assertTrue(mPackageDexUsage.clearUsedByOtherApps(mFooSplit2UsedByOtherApps0.mPackageName));
+        // Clearing again should return false as there should be no update on the use info.
+        assertFalse(mPackageDexUsage.clearUsedByOtherApps(mFooSplit2UsedByOtherApps0.mPackageName));
+    }
+
     private void assertPackageDexUsage(TestData primary, TestData... secondaries) {
         String packageName = primary == null ? secondaries[0].mPackageName : primary.mPackageName;
         boolean primaryUsedByOtherApps = primary == null ? false : primary.mUsedByOtherApps;
diff --git a/services/tests/servicestests/src/com/android/server/power/BatterySaverPolicyTest.java b/services/tests/servicestests/src/com/android/server/power/BatterySaverPolicyTest.java
new file mode 100644
index 0000000..7282b3e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/power/BatterySaverPolicyTest.java
@@ -0,0 +1,175 @@
+/*
+ * 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.power;
+
+import android.os.PowerSaveState;
+import android.os.Handler;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import com.android.server.power.BatterySaverPolicy.ServiceType;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import static com.google.common.truth.Truth.assertThat;
+
+/**
+ * Tests for {@link com.android.server.power.BatterySaverPolicy}
+ */
+public class BatterySaverPolicyTest extends AndroidTestCase {
+    private static final boolean BATTERY_SAVER_ON = true;
+    private static final boolean BATTERY_SAVER_OFF = false;
+    private static final float BRIGHTNESS_FACTOR = 0.7f;
+    private static final float DEFAULT_BRIGHTNESS_FACTOR = 0.5f;
+    private static final float PRECISION = 0.001f;
+    private static final int GPS_MODE = 0;
+    private static final int DEFAULT_GPS_MODE = 1;
+    private static final String BATTERY_SAVER_CONSTANTS = "vibration_disabled=true,"
+            + "animation_disabled=false,"
+            + "soundtrigger_disabled=true,"
+            + "firewall_disabled=false,"
+            + "adjust_brightness_disabled=true,"
+            + "adjust_brightness_factor=0.7,"
+            + "fullbackup_deferred=true,"
+            + "keyvaluebackup_deferred=false,"
+            + "gps_mode=0";
+    private static final String BATTERY_SAVER_INCORRECT_CONSTANTS = "vi*,!=,,true";
+
+    @Mock
+    Handler mHandler;
+    private BatterySaverPolicy mBatterySaverPolicy;
+
+    public void setUp() throws Exception {
+        super.setUp();
+        MockitoAnnotations.initMocks(this);
+        mBatterySaverPolicy = new BatterySaverPolicy(mHandler);
+        mBatterySaverPolicy.start(getContext().getContentResolver());
+    }
+
+    @SmallTest
+    public void testGetBatterySaverPolicy_PolicyNull_DefaultValueCorrect() {
+        testServiceDefaultValue(ServiceType.NULL);
+    }
+
+    @SmallTest
+    public void testGetBatterySaverPolicy_PolicyVibration_DefaultValueCorrect() {
+        testServiceDefaultValue(ServiceType.VIBRATION);
+    }
+
+    @SmallTest
+    public void testGetBatterySaverPolicy_PolicySound_DefaultValueCorrect() {
+        testServiceDefaultValue(ServiceType.SOUND);
+    }
+
+    @SmallTest
+    public void testGetBatterySaverPolicy_PolicyFullBackup_DefaultValueCorrect() {
+        testServiceDefaultValue(ServiceType.FULL_BACKUP);
+    }
+
+    @SmallTest
+    public void testGetBatterySaverPolicy_PolicyKeyValueBackup_DefaultValueCorrect() {
+        testServiceDefaultValue(ServiceType.KEYVALUE_BACKUP);
+    }
+
+    @SmallTest
+    public void testGetBatterySaverPolicy_PolicyAnimation_DefaultValueCorrect() {
+        testServiceDefaultValue(ServiceType.ANIMATION);
+    }
+
+    @SmallTest
+    public void testGetBatterySaverPolicy_PolicyBatteryStats_DefaultValueCorrect() {
+        testServiceDefaultValue(ServiceType.BATTERY_STATS);
+    }
+
+    @SmallTest
+    public void testGetBatterySaverPolicy_PolicyNetworkFirewall_DefaultValueCorrect() {
+        testServiceDefaultValue(ServiceType.NETWORK_FIREWALL);
+    }
+
+    @SmallTest
+    public void testGetBatterySaverPolicy_PolicyScreenBrightness_DefaultValueCorrect() {
+        testServiceDefaultValue(ServiceType.SCREEN_BRIGHTNESS);
+
+        PowerSaveState stateOn =
+                mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.SCREEN_BRIGHTNESS, true);
+        assertThat(stateOn.brightnessFactor).isWithin(PRECISION).of(DEFAULT_BRIGHTNESS_FACTOR);
+    }
+
+    @SmallTest
+    public void testGetBatterySaverPolicy_PolicyGps_DefaultValueCorrect() {
+        testServiceDefaultValue(ServiceType.GPS);
+
+        PowerSaveState stateOn =
+                mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.GPS, true);
+        assertThat(stateOn.gpsMode).isEqualTo(DEFAULT_GPS_MODE);
+    }
+
+    @SmallTest
+    public void testUpdateConstants_getCorrectData() {
+        mBatterySaverPolicy.updateConstants(BATTERY_SAVER_CONSTANTS);
+
+        final PowerSaveState vibrationState =
+                mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.VIBRATION, BATTERY_SAVER_ON);
+        assertThat(vibrationState.batterySaverEnabled).isTrue();
+
+        final PowerSaveState animationState =
+                mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.ANIMATION, BATTERY_SAVER_ON);
+        assertThat(animationState.batterySaverEnabled).isFalse();
+
+        final PowerSaveState soundState =
+                mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.SOUND, BATTERY_SAVER_ON);
+        assertThat(soundState.batterySaverEnabled).isTrue();
+
+        final PowerSaveState networkState = mBatterySaverPolicy.getBatterySaverPolicy(
+                ServiceType.NETWORK_FIREWALL, BATTERY_SAVER_ON);
+        assertThat(networkState.batterySaverEnabled).isTrue();
+
+        final PowerSaveState screenState =
+                mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.SCREEN_BRIGHTNESS, BATTERY_SAVER_ON);
+        assertThat(screenState.batterySaverEnabled).isFalse();
+        assertThat(screenState.brightnessFactor).isWithin(PRECISION).of(BRIGHTNESS_FACTOR);
+
+        final PowerSaveState fullBackupState = mBatterySaverPolicy.getBatterySaverPolicy(
+                ServiceType.FULL_BACKUP, BATTERY_SAVER_ON);
+        assertThat(fullBackupState.batterySaverEnabled).isTrue();
+
+        final PowerSaveState keyValueBackupState = mBatterySaverPolicy.getBatterySaverPolicy(
+                ServiceType.KEYVALUE_BACKUP, BATTERY_SAVER_ON);
+        assertThat(keyValueBackupState.batterySaverEnabled).isFalse();
+
+        final PowerSaveState gpsState =
+                mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.GPS, BATTERY_SAVER_ON);
+        assertThat(gpsState.batterySaverEnabled).isTrue();
+        assertThat(gpsState.gpsMode).isEqualTo(GPS_MODE);
+    }
+
+    @SmallTest
+    public void testUpdateConstants_IncorrectData_NotCrash() {
+        //Should not crash
+        mBatterySaverPolicy.updateConstants(BATTERY_SAVER_INCORRECT_CONSTANTS);
+        mBatterySaverPolicy.updateConstants(null);
+    }
+
+    private void testServiceDefaultValue(@ServiceType int type) {
+        mBatterySaverPolicy.updateConstants("");
+        final PowerSaveState batterySaverStateOn =
+                mBatterySaverPolicy.getBatterySaverPolicy(type, BATTERY_SAVER_ON);
+        assertThat(batterySaverStateOn.batterySaverEnabled).isTrue();
+
+        final PowerSaveState batterySaverStateOff =
+                mBatterySaverPolicy.getBatterySaverPolicy(type, BATTERY_SAVER_OFF);
+        assertThat(batterySaverStateOff.batterySaverEnabled).isFalse();
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
new file mode 100644
index 0000000..967b0a4
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.power;
+
+import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
+import android.os.PowerSaveState;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.when;
+
+/**
+ * Tests for {@link com.android.server.power.PowerManagerService}
+ */
+public class PowerManagerServiceTest extends AndroidTestCase {
+    private static final float PRECISION = 0.001f;
+    private static final float BRIGHTNESS_FACTOR = 0.7f;
+    private static final boolean BATTERY_SAVER_ENABLED = true;
+
+    private @Mock BatterySaverPolicy mBatterySaverPolicy;
+    private PowerManagerService mService;
+    private PowerSaveState mPowerSaveState;
+    private DisplayPowerRequest mDisplayPowerRequest;
+
+    public void setUp() throws Exception {
+        super.setUp();
+        MockitoAnnotations.initMocks(this);
+
+        mPowerSaveState = new PowerSaveState.Builder()
+                .setBatterySaverEnabled(BATTERY_SAVER_ENABLED)
+                .setBrightnessFactor(BRIGHTNESS_FACTOR)
+                .build();
+        when(mBatterySaverPolicy.getBatterySaverPolicy(
+                eq(BatterySaverPolicy.ServiceType.SCREEN_BRIGHTNESS), anyBoolean()))
+                .thenReturn(mPowerSaveState);
+        mDisplayPowerRequest = new DisplayPowerRequest();
+        mService = new PowerManagerService(getContext(), mBatterySaverPolicy);
+    }
+
+    @SmallTest
+    public void testUpdatePowerScreenPolicy_UpdateDisplayPowerRequest() {
+        mService.updatePowerRequestFromBatterySaverPolicy(mDisplayPowerRequest);
+        assertThat(mDisplayPowerRequest.lowPowerMode).isEqualTo(BATTERY_SAVER_ENABLED);
+        assertThat(mDisplayPowerRequest.screenLowPowerBrightnessFactor)
+                .isWithin(PRECISION).of(BRIGHTNESS_FACTOR);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/storage/AppCollectorTest.java b/services/tests/servicestests/src/com/android/server/storage/AppCollectorTest.java
index da22e77..8cf7c8a 100644
--- a/services/tests/servicestests/src/com/android/server/storage/AppCollectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/storage/AppCollectorTest.java
@@ -16,12 +16,15 @@
 
 package com.android.server.storage;
 
+import android.app.usage.StorageStats;
+import android.app.usage.StorageStatsManager;
 import android.content.pm.UserInfo;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageStatsObserver;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageStats;
+import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.storage.VolumeInfo;
 import android.test.AndroidTestCase;
@@ -53,6 +56,7 @@
     @Mock private Context mContext;
     @Mock private PackageManager mPm;
     @Mock private UserManager mUm;
+    @Mock private StorageStatsManager mSsm;
     private List<ApplicationInfo> mApps;
     private List<UserInfo> mUsers;
 
@@ -63,6 +67,7 @@
         mApps = new ArrayList<>();
         when(mContext.getPackageManager()).thenReturn(mPm);
         when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUm);
+        when(mContext.getSystemService(Context.STORAGE_STATS_SERVICE)).thenReturn(mSsm);
 
         // Set up the app list.
         when(mPm.getInstalledApplications(anyInt())).thenReturn(mApps);
@@ -100,39 +105,9 @@
         AppCollector collector = new AppCollector(mContext, volume);
         PackageStats stats = new PackageStats("com.test.app");
 
-        // Set up this to handle the asynchronous call to the PackageManager. This returns the
-        // package info for the specified package.
-        doAnswer(new Answer<Void>() {
-             @Override
-             public Void answer(InvocationOnMock invocation) {
-                 try {
-                     ((IPackageStatsObserver.Stub) invocation.getArguments()[2])
-                             .onGetStatsCompleted(stats, true);
-                 } catch (Exception e) {
-                     // We fail instead of just letting the exception fly because throwing
-                     // out of the callback like this on the background thread causes the test
-                     // runner to crash, rather than reporting the failure.
-                     fail();
-                 }
-                 return null;
-             }
-        }).when(mPm).getPackageSizeInfoAsUser(eq("com.test.app"), eq(0), any());
-
-
-        // Because getPackageStats is a blocking call, we block execution of the test until the
-        // call finishes. In order to finish the call, we need the above answer to execute.
-        List<PackageStats> myStats = new ArrayList<>();
-        CountDownLatch latch = new CountDownLatch(1);
-        new Thread(new Runnable() {
-            @Override
-            public void run() {
-                myStats.addAll(collector.getPackageStats(TIMEOUT));
-                latch.countDown();
-            }
-        }).start();
-        latch.await();
-
-        assertThat(myStats).containsExactly(stats);
+        when(mSsm.queryStatsForPackage(eq("testuuid"),
+                eq("com.test.app"), eq(UserHandle.of(0)))).thenReturn(new StorageStats());
+        assertThat(collector.getPackageStats(TIMEOUT)).containsExactly(stats);
     }
 
     @Test
@@ -151,44 +126,16 @@
         PackageStats otherStats = new PackageStats("com.test.app");
         otherStats.userHandle = 1;
 
-        // Set up this to handle the asynchronous call to the PackageManager. This returns the
-        // package info for our packages.
-        doAnswer(new Answer<Void>() {
-             @Override
-             public Void answer(InvocationOnMock invocation) {
-                 try {
-                     ((IPackageStatsObserver.Stub) invocation.getArguments()[2])
-                             .onGetStatsCompleted(stats, true);
+        when(mSsm.queryStatsForPackage(eq("testuuid"),
+                eq("com.test.app"), eq(UserHandle.of(0)))).thenReturn(new StorageStats());
+        when(mSsm.queryStatsForPackage(eq("testuuid"),
+                eq("com.test.app"), eq(UserHandle.of(1)))).thenReturn(new StorageStats());
+        assertThat(collector.getPackageStats(TIMEOUT)).containsExactly(stats, otherStats);
+    }
 
-                     // Now callback for the other uid.
-                     ((IPackageStatsObserver.Stub) invocation.getArguments()[2])
-                             .onGetStatsCompleted(otherStats, true);
-                 } catch (Exception e) {
-                     // We fail instead of just letting the exception fly because throwing
-                     // out of the callback like this on the background thread causes the test
-                     // runner to crash, rather than reporting the failure.
-                     fail();
-                 }
-                 return null;
-             }
-        }).when(mPm).getPackageSizeInfoAsUser(eq("com.test.app"), eq(0), any());
-
-
-        // Because getPackageStats is a blocking call, we block execution of the test until the
-        // call finishes. In order to finish the call, we need the above answer to execute.
-        List<PackageStats> myStats = new ArrayList<>();
-        CountDownLatch latch = new CountDownLatch(1);
-        new Thread(new Runnable() {
-            @Override
-            public void run() {
-                myStats.addAll(collector.getPackageStats(TIMEOUT));
-                latch.countDown();
-            }
-        }).start();
-        latch.await();
-
-        // This should
-        assertThat(myStats).containsAllOf(stats, otherStats);
+    @Test(expected=NullPointerException.class)
+    public void testNullVolumeShouldCauseNPE() throws Exception {
+        AppCollector collector = new AppCollector(mContext, null);
     }
 
     private void addApplication(String packageName, String uuid) {
diff --git a/services/tests/servicestests/src/com/android/server/storage/CacheQuotaStrategyTest.java b/services/tests/servicestests/src/com/android/server/storage/CacheQuotaStrategyTest.java
new file mode 100644
index 0000000..1d62e01
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/storage/CacheQuotaStrategyTest.java
@@ -0,0 +1,128 @@
+/*
+ * 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.storage;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.usage.CacheQuotaHint;
+import android.test.AndroidTestCase;
+import android.util.Pair;
+
+import com.android.internal.util.FastXmlSerializer;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.io.ByteArrayInputStream;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(JUnit4.class)
+public class CacheQuotaStrategyTest extends AndroidTestCase {
+    StringWriter mWriter;
+    FastXmlSerializer mOut;
+
+    @Before
+    public void setUp() throws Exception {
+        mWriter = new StringWriter();
+        mOut = new FastXmlSerializer();
+        mOut.setOutput(mWriter);
+    }
+
+    @Test
+    public void testEmptyWrite() throws Exception {
+        CacheQuotaStrategy.saveToXml(mOut, new ArrayList<>(), 0);
+        mOut.flush();
+
+        assertThat(mWriter.toString()).isEqualTo(
+                "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" +
+                        "<cache-info previousBytes=\"0\" />\n");
+    }
+
+    @Test
+    public void testWriteOneQuota() throws Exception {
+        ArrayList<CacheQuotaHint> requests = new ArrayList<>();
+        requests.add(buildCacheQuotaHint("uuid", 0, 100));
+
+        CacheQuotaStrategy.saveToXml(mOut, requests, 1000);
+        mOut.flush();
+
+        assertThat(mWriter.toString()).isEqualTo(
+                "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" +
+                "<cache-info previousBytes=\"1000\">\n"
+                        + "<quota uuid=\"uuid\" uid=\"0\" bytes=\"100\" />\n"
+                        + "</cache-info>\n");
+    }
+
+    @Test
+    public void testWriteMultipleQuotas() throws Exception {
+        ArrayList<CacheQuotaHint> requests = new ArrayList<>();
+        requests.add(buildCacheQuotaHint("uuid", 0, 100));
+        requests.add(buildCacheQuotaHint("uuid2", 10, 250));
+
+        CacheQuotaStrategy.saveToXml(mOut, requests, 1000);
+        mOut.flush();
+
+        assertThat(mWriter.toString()).isEqualTo(
+                "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" +
+                        "<cache-info previousBytes=\"1000\">\n"
+                        + "<quota uuid=\"uuid\" uid=\"0\" bytes=\"100\" />\n"
+                        + "<quota uuid=\"uuid2\" uid=\"10\" bytes=\"250\" />\n"
+                        + "</cache-info>\n");
+    }
+
+    @Test
+    public void testNullUuidDoesntCauseCrash() throws Exception {
+        ArrayList<CacheQuotaHint> requests = new ArrayList<>();
+        requests.add(buildCacheQuotaHint(null, 0, 100));
+        requests.add(buildCacheQuotaHint(null, 10, 250));
+
+        CacheQuotaStrategy.saveToXml(mOut, requests, 1000);
+        mOut.flush();
+
+        assertThat(mWriter.toString()).isEqualTo(
+                "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" +
+                        "<cache-info previousBytes=\"1000\">\n"
+                        + "<quota uid=\"0\" bytes=\"100\" />\n"
+                        + "<quota uid=\"10\" bytes=\"250\" />\n"
+                        + "</cache-info>\n");
+    }
+
+    @Test
+    public void testReadMultipleQuotas() throws Exception {
+        String input = "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+                + "<cache-info previousBytes=\"1000\">\n"
+                + "<quota uuid=\"uuid\" uid=\"0\" bytes=\"100\" />\n"
+                + "<quota uuid=\"uuid2\" uid=\"10\" bytes=\"250\" />\n"
+                + "</cache-info>\n";
+
+        Pair<Long, List<CacheQuotaHint>> output =
+                CacheQuotaStrategy.readFromXml(new ByteArrayInputStream(input.getBytes("UTF-8")));
+
+        assertThat(output.first).isEqualTo(1000);
+        assertThat(output.second).containsExactly(buildCacheQuotaHint("uuid", 0, 100),
+                buildCacheQuotaHint("uuid2", 10, 250));
+    }
+
+    private CacheQuotaHint buildCacheQuotaHint(String volumeUuid, int uid, long quota) {
+        return new CacheQuotaHint.Builder()
+                .setVolumeUuid(volumeUuid).setUid(uid).setQuota(quota).build();
+    }
+}
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java b/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java
index 0bd014c..42ddedf 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java
@@ -45,12 +45,12 @@
         final int userId = 0;
         AppIdleHistory aih = new AppIdleHistory(mStorageDir, 0);
 
-        aih.updateDisplayLocked(true, /* elapsedRealtime= */ 1000);
-        aih.updateDisplayLocked(false, /* elapsedRealtime= */ 2000);
+        aih.updateDisplay(true, /* elapsedRealtime= */ 1000);
+        aih.updateDisplay(false, /* elapsedRealtime= */ 2000);
         // Screen On time file should be written right away
         assertTrue(aih.getScreenOnTimeFile().exists());
 
-        aih.writeAppIdleTimesLocked(userId);
+        aih.writeAppIdleTimes(userId);
         // stats file should be written now
         assertTrue(new File(new File(mStorageDir, "users/" + userId),
                 AppIdleHistory.APP_IDLE_FILENAME).exists());
@@ -58,43 +58,43 @@
 
     public void testScreenOnTime() {
         AppIdleHistory aih = new AppIdleHistory(mStorageDir, 1000);
-        aih.updateDisplayLocked(false, 2000);
-        assertEquals(aih.getScreenOnTimeLocked(2000), 0);
-        aih.updateDisplayLocked(true, 3000);
-        assertEquals(aih.getScreenOnTimeLocked(4000), 1000);
-        assertEquals(aih.getScreenOnTimeLocked(5000), 2000);
-        aih.updateDisplayLocked(false, 6000);
+        aih.updateDisplay(false, 2000);
+        assertEquals(aih.getScreenOnTime(2000), 0);
+        aih.updateDisplay(true, 3000);
+        assertEquals(aih.getScreenOnTime(4000), 1000);
+        assertEquals(aih.getScreenOnTime(5000), 2000);
+        aih.updateDisplay(false, 6000);
         // Screen on time should not keep progressing with screen is off
-        assertEquals(aih.getScreenOnTimeLocked(7000), 3000);
-        assertEquals(aih.getScreenOnTimeLocked(8000), 3000);
-        aih.writeAppIdleDurationsLocked();
+        assertEquals(aih.getScreenOnTime(7000), 3000);
+        assertEquals(aih.getScreenOnTime(8000), 3000);
+        aih.writeAppIdleDurations();
 
         // Check if the screen on time is persisted across instantiations
         AppIdleHistory aih2 = new AppIdleHistory(mStorageDir, 0);
-        assertEquals(aih2.getScreenOnTimeLocked(11000), 3000);
-        aih2.updateDisplayLocked(true, 4000);
-        aih2.updateDisplayLocked(false, 5000);
-        assertEquals(aih2.getScreenOnTimeLocked(13000), 4000);
+        assertEquals(aih2.getScreenOnTime(11000), 3000);
+        aih2.updateDisplay(true, 4000);
+        aih2.updateDisplay(false, 5000);
+        assertEquals(aih2.getScreenOnTime(13000), 4000);
     }
 
     public void testPackageEvents() {
         AppIdleHistory aih = new AppIdleHistory(mStorageDir, 1000);
         aih.setThresholds(4000, 1000);
-        aih.updateDisplayLocked(true, 1000);
+        aih.updateDisplay(true, 1000);
         // App is not-idle by default
-        assertFalse(aih.isIdleLocked(PACKAGE_1, 0, 1500));
+        assertFalse(aih.isIdle(PACKAGE_1, 0, 1500));
         // Still not idle
-        assertFalse(aih.isIdleLocked(PACKAGE_1, 0, 3000));
+        assertFalse(aih.isIdle(PACKAGE_1, 0, 3000));
         // Idle now
-        assertTrue(aih.isIdleLocked(PACKAGE_1, 0, 8000));
+        assertTrue(aih.isIdle(PACKAGE_1, 0, 8000));
         // Not idle
-        assertFalse(aih.isIdleLocked(PACKAGE_2, 0, 9000));
+        assertFalse(aih.isIdle(PACKAGE_2, 0, 9000));
 
         // Screen off
-        aih.updateDisplayLocked(false, 9100);
+        aih.updateDisplay(false, 9100);
         // Still idle after 10 seconds because screen hasn't been on long enough
-        assertFalse(aih.isIdleLocked(PACKAGE_2, 0, 20000));
-        aih.updateDisplayLocked(true, 21000);
-        assertTrue(aih.isIdleLocked(PACKAGE_2, 0, 23000));
+        assertFalse(aih.isIdle(PACKAGE_2, 0, 20000));
+        aih.updateDisplay(true, 21000);
+        assertTrue(aih.isIdle(PACKAGE_2, 0, 23000));
     }
 }
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/usage/StorageStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/usage/StorageStatsServiceTest.java
new file mode 100644
index 0000000..baee865
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/usage/StorageStatsServiceTest.java
@@ -0,0 +1,55 @@
+/*
+ * 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.usage;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.provider.Settings;
+import android.test.AndroidTestCase;
+import android.test.mock.MockContentResolver;
+
+import com.android.internal.util.test.FakeSettingsProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class StorageStatsServiceTest extends AndroidTestCase {
+    private MockContentResolver mContentResolver;
+
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        mContentResolver = new MockContentResolver();
+        mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
+    }
+
+    @Test
+    public void testDontRunWhenDisabledFromSettingsGlobal() throws Exception {
+        Settings.Global.putInt(mContentResolver, Settings.Global.ENABLE_CACHE_QUOTA_CALCULATION, 0);
+
+        assertThat(StorageStatsService.isCacheQuotaCalculationsEnabled(mContentResolver)).isFalse();
+    }
+
+    @Test
+    public void testCalculationTaskIsEnabledByDefault() throws Exception {
+        // Put null to act as though there is no value here.
+        Settings.Global.putString(
+                mContentResolver, Settings.Global.ENABLE_CACHE_QUOTA_CALCULATION, null);
+
+        assertThat(StorageStatsService.isCacheQuotaCalculationsEnabled(mContentResolver)).isTrue();
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
index 04e5583..2ccaefc 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
@@ -138,19 +138,18 @@
 
     @Test
     public void testReparent() throws Exception {
+        final StackWindowController stackController =
+            createStackControllerOnDisplay(sDisplayContent);
         final TestTaskWindowContainerController taskController1 =
-                new TestTaskWindowContainerController(
-                        createStackControllerOnDisplay(sDisplayContent));
+                new TestTaskWindowContainerController(stackController);
         final TestAppWindowContainerController appWindowController1 = createAppWindowController(
                 taskController1);
         final TestTaskWindowContainerController taskController2 =
-                new TestTaskWindowContainerController(
-                        createStackControllerOnDisplay(sDisplayContent));
+                new TestTaskWindowContainerController(stackController);
         final TestAppWindowContainerController appWindowController2 = createAppWindowController(
                 taskController2);
         final TestTaskWindowContainerController taskController3 =
-                new TestTaskWindowContainerController(
-                        createStackControllerOnDisplay(sDisplayContent));
+                new TestTaskWindowContainerController(stackController);
 
         try {
             appWindowController1.reparent(taskController1, 0);
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
index 30f99e5..e589bc7 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -16,24 +16,26 @@
 
 package com.android.server.wm;
 
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 import android.content.res.Configuration;
-import android.hardware.display.DisplayManagerGlobal;
 import android.platform.test.annotations.Presubmit;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
-import android.view.Display;
-import android.view.DisplayInfo;
 
-import java.util.ArrayList;
-
-import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
-import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
-import static org.junit.Assert.assertEquals;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
 
 /**
  * Tests for the {@link DisplayContent} class.
@@ -52,40 +54,19 @@
                 sDisplayContent, "exiting app");
         final AppWindowToken exitingAppToken = exitingAppWindow.mAppToken;
         exitingAppToken.mIsExiting = true;
-        exitingAppToken.mTask.mStack.mExitingAppTokens.add(exitingAppToken);
+        exitingAppToken.getTask().mStack.mExitingAppTokens.add(exitingAppToken);
 
-        final ArrayList<WindowState> windows = new ArrayList();
-
-        // Test forward traversal.
-        sDisplayContent.forAllWindows(w -> {windows.add(w);}, false /* traverseTopToBottom */);
-
-        assertEquals(sWallpaperWindow, windows.get(0));
-        assertEquals(exitingAppWindow, windows.get(1));
-        assertEquals(sChildAppWindowBelow, windows.get(2));
-        assertEquals(sAppWindow, windows.get(3));
-        assertEquals(sChildAppWindowAbove, windows.get(4));
-        assertEquals(sDockedDividerWindow, windows.get(5));
-        assertEquals(sStatusBarWindow, windows.get(6));
-        assertEquals(sNavBarWindow, windows.get(7));
-        assertEquals(sImeWindow, windows.get(8));
-        assertEquals(sImeDialogWindow, windows.get(9));
-
-        // Test backward traversal.
-        windows.clear();
-        sDisplayContent.forAllWindows(w -> {windows.add(w);}, true /* traverseTopToBottom */);
-
-        assertEquals(sWallpaperWindow, windows.get(9));
-        assertEquals(exitingAppWindow, windows.get(8));
-        assertEquals(sChildAppWindowBelow, windows.get(7));
-        assertEquals(sAppWindow, windows.get(6));
-        assertEquals(sChildAppWindowAbove, windows.get(5));
-        assertEquals(sDockedDividerWindow, windows.get(4));
-        assertEquals(sStatusBarWindow, windows.get(3));
-        assertEquals(sNavBarWindow, windows.get(2));
-        assertEquals(sImeWindow, windows.get(1));
-        assertEquals(sImeDialogWindow, windows.get(0));
-
-        exitingAppWindow.removeImmediately();
+        assertForAllWindowsOrder(Arrays.asList(
+                sWallpaperWindow,
+                exitingAppWindow,
+                sChildAppWindowBelow,
+                sAppWindow,
+                sChildAppWindowAbove,
+                sDockedDividerWindow,
+                sStatusBarWindow,
+                sNavBarWindow,
+                sImeWindow,
+                sImeDialogWindow));
     }
 
     @Test
@@ -95,78 +76,49 @@
 
         sWm.mInputMethodTarget = imeAppTarget;
 
-        final ArrayList<WindowState> windows = new ArrayList();
+        assertForAllWindowsOrder(Arrays.asList(
+                sWallpaperWindow,
+                sChildAppWindowBelow,
+                sAppWindow,
+                sChildAppWindowAbove,
+                imeAppTarget,
+                sImeWindow,
+                sImeDialogWindow,
+                sDockedDividerWindow,
+                sStatusBarWindow,
+                sNavBarWindow));
+    }
 
-        // Test forward traversal.
-        sDisplayContent.forAllWindows(w -> {windows.add(w);}, false /* traverseTopToBottom */);
+    @Test
+    public void testForAllWindows_WithChildWindowImeTarget() throws Exception {
+        sWm.mInputMethodTarget = sChildAppWindowAbove;
 
-        assertEquals(sWallpaperWindow, windows.get(0));
-        assertEquals(sChildAppWindowBelow, windows.get(1));
-        assertEquals(sAppWindow, windows.get(2));
-        assertEquals(sChildAppWindowAbove, windows.get(3));
-        assertEquals(imeAppTarget, windows.get(4));
-        assertEquals(sImeWindow, windows.get(5));
-        assertEquals(sImeDialogWindow, windows.get(6));
-        assertEquals(sDockedDividerWindow, windows.get(7));
-        assertEquals(sStatusBarWindow, windows.get(8));
-        assertEquals(sNavBarWindow, windows.get(9));
-
-        // Test backward traversal.
-        windows.clear();
-        sDisplayContent.forAllWindows(w -> {windows.add(w);}, true /* traverseTopToBottom */);
-
-        assertEquals(sWallpaperWindow, windows.get(9));
-        assertEquals(sChildAppWindowBelow, windows.get(8));
-        assertEquals(sAppWindow, windows.get(7));
-        assertEquals(sChildAppWindowAbove, windows.get(6));
-        assertEquals(imeAppTarget, windows.get(5));
-        assertEquals(sImeWindow, windows.get(4));
-        assertEquals(sImeDialogWindow, windows.get(3));
-        assertEquals(sDockedDividerWindow, windows.get(2));
-        assertEquals(sStatusBarWindow, windows.get(1));
-        assertEquals(sNavBarWindow, windows.get(0));
-
-        // Clean-up
-        sWm.mInputMethodTarget = null;
-        imeAppTarget.removeImmediately();
+        assertForAllWindowsOrder(Arrays.asList(
+                sWallpaperWindow,
+                sChildAppWindowBelow,
+                sAppWindow,
+                sChildAppWindowAbove,
+                sImeWindow,
+                sImeDialogWindow,
+                sDockedDividerWindow,
+                sStatusBarWindow,
+                sNavBarWindow));
     }
 
     @Test
     public void testForAllWindows_WithStatusBarImeTarget() throws Exception {
-
         sWm.mInputMethodTarget = sStatusBarWindow;
 
-        final ArrayList<WindowState> windows = new ArrayList();
-
-        // Test forward traversal.
-        sDisplayContent.forAllWindows(w -> {windows.add(w);}, false /* traverseTopToBottom */);
-
-        assertEquals(sWallpaperWindow, windows.get(0));
-        assertEquals(sChildAppWindowBelow, windows.get(1));
-        assertEquals(sAppWindow, windows.get(2));
-        assertEquals(sChildAppWindowAbove, windows.get(3));
-        assertEquals(sDockedDividerWindow, windows.get(4));
-        assertEquals(sStatusBarWindow, windows.get(5));
-        assertEquals(sImeWindow, windows.get(6));
-        assertEquals(sImeDialogWindow, windows.get(7));
-        assertEquals(sNavBarWindow, windows.get(8));
-
-        // Test backward traversal.
-        windows.clear();
-        sDisplayContent.forAllWindows(w -> {windows.add(w);}, true /* traverseTopToBottom */);
-
-        assertEquals(sWallpaperWindow, windows.get(8));
-        assertEquals(sChildAppWindowBelow, windows.get(7));
-        assertEquals(sAppWindow, windows.get(6));
-        assertEquals(sChildAppWindowAbove, windows.get(5));
-        assertEquals(sDockedDividerWindow, windows.get(4));
-        assertEquals(sStatusBarWindow, windows.get(3));
-        assertEquals(sImeWindow, windows.get(2));
-        assertEquals(sImeDialogWindow, windows.get(1));
-        assertEquals(sNavBarWindow, windows.get(0));
-
-        // Clean-up
-        sWm.mInputMethodTarget = null;
+        assertForAllWindowsOrder(Arrays.asList(
+                sWallpaperWindow,
+                sChildAppWindowBelow,
+                sAppWindow,
+                sChildAppWindowAbove,
+                sDockedDividerWindow,
+                sStatusBarWindow,
+                sImeWindow,
+                sImeDialogWindow,
+                sNavBarWindow));
     }
 
     @Test
@@ -176,38 +128,50 @@
         final WindowState voiceInteractionWindow = createWindow(null, TYPE_VOICE_INTERACTION,
                 sDisplayContent, "voiceInteractionWindow");
 
-        final ArrayList<WindowState> windows = new ArrayList();
+        assertForAllWindowsOrder(Arrays.asList(
+                sWallpaperWindow,
+                sChildAppWindowBelow,
+                sAppWindow,
+                sChildAppWindowAbove,
+                sDockedDividerWindow,
+                voiceInteractionWindow,
+                sStatusBarWindow,
+                sNavBarWindow,
+                sImeWindow,
+                sImeDialogWindow));
+    }
 
-        // Test forward traversal.
-        sDisplayContent.forAllWindows(w -> {windows.add(w);}, false /* traverseTopToBottom */);
+    @Test
+    public void testComputeImeTarget() throws Exception {
+        // Verify that an app window can be an ime target.
+        final WindowState appWin = createWindow(null, TYPE_APPLICATION, sDisplayContent, "appWin");
+        appWin.setHasSurface(true);
+        assertTrue(appWin.canBeImeTarget());
+        sWm.mInputMethodTargetCandidate = appWin.mClient.asBinder();
+        WindowState imeTarget = sDisplayContent.computeImeTarget(false /* updateImeTarget */);
+        assertEquals(appWin, imeTarget);
 
-        assertEquals(sWallpaperWindow, windows.get(0));
-        assertEquals(sChildAppWindowBelow, windows.get(1));
-        assertEquals(sAppWindow, windows.get(2));
-        assertEquals(sChildAppWindowAbove, windows.get(3));
-        assertEquals(sDockedDividerWindow, windows.get(4));
-        assertEquals(voiceInteractionWindow, windows.get(5));
-        assertEquals(sStatusBarWindow, windows.get(6));
-        assertEquals(sNavBarWindow, windows.get(7));
-        assertEquals(sImeWindow, windows.get(8));
-        assertEquals(sImeDialogWindow, windows.get(9));
+        // Verify that an child window can be an ime target.
+        final WindowState childWin = createWindow(appWin,
+                TYPE_APPLICATION_ATTACHED_DIALOG, "childWin");
+        childWin.setHasSurface(true);
+        assertTrue(childWin.canBeImeTarget());
+        imeTarget = sDisplayContent.computeImeTarget(false /* updateImeTarget */);
+        assertEquals(childWin, imeTarget);
 
-        // Test backward traversal.
-        windows.clear();
-        sDisplayContent.forAllWindows(w -> {windows.add(w);}, true /* traverseTopToBottom */);
+        final WindowState appWin2 =
+                createWindow(null, TYPE_APPLICATION, sDisplayContent, "appWin2");
+        appWin2.setHasSurface(true);
+        assertTrue(appWin2.canBeImeTarget());
+        // Verify that the IME target isn't adjusted since mInputMethodTargetCandidate didn't change
+        // to the new app.
+        imeTarget = sDisplayContent.computeImeTarget(false /* updateImeTarget */);
+        assertNotEquals(appWin2, imeTarget);
 
-        assertEquals(sWallpaperWindow, windows.get(9));
-        assertEquals(sChildAppWindowBelow, windows.get(8));
-        assertEquals(sAppWindow, windows.get(7));
-        assertEquals(sChildAppWindowAbove, windows.get(6));
-        assertEquals(sDockedDividerWindow, windows.get(5));
-        assertEquals(voiceInteractionWindow, windows.get(4));
-        assertEquals(sStatusBarWindow, windows.get(3));
-        assertEquals(sNavBarWindow, windows.get(2));
-        assertEquals(sImeWindow, windows.get(1));
-        assertEquals(sImeDialogWindow, windows.get(0));
-
-        voiceInteractionWindow.removeImmediately();
+        sWm.mInputMethodTargetCandidate = appWin2.mClient.asBinder();
+        // Verify app is not IME target since its token is set as a candidate.
+        imeTarget = sDisplayContent.computeImeTarget(false /* updateImeTarget */);
+        assertEquals(appWin2, imeTarget);
     }
 
     /**
@@ -284,4 +248,24 @@
         assertEquals(currentOverrideConfig.densityDpi, globalConfig.densityDpi);
         assertEquals(currentOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
     }
+
+    private void assertForAllWindowsOrder(List<WindowState> expectedWindows) {
+        final LinkedList<WindowState> actualWindows = new LinkedList();
+
+        // Test forward traversal.
+        sDisplayContent.forAllWindows(actualWindows::addLast, false /* traverseTopToBottom */);
+        assertEquals(expectedWindows.size(), actualWindows.size());
+        for (WindowState w : expectedWindows) {
+            assertEquals(w, actualWindows.pollFirst());
+        }
+        assertTrue(actualWindows.isEmpty());
+
+        // Test backward traversal.
+        sDisplayContent.forAllWindows(actualWindows::addLast, true /* traverseTopToBottom */);
+        assertEquals(expectedWindows.size(), actualWindows.size());
+        for (WindowState w : expectedWindows) {
+            assertEquals(w, actualWindows.pollLast());
+        }
+        assertTrue(actualWindows.isEmpty());
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java
index 5dff997..58d277b 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java
@@ -49,7 +49,7 @@
         final ArraySet<Task> closingTasks = new ArraySet<>();
         sWm.mTaskSnapshotController.getClosingTasks(closingApps, closingTasks);
         assertEquals(1, closingTasks.size());
-        assertEquals(closingWindow.mAppToken.mTask, closingTasks.valueAt(0));
+        assertEquals(closingWindow.mAppToken.getTask(), closingTasks.valueAt(0));
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index dd45d9b..c8b73f1 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -17,9 +17,13 @@
 package com.android.server.wm;
 
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.doAnswer;
+
+import android.os.PowerSaveState;
 import org.mockito.invocation.InvocationOnMock;
 
 import android.annotation.Nullable;
@@ -67,6 +71,10 @@
             if (LocalServices.getService(PowerManagerInternal.class) == null) {
                 LocalServices.addService(PowerManagerInternal.class,
                         mock(PowerManagerInternal.class));
+                final PowerManagerInternal pm =
+                        LocalServices.getService(PowerManagerInternal.class);
+                PowerSaveState state = new PowerSaveState.Builder().build();
+                doReturn(state).when(pm).getLowPowerState(anyInt());
             }
             if (LocalServices.getService(ActivityManagerInternal.class) == null) {
                 LocalServices.addService(ActivityManagerInternal.class,
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
index df35b7ee..5f51898 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
@@ -23,10 +23,17 @@
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
+import java.util.LinkedList;
+
 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
 import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -167,4 +174,34 @@
         assertFalse(appWindow.canBeImeTarget());
         assertFalse(imeWindow.canBeImeTarget());
     }
+
+    @Test
+    public void testGetWindow() throws Exception {
+        final WindowState root = createWindow(null, TYPE_APPLICATION, "root");
+        final WindowState mediaChild = createWindow(root, TYPE_APPLICATION_MEDIA, "mediaChild");
+        final WindowState mediaOverlayChild = createWindow(root,
+                TYPE_APPLICATION_MEDIA_OVERLAY, "mediaOverlayChild");
+        final WindowState attachedDialogChild = createWindow(root,
+                TYPE_APPLICATION_ATTACHED_DIALOG, "attachedDialogChild");
+        final WindowState subPanelChild = createWindow(root,
+                TYPE_APPLICATION_SUB_PANEL, "subPanelChild");
+        final WindowState aboveSubPanelChild = createWindow(root,
+                TYPE_APPLICATION_ABOVE_SUB_PANEL, "aboveSubPanelChild");
+
+        final LinkedList<WindowState> windows = new LinkedList();
+
+        root.getWindow(w -> {
+            windows.addLast(w);
+            return false;
+        });
+
+        // getWindow should have returned candidate windows in z-order.
+        assertEquals(aboveSubPanelChild, windows.pollFirst());
+        assertEquals(subPanelChild, windows.pollFirst());
+        assertEquals(attachedDialogChild, windows.pollFirst());
+        assertEquals(root, windows.pollFirst());
+        assertEquals(mediaOverlayChild, windows.pollFirst());
+        assertEquals(mediaChild, windows.pollFirst());
+        assertTrue(windows.isEmpty());
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index e5e3512..18c48b7 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -44,6 +44,7 @@
 import static android.content.res.Configuration.EMPTY;
 import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
@@ -60,6 +61,7 @@
 import com.android.server.AttributeCache;
 
 import java.util.HashSet;
+import java.util.LinkedList;
 
 /**
  * Common base class for window manager unit test classes.
@@ -67,7 +69,6 @@
 class WindowTestsBase {
     static WindowManagerService sWm = null;
     static TestWindowManagerPolicy sPolicy = null;
-    private final static IWindow sIWindow = new TestIWindow();
     private final static Session sMockSession = mock(Session.class);
     private static int sNextDisplayId = Display.DEFAULT_DISPLAY + 1;
     static int sNextStackId = FIRST_DYNAMIC_STACK_ID;
@@ -120,6 +121,7 @@
         sCommonWindows = new HashSet();
         sWallpaperWindow = createCommonWindow(null, TYPE_WALLPAPER, "wallpaperWindow");
         sImeWindow = createCommonWindow(null, TYPE_INPUT_METHOD, "sImeWindow");
+        sWm.mInputMethodWindow = sImeWindow;
         sImeDialogWindow = createCommonWindow(null, TYPE_INPUT_METHOD_DIALOG, "sImeDialogWindow");
         sStatusBarWindow = createCommonWindow(null, TYPE_STATUS_BAR, "sStatusBarWindow");
         sNavBarWindow = createCommonWindow(null, TYPE_NAVIGATION_BAR, "sNavBarWindow");
@@ -133,31 +135,26 @@
 
     @After
     public void tearDown() throws Exception {
+        final LinkedList<WindowState> nonCommonWindows = new LinkedList();
         sWm.mRoot.forAllWindows(w -> {
             if (!sCommonWindows.contains(w)) {
-                w.removeImmediately();
+                nonCommonWindows.addLast(w);
             }
         }, true /* traverseTopToBottom */);
+
+        while (!nonCommonWindows.isEmpty()) {
+            nonCommonWindows.pollLast().removeImmediately();
+        }
+
+        sWm.mInputMethodTarget = null;
+        sWm.mInputMethodTargetCandidate = null;
     }
 
     private static WindowState createCommonWindow(WindowState parent, int type, String name) {
         final WindowState win = createWindow(parent, type, name);
         sCommonWindows.add(win);
-        return win;
-    }
-
-    /**
-     * Creates a window for a task on a the given {@param stackId}.
-     */
-    private WindowState createStackWindow(int stackId, String name) {
-        final StackWindowController stackController = createStackControllerOnStackOnDisplay(stackId,
-                sDisplayContent);
-        final TestTaskWindowContainerController taskController =
-                new TestTaskWindowContainerController(stackController);
-        TestAppWindowToken appWinToken = new TestAppWindowToken(sDisplayContent);
-        appWinToken.mTask = taskController.mContainer;
-        final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, name);
-        win.mAppToken = appWinToken;
+        // Prevent common windows from been IMe targets
+        win.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
         return win;
     }
 
@@ -225,11 +222,12 @@
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(type);
         attrs.setTitle(name);
 
-        final WindowState w = new WindowState(sWm, sMockSession, sIWindow, token, parent, OP_NONE,
-                0, attrs, 0, 0, ownerCanAddInternalSystemWindow);
+        final WindowState w = new WindowState(sWm, sMockSession, new TestIWindow(), token, parent,
+                OP_NONE, 0, attrs, 0, 0, ownerCanAddInternalSystemWindow);
         // TODO: Probably better to make this call in the WindowState ctor to avoid errors with
         // adding it to the token...
         token.addWindow(w);
+        sWm.mWindowMap.put(w.mClient.asBinder(), w);
         return w;
     }
 
@@ -267,6 +265,7 @@
 
     /* Used so we can gain access to some protected members of the {@link WindowToken} class */
     static class TestWindowToken extends WindowToken {
+        int adj = 0;
 
         TestWindowToken(int type, DisplayContent dc) {
             this(type, dc, false /* persistOnEmpty */);
@@ -284,6 +283,11 @@
         boolean hasWindow(WindowState w) {
             return mChildren.contains(w);
         }
+
+        @Override
+        int getAnimLayerAdjustment() {
+            return adj;
+        }
     }
 
     /** Used so we can gain access to some protected members of the {@link AppWindowToken} class. */
@@ -451,8 +455,9 @@
         boolean resizeReported;
 
         TestWindowState(WindowManager.LayoutParams attrs, WindowToken token) {
-            super(sWm, sMockSession, sIWindow, token, null, OP_NONE, 0, attrs, 0, 0,
+            super(sWm, sMockSession, new TestIWindow(), token, null, OP_NONE, 0, attrs, 0, 0,
                     false /* ownerCanAddInternalSystemWindow */);
+            sWm.mWindowMap.put(mClient.asBinder(), this);
         }
 
         @Override
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
index 0c053b9..babb6d9 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
@@ -102,14 +102,28 @@
         final WindowState window2 = createWindow(null, TYPE_APPLICATION, token, "window2");
         final WindowState window3 = createWindow(null, TYPE_APPLICATION, token, "window3");
 
-        final int adj = 50;
-        final int window2StartLayer = window2.mLayer = 100;
-        final int window3StartLayer = window3.mLayer = 200;
-        final int highestLayer = token.adjustAnimLayer(adj);
+        window2.mLayer = 100;
+        window3.mLayer = 200;
 
-        assertEquals(adj, window1.mWinAnimator.mAnimLayer);
-        assertEquals(adj, window11.mWinAnimator.mAnimLayer);
-        assertEquals(adj, window12.mWinAnimator.mAnimLayer);
+        // We assign layers once, to get the base values computed by
+        // the controller.
+        sLayersController.assignWindowLayers(sDisplayContent);
+
+        final int window1StartLayer = window1.mWinAnimator.mAnimLayer;
+        final int window11StartLayer = window11.mWinAnimator.mAnimLayer;
+        final int window12StartLayer = window12.mWinAnimator.mAnimLayer;
+        final int window2StartLayer = window2.mWinAnimator.mAnimLayer;
+        final int window3StartLayer = window3.mWinAnimator.mAnimLayer;
+
+        // Then we set an adjustment, and assign them again, they should
+        // be offset.
+        int adj = token.adj = 50;
+        sLayersController.assignWindowLayers(sDisplayContent);
+        final int highestLayer = token.getHighestAnimLayer();
+
+        assertEquals(window1StartLayer + adj, window1.mWinAnimator.mAnimLayer);
+        assertEquals(window11StartLayer + adj, window11.mWinAnimator.mAnimLayer);
+        assertEquals(window12StartLayer + adj, window12.mWinAnimator.mAnimLayer);
         assertEquals(window2StartLayer + adj, window2.mWinAnimator.mAnimLayer);
         assertEquals(window3StartLayer + adj, window3.mWinAnimator.mAnimLayer);
         assertEquals(window3StartLayer + adj, highestLayer);
diff --git a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
index ea45bd1..fd335c3 100644
--- a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
+++ b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
@@ -508,6 +508,13 @@
         return actualShortcuts;
     }
 
+    public static List<ShortcutInfo> assertAllChooser(List<ShortcutInfo> actualShortcuts) {
+        for (ShortcutInfo s : actualShortcuts) {
+            assertTrue("ID " + s.getId(), s.isChooser());
+        }
+        return actualShortcuts;
+    }
+
     public static List<ShortcutInfo> assertAllPinned(List<ShortcutInfo> actualShortcuts) {
         for (ShortcutInfo s : actualShortcuts) {
             assertTrue("ID " + s.getId(), s.isPinned());
diff --git a/services/usage/java/com/android/server/usage/AppIdleHistory.java b/services/usage/java/com/android/server/usage/AppIdleHistory.java
index f69dae4..f298559 100644
--- a/services/usage/java/com/android/server/usage/AppIdleHistory.java
+++ b/services/usage/java/com/android/server/usage/AppIdleHistory.java
@@ -18,7 +18,6 @@
 
 import android.os.Environment;
 import android.os.SystemClock;
-import android.os.UserHandle;
 import android.util.ArrayMap;
 import android.util.AtomicFile;
 import android.util.Slog;
@@ -101,7 +100,7 @@
         mElapsedSnapshot = elapsedRealtime;
         mScreenOnSnapshot = elapsedRealtime;
         mStorageDir = storageDir;
-        readScreenOnTimeLocked();
+        readScreenOnTime();
     }
 
     public void setThresholds(long elapsedTimeThreshold, long screenOnTimeThreshold) {
@@ -109,7 +108,7 @@
         mScreenOnTimeThreshold = screenOnTimeThreshold;
     }
 
-    public void updateDisplayLocked(boolean screenOn, long elapsedRealtime) {
+    public void updateDisplay(boolean screenOn, long elapsedRealtime) {
         if (screenOn == mScreenOn) return;
 
         mScreenOn = screenOn;
@@ -122,7 +121,7 @@
         }
     }
 
-    public long getScreenOnTimeLocked(long elapsedRealtime) {
+    public long getScreenOnTime(long elapsedRealtime) {
         long screenOnTime = mScreenOnDuration;
         if (mScreenOn) {
             screenOnTime += elapsedRealtime - mScreenOnSnapshot;
@@ -135,7 +134,7 @@
         return new File(mStorageDir, "screen_on_time");
     }
 
-    private void readScreenOnTimeLocked() {
+    private void readScreenOnTime() {
         File screenOnTimeFile = getScreenOnTimeFile();
         if (screenOnTimeFile.exists()) {
             try {
@@ -146,11 +145,11 @@
             } catch (IOException | NumberFormatException e) {
             }
         } else {
-            writeScreenOnTimeLocked();
+            writeScreenOnTime();
         }
     }
 
-    private void writeScreenOnTimeLocked() {
+    private void writeScreenOnTime() {
         AtomicFile screenOnTimeFile = new AtomicFile(getScreenOnTimeFile());
         FileOutputStream fos = null;
         try {
@@ -166,30 +165,30 @@
     /**
      * To be called periodically to keep track of elapsed time when app idle times are written
      */
-    public void writeAppIdleDurationsLocked() {
+    public void writeAppIdleDurations() {
         final long elapsedRealtime = SystemClock.elapsedRealtime();
         // Only bump up and snapshot the elapsed time. Don't change screen on duration.
         mElapsedDuration += elapsedRealtime - mElapsedSnapshot;
         mElapsedSnapshot = elapsedRealtime;
-        writeScreenOnTimeLocked();
+        writeScreenOnTime();
     }
 
-    public void reportUsageLocked(String packageName, int userId, long elapsedRealtime) {
-        ArrayMap<String, PackageHistory> userHistory = getUserHistoryLocked(userId);
-        PackageHistory packageHistory = getPackageHistoryLocked(userHistory, packageName,
+    public void reportUsage(String packageName, int userId, long elapsedRealtime) {
+        ArrayMap<String, PackageHistory> userHistory = getUserHistory(userId);
+        PackageHistory packageHistory = getPackageHistory(userHistory, packageName,
                 elapsedRealtime);
 
         shiftHistoryToNow(userHistory, elapsedRealtime);
 
         packageHistory.lastUsedElapsedTime = mElapsedDuration
                 + (elapsedRealtime - mElapsedSnapshot);
-        packageHistory.lastUsedScreenTime = getScreenOnTimeLocked(elapsedRealtime);
+        packageHistory.lastUsedScreenTime = getScreenOnTime(elapsedRealtime);
         packageHistory.recent[HISTORY_SIZE - 1] = FLAG_LAST_STATE | FLAG_PARTIAL_ACTIVE;
     }
 
     public void setIdle(String packageName, int userId, long elapsedRealtime) {
-        ArrayMap<String, PackageHistory> userHistory = getUserHistoryLocked(userId);
-        PackageHistory packageHistory = getPackageHistoryLocked(userHistory, packageName,
+        ArrayMap<String, PackageHistory> userHistory = getUserHistory(userId);
+        PackageHistory packageHistory = getPackageHistory(userHistory, packageName,
                 elapsedRealtime);
 
         shiftHistoryToNow(userHistory, elapsedRealtime);
@@ -222,23 +221,23 @@
         mLastPeriod = thisPeriod;
     }
 
-    private ArrayMap<String, PackageHistory> getUserHistoryLocked(int userId) {
+    private ArrayMap<String, PackageHistory> getUserHistory(int userId) {
         ArrayMap<String, PackageHistory> userHistory = mIdleHistory.get(userId);
         if (userHistory == null) {
             userHistory = new ArrayMap<>();
             mIdleHistory.put(userId, userHistory);
-            readAppIdleTimesLocked(userId, userHistory);
+            readAppIdleTimes(userId, userHistory);
         }
         return userHistory;
     }
 
-    private PackageHistory getPackageHistoryLocked(ArrayMap<String, PackageHistory> userHistory,
+    private PackageHistory getPackageHistory(ArrayMap<String, PackageHistory> userHistory,
             String packageName, long elapsedRealtime) {
         PackageHistory packageHistory = userHistory.get(packageName);
         if (packageHistory == null) {
             packageHistory = new PackageHistory();
-            packageHistory.lastUsedElapsedTime = getElapsedTimeLocked(elapsedRealtime);
-            packageHistory.lastUsedScreenTime = getScreenOnTimeLocked(elapsedRealtime);
+            packageHistory.lastUsedElapsedTime = getElapsedTime(elapsedRealtime);
+            packageHistory.lastUsedScreenTime = getScreenOnTime(elapsedRealtime);
             userHistory.put(packageName, packageHistory);
         }
         return packageHistory;
@@ -248,41 +247,41 @@
         mIdleHistory.remove(userId);
     }
 
-    public boolean isIdleLocked(String packageName, int userId, long elapsedRealtime) {
-        ArrayMap<String, PackageHistory> userHistory = getUserHistoryLocked(userId);
+    public boolean isIdle(String packageName, int userId, long elapsedRealtime) {
+        ArrayMap<String, PackageHistory> userHistory = getUserHistory(userId);
         PackageHistory packageHistory =
-                getPackageHistoryLocked(userHistory, packageName, elapsedRealtime);
+                getPackageHistory(userHistory, packageName, elapsedRealtime);
         if (packageHistory == null) {
             return false; // Default to not idle
         } else {
-            return hasPassedThresholdsLocked(packageHistory, elapsedRealtime);
+            return hasPassedThresholds(packageHistory, elapsedRealtime);
         }
     }
 
-    private long getElapsedTimeLocked(long elapsedRealtime) {
+    private long getElapsedTime(long elapsedRealtime) {
         return (elapsedRealtime - mElapsedSnapshot + mElapsedDuration);
     }
 
-    public void setIdleLocked(String packageName, int userId, boolean idle, long elapsedRealtime) {
-        ArrayMap<String, PackageHistory> userHistory = getUserHistoryLocked(userId);
-        PackageHistory packageHistory = getPackageHistoryLocked(userHistory, packageName,
+    public void setIdle(String packageName, int userId, boolean idle, long elapsedRealtime) {
+        ArrayMap<String, PackageHistory> userHistory = getUserHistory(userId);
+        PackageHistory packageHistory = getPackageHistory(userHistory, packageName,
                 elapsedRealtime);
-        packageHistory.lastUsedElapsedTime = getElapsedTimeLocked(elapsedRealtime)
+        packageHistory.lastUsedElapsedTime = getElapsedTime(elapsedRealtime)
                 - mElapsedTimeThreshold;
-        packageHistory.lastUsedScreenTime = getScreenOnTimeLocked(elapsedRealtime)
+        packageHistory.lastUsedScreenTime = getScreenOnTime(elapsedRealtime)
                 - (idle ? mScreenOnTimeThreshold : 0) - 1000 /* just a second more */;
     }
 
-    public void clearUsageLocked(String packageName, int userId) {
-        ArrayMap<String, PackageHistory> userHistory = getUserHistoryLocked(userId);
+    public void clearUsage(String packageName, int userId) {
+        ArrayMap<String, PackageHistory> userHistory = getUserHistory(userId);
         userHistory.remove(packageName);
     }
 
-    private boolean hasPassedThresholdsLocked(PackageHistory packageHistory, long elapsedRealtime) {
+    private boolean hasPassedThresholds(PackageHistory packageHistory, long elapsedRealtime) {
         return (packageHistory.lastUsedScreenTime
-                    <= getScreenOnTimeLocked(elapsedRealtime) - mScreenOnTimeThreshold)
+                    <= getScreenOnTime(elapsedRealtime) - mScreenOnTimeThreshold)
                 && (packageHistory.lastUsedElapsedTime
-                        <= getElapsedTimeLocked(elapsedRealtime) - mElapsedTimeThreshold);
+                        <= getElapsedTime(elapsedRealtime) - mElapsedTimeThreshold);
     }
 
     private File getUserFile(int userId) {
@@ -290,7 +289,7 @@
                 Integer.toString(userId)), APP_IDLE_FILENAME);
     }
 
-    private void readAppIdleTimesLocked(int userId, ArrayMap<String, PackageHistory> userHistory) {
+    private void readAppIdleTimes(int userId, ArrayMap<String, PackageHistory> userHistory) {
         FileInputStream fis = null;
         try {
             AtomicFile appIdleFile = new AtomicFile(getUserFile(userId));
@@ -332,7 +331,7 @@
         }
     }
 
-    public void writeAppIdleTimesLocked(int userId) {
+    public void writeAppIdleTimes(int userId) {
         FileOutputStream fos = null;
         AtomicFile appIdleFile = new AtomicFile(getUserFile(userId));
         try {
@@ -346,7 +345,7 @@
 
             xml.startTag(null, TAG_PACKAGES);
 
-            ArrayMap<String,PackageHistory> userHistory = getUserHistoryLocked(userId);
+            ArrayMap<String,PackageHistory> userHistory = getUserHistory(userId);
             final int N = userHistory.size();
             for (int i = 0; i < N; i++) {
                 String packageName = userHistory.keyAt(i);
@@ -374,8 +373,8 @@
         idpw.increaseIndent();
         ArrayMap<String, PackageHistory> userHistory = mIdleHistory.get(userId);
         final long elapsedRealtime = SystemClock.elapsedRealtime();
-        final long totalElapsedTime = getElapsedTimeLocked(elapsedRealtime);
-        final long screenOnTime = getScreenOnTimeLocked(elapsedRealtime);
+        final long totalElapsedTime = getElapsedTime(elapsedRealtime);
+        final long screenOnTime = getScreenOnTime(elapsedRealtime);
         if (userHistory == null) return;
         final int P = userHistory.size();
         for (int p = 0; p < P; p++) {
@@ -386,15 +385,15 @@
             TimeUtils.formatDuration(totalElapsedTime - packageHistory.lastUsedElapsedTime, idpw);
             idpw.print(" lastUsedScreenOn=");
             TimeUtils.formatDuration(screenOnTime - packageHistory.lastUsedScreenTime, idpw);
-            idpw.print(" idle=" + (isIdleLocked(packageName, userId, elapsedRealtime) ? "y" : "n"));
+            idpw.print(" idle=" + (isIdle(packageName, userId, elapsedRealtime) ? "y" : "n"));
             idpw.println();
         }
         idpw.println();
         idpw.print("totalElapsedTime=");
-        TimeUtils.formatDuration(getElapsedTimeLocked(elapsedRealtime), idpw);
+        TimeUtils.formatDuration(getElapsedTime(elapsedRealtime), idpw);
         idpw.println();
         idpw.print("totalScreenOnTime=");
-        TimeUtils.formatDuration(getScreenOnTimeLocked(elapsedRealtime), idpw);
+        TimeUtils.formatDuration(getScreenOnTime(elapsedRealtime), idpw);
         idpw.println();
         idpw.decreaseIndent();
     }
@@ -410,7 +409,7 @@
             for (int i = 0; i < HISTORY_SIZE; i++) {
                 idpw.print(history[i] == 0 ? '.' : 'A');
             }
-            idpw.print(" idle=" + (isIdleLocked(packageName, userId, elapsedRealtime) ? "y" : "n"));
+            idpw.print(" idle=" + (isIdle(packageName, userId, elapsedRealtime) ? "y" : "n"));
             idpw.print("  " + packageName);
             idpw.println();
         }
diff --git a/services/usage/java/com/android/server/usage/StorageStatsService.java b/services/usage/java/com/android/server/usage/StorageStatsService.java
index 6826975..89e68a6 100644
--- a/services/usage/java/com/android/server/usage/StorageStatsService.java
+++ b/services/usage/java/com/android/server/usage/StorageStatsService.java
@@ -20,6 +20,8 @@
 import android.app.usage.ExternalStorageStats;
 import android.app.usage.IStorageStatsManager;
 import android.app.usage.StorageStats;
+import android.app.usage.UsageStatsManagerInternal;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
@@ -28,25 +30,40 @@
 import android.content.pm.UserInfo;
 import android.os.Binder;
 import android.os.Environment;
+import android.os.FileUtils;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.StatFs;
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.storage.StorageEventListener;
 import android.os.storage.StorageManager;
 import android.os.storage.VolumeInfo;
+import android.provider.Settings;
+import android.text.format.DateUtils;
 import android.util.Slog;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.Preconditions;
+import com.android.server.IoThread;
+import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.pm.Installer;
 import com.android.server.pm.Installer.InstallerException;
+import com.android.server.storage.CacheQuotaStrategy;
+
+import java.io.IOException;
 
 public class StorageStatsService extends IStorageStatsManager.Stub {
     private static final String TAG = "StorageStatsService";
 
     private static final String PROP_VERIFY_STORAGE = "fw.verify_storage";
 
+    private static final long DELAY_IN_MILLIS = 30 * DateUtils.SECOND_IN_MILLIS;
+
     public static class Lifecycle extends SystemService {
         private StorageStatsService mService;
 
@@ -68,6 +85,7 @@
     private final StorageManager mStorage;
 
     private final Installer mInstaller;
+    private final H mHandler;
 
     public StorageStatsService(Context context) {
         mContext = Preconditions.checkNotNull(context);
@@ -80,6 +98,9 @@
         mInstaller.onStart();
         invalidateMounts();
 
+        mHandler = new H(IoThread.get().getLooper());
+        mHandler.sendEmptyMessageDelayed(H.MSG_LOAD_CACHED_QUOTAS_FROM_FILE, DELAY_IN_MILLIS);
+
         mStorage.registerListener(new StorageEventListener() {
             @Override
             public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
@@ -115,15 +136,25 @@
     }
 
     @Override
+    public boolean isQuotaSupported(String volumeUuid, String callingPackage) {
+        enforcePermission(Binder.getCallingUid(), callingPackage);
+
+        try {
+            return mInstaller.isQuotaSupported(volumeUuid);
+        } catch (InstallerException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    @Override
     public long getTotalBytes(String volumeUuid, String callingPackage) {
         enforcePermission(Binder.getCallingUid(), callingPackage);
 
         if (volumeUuid == StorageManager.UUID_PRIVATE_INTERNAL) {
-            // TODO: round total size to nearest power of two
-            return mStorage.getPrimaryStorageSize();
+            return FileUtils.roundStorageSize(mStorage.getPrimaryStorageSize());
         } else {
             final VolumeInfo vol = mStorage.findVolumeByUuid(volumeUuid);
-            return vol.disk.size;
+            return FileUtils.roundStorageSize(vol.disk.size);
         }
     }
 
@@ -146,6 +177,43 @@
     }
 
     @Override
+    public StorageStats queryStatsForPackage(String volumeUuid, String packageName, int userId,
+            String callingPackage) {
+        enforcePermission(Binder.getCallingUid(), callingPackage);
+        if (userId != UserHandle.getCallingUserId()) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.INTERACT_ACROSS_USERS, TAG);
+        }
+
+        final ApplicationInfo appInfo;
+        try {
+            appInfo = mPackage.getApplicationInfoAsUser(packageName, 0, userId);
+        } catch (NameNotFoundException e) {
+            throw new IllegalStateException(e);
+        }
+
+        if (mPackage.getPackagesForUid(appInfo.uid).length == 1) {
+            // Only one package inside UID means we can fast-path
+            return queryStatsForUid(volumeUuid, appInfo.uid, callingPackage);
+        } else {
+            // Multiple packages means we need to go manual
+            final int appId = UserHandle.getUserId(appInfo.uid);
+            final String[] packageNames = new String[] { packageName };
+            final long[] ceDataInodes = new long[1];
+            final String[] codePaths = new String[] { appInfo.getCodePath() };
+
+            final PackageStats stats = new PackageStats(TAG);
+            try {
+                mInstaller.getAppSize(volumeUuid, packageNames, userId, 0,
+                        appId, ceDataInodes, codePaths, stats);
+            } catch (InstallerException e) {
+                throw new IllegalStateException(e);
+            }
+            return translate(stats);
+        }
+    }
+
+    @Override
     public StorageStats queryStatsForUid(String volumeUuid, int uid, String callingPackage) {
         enforcePermission(Binder.getCallingUid(), callingPackage);
         if (UserHandle.getUserId(uid) != UserHandle.getCallingUserId()) {
@@ -274,4 +342,95 @@
         res.cacheBytes = stats.cacheSize + stats.externalCacheSize;
         return res;
     }
+
+    private class H extends Handler {
+        private static final int MSG_CHECK_STORAGE_DELTA = 100;
+        private static final int MSG_LOAD_CACHED_QUOTAS_FROM_FILE = 101;
+        /**
+         * By only triggering a re-calculation after the storage has changed sizes, we can avoid
+         * recalculating quotas too often. Minimum change delta defines the percentage of change
+         * we need to see before we recalculate.
+         */
+        private static final double MINIMUM_CHANGE_DELTA = 0.05;
+        private static final int UNSET = -1;
+        private static final boolean DEBUG = false;
+
+        private final StatFs mStats;
+        private long mPreviousBytes;
+        private double mMinimumThresholdBytes;
+
+        public H(Looper looper) {
+            super(looper);
+            // TODO: Handle all private volumes.
+            mStats = new StatFs(Environment.getDataDirectory().getAbsolutePath());
+            mPreviousBytes = mStats.getFreeBytes();
+            mMinimumThresholdBytes = mStats.getTotalBytes() * MINIMUM_CHANGE_DELTA;
+        }
+
+        public void handleMessage(Message msg) {
+            if (DEBUG) {
+                Slog.v(TAG, ">>> handling " + msg.what);
+            }
+
+            if (!isCacheQuotaCalculationsEnabled(mContext.getContentResolver())) {
+                return;
+            }
+
+            switch (msg.what) {
+                case MSG_CHECK_STORAGE_DELTA: {
+                    long bytesDelta = Math.abs(mPreviousBytes - mStats.getFreeBytes());
+                    if (bytesDelta > mMinimumThresholdBytes) {
+                        mPreviousBytes = mStats.getFreeBytes();
+                        recalculateQuotas(getInitializedStrategy());
+                    }
+                    sendEmptyMessageDelayed(MSG_CHECK_STORAGE_DELTA, DELAY_IN_MILLIS);
+                    break;
+                }
+                case MSG_LOAD_CACHED_QUOTAS_FROM_FILE: {
+                    CacheQuotaStrategy strategy = getInitializedStrategy();
+                    mPreviousBytes = UNSET;
+                    try {
+                        mPreviousBytes = strategy.setupQuotasFromFile();
+                    } catch (IOException e) {
+                        Slog.e(TAG, "An error occurred while reading the cache quota file.", e);
+                    } catch (IllegalStateException e) {
+                        Slog.e(TAG, "Cache quota XML file is malformed?", e);
+                    }
+
+                    // If errors occurred getting the quotas from disk, let's re-calc them.
+                    if (mPreviousBytes < 0) {
+                        mPreviousBytes = mStats.getFreeBytes();
+                        recalculateQuotas(strategy);
+                    }
+                    sendEmptyMessageDelayed(MSG_CHECK_STORAGE_DELTA, DELAY_IN_MILLIS);
+                    break;
+                }
+                default:
+                    if (DEBUG) {
+                        Slog.v(TAG, ">>> default message case ");
+                    }
+                    return;
+            }
+        }
+
+        private void recalculateQuotas(CacheQuotaStrategy strategy) {
+            if (DEBUG) {
+                Slog.v(TAG, ">>> recalculating quotas ");
+            }
+
+            strategy.recalculateQuotas();
+        }
+
+        private CacheQuotaStrategy getInitializedStrategy() {
+            UsageStatsManagerInternal usageStatsManager =
+                    LocalServices.getService(UsageStatsManagerInternal.class);
+            return new CacheQuotaStrategy(mContext, usageStatsManager, mInstaller);
+        }
+    }
+
+    @VisibleForTesting
+    static boolean isCacheQuotaCalculationsEnabled(ContentResolver resolver) {
+        return Settings.Global.getInt(
+                resolver, Settings.Global.ENABLE_CACHE_QUOTA_CALCULATION, 1) != 0;
+    }
 }
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 7a69803..3c7ee43 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -60,6 +60,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
+import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
@@ -96,6 +97,8 @@
         UserUsageStatsService.StatsUpdatedListener {
 
     static final String TAG = "UsageStatsService";
+    public static final boolean ENABLE_TIME_CHANGE_CORRECTION
+            = SystemProperties.getBoolean("persist.debug.time_correction", true);
 
     static final boolean DEBUG = false; // Never submit with true
     static final boolean COMPRESS_TIME = false;
@@ -153,13 +156,17 @@
     private volatile boolean mPendingOneTimeCheckIdleStates;
     private boolean mSystemServicesReady = false;
 
-    @GuardedBy("mLock")
+    private final Object mAppIdleLock = new Object();
+    @GuardedBy("mAppIdleLock")
     private AppIdleHistory mAppIdleHistory;
 
+    @GuardedBy("mAppIdleLock")
     private ArrayList<UsageStatsManagerInternal.AppIdleStateChangeListener>
             mPackageAccessListeners = new ArrayList<>();
 
+    @GuardedBy("mAppIdleLock")
     private boolean mHaveCarrierPrivilegedApps;
+    @GuardedBy("mAppIdleLock")
     private List<String> mCarrierPrivilegedApps;
 
     public UsageStatsService(Context context) {
@@ -206,6 +213,8 @@
 
         synchronized (mLock) {
             cleanUpRemovedUsersLocked();
+        }
+        synchronized (mAppIdleLock) {
             mAppIdleHistory = new AppIdleHistory(SystemClock.elapsedRealtime());
         }
 
@@ -234,8 +243,8 @@
             mPowerManager = getContext().getSystemService(PowerManager.class);
 
             mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
-            synchronized (mLock) {
-                mAppIdleHistory.updateDisplayLocked(isDisplayOn(), SystemClock.elapsedRealtime());
+            synchronized (mAppIdleLock) {
+                mAppIdleHistory.updateDisplay(isDisplayOn(), SystemClock.elapsedRealtime());
             }
 
             if (mPendingOneTimeCheckIdleStates) {
@@ -324,8 +333,8 @@
         @Override public void onDisplayChanged(int displayId) {
             if (displayId == Display.DEFAULT_DISPLAY) {
                 final boolean displayOn = isDisplayOn();
-                synchronized (UsageStatsService.this.mLock) {
-                    mAppIdleHistory.updateDisplayLocked(displayOn, SystemClock.elapsedRealtime());
+                synchronized (UsageStatsService.this.mAppIdleLock) {
+                    mAppIdleHistory.updateDisplay(displayOn, SystemClock.elapsedRealtime());
                 }
             }
         }
@@ -386,18 +395,20 @@
                 PackageManager.MATCH_DISABLED_COMPONENTS,
                 userId);
         final int packageCount = packages.size();
-        for (int i = 0; i < packageCount; i++) {
-            final PackageInfo pi = packages.get(i);
-            String packageName = pi.packageName;
-            if (pi.applicationInfo != null && pi.applicationInfo.isSystemApp()) {
-                mAppIdleHistory.reportUsageLocked(packageName, userId, elapsedRealtime);
+        synchronized (mAppIdleLock) {
+            for (int i = 0; i < packageCount; i++) {
+                final PackageInfo pi = packages.get(i);
+                String packageName = pi.packageName;
+                if (pi.applicationInfo != null && pi.applicationInfo.isSystemApp()) {
+                    mAppIdleHistory.reportUsage(packageName, userId, elapsedRealtime);
+                }
             }
         }
     }
 
     void clearAppIdleForPackage(String packageName, int userId) {
-        synchronized (mLock) {
-            mAppIdleHistory.clearUsageLocked(packageName, userId);
+        synchronized (mAppIdleLock) {
+            mAppIdleHistory.clearUsage(packageName, userId);
         }
     }
 
@@ -429,7 +440,7 @@
     }
 
     void setChargingState(boolean charging) {
-        synchronized (mLock) {
+        synchronized (mAppIdleLock) {
             if (mCharging != charging) {
                 mCharging = charging;
                 postParoleStateChanged();
@@ -439,15 +450,16 @@
 
     /** Paroled here means temporary pardon from being inactive */
     void setAppIdleParoled(boolean paroled) {
-        synchronized (mLock) {
+        synchronized (mAppIdleLock) {
+            final long now = System.currentTimeMillis();
             if (mAppIdleTempParoled != paroled) {
                 mAppIdleTempParoled = paroled;
                 if (DEBUG) Slog.d(TAG, "Changing paroled to " + mAppIdleTempParoled);
                 if (paroled) {
                     postParoleEndTimeout();
                 } else {
-                    mLastAppIdleParoledTime = checkAndGetTimeLocked();
-                    postNextParoleTimeout();
+                    mLastAppIdleParoledTime = now;
+                    postNextParoleTimeout(now);
                 }
                 postParoleStateChanged();
             }
@@ -455,19 +467,18 @@
     }
 
     boolean isParoledOrCharging() {
-        synchronized (mLock) {
+        synchronized (mAppIdleLock) {
             return mAppIdleTempParoled || mCharging;
         }
     }
 
-    private void postNextParoleTimeout() {
+    private void postNextParoleTimeout(long now) {
         if (DEBUG) Slog.d(TAG, "Posting MSG_CHECK_PAROLE_TIMEOUT");
         mHandler.removeMessages(MSG_CHECK_PAROLE_TIMEOUT);
         // Compute when the next parole needs to happen. We check more frequently than necessary
         // since the message handler delays are based on elapsedRealTime and not wallclock time.
         // The comparison is done in wallclock time.
-        long timeLeft = (mLastAppIdleParoledTime + mAppIdleParoleIntervalMillis)
-                - checkAndGetTimeLocked();
+        long timeLeft = (mLastAppIdleParoledTime + mAppIdleParoleIntervalMillis) - now;
         if (timeLeft < 0) {
             timeLeft = 0;
         }
@@ -546,7 +557,7 @@
                 mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS,
                         userId, isIdle ? 1 : 0, packageName));
                 if (isIdle) {
-                    synchronized (mLock) {
+                    synchronized (mAppIdleLock) {
                         mAppIdleHistory.setIdle(packageName, userId, elapsedRealtime);
                     }
                 }
@@ -561,18 +572,23 @@
 
     /** Check if it's been a while since last parole and let idle apps do some work */
     void checkParoleTimeout() {
-        synchronized (mLock) {
+        boolean setParoled = false;
+        synchronized (mAppIdleLock) {
+            final long now = System.currentTimeMillis();
             if (!mAppIdleTempParoled) {
-                final long timeSinceLastParole = checkAndGetTimeLocked() - mLastAppIdleParoledTime;
+                final long timeSinceLastParole = now - mLastAppIdleParoledTime;
                 if (timeSinceLastParole > mAppIdleParoleIntervalMillis) {
                     if (DEBUG) Slog.d(TAG, "Crossed default parole interval");
-                    setAppIdleParoled(true);
+                    setParoled = true;
                 } else {
                     if (DEBUG) Slog.d(TAG, "Not long enough to go to parole");
-                    postNextParoleTimeout();
+                    postNextParoleTimeout(now);
                 }
             }
         }
+        if (setParoled) {
+            setAppIdleParoled(true);
+        }
     }
 
     private void notifyBatteryStats(String packageName, int userId, boolean idle) {
@@ -593,17 +609,23 @@
     void onDeviceIdleModeChanged() {
         final boolean deviceIdle = mPowerManager.isDeviceIdleMode();
         if (DEBUG) Slog.i(TAG, "DeviceIdleMode changed to " + deviceIdle);
-        synchronized (mLock) {
-            final long timeSinceLastParole = checkAndGetTimeLocked() - mLastAppIdleParoledTime;
+        boolean paroled = false;
+        synchronized (mAppIdleLock) {
+            final long timeSinceLastParole = System.currentTimeMillis() - mLastAppIdleParoledTime;
             if (!deviceIdle
                     && timeSinceLastParole >= mAppIdleParoleIntervalMillis) {
-                if (DEBUG) Slog.i(TAG, "Bringing idle apps out of inactive state due to deviceIdleMode=false");
-                setAppIdleParoled(true);
+                if (DEBUG) {
+                    Slog.i(TAG, "Bringing idle apps out of inactive state due to deviceIdleMode=false");
+                }
+                paroled = true;
             } else if (deviceIdle) {
                 if (DEBUG) Slog.i(TAG, "Device idle, back to prison");
-                setAppIdleParoled(false);
+                paroled = false;
+            } else {
+                return;
             }
         }
+        setAppIdleParoled(paroled);
     }
 
     private static void deleteRecursively(File f) {
@@ -639,7 +661,8 @@
         final long actualRealtime = SystemClock.elapsedRealtime();
         final long expectedSystemTime = (actualRealtime - mRealTimeSnapshot) + mSystemTimeSnapshot;
         final long diffSystemTime = actualSystemTime - expectedSystemTime;
-        if (Math.abs(diffSystemTime) > TIME_CHANGE_THRESHOLD_MILLIS) {
+        if (Math.abs(diffSystemTime) > TIME_CHANGE_THRESHOLD_MILLIS
+                && ENABLE_TIME_CHANGE_CORRECTION) {
             // The time has changed.
             Slog.i(TAG, "Time changed in UsageStats by " + (diffSystemTime / 1000) + " seconds");
             final int userCount = mUserState.size();
@@ -682,21 +705,24 @@
 
             final UserUsageStatsService service =
                     getUserDataAndInitializeIfNeededLocked(userId, timeNow);
-            // TODO: Ideally this should call isAppIdleFiltered() to avoid calling back
-            // about apps that are on some kind of whitelist anyway.
-            final boolean previouslyIdle = mAppIdleHistory.isIdleLocked(
-                    event.mPackage, userId, elapsedRealtime);
             service.reportEvent(event);
-            // Inform listeners if necessary
-            if ((event.mEventType == Event.MOVE_TO_FOREGROUND
-                    || event.mEventType == Event.MOVE_TO_BACKGROUND
-                    || event.mEventType == Event.SYSTEM_INTERACTION
-                    || event.mEventType == Event.USER_INTERACTION)) {
-                mAppIdleHistory.reportUsageLocked(event.mPackage, userId, elapsedRealtime);
-                if (previouslyIdle) {
-                    mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
-                            /* idle = */ 0, event.mPackage));
-                    notifyBatteryStats(event.mPackage, userId, false);
+
+            synchronized (mAppIdleLock) {
+                // TODO: Ideally this should call isAppIdleFiltered() to avoid calling back
+                // about apps that are on some kind of whitelist anyway.
+                final boolean previouslyIdle = mAppIdleHistory.isIdle(
+                        event.mPackage, userId, elapsedRealtime);
+                // Inform listeners if necessary
+                if ((event.mEventType == Event.MOVE_TO_FOREGROUND
+                        || event.mEventType == Event.MOVE_TO_BACKGROUND
+                        || event.mEventType == Event.SYSTEM_INTERACTION
+                        || event.mEventType == Event.USER_INTERACTION)) {
+                    mAppIdleHistory.reportUsage(event.mPackage, userId, elapsedRealtime);
+                    if (previouslyIdle) {
+                        mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
+                                /* idle = */ 0, event.mPackage));
+                        notifyBatteryStats(event.mPackage, userId, false);
+                    }
                 }
             }
         }
@@ -716,7 +742,7 @@
                     continue;
                 }
                 if (!packageName.equals(providerPkgName)) {
-                    forceIdleState(packageName, userId, false);
+                    setAppIdleAsync(packageName, false, userId);
                 }
             } catch (NameNotFoundException e) {
                 // Shouldn't happen
@@ -728,25 +754,28 @@
      * Forces the app's beginIdleTime and lastUsedTime to reflect idle or active. If idle,
      * then it rolls back the beginIdleTime and lastUsedTime to a point in time that's behind
      * the threshold for idle.
+     *
+     * This method is always called from the handler thread, so not much synchronization is
+     * required.
      */
     void forceIdleState(String packageName, int userId, boolean idle) {
         final int appId = getAppId(packageName);
         if (appId < 0) return;
-        synchronized (mLock) {
-            final long elapsedRealtime = SystemClock.elapsedRealtime();
+        final long elapsedRealtime = SystemClock.elapsedRealtime();
 
-            final boolean previouslyIdle = isAppIdleFiltered(packageName, appId,
-                    userId, elapsedRealtime);
-            mAppIdleHistory.setIdleLocked(packageName, userId, idle, elapsedRealtime);
-            final boolean stillIdle = isAppIdleFiltered(packageName, appId,
-                    userId, elapsedRealtime);
-            // Inform listeners if necessary
-            if (previouslyIdle != stillIdle) {
-                mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
-                        /* idle = */ stillIdle ? 1 : 0, packageName));
-                if (!stillIdle) {
-                    notifyBatteryStats(packageName, userId, idle);
-                }
+        final boolean previouslyIdle = isAppIdleFiltered(packageName, appId,
+                userId, elapsedRealtime);
+        synchronized (mAppIdleLock) {
+            mAppIdleHistory.setIdle(packageName, userId, idle, elapsedRealtime);
+        }
+        final boolean stillIdle = isAppIdleFiltered(packageName, appId,
+                userId, elapsedRealtime);
+        // Inform listeners if necessary
+        if (previouslyIdle != stillIdle) {
+            mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
+                    /* idle = */ stillIdle ? 1 : 0, packageName));
+            if (!stillIdle) {
+                notifyBatteryStats(packageName, userId, idle);
             }
         }
     }
@@ -767,7 +796,9 @@
         synchronized (mLock) {
             Slog.i(TAG, "Removing user " + userId + " and all data.");
             mUserState.remove(userId);
-            mAppIdleHistory.onUserRemoved(userId);
+            synchronized (mAppIdleLock) {
+                mAppIdleHistory.onUserRemoved(userId);
+            }
             cleanUpRemovedUsersLocked();
         }
     }
@@ -822,13 +853,13 @@
     }
 
     private boolean isAppIdleUnfiltered(String packageName, int userId, long elapsedRealtime) {
-        synchronized (mLock) {
-            return mAppIdleHistory.isIdleLocked(packageName, userId, elapsedRealtime);
+        synchronized (mAppIdleLock) {
+            return mAppIdleHistory.isIdle(packageName, userId, elapsedRealtime);
         }
     }
 
     void addListener(AppIdleStateChangeListener listener) {
-        synchronized (mLock) {
+        synchronized (mAppIdleLock) {
             if (!mPackageAccessListeners.contains(listener)) {
                 mPackageAccessListeners.add(listener);
             }
@@ -836,7 +867,7 @@
     }
 
     void removeListener(AppIdleStateChangeListener listener) {
-        synchronized (mLock) {
+        synchronized (mAppIdleLock) {
             mPackageAccessListeners.remove(listener);
         }
     }
@@ -988,7 +1019,7 @@
         return res;
     }
 
-    void setAppIdle(String packageName, boolean idle, int userId) {
+    void setAppIdleAsync(String packageName, boolean idle, int userId) {
         if (packageName == null) return;
 
         mHandler.obtainMessage(MSG_FORCE_IDLE_STATE, userId, idle ? 1 : 0, packageName)
@@ -1012,9 +1043,9 @@
     }
 
     private boolean isCarrierApp(String packageName) {
-        synchronized (mLock) {
+        synchronized (mAppIdleLock) {
             if (!mHaveCarrierPrivilegedApps) {
-                fetchCarrierPrivilegedAppsLocked();
+                fetchCarrierPrivilegedAppsLA();
             }
             if (mCarrierPrivilegedApps != null) {
                 return mCarrierPrivilegedApps.contains(packageName);
@@ -1027,13 +1058,14 @@
         if (DEBUG) {
             Slog.i(TAG, "Clearing carrier privileged apps list");
         }
-        synchronized (mLock) {
+        synchronized (mAppIdleLock) {
             mHaveCarrierPrivilegedApps = false;
             mCarrierPrivilegedApps = null; // Need to be refetched.
         }
     }
 
-    private void fetchCarrierPrivilegedAppsLocked() {
+    @GuardedBy("mAppIdleLock")
+    private void fetchCarrierPrivilegedAppsLA() {
         TelephonyManager telephonyManager =
                 getContext().getSystemService(TelephonyManager.class);
         mCarrierPrivilegedApps = telephonyManager.getPackagesWithCarrierPrivileges();
@@ -1071,11 +1103,15 @@
         for (int i = 0; i < userCount; i++) {
             UserUsageStatsService service = mUserState.valueAt(i);
             service.persistActiveStats();
-            mAppIdleHistory.writeAppIdleTimesLocked(mUserState.keyAt(i));
+            synchronized (mAppIdleLock) {
+                mAppIdleHistory.writeAppIdleTimes(mUserState.keyAt(i));
+            }
         }
         // Persist elapsed and screen on time. If this fails for whatever reason, the apps will be
         // considered not-idle, which is the safest outcome in such an event.
-        mAppIdleHistory.writeAppIdleDurationsLocked();
+        synchronized (mAppIdleLock) {
+            mAppIdleHistory.writeAppIdleDurations();
+        }
         mHandler.removeMessages(MSG_FLUSH_TO_DISK);
     }
 
@@ -1100,20 +1136,26 @@
                     idpw.println();
                     if (args.length > 0) {
                         if ("history".equals(args[0])) {
-                            mAppIdleHistory.dumpHistory(idpw, mUserState.keyAt(i));
+                            synchronized (mAppIdleLock) {
+                                mAppIdleHistory.dumpHistory(idpw, mUserState.keyAt(i));
+                            }
                         } else if ("flush".equals(args[0])) {
                             UsageStatsService.this.flushToDiskLocked();
                             pw.println("Flushed stats to disk");
                         }
                     }
                 }
-                mAppIdleHistory.dump(idpw, mUserState.keyAt(i));
+                synchronized (mAppIdleLock) {
+                    mAppIdleHistory.dump(idpw, mUserState.keyAt(i));
+                }
                 idpw.decreaseIndent();
             }
 
             pw.println();
-            pw.println("Carrier privileged apps (have=" + mHaveCarrierPrivilegedApps
-                    + "): " + mCarrierPrivilegedApps);
+            synchronized (mAppIdleLock) {
+                pw.println("Carrier privileged apps (have=" + mHaveCarrierPrivilegedApps
+                        + "): " + mCarrierPrivilegedApps);
+            }
 
             pw.println();
             pw.println("Settings:");
@@ -1252,7 +1294,7 @@
         }
 
         void updateSettings() {
-            synchronized (mLock) {
+            synchronized (mAppIdleLock) {
                 // Look at global settings for this.
                 // TODO: Maybe apply different thresholds for different users.
                 try {
@@ -1384,7 +1426,7 @@
             try {
                 userId = ActivityManager.getService().handleIncomingUser(
                         Binder.getCallingPid(), callingUid, userId, false, true,
-                        "setAppIdle", null);
+                        "setAppInactive", null);
             } catch (RemoteException re) {
                 throw re.rethrowFromSystemServer();
             }
@@ -1394,7 +1436,7 @@
             try {
                 final int appId = getAppId(packageName);
                 if (appId < 0) return;
-                UsageStatsService.this.setAppIdle(packageName, idle, userId);
+                UsageStatsService.this.setAppIdleAsync(packageName, idle, userId);
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -1586,22 +1628,33 @@
         @Override
         public byte[] getBackupPayload(int user, String key) {
             // Check to ensure that only user 0's data is b/r for now
-            if (user == UserHandle.USER_SYSTEM) {
-                final UserUsageStatsService userStats =
-                        getUserDataAndInitializeIfNeededLocked(user, checkAndGetTimeLocked());
-                return userStats.getBackupPayload(key);
-            } else {
-                return null;
+            synchronized (UsageStatsService.this.mLock) {
+                if (user == UserHandle.USER_SYSTEM) {
+                    final UserUsageStatsService userStats =
+                            getUserDataAndInitializeIfNeededLocked(user, checkAndGetTimeLocked());
+                    return userStats.getBackupPayload(key);
+                } else {
+                    return null;
+                }
             }
         }
 
         @Override
         public void applyRestoredPayload(int user, String key, byte[] payload) {
-            if (user == UserHandle.USER_SYSTEM) {
-                final UserUsageStatsService userStats =
-                        getUserDataAndInitializeIfNeededLocked(user, checkAndGetTimeLocked());
-                userStats.applyRestoredPayload(key, payload);
+            synchronized (UsageStatsService.this.mLock) {
+                if (user == UserHandle.USER_SYSTEM) {
+                    final UserUsageStatsService userStats =
+                            getUserDataAndInitializeIfNeededLocked(user, checkAndGetTimeLocked());
+                    userStats.applyRestoredPayload(key, payload);
+                }
             }
         }
+
+        @Override
+        public List<UsageStats> queryUsageStatsForUser(
+                int userId, int intervalType, long beginTime, long endTime) {
+            return UsageStatsService.this.queryUsageStats(
+                    userId, intervalType, beginTime, endTime);
+        }
     }
 }
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index d9f352c..8d335a5 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -529,7 +529,6 @@
         pw.decreaseIndent();
 
         pw.println();
-        pw.increaseIndent();
         pw.println("ChooserCounts");
         pw.increaseIndent();
         for (UsageStats usageStats : pkgStats.values()) {
@@ -553,6 +552,7 @@
             }
             pw.println();
         }
+        pw.decreaseIndent();
 
         pw.println("configurations");
         pw.increaseIndent();
diff --git a/services/usb/java/com/android/server/usb/MtpNotificationManager.java b/services/usb/java/com/android/server/usb/MtpNotificationManager.java
index 5c46222..db7b385 100644
--- a/services/usb/java/com/android/server/usb/MtpNotificationManager.java
+++ b/services/usb/java/com/android/server/usb/MtpNotificationManager.java
@@ -20,7 +20,6 @@
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -32,6 +31,8 @@
 import android.hardware.usb.UsbManager;
 import android.os.UserHandle;
 
+import com.android.internal.notification.SystemNotificationChannels;
+
 /**
  * Manager for MTP storage notification.
  */
@@ -77,11 +78,12 @@
                 device.getProductName());
         final String description = resources.getString(
                 com.android.internal.R.string.usb_mtp_launch_notification_description);
-        final Notification.Builder builder = new Notification.Builder(mContext)
-                .setContentTitle(title)
-                .setContentText(description)
-                .setSmallIcon(com.android.internal.R.drawable.stat_sys_data_usb)
-                .setCategory(Notification.CATEGORY_SYSTEM);
+        final Notification.Builder builder =
+                new Notification.Builder(mContext, SystemNotificationChannels.USB)
+                        .setContentTitle(title)
+                        .setContentText(description)
+                        .setSmallIcon(com.android.internal.R.drawable.stat_sys_data_usb)
+                        .setCategory(Notification.CATEGORY_SYSTEM);
 
         final Intent intent = new Intent(ACTION_OPEN_IN_APPS);
         intent.putExtra(UsbManager.EXTRA_DEVICE, device);
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
index 058de05..40bdaa5 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
@@ -497,6 +497,7 @@
     //
     // Devices List
     //
+/*
     public ArrayList<UsbAudioDevice> getConnectedDevices() {
         ArrayList<UsbAudioDevice> devices = new ArrayList<UsbAudioDevice>(mAudioDevices.size());
         for (HashMap.Entry<UsbDevice,UsbAudioDevice> entry : mAudioDevices.entrySet()) {
@@ -504,6 +505,7 @@
         }
         return devices;
     }
+*/
 
     //
     // Logging
@@ -519,6 +521,7 @@
         }
     }
 
+/*
     public void logDevicesList(String title) {
       if (DEBUG) {
           for (HashMap.Entry<UsbDevice,UsbAudioDevice> entry : mAudioDevices.entrySet()) {
@@ -528,15 +531,19 @@
               Slog.i(TAG, "" + entry.getValue());
           }
       }
-  }
+    }
+*/
 
-  // This logs a more terse (and more readable) version of the devices list
-  public void logDevices(String title) {
+    // This logs a more terse (and more readable) version of the devices list
+/*
+    public void logDevices(String title) {
       if (DEBUG) {
           Slog.i(TAG, title);
           for (HashMap.Entry<UsbDevice,UsbAudioDevice> entry : mAudioDevices.entrySet()) {
               Slog.i(TAG, entry.getValue().toShortString());
           }
       }
-  }
+    }
+*/
+
 }
diff --git a/services/usb/java/com/android/server/usb/UsbAudioDevice.java b/services/usb/java/com/android/server/usb/UsbAudioDevice.java
index bdd28e4..70d1fc6 100644
--- a/services/usb/java/com/android/server/usb/UsbAudioDevice.java
+++ b/services/usb/java/com/android/server/usb/UsbAudioDevice.java
@@ -20,10 +20,10 @@
     private static final String TAG = "UsbAudioDevice";
     protected static final boolean DEBUG = false;
 
-    public int mCard;
-    public int mDevice;
-    public boolean mHasPlayback;
-    public boolean mHasCapture;
+    public final int mCard;
+    public final int mDevice;
+    public final boolean mHasPlayback;
+    public final boolean mHasCapture;
 
     // Device "class" flags
     public static final int kAudioDeviceClassMask = 0x00FFFFFF;
@@ -34,7 +34,7 @@
     public static final int kAudioDeviceMetaMask = 0xFF000000;
     public static final int kAudioDeviceMeta_Alsa = 0x80000000;
     // This member is a combination of the above bit-flags
-    public int mDeviceClass;
+    public final int mDeviceClass;
 
     public String mDeviceName = "";
     public String mDeviceDescription = "";
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 07b4ca1..a17676a 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -50,6 +50,7 @@
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.os.SomeArgs;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.FgThread;
@@ -748,7 +749,7 @@
                         mMidiCard = scanner.nextInt();
                         mMidiDevice = scanner.nextInt();
                     } catch (FileNotFoundException e) {
-                        Slog.e(TAG, "could not open MIDI PCM file", e);
+                        Slog.e(TAG, "could not open MIDI file", e);
                         enabled = false;
                     } finally {
                         if (scanner != null) {
@@ -912,13 +913,13 @@
                     PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0,
                             intent, 0, null, UserHandle.CURRENT);
 
-                    Notification notification = new Notification.Builder(mContext)
+                    Notification notification =
+                            new Notification.Builder(mContext, SystemNotificationChannels.USB)
                             .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
                             .setWhen(0)
                             .setOngoing(true)
                             .setTicker(title)
                             .setDefaults(0)  // please be quiet
-                            .setPriority(Notification.PRIORITY_MIN)
                             .setColor(mContext.getColor(
                                     com.android.internal.R.color.system_notification_accent_color))
                             .setContentTitle(title)
@@ -951,13 +952,13 @@
                     PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0,
                             intent, 0, null, UserHandle.CURRENT);
 
-                    Notification notification = new Notification.Builder(mContext)
+                    Notification notification =
+                            new Notification.Builder(mContext, SystemNotificationChannels.DEVELOPER)
                             .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
                             .setWhen(0)
                             .setOngoing(true)
                             .setTicker(title)
                             .setDefaults(0)  // please be quiet
-                            .setPriority(Notification.PRIORITY_DEFAULT)
                             .setColor(mContext.getColor(
                                     com.android.internal.R.color.system_notification_accent_color))
                             .setContentTitle(title)
diff --git a/services/usb/java/com/android/server/usb/UsbPortManager.java b/services/usb/java/com/android/server/usb/UsbPortManager.java
index 4b8e4c8..a923fc3 100644
--- a/services/usb/java/com/android/server/usb/UsbPortManager.java
+++ b/services/usb/java/com/android/server/usb/UsbPortManager.java
@@ -117,7 +117,7 @@
     public UsbPortManager(Context context) {
         mContext = context;
         try {
-            boolean ret = IServiceManager.getService("manager")
+            boolean ret = IServiceManager.getService()
                     .registerForNotifications("android.hardware.usb@1.0::IUsb",
                     "", mServiceNotification);
             if (!ret) {
@@ -455,9 +455,9 @@
 
         public void notifyRoleSwitchStatus(String portName, PortRole role, int retval) {
             if (retval == Status.SUCCESS) {
-                logAndPrint(Log.INFO, pw, portName + "role switch successful");
+                logAndPrint(Log.INFO, pw, portName + " role switch successful");
             } else {
-                logAndPrint(Log.ERROR, pw, portName + "role switch failed");
+                logAndPrint(Log.ERROR, pw, portName + " role switch failed");
             }
         }
     };
@@ -498,11 +498,12 @@
                 mProxy.setCallback(mHALCallback);
                 mProxy.queryPortStatus();
             } catch (NoSuchElementException e) {
-                logAndPrint(Log.ERROR, pw, sSERVICENAME + "not found."
-                        + " Did the service failed to start ?");
+                logAndPrint(Log.ERROR, pw, sSERVICENAME + " not found."
+                        + " Did the service fail to start?");
                 Thread.dumpStack();
             } catch (RemoteException e) {
-                logAndPrint(Log.ERROR, pw, sSERVICENAME + "connectToProxy: Service not responding");
+                logAndPrint(Log.ERROR, pw, sSERVICENAME
+                        + " connectToProxy: Service not responding");
                 Thread.dumpStack();
             }
         }
diff --git a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
index caf9ec6..7b8ebd4 100644
--- a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
@@ -602,7 +602,8 @@
                 new MtpNotificationManager.OnOpenInAppListener() {
                     @Override
                     public void onOpenInApp(UsbDevice device) {
-                        resolveActivity(createDeviceAttachedIntent(device), device);
+                        resolveActivity(createDeviceAttachedIntent(device),
+                                device, false /* showMtpNotification */);
                     }
                 });
     }
@@ -958,31 +959,27 @@
         // Send broadcast to running activities with registered intent
         mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
 
-        if (MtpNotificationManager.shouldShowNotification(mPackageManager, device)) {
-            // Show notification if the device is MTP storage.
-            mMtpNotificationManager.showNotification(device);
-        } else {
-            resolveActivity(intent, device);
-        }
+        resolveActivity(intent, device, true /* showMtpNotification */);
     }
 
-    private void resolveActivity(Intent intent, UsbDevice device) {
-        ArrayList<ResolveInfo> matches;
-        String defaultPackage = null;
-        UserHandle user = null;
+    private void resolveActivity(Intent intent, UsbDevice device, boolean showMtpNotification) {
+        final ArrayList<ResolveInfo> matches;
+        final ActivityInfo defaultActivity;
         synchronized (mLock) {
             matches = getDeviceMatchesLocked(device, intent);
-            // Launch our default activity directly, if we have one.
-            // Otherwise we will start the UsbResolverActivity to allow the user to choose.
-            UserPackage userPackage = mDevicePreferenceMap.get(new DeviceFilter(device));
-            if (userPackage != null) {
-                defaultPackage = userPackage.packageName;
-                user = userPackage.user;
-            }
+            defaultActivity = getDefaultActivityLocked(
+                    matches, mDevicePreferenceMap.get(new DeviceFilter(device)));
+        }
+
+        if (showMtpNotification && MtpNotificationManager.shouldShowNotification(
+                mPackageManager, device) && defaultActivity == null) {
+            // Show notification if the device is MTP storage.
+            mMtpNotificationManager.showNotification(device);
+            return;
         }
 
         // Start activity with registered intent
-        resolveActivity(intent, matches, defaultPackage, user, device, null);
+        resolveActivity(intent, matches, defaultActivity, device, null);
     }
 
     public void deviceAttachedForFixedHandler(UsbDevice device, ComponentName component) {
@@ -1027,21 +1024,15 @@
                 Intent.FLAG_ACTIVITY_NEW_TASK |
                 Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
 
-        ArrayList<ResolveInfo> matches;
-        String defaultPackage = null;
-        UserHandle user = null;
+        final ArrayList<ResolveInfo> matches;
+        final ActivityInfo defaultActivity;
         synchronized (mLock) {
             matches = getAccessoryMatchesLocked(accessory, intent);
-            // Launch our default activity directly, if we have one.
-            // Otherwise we will start the UsbResolverActivity to allow the user to choose.
-            UserPackage userPackage = mAccessoryPreferenceMap.get(new AccessoryFilter(accessory));
-            if (userPackage != null) {
-                defaultPackage = userPackage.packageName;
-                user = userPackage.user;
-            }
+            defaultActivity = getDefaultActivityLocked(
+                    matches, mAccessoryPreferenceMap.get(new AccessoryFilter(accessory)));
         }
 
-        resolveActivity(intent, matches, defaultPackage, user, null, accessory);
+        resolveActivity(intent, matches, defaultActivity, null, accessory);
     }
 
     /**
@@ -1049,14 +1040,13 @@
      *
      * @param intent The intent to start the package
      * @param matches The available resolutions of the intent
-     * @param defaultPackage The default package for the device (if set)
-     * @param defaultUser The user of the default package (if package is set)
+     * @param defaultActivity The default activity for the device (if set)
      * @param device The device if a device was attached
      * @param accessory The accessory if a device was attached
      */
     private void resolveActivity(@NonNull Intent intent, @NonNull ArrayList<ResolveInfo> matches,
-            @Nullable String defaultPackage, @Nullable UserHandle defaultUser,
-            @Nullable UsbDevice device, @Nullable UsbAccessory accessory) {
+            @Nullable ActivityInfo defaultActivity, @Nullable UsbDevice device,
+            @Nullable UsbAccessory accessory) {
         int count = matches.size();
 
         // don't show the resolver activity if there are no choices available
@@ -1083,62 +1073,25 @@
             return;
         }
 
-        ResolveInfo defaultRI = null;
-        if (count == 1 && defaultPackage == null) {
-            // Check to see if our single choice is on the system partition.
-            // If so, treat it as our default without calling UsbResolverActivity
-            ResolveInfo rInfo = matches.get(0);
-            if (rInfo.activityInfo != null &&
-                    rInfo.activityInfo.applicationInfo != null &&
-                    (rInfo.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
-                defaultRI = rInfo;
-            }
-
-            if (mDisablePermissionDialogs) {
-                // bypass dialog and launch the only matching activity
-                rInfo = matches.get(0);
-                if (rInfo.activityInfo != null) {
-                    defaultPackage = rInfo.activityInfo.packageName;
-                    defaultUser = UserHandle.getUserHandleForUid(
-                            rInfo.activityInfo.applicationInfo.uid);
-                }
-            }
-        }
-
-        if (defaultRI == null && defaultPackage != null) {
-            // look for default activity
-            for (int i = 0; i < count; i++) {
-                ResolveInfo rInfo = matches.get(i);
-                if (rInfo.activityInfo != null &&
-                        defaultPackage.equals(rInfo.activityInfo.packageName) &&
-                        defaultUser.getIdentifier() ==
-                                UserHandle.getUserId(rInfo.activityInfo.applicationInfo.uid)) {
-                    defaultRI = rInfo;
-                    break;
-                }
-            }
-        }
-
-        if (defaultRI != null) {
+        if (defaultActivity != null) {
             UsbUserSettingsManager defaultRIUserSettings = mSettingsManager.getSettingsForUser(
-                    UserHandle.getUserId(defaultRI.activityInfo.applicationInfo.uid));
+                    UserHandle.getUserId(defaultActivity.applicationInfo.uid));
             // grant permission for default activity
             if (device != null) {
                 defaultRIUserSettings.
-                        grantDevicePermission(device, defaultRI.activityInfo.applicationInfo.uid);
+                        grantDevicePermission(device, defaultActivity.applicationInfo.uid);
             } else if (accessory != null) {
                 defaultRIUserSettings.grantAccessoryPermission(accessory,
-                                defaultRI.activityInfo.applicationInfo.uid);
+                        defaultActivity.applicationInfo.uid);
             }
 
             // start default activity directly
             try {
                 intent.setComponent(
-                        new ComponentName(defaultRI.activityInfo.packageName,
-                                defaultRI.activityInfo.name));
+                        new ComponentName(defaultActivity.packageName, defaultActivity.name));
 
                 UserHandle user = UserHandle.getUserHandleForUid(
-                        defaultRI.activityInfo.applicationInfo.uid);
+                        defaultActivity.applicationInfo.uid);
                 mContext.startActivityAsUser(intent, user);
             } catch (ActivityNotFoundException e) {
                 Slog.e(TAG, "startActivity failed", e);
@@ -1179,6 +1132,46 @@
         }
     }
 
+    /**
+     * Returns a default activity for matched ResolveInfo.
+     * @param matches Resolved activities matched with connected device/accesary.
+     * @param userPackage Default activity choosed by a user before. Should be null if no activity
+     *     is choosed by a user.
+     * @return Default activity
+     */
+    private @Nullable ActivityInfo getDefaultActivityLocked(
+            @NonNull ArrayList<ResolveInfo> matches,
+            @Nullable UserPackage userPackage) {
+        if (userPackage != null) {
+            // look for default activity
+            for (final ResolveInfo info : matches) {
+                if (info.activityInfo != null
+                        && userPackage.packageName.equals(info.activityInfo.packageName)
+                        && userPackage.user.getIdentifier()
+                                == UserHandle.getUserId(info.activityInfo.applicationInfo.uid)) {
+                    return info.activityInfo;
+                }
+            }
+        }
+
+        if (matches.size() == 1) {
+            final ActivityInfo activityInfo = matches.get(0).activityInfo;
+            if (activityInfo != null) {
+                // bypass dialog and launch the only matching activity
+                if (mDisablePermissionDialogs) {
+                    return activityInfo;
+                }
+                if (activityInfo.applicationInfo != null
+                        && (activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM)
+                                != 0) {
+                    return activityInfo;
+                }
+            }
+        }
+
+        return null;
+    }
+
     private boolean clearCompatibleMatchesLocked(String packageName, DeviceFilter filter) {
         boolean changed = false;
         for (DeviceFilter test : mDevicePreferenceMap.keySet()) {
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
index e89585c..ca37631 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
@@ -16,8 +16,6 @@
 
 package com.android.server.soundtrigger;
 
-import static android.hardware.soundtrigger.SoundTrigger.STATUS_ERROR;
-
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -42,6 +40,7 @@
 import android.telephony.TelephonyManager;
 import android.util.Slog;
 import com.android.internal.logging.MetricsLogger;
+import com.android.server.power.BatterySaverPolicy.ServiceType;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -841,7 +840,8 @@
             if (!PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(intent.getAction())) {
                 return;
             }
-            boolean active = mPowerManager.isPowerSaveMode();
+            boolean active = mPowerManager.getPowerSaveState(ServiceType.SOUND)
+                    .batterySaverEnabled;
             if (DBG) Slog.d(TAG, "onPowerSaveModeChanged: " + active);
             synchronized (mLock) {
                 onPowerSaveModeChangedLocked(active);
@@ -874,7 +874,8 @@
             mContext.registerReceiver(mPowerSaveModeListener,
                     new IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED));
         }
-        mIsPowerSaveMode = mPowerManager.isPowerSaveMode();
+        mIsPowerSaveMode = mPowerManager.getPowerSaveState(ServiceType.SOUND)
+                .batterySaverEnabled;
     }
 
     // Sends an error callback to all models with a valid registered callback.
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index b20384d..c790902 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -16,12 +16,21 @@
 
 package android.telecom;
 
+import android.annotation.IntDef;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.ParcelFileDescriptor;
 
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
 import java.lang.String;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -319,8 +328,15 @@
          */
         public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 0x00000080;
 
+        /**
+         * Indicates that the call is from a self-managed {@link ConnectionService}.
+         * <p>
+         * See also {@link Connection#PROPERTY_SELF_MANAGED}
+         */
+        public static final int PROPERTY_SELF_MANAGED = 0x00000100;
+
         //******************************************************************************************
-        // Next PROPERTY value: 0x00000100
+        // Next PROPERTY value: 0x00000200
         //******************************************************************************************
 
         private final String mTelecomCallId;
@@ -835,6 +851,155 @@
          * @param extras Extras associated with the connection event.
          */
         public void onConnectionEvent(Call call, String event, Bundle extras) {}
+
+        /**
+         * Invoked when the RTT mode changes for this call.
+         * @param call The call whose RTT mode has changed.
+         * @param mode the new RTT mode, one of
+         * {@link RttCall#RTT_MODE_FULL}, {@link RttCall#RTT_MODE_HCO},
+         *             or {@link RttCall#RTT_MODE_VCO}
+         */
+        public void onRttModeChanged(Call call, int mode) {}
+
+        /**
+         * Invoked when the call's RTT status changes, either from off to on or from on to off.
+         * @param call The call whose RTT status has changed.
+         * @param enabled whether RTT is now enabled or disabled
+         * @param rttCall the {@link RttCall} object to use for reading and writing if RTT is now
+         *                on, null otherwise.
+         */
+        public void onRttStatusChanged(Call call, boolean enabled, RttCall rttCall) {}
+
+        /**
+         * Invoked when the remote end of the connection has requested that an RTT communication
+         * channel be opened. A response to this should be sent via {@link #respondToRttRequest}
+         * with the same ID that this method is invoked with.
+         * @param call The call which the RTT request was placed on
+         * @param id The ID of the request.
+         */
+        public void onRttRequest(Call call, int id) {}
+
+        /**
+         * Invoked when the RTT session failed to initiate for some reason, including rejection
+         * by the remote party.
+         * @param call The call which the RTT initiation failure occurred on.
+         * @param reason One of the status codes defined in
+         *               {@link android.telecom.Connection.RttModifyStatus}, with the exception of
+         *               {@link android.telecom.Connection.RttModifyStatus#SESSION_MODIFY_REQUEST_SUCCESS}.
+         */
+        public void onRttInitiationFailure(Call call, int reason) {}
+    }
+
+    /**
+     * A class that holds the state that describes the state of the RTT channel to the remote
+     * party, if it is active.
+     */
+    public static final class RttCall {
+        /** @hide */
+        @Retention(RetentionPolicy.SOURCE)
+        @IntDef({RTT_MODE_INVALID, RTT_MODE_FULL, RTT_MODE_HCO, RTT_MODE_VCO})
+        public @interface RttAudioMode {}
+
+        /**
+         * For metrics use. Default value in the proto.
+         * @hide
+         */
+        public static final int RTT_MODE_INVALID = 0;
+
+        /**
+         * Indicates that there should be a bidirectional audio stream between the two parties
+         * on the call.
+         */
+        public static final int RTT_MODE_FULL = 1;
+
+        /**
+         * Indicates that the local user should be able to hear the audio stream from the remote
+         * user, but not vice versa. Equivalent to muting the microphone.
+         */
+        public static final int RTT_MODE_HCO = 2;
+
+        /**
+         * Indicates that the remote user should be able to hear the audio stream from the local
+         * user, but not vice versa. Equivalent to setting the volume to zero.
+         */
+        public static final int RTT_MODE_VCO = 3;
+
+        private static final int READ_BUFFER_SIZE = 1000;
+
+        private InputStreamReader mReceiveStream;
+        private OutputStreamWriter mTransmitStream;
+        private int mRttMode;
+        private final InCallAdapter mInCallAdapter;
+        private final String mTelecomCallId;
+        private char[] mReadBuffer = new char[READ_BUFFER_SIZE];
+
+        /**
+         * @hide
+         */
+        public RttCall(String telecomCallId, InputStreamReader receiveStream,
+                OutputStreamWriter transmitStream, int mode, InCallAdapter inCallAdapter) {
+            mTelecomCallId = telecomCallId;
+            mReceiveStream = receiveStream;
+            mTransmitStream = transmitStream;
+            mRttMode = mode;
+            mInCallAdapter = inCallAdapter;
+        }
+
+        /**
+         * Returns the current RTT audio mode.
+         * @return Current RTT audio mode. One of {@link #RTT_MODE_FULL}, {@link #RTT_MODE_VCO}, or
+         * {@link #RTT_MODE_HCO}.
+         */
+        public int getRttAudioMode() {
+            return mRttMode;
+        }
+
+        /**
+         * Sets the RTT audio mode. The requested mode change will be communicated through
+         * {@link Callback#onRttModeChanged(Call, int)}.
+         * @param mode The desired RTT audio mode, one of {@link #RTT_MODE_FULL},
+         * {@link #RTT_MODE_VCO}, or {@link #RTT_MODE_HCO}.
+         */
+        public void setRttMode(@RttAudioMode int mode) {
+            mInCallAdapter.setRttMode(mTelecomCallId, mode);
+        }
+
+        /**
+         * Writes the string {@param input} into the outgoing text stream for this RTT call. Since
+         * RTT transmits text in real-time, this method should be called once for each character
+         * the user enters into the device.
+         *
+         * This method is not thread-safe -- calling it from multiple threads simultaneously may
+         * lead to interleaved text.
+         * @param input The message to send to the remote user.
+         */
+        public void write(String input) throws IOException {
+            mTransmitStream.write(input);
+            mTransmitStream.flush();
+        }
+
+        /**
+         * Reads a string from the remote user, blocking if there is no data available. Returns
+         * {@code null} if the RTT conversation has been terminated and there is no further data
+         * to read.
+         *
+         * This method is not thread-safe -- calling it from multiple threads simultaneously may
+         * lead to interleaved text.
+         * @return A string containing text sent by the remote user, or {@code null} if the
+         * conversation has been terminated or if there was an error while reading.
+         */
+        public String read() {
+            try {
+                int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
+                if (numRead < 0) {
+                    return null;
+                }
+                return new String(mReadBuffer, 0, numRead);
+            } catch (IOException e) {
+                Log.w(this, "Exception encountered when reading from InputStreamReader: %s", e);
+                return null;
+            }
+        }
     }
 
     /**
@@ -861,8 +1026,10 @@
     private int mState;
     private List<String> mCannedTextResponses = null;
     private String mCallingPackage;
+    private int mTargetSdkVersion;
     private String mRemainingPostDialSequence;
     private VideoCallImpl mVideoCallImpl;
+    private RttCall mRttCall;
     private Details mDetails;
     private Bundle mExtras;
 
@@ -1061,6 +1228,34 @@
     }
 
     /**
+     * Sends an RTT upgrade request to the remote end of the connection. Success is not
+     * guaranteed, and notification of success will be via the
+     * {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
+     */
+    public void sendRttRequest() {
+        mInCallAdapter.sendRttRequest(mTelecomCallId);
+    }
+
+    /**
+     * Responds to an RTT request received via the {@link Callback#onRttRequest(Call, int)} )}
+     * callback.
+     * The ID used here should be the same as the ID that was received via the callback.
+     * @param id The request ID received via {@link Callback#onRttRequest(Call, int)}
+     * @param accept {@code true} if the RTT request should be accepted, {@code false} otherwise.
+     */
+    public void respondToRttRequest(int id, boolean accept) {
+        mInCallAdapter.respondToRttRequest(mTelecomCallId, id, accept);
+    }
+
+    /**
+     * Terminate the RTT session on this call. The resulting state change will be notified via
+     * the {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
+     */
+    public void stopRtt() {
+        mInCallAdapter.stopRtt(mTelecomCallId);
+    }
+
+    /**
      * Adds some extras to this {@link Call}.  Existing keys are replaced and new ones are
      * added.
      * <p>
@@ -1240,6 +1435,23 @@
     }
 
     /**
+     * Returns this call's RttCall object. The {@link RttCall} instance is used to send and
+     * receive RTT text data, as well as to change the RTT mode.
+     * @return A {@link Call.RttCall}. {@code null} if there is no active RTT connection.
+     */
+    public @Nullable RttCall getRttCall() {
+        return mRttCall;
+    }
+
+    /**
+     * Returns whether this call has an active RTT connection.
+     * @return true if there is a connection, false otherwise.
+     */
+    public boolean isRttActive() {
+        return mRttCall != null;
+    }
+
+    /**
      * Registers a callback to this {@code Call}.
      *
      * @param callback A {@code Callback}.
@@ -1348,22 +1560,25 @@
     }
 
     /** {@hide} */
-    Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, String callingPackage) {
+    Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, String callingPackage,
+         int targetSdkVersion) {
         mPhone = phone;
         mTelecomCallId = telecomCallId;
         mInCallAdapter = inCallAdapter;
         mState = STATE_NEW;
         mCallingPackage = callingPackage;
+        mTargetSdkVersion = targetSdkVersion;
     }
 
     /** {@hide} */
     Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, int state,
-            String callingPackage) {
+            String callingPackage, int targetSdkVersion) {
         mPhone = phone;
         mTelecomCallId = telecomCallId;
         mInCallAdapter = inCallAdapter;
         mState = state;
         mCallingPackage = callingPackage;
+        mTargetSdkVersion = targetSdkVersion;
     }
 
     /** {@hide} */
@@ -1389,7 +1604,8 @@
             cannedTextResponsesChanged = true;
         }
 
-        VideoCallImpl newVideoCallImpl = parcelableCall.getVideoCallImpl(mCallingPackage);
+        VideoCallImpl newVideoCallImpl = parcelableCall.getVideoCallImpl(mCallingPackage,
+                mTargetSdkVersion);
         boolean videoCallChanged = parcelableCall.isVideoCallProviderChanged() &&
                 !Objects.equals(mVideoCallImpl, newVideoCallImpl);
         if (videoCallChanged) {
@@ -1433,6 +1649,32 @@
             fireConferenceableCallsChanged();
         }
 
+        boolean isRttChanged = false;
+        boolean rttModeChanged = false;
+        if (parcelableCall.getParcelableRttCall() != null && parcelableCall.getIsRttCallChanged()) {
+            ParcelableRttCall parcelableRttCall = parcelableCall.getParcelableRttCall();
+            InputStreamReader receiveStream = new InputStreamReader(
+                    new ParcelFileDescriptor.AutoCloseInputStream(
+                            parcelableRttCall.getReceiveStream()),
+                    StandardCharsets.UTF_8);
+            OutputStreamWriter transmitStream = new OutputStreamWriter(
+                    new ParcelFileDescriptor.AutoCloseOutputStream(
+                            parcelableRttCall.getTransmitStream()),
+                    StandardCharsets.UTF_8);
+            RttCall newRttCall = new Call.RttCall(mTelecomCallId,
+                    receiveStream, transmitStream, parcelableRttCall.getRttMode(), mInCallAdapter);
+            if (mRttCall == null) {
+                isRttChanged = true;
+            } else if (mRttCall.getRttAudioMode() != newRttCall.getRttAudioMode()) {
+                rttModeChanged = true;
+            }
+            mRttCall = newRttCall;
+        } else if (mRttCall != null && parcelableCall.getParcelableRttCall() == null
+                && parcelableCall.getIsRttCallChanged()) {
+            isRttChanged = true;
+            mRttCall = null;
+        }
+
         // Now we fire updates, ensuring that any client who listens to any of these notifications
         // gets the most up-to-date state.
 
@@ -1454,6 +1696,12 @@
         if (childrenChanged) {
             fireChildrenChanged(getChildren());
         }
+        if (isRttChanged) {
+            fireOnIsRttChanged(mRttCall != null, mRttCall);
+        }
+        if (rttModeChanged) {
+            fireOnRttModeChanged(mRttCall.getRttAudioMode());
+        }
 
         // If we have transitioned to DISCONNECTED, that means we need to notify clients and
         // remove ourselves from the Phone. Note that we do this after completing all state updates
@@ -1484,6 +1732,24 @@
         fireOnConnectionEvent(event, extras);
     }
 
+    /** {@hide} */
+    final void internalOnRttUpgradeRequest(final int requestId) {
+        for (CallbackRecord<Callback> record : mCallbackRecords) {
+            final Call call = this;
+            final Callback callback = record.getCallback();
+            record.getHandler().post(() -> callback.onRttRequest(call, requestId));
+        }
+    }
+
+    /** @hide */
+    final void internalOnRttInitiationFailure(int reason) {
+        for (CallbackRecord<Callback> record : mCallbackRecords) {
+            final Call call = this;
+            final Callback callback = record.getCallback();
+            record.getHandler().post(() -> callback.onRttInitiationFailure(call, reason));
+        }
+    }
+
     private void fireStateChanged(final int newState) {
         for (CallbackRecord<Callback> record : mCallbackRecords) {
             final Call call = this;
@@ -1652,6 +1918,32 @@
     }
 
     /**
+     * Notifies listeners of an RTT on/off change
+     *
+     * @param enabled True if RTT is now enabled, false otherwise
+     */
+    private void fireOnIsRttChanged(final boolean enabled, final RttCall rttCall) {
+        for (CallbackRecord<Callback> record : mCallbackRecords) {
+            final Call call = this;
+            final Callback callback = record.getCallback();
+            record.getHandler().post(() -> callback.onRttStatusChanged(call, enabled, rttCall));
+        }
+    }
+
+    /**
+     * Notifies listeners of a RTT mode change
+     *
+     * @param mode The new RTT mode
+     */
+    private void fireOnRttModeChanged(final int mode) {
+        for (CallbackRecord<Callback> record : mCallbackRecords) {
+            final Call call = this;
+            final Callback callback = record.getCallback();
+            record.getHandler().post(() -> callback.onRttModeChanged(call, mode));
+        }
+    }
+
+    /**
      * Determines if two bundles are equal.
      *
      * @param bundle The original bundle.
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index b7391b4..833affa 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -20,9 +20,12 @@
 import com.android.internal.telecom.IVideoCallback;
 import com.android.internal.telecom.IVideoProvider;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.app.Notification;
+import android.content.Intent;
 import android.hardware.camera2.CameraManager;
 import android.net.Uri;
 import android.os.Binder;
@@ -31,10 +34,16 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.util.ArraySet;
 import android.view.Surface;
 
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -385,8 +394,14 @@
      */
     public static final int PROPERTY_SELF_MANAGED = 1<<7;
 
+    /**
+     * When set, indicates that a connection has an active RTT session associated with it.
+     * @hide
+     */
+    public static final int PROPERTY_IS_RTT = 1 << 8;
+
     //**********************************************************************************************
-    // Next PROPERTY value: 1<<8
+    // Next PROPERTY value: 1<<9
     //**********************************************************************************************
 
     /**
@@ -754,6 +769,114 @@
         /** @hide */
         public void onConferenceSupportedChanged(Connection c, boolean isConferenceSupported) {}
         public void onAudioRouteChanged(Connection c, int audioRoute) {}
+        public void onRttInitiationSuccess(Connection c) {}
+        public void onRttInitiationFailure(Connection c, int reason) {}
+        public void onRttSessionRemotelyTerminated(Connection c) {}
+        public void onRemoteRttRequest(Connection c) {}
+    }
+
+    /**
+     * Provides methods to read and write RTT data to/from the in-call app.
+     * @hide
+     */
+    public static final class RttTextStream {
+        private static final int READ_BUFFER_SIZE = 1000;
+        private final InputStreamReader mPipeFromInCall;
+        private final OutputStreamWriter mPipeToInCall;
+        private final ParcelFileDescriptor mFdFromInCall;
+        private final ParcelFileDescriptor mFdToInCall;
+        private char[] mReadBuffer = new char[READ_BUFFER_SIZE];
+
+        /**
+         * @hide
+         */
+        public RttTextStream(ParcelFileDescriptor toInCall, ParcelFileDescriptor fromInCall) {
+            mFdFromInCall = fromInCall;
+            mFdToInCall = toInCall;
+            mPipeFromInCall = new InputStreamReader(
+                    new ParcelFileDescriptor.AutoCloseInputStream(fromInCall));
+            mPipeToInCall = new OutputStreamWriter(
+                    new ParcelFileDescriptor.AutoCloseOutputStream(toInCall));
+        }
+
+        /**
+         * Writes the string {@param input} into the text stream to the UI for this RTT call. Since
+         * RTT transmits text in real-time, this method should be called as often as text snippets
+         * are received from the remote user, even if it is only one character.
+         *
+         * This method is not thread-safe -- calling it from multiple threads simultaneously may
+         * lead to interleaved text.
+         * @param input The message to send to the in-call app.
+         */
+        public void write(String input) throws IOException {
+            mPipeToInCall.write(input);
+            mPipeToInCall.flush();
+        }
+
+
+        /**
+         * Reads a string from the in-call app, blocking if there is no data available. Returns
+         * {@code null} if the RTT conversation has been terminated and there is no further data
+         * to read.
+         *
+         * This method is not thread-safe -- calling it from multiple threads simultaneously may
+         * lead to interleaved text.
+         * @return A string containing text entered by the user, or {@code null} if the
+         * conversation has been terminated or if there was an error while reading.
+         */
+        public String read() {
+            try {
+                int numRead = mPipeFromInCall.read(mReadBuffer, 0, READ_BUFFER_SIZE);
+                if (numRead < 0) {
+                    return null;
+                }
+                return new String(mReadBuffer, 0, numRead);
+            } catch (IOException e) {
+                Log.w(this, "Exception encountered when reading from InputStreamReader: %s", e);
+                return null;
+            }
+        }
+
+        /** @hide */
+        public ParcelFileDescriptor getFdFromInCall() {
+            return mFdFromInCall;
+        }
+
+        /** @hide */
+        public ParcelFileDescriptor getFdToInCall() {
+            return mFdToInCall;
+        }
+    }
+
+    /**
+     * Provides constants to represent the results of responses to session modify requests sent via
+     * {@link Call#sendRttRequest()}
+     */
+    public static final class RttModifyStatus {
+        /**
+         * Session modify request was successful.
+         */
+        public static final int SESSION_MODIFY_REQUEST_SUCCESS = 1;
+
+        /**
+         * Session modify request failed.
+         */
+        public static final int SESSION_MODIFY_REQUEST_FAIL = 2;
+
+        /**
+         * Session modify request ignored due to invalid parameters.
+         */
+        public static final int SESSION_MODIFY_REQUEST_INVALID = 3;
+
+        /**
+         * Session modify request timed out.
+         */
+        public static final int SESSION_MODIFY_REQUEST_TIMED_OUT = 4;
+
+        /**
+         * Session modify request rejected by remote user.
+         */
+        public static final int SESSION_MODIFY_REQUEST_REJECTED_BY_REMOTE = 5;
     }
 
     /**
@@ -936,7 +1059,7 @@
                         try {
                             onSetCamera((String) args.arg1);
                             onSetCamera((String) args.arg1, (String) args.arg2, args.argi1,
-                                    args.argi2);
+                                    args.argi2, args.argi3);
                         } finally {
                             args.recycle();
                         }
@@ -996,7 +1119,9 @@
                         MSG_REMOVE_VIDEO_CALLBACK, videoCallbackBinder).sendToTarget();
             }
 
-            public void setCamera(String cameraId, String callingPackageName) {
+            public void setCamera(String cameraId, String callingPackageName,
+                                  int targetSdkVersion) {
+
                 SomeArgs args = SomeArgs.obtain();
                 args.arg1 = cameraId;
                 // Propagate the calling package; originally determined in
@@ -1008,6 +1133,9 @@
                 // check to see if the calling app is able to use the camera.
                 args.argi1 = Binder.getCallingUid();
                 args.argi2 = Binder.getCallingPid();
+                // Pass along the target SDK version of the calling InCallService.  This is used to
+                // maintain backwards compatibility of the API for older callers.
+                args.argi3 = targetSdkVersion;
                 mMessageHandler.obtainMessage(MSG_SET_CAMERA, args).sendToTarget();
             }
 
@@ -1110,10 +1238,11 @@
          * @param callingPackageName The AppOpps package name of the caller.
          * @param callingUid The UID of the caller.
          * @param callingPid The PID of the caller.
+         * @param targetSdkVersion The target SDK version of the caller.
          * @hide
          */
         public void onSetCamera(String cameraId, String callingPackageName, int callingUid,
-                int callingPid) {}
+                int callingPid, int targetSdkVersion) {}
 
         /**
          * Sets the surface to be used for displaying a preview of what the user's camera is
@@ -2357,6 +2486,47 @@
     }
 
     /**
+     * Informs listeners that a previously requested RTT session via
+     * {@link ConnectionRequest#isRequestingRtt()} or
+     * {@link #onStartRtt(ParcelFileDescriptor, ParcelFileDescriptor)} has succeeded.
+     * @hide
+     */
+    public final void sendRttInitiationSuccess() {
+        mListeners.forEach((l) -> l.onRttInitiationSuccess(Connection.this));
+    }
+
+    /**
+     * Informs listeners that a previously requested RTT session via
+     * {@link ConnectionRequest#isRequestingRtt()} or
+     * {@link #onStartRtt(ParcelFileDescriptor, ParcelFileDescriptor)}
+     * has failed.
+     * @param reason One of the reason codes defined in {@link RttModifyStatus}, with the
+     *               exception of {@link RttModifyStatus#SESSION_MODIFY_REQUEST_SUCCESS}.
+     * @hide
+     */
+    public final void sendRttInitiationFailure(int reason) {
+        mListeners.forEach((l) -> l.onRttInitiationFailure(Connection.this, reason));
+    }
+
+    /**
+     * Informs listeners that a currently active RTT session has been terminated by the remote
+     * side of the coll.
+     * @hide
+     */
+    public final void sendRttSessionRemotelyTerminated() {
+        mListeners.forEach((l) -> l.onRttSessionRemotelyTerminated(Connection.this));
+    }
+
+    /**
+     * Informs listeners that the remote side of the call has requested an upgrade to include an
+     * RTT session in the call.
+     * @hide
+     */
+    public final void sendRemoteRttRequest() {
+        mListeners.forEach((l) -> l.onRemoteRttRequest(Connection.this));
+    }
+
+    /**
      * Notifies this Connection that the {@link #getAudioState()} property has a new value.
      *
      * @param state The new connection audio state.
@@ -2523,9 +2693,73 @@
      * regular {@link ConnectionService}, the Telecom framework will display its own incoming call
      * user interface to allow the user to choose whether to answer the new incoming call and
      * disconnect other ongoing calls, or to reject the new incoming call.
+     * <p>
+     * You should trigger the display of the incoming call user interface for your application by
+     * showing a {@link Notification} with a full-screen {@link Intent} specified.
+     * For example:
+     * <pre><code>
+     *     // Create an intent which triggers your fullscreen incoming call user interface.
+     *     Intent intent = new Intent(Intent.ACTION_MAIN, null);
+     *     intent.setFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION | Intent.FLAG_ACTIVITY_NEW_TASK);
+     *     intent.setClass(context, YourIncomingCallActivity.class);
+     *     PendingIntent pendingIntent = PendingIntent.getActivity(context, 1, intent, 0);
+     *
+     *     // Build the notification as an ongoing high priority item; this ensures it will show as
+     *     // a heads up notification which slides down over top of the current content.
+     *     final Notification.Builder builder = new Notification.Builder(context);
+     *     builder.setOngoing(true);
+     *     builder.setPriority(Notification.PRIORITY_HIGH);
+     *
+     *     // Set notification content intent to take user to fullscreen UI if user taps on the
+     *     // notification body.
+     *     builder.setContentIntent(pendingIntent);
+     *     // Set full screen intent to trigger display of the fullscreen UI when the notification
+     *     // manager deems it appropriate.
+     *     builder.setFullScreenIntent(pendingIntent, true);
+     *
+     *     // Setup notification content.
+     *     builder.setSmallIcon( yourIconResourceId );
+     *     builder.setContentTitle("Your notification title");
+     *     builder.setContentText("Your notification content.");
+     *
+     *     // Use builder.addAction(..) to add buttons to answer or reject the call.
+     *
+     *     NotificationManager notificationManager = mContext.getSystemService(
+     *         NotificationManager.class);
+     *     notificationManager.notify(YOUR_TAG, YOUR_ID, builder.build());
+     * </code></pre>
      */
     public void onShowIncomingCallUi() {}
 
+    /**
+     * Notifies this {@link Connection} that the user has requested an RTT session.
+     * The connection service should call {@link #sendRttInitiationSuccess} or
+     * {@link #sendRttInitiationFailure} to inform Telecom of the success or failure of the
+     * request, respectively.
+     * @param rttTextStream The object that should be used to send text to or receive text from
+     *                      the in-call app.
+     * @hide
+     */
+    public void onStartRtt(@NonNull RttTextStream rttTextStream) {}
+
+    /**
+     * Notifies this {@link Connection} that it should terminate any existing RTT communication
+     * channel. No response to Telecom is needed for this method.
+     * @hide
+     */
+    public void onStopRtt() {}
+
+    /**
+     * Notifies this connection of a response to a previous remotely-initiated RTT upgrade
+     * request sent via {@link #sendRemoteRttRequest}. Acceptance of the request is
+     * indicated by the supplied {@link RttTextStream} being non-null, and rejection is
+     * indicated by {@code rttTextStream} being {@code null}
+     * @hide
+     * @param rttTextStream The object that should be used to send text to or receive text from
+     *                      the in-call app.
+     */
+    public void handleRttUpgradeResponse(@Nullable RttTextStream rttTextStream) {}
+
     static String toLogSafePhoneNumber(String number) {
         // For unknown number, log empty string.
         if (number == null) {
diff --git a/telecomm/java/android/telecom/ConnectionRequest.java b/telecomm/java/android/telecom/ConnectionRequest.java
index 2343462..054de4c 100644
--- a/telecomm/java/android/telecom/ConnectionRequest.java
+++ b/telecomm/java/android/telecom/ConnectionRequest.java
@@ -19,6 +19,7 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Parcel;
+import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
 
 /**
@@ -27,13 +28,121 @@
  */
 public final class ConnectionRequest implements Parcelable {
 
-    // TODO: Token to limit recursive invocations
+    /**
+     * Builder class for {@link ConnectionRequest}
+     * @hide
+     */
+    public static final class Builder {
+        private PhoneAccountHandle mAccountHandle;
+        private Uri mAddress;
+        private Bundle mExtras;
+        private int mVideoState = VideoProfile.STATE_AUDIO_ONLY;
+        private String mTelecomCallId;
+        private boolean mShouldShowIncomingCallUi = false;
+        private ParcelFileDescriptor mRttPipeToInCall;
+        private ParcelFileDescriptor mRttPipeFromInCall;
+
+        public Builder() { }
+
+        /**
+         * Sets the phone account handle for the resulting {@link ConnectionRequest}
+         * @param accountHandle The accountHandle which should be used to place the call.
+         */
+        public Builder setAccountHandle(PhoneAccountHandle accountHandle) {
+            this.mAccountHandle = accountHandle;
+            return this;
+        }
+
+        /**
+         * Sets the address for the resulting {@link ConnectionRequest}
+         * @param address The address(e.g., phone number) to which the {@link Connection} is to
+         *                connect.
+         */
+        public Builder setAddress(Uri address) {
+            this.mAddress = address;
+            return this;
+        }
+
+        /**
+         * Sets the extras bundle for the resulting {@link ConnectionRequest}
+         * @param extras Application-specific extra data.
+         */
+        public Builder setExtras(Bundle extras) {
+            this.mExtras = extras;
+            return this;
+        }
+
+        /**
+         * Sets the video state for the resulting {@link ConnectionRequest}
+         * @param videoState Determines the video state for the connection.
+         */
+        public Builder setVideoState(int videoState) {
+            this.mVideoState = videoState;
+            return this;
+        }
+
+        /**
+         * Sets the Telecom call ID for the resulting {@link ConnectionRequest}
+         * @param telecomCallId The telecom call ID.
+         */
+        public Builder setTelecomCallId(String telecomCallId) {
+            this.mTelecomCallId = telecomCallId;
+            return this;
+        }
+
+        /**
+         * Sets shouldShowIncomingUi for the resulting {@link ConnectionRequest}
+         * @param shouldShowIncomingCallUi For a self-managed {@link ConnectionService}, will be
+         *                                 {@code true} if the {@link ConnectionService} should show
+         *                                 its own incoming call UI for an incoming call.  When
+         *                                 {@code false}, Telecom shows the incoming call UI.
+         */
+        public Builder setShouldShowIncomingCallUi(boolean shouldShowIncomingCallUi) {
+            this.mShouldShowIncomingCallUi = shouldShowIncomingCallUi;
+            return this;
+        }
+
+        /**
+         * Sets the RTT pipe for transferring text into the {@link ConnectionService} for the
+         * resulting {@link ConnectionRequest}
+         * @param rttPipeFromInCall The data pipe to read from.
+         */
+        public Builder setRttPipeFromInCall(ParcelFileDescriptor rttPipeFromInCall) {
+            this.mRttPipeFromInCall = rttPipeFromInCall;
+            return this;
+        }
+
+        /**
+         * Sets the RTT pipe for transferring text out of {@link ConnectionService} for the
+         * resulting {@link ConnectionRequest}
+         * @param rttPipeToInCall The data pipe to write to.
+         */
+        public Builder setRttPipeToInCall(ParcelFileDescriptor rttPipeToInCall) {
+            this.mRttPipeToInCall = rttPipeToInCall;
+            return this;
+        }
+
+        public ConnectionRequest build() {
+            return new ConnectionRequest(
+                    mAccountHandle,
+                    mAddress,
+                    mExtras,
+                    mVideoState,
+                    mTelecomCallId,
+                    mShouldShowIncomingCallUi,
+                    mRttPipeFromInCall,
+                    mRttPipeToInCall);
+        }
+    }
+
     private final PhoneAccountHandle mAccountHandle;
     private final Uri mAddress;
     private final Bundle mExtras;
     private final int mVideoState;
     private final String mTelecomCallId;
     private final boolean mShouldShowIncomingCallUi;
+    private final ParcelFileDescriptor mRttPipeToInCall;
+    private final ParcelFileDescriptor mRttPipeFromInCall;
 
     /**
      * @param accountHandle The accountHandle which should be used to place the call.
@@ -44,7 +153,7 @@
             PhoneAccountHandle accountHandle,
             Uri handle,
             Bundle extras) {
-        this(accountHandle, handle, extras, VideoProfile.STATE_AUDIO_ONLY, null, false);
+        this(accountHandle, handle, extras, VideoProfile.STATE_AUDIO_ONLY, null, false, null, null);
     }
 
     /**
@@ -58,7 +167,7 @@
             Uri handle,
             Bundle extras,
             int videoState) {
-        this(accountHandle, handle, extras, videoState, null, false);
+        this(accountHandle, handle, extras, videoState, null, false, null, null);
     }
 
     /**
@@ -80,12 +189,27 @@
             int videoState,
             String telecomCallId,
             boolean shouldShowIncomingCallUi) {
+        this(accountHandle, handle, extras, videoState, telecomCallId,
+                shouldShowIncomingCallUi, null, null);
+    }
+
+    private ConnectionRequest(
+            PhoneAccountHandle accountHandle,
+            Uri handle,
+            Bundle extras,
+            int videoState,
+            String telecomCallId,
+            boolean shouldShowIncomingCallUi,
+            ParcelFileDescriptor rttPipeFromInCall,
+            ParcelFileDescriptor rttPipeToInCall) {
         mAccountHandle = accountHandle;
         mAddress = handle;
         mExtras = extras;
         mVideoState = videoState;
         mTelecomCallId = telecomCallId;
         mShouldShowIncomingCallUi = shouldShowIncomingCallUi;
+        mRttPipeFromInCall = rttPipeFromInCall;
+        mRttPipeToInCall = rttPipeToInCall;
     }
 
     private ConnectionRequest(Parcel in) {
@@ -95,6 +219,8 @@
         mVideoState = in.readInt();
         mTelecomCallId = in.readString();
         mShouldShowIncomingCallUi = in.readInt() == 1;
+        mRttPipeFromInCall = in.readParcelable(getClass().getClassLoader());
+        mRttPipeToInCall = in.readParcelable(getClass().getClassLoader());
     }
 
     /**
@@ -149,6 +275,59 @@
         return mShouldShowIncomingCallUi;
     }
 
+    /**
+     * Gets the {@link ParcelFileDescriptor} that is used to send RTT text from the connection
+     * service to the in-call UI. In order to obtain an
+     * {@link java.io.InputStream} from this {@link ParcelFileDescriptor}, use
+     * {@link android.os.ParcelFileDescriptor.AutoCloseInputStream}.
+     * Only text data encoded using UTF-8 should be written into this {@link ParcelFileDescriptor}.
+     * @return The {@link ParcelFileDescriptor} that should be used for communication.
+     * Do not un-hide -- only for use by Telephony
+     * @hide
+     */
+    public ParcelFileDescriptor getRttPipeToInCall() {
+        return mRttPipeToInCall;
+    }
+
+    /**
+     * Gets the {@link ParcelFileDescriptor} that is used to send RTT text from the in-call UI to
+     * the connection service. In order to obtain an
+     * {@link java.io.OutputStream} from this {@link ParcelFileDescriptor}, use
+     * {@link android.os.ParcelFileDescriptor.AutoCloseOutputStream}.
+     * The contents of this {@link ParcelFileDescriptor} will consist solely of text encoded in
+     * UTF-8.
+     * @return The {@link ParcelFileDescriptor} that should be used for communication
+     * Do not un-hide -- only for use by Telephony
+     * @hide
+     */
+    public ParcelFileDescriptor getRttPipeFromInCall() {
+        return mRttPipeFromInCall;
+    }
+
+    /**
+     * Gets the {@link android.telecom.Connection.RttTextStream} object that should be used to
+     * send and receive RTT text to/from the in-call app.
+     * @return An instance of {@link android.telecom.Connection.RttTextStream}, or {@code null}
+     * if this connection request is not requesting an RTT session upon connection establishment.
+     * @hide
+     */
+    public Connection.RttTextStream getRttTextStream() {
+        if (isRequestingRtt()) {
+            return new Connection.RttTextStream(mRttPipeToInCall, mRttPipeFromInCall);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Convenience method for determining whether the ConnectionRequest is requesting an RTT session
+     * @return {@code true} if RTT is requested, {@code false} otherwise.
+     * @hide
+     */
+    public boolean isRequestingRtt() {
+        return mRttPipeFromInCall != null && mRttPipeToInCall != null;
+    }
+
     @Override
     public String toString() {
         return String.format("ConnectionRequest %s %s",
@@ -186,5 +365,7 @@
         destination.writeInt(mVideoState);
         destination.writeString(mTelecomCallId);
         destination.writeInt(mShouldShowIncomingCallUi ? 1 : 0);
+        destination.writeParcelable(mRttPipeFromInCall, 0);
+        destination.writeParcelable(mRttPipeToInCall, 0);
     }
 }
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 6e10029..bf8f8e4 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -26,6 +26,8 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
 import android.telecom.Logging.Session;
 
 import com.android.internal.os.SomeArgs;
@@ -119,6 +121,9 @@
     private static final String SESSION_PULL_EXTERNAL_CALL = "CS.pEC";
     private static final String SESSION_SEND_CALL_EVENT = "CS.sCE";
     private static final String SESSION_EXTRAS_CHANGED = "CS.oEC";
+    private static final String SESSION_START_RTT = "CS.+RTT";
+    private static final String SESSION_STOP_RTT = "CS.-RTT";
+    private static final String SESSION_RTT_UPGRADE_RESPONSE = "CS.rTRUR";
 
     private static final int MSG_ADD_CONNECTION_SERVICE_ADAPTER = 1;
     private static final int MSG_CREATE_CONNECTION = 2;
@@ -144,6 +149,9 @@
     private static final int MSG_SEND_CALL_EVENT = 23;
     private static final int MSG_ON_EXTRAS_CHANGED = 24;
     private static final int MSG_CREATE_CONNECTION_FAILED = 25;
+    private static final int MSG_ON_START_RTT = 26;
+    private static final int MSG_ON_STOP_RTT = 27;
+    private static final int MSG_RTT_UPGRADE_RESPONSE = 28;
 
     private static Connection sNullConnection;
 
@@ -214,6 +222,7 @@
 
         @Override
         public void createConnectionFailed(
+                PhoneAccountHandle connectionManagerPhoneAccount,
                 String callId,
                 ConnectionRequest request,
                 boolean isIncoming,
@@ -224,6 +233,7 @@
                 args.arg1 = callId;
                 args.arg2 = request;
                 args.arg3 = Log.createSubsession();
+                args.arg4 = connectionManagerPhoneAccount;
                 args.argi1 = isIncoming ? 1 : 0;
                 mHandler.obtainMessage(MSG_CREATE_CONNECTION_FAILED, args).sendToTarget();
             } finally {
@@ -501,6 +511,53 @@
                 Log.endSession();
             }
         }
+
+        @Override
+        public void startRtt(String callId, ParcelFileDescriptor fromInCall,
+                ParcelFileDescriptor toInCall, Session.Info sessionInfo) throws RemoteException {
+            Log.startSession(sessionInfo, SESSION_START_RTT);
+            try {
+                SomeArgs args = SomeArgs.obtain();
+                args.arg1 = callId;
+                args.arg2 = new Connection.RttTextStream(toInCall, fromInCall);
+                args.arg3 = Log.createSubsession();
+                mHandler.obtainMessage(MSG_ON_START_RTT, args).sendToTarget();
+            } finally {
+                Log.endSession();
+            }
+        }
+
+        @Override
+        public void stopRtt(String callId, Session.Info sessionInfo) throws RemoteException {
+            Log.startSession(sessionInfo, SESSION_STOP_RTT);
+            try {
+                SomeArgs args = SomeArgs.obtain();
+                args.arg1 = callId;
+                args.arg2 = Log.createSubsession();
+                mHandler.obtainMessage(MSG_ON_STOP_RTT, args).sendToTarget();
+            } finally {
+                Log.endSession();
+            }
+        }
+
+        @Override
+        public void respondToRttUpgradeRequest(String callId, ParcelFileDescriptor fromInCall,
+                ParcelFileDescriptor toInCall, Session.Info sessionInfo) throws RemoteException {
+            Log.startSession(sessionInfo, SESSION_RTT_UPGRADE_RESPONSE);
+            try {
+                SomeArgs args = SomeArgs.obtain();
+                args.arg1 = callId;
+                if (toInCall == null || fromInCall == null) {
+                    args.arg2 = null;
+                } else {
+                    args.arg2 = new Connection.RttTextStream(toInCall, fromInCall);
+                }
+                args.arg3 = Log.createSubsession();
+                mHandler.obtainMessage(MSG_RTT_UPGRADE_RESPONSE, args).sendToTarget();
+            } finally {
+                Log.endSession();
+            }
+        }
     };
 
     private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@@ -581,6 +638,8 @@
                         final String id = (String) args.arg1;
                         final ConnectionRequest request = (ConnectionRequest) args.arg2;
                         final boolean isIncoming = args.argi1 == 1;
+                        final PhoneAccountHandle connectionMgrPhoneAccount =
+                                (PhoneAccountHandle) args.arg4;
                         if (!mAreAccountsInitialized) {
                             Log.d(this, "Enqueueing pre-init request %s", id);
                             mPreInitializationConnectionRequests.add(
@@ -589,12 +648,14 @@
                                             null /*lock*/) {
                                         @Override
                                         public void loggedRun() {
-                                            createConnectionFailed(id, request, isIncoming);
+                                            createConnectionFailed(connectionMgrPhoneAccount, id,
+                                                    request, isIncoming);
                                         }
                                     }.prepare());
                         } else {
                             Log.i(this, "createConnectionFailed %s", id);
-                            createConnectionFailed(id, request, isIncoming);
+                            createConnectionFailed(connectionMgrPhoneAccount, id, request,
+                                    isIncoming);
                         }
                     } finally {
                         args.recycle();
@@ -848,6 +909,49 @@
                     }
                     break;
                 }
+                case MSG_ON_START_RTT: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    try {
+                        Log.continueSession((Session) args.arg3,
+                                SESSION_HANDLER + SESSION_START_RTT);
+                        String callId = (String) args.arg1;
+                        Connection.RttTextStream rttTextStream =
+                                (Connection.RttTextStream) args.arg2;
+                        startRtt(callId, rttTextStream);
+                    } finally {
+                        args.recycle();
+                        Log.endSession();
+                    }
+                    break;
+                }
+                case MSG_ON_STOP_RTT: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    try {
+                        Log.continueSession((Session) args.arg2,
+                                SESSION_HANDLER + SESSION_STOP_RTT);
+                        String callId = (String) args.arg1;
+                        stopRtt(callId);
+                    } finally {
+                        args.recycle();
+                        Log.endSession();
+                    }
+                    break;
+                }
+                case MSG_RTT_UPGRADE_RESPONSE: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    try {
+                        Log.continueSession((Session) args.arg3,
+                                SESSION_HANDLER + SESSION_RTT_UPGRADE_RESPONSE);
+                        String callId = (String) args.arg1;
+                        Connection.RttTextStream rttTextStream =
+                                (Connection.RttTextStream) args.arg2;
+                        handleRttUpgradeResponse(callId, rttTextStream);
+                    } finally {
+                        args.recycle();
+                        Log.endSession();
+                    }
+                    break;
+                }
                 default:
                     break;
             }
@@ -1136,6 +1240,38 @@
                 mAdapter.setAudioRoute(id, audioRoute);
             }
         }
+
+        @Override
+        public void onRttInitiationSuccess(Connection c) {
+            String id = mIdByConnection.get(c);
+            if (id != null) {
+                mAdapter.onRttInitiationSuccess(id);
+            }
+        }
+
+        @Override
+        public void onRttInitiationFailure(Connection c, int reason) {
+            String id = mIdByConnection.get(c);
+            if (id != null) {
+                mAdapter.onRttInitiationFailure(id, reason);
+            }
+        }
+
+        @Override
+        public void onRttSessionRemotelyTerminated(Connection c) {
+            String id = mIdByConnection.get(c);
+            if (id != null) {
+                mAdapter.onRttSessionRemotelyTerminated(id);
+            }
+        }
+
+        @Override
+        public void onRemoteRttRequest(Connection c) {
+            String id = mIdByConnection.get(c);
+            if (id != null) {
+                mAdapter.onRemoteRttRequest(id);
+            }
+        }
     };
 
     /** {@inheritDoc} */
@@ -1225,14 +1361,15 @@
         }
     }
 
-    private void createConnectionFailed(final String callId, final ConnectionRequest request,
-            boolean isIncoming) {
+    private void createConnectionFailed(final PhoneAccountHandle callManagerAccount,
+                                        final String callId, final ConnectionRequest request,
+                                        boolean isIncoming) {
 
         Log.i(this, "createConnectionFailed %s", callId);
         if (isIncoming) {
-            onCreateIncomingConnectionFailed(request);
+            onCreateIncomingConnectionFailed(callManagerAccount, request);
         } else {
-            onCreateOutgoingConnectionFailed(request);
+            onCreateOutgoingConnectionFailed(callManagerAccount, request);
         }
     }
 
@@ -1430,7 +1567,6 @@
         if (connection != null) {
             connection.onCallEvent(event, extras);
         }
-
     }
 
     /**
@@ -1454,6 +1590,34 @@
         }
     }
 
+    private void startRtt(String callId, Connection.RttTextStream rttTextStream) {
+        Log.d(this, "startRtt(%s)", callId);
+        if (mConnectionById.containsKey(callId)) {
+            findConnectionForAction(callId, "startRtt").onStartRtt(rttTextStream);
+        } else if (mConferenceById.containsKey(callId)) {
+            Log.w(this, "startRtt called on a conference.");
+        }
+    }
+
+    private void stopRtt(String callId) {
+        Log.d(this, "stopRtt(%s)", callId);
+        if (mConnectionById.containsKey(callId)) {
+            findConnectionForAction(callId, "stopRtt").onStopRtt();
+        } else if (mConferenceById.containsKey(callId)) {
+            Log.w(this, "stopRtt called on a conference.");
+        }
+    }
+
+    private void handleRttUpgradeResponse(String callId, Connection.RttTextStream rttTextStream) {
+        Log.d(this, "handleRttUpgradeResponse(%s, %s)", callId, rttTextStream == null);
+        if (mConnectionById.containsKey(callId)) {
+            findConnectionForAction(callId, "handleRttUpgradeResponse")
+                    .handleRttUpgradeResponse(rttTextStream);
+        } else if (mConferenceById.containsKey(callId)) {
+            Log.w(this, "handleRttUpgradeResponse called on a conference.");
+        }
+    }
+
     private void onPostDialContinue(String callId, boolean proceed) {
         Log.d(this, "onPostDialContinue(%s)", callId);
         findConnectionForAction(callId, "stopDtmfTone").onPostDialContinue(proceed);
@@ -1682,9 +1846,12 @@
      * <p>
      * See {@link TelecomManager#isIncomingCallPermitted(PhoneAccountHandle)} for more information.
      *
+     * @param connectionManagerPhoneAccount See description at
+     *         {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
      * @param request The incoming connection request.
      */
-    public void onCreateIncomingConnectionFailed(ConnectionRequest request) {
+    public void onCreateIncomingConnectionFailed(PhoneAccountHandle connectionManagerPhoneAccount,
+                                                 ConnectionRequest request) {
     }
 
     /**
@@ -1698,9 +1865,12 @@
      * <p>
      * See {@link TelecomManager#isOutgoingCallPermitted(PhoneAccountHandle)} for more information.
      *
+     * @param connectionManagerPhoneAccount See description at
+     *         {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
      * @param request The outgoing connection request.
      */
-    public void onCreateOutgoingConnectionFailed(ConnectionRequest request) {
+    public void onCreateOutgoingConnectionFailed(PhoneAccountHandle connectionManagerPhoneAccount,
+                                                 ConnectionRequest request) {
     }
 
     /**
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapter.java b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
index 9542b73..63bdf74 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapter.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
@@ -547,4 +547,66 @@
             }
         }
     }
+
+    /**
+     * Notifies Telecom that an RTT session was successfully established.
+     *
+     * @param callId The unique ID of the call.
+     */
+    void onRttInitiationSuccess(String callId) {
+        Log.v(this, "onRttInitiationSuccess: %s", callId);
+        for (IConnectionServiceAdapter adapter : mAdapters) {
+            try {
+                adapter.onRttInitiationSuccess(callId, Log.getExternalSession());
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
+    /**
+     * Notifies Telecom that a requested RTT session failed to be established.
+     *
+     * @param callId The unique ID of the call.
+     */
+    void onRttInitiationFailure(String callId, int reason) {
+        Log.v(this, "onRttInitiationFailure: %s", callId);
+        for (IConnectionServiceAdapter adapter : mAdapters) {
+            try {
+                adapter.onRttInitiationFailure(callId, reason, Log.getExternalSession());
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
+    /**
+     * Notifies Telecom that an established RTT session was terminated by the remote user on
+     * the call.
+     *
+     * @param callId The unique ID of the call.
+     */
+    void onRttSessionRemotelyTerminated(String callId) {
+        Log.v(this, "onRttSessionRemotelyTerminated: %s", callId);
+        for (IConnectionServiceAdapter adapter : mAdapters) {
+            try {
+                adapter.onRttSessionRemotelyTerminated(callId, Log.getExternalSession());
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
+    /**
+     * Notifies Telecom that the remote user on the call has requested an upgrade to an RTT
+     * session for this call.
+     *
+     * @param callId The unique ID of the call.
+     */
+    void onRemoteRttRequest(String callId) {
+        Log.v(this, "onRemoteRttRequest: %s", callId);
+        for (IConnectionServiceAdapter adapter : mAdapters) {
+            try {
+                adapter.onRemoteRttRequest(callId, Log.getExternalSession());
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
 }
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
index cc437f9..80e3c33 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
@@ -68,6 +68,10 @@
     private static final int MSG_SET_CONNECTION_PROPERTIES = 27;
     private static final int MSG_SET_PULLING = 28;
     private static final int MSG_SET_AUDIO_ROUTE = 29;
+    private static final int MSG_ON_RTT_INITIATION_SUCCESS = 30;
+    private static final int MSG_ON_RTT_INITIATION_FAILURE = 31;
+    private static final int MSG_ON_RTT_REMOTELY_TERMINATED = 32;
+    private static final int MSG_ON_RTT_UPGRADE_REQUEST = 33;
 
     private final IConnectionServiceAdapter mDelegate;
 
@@ -300,6 +304,20 @@
                     }
                     break;
                 }
+                case MSG_ON_RTT_INITIATION_SUCCESS:
+                    mDelegate.onRttInitiationSuccess((String) msg.obj, null /*Session.Info*/);
+                    break;
+                case MSG_ON_RTT_INITIATION_FAILURE:
+                    mDelegate.onRttInitiationFailure((String) msg.obj, msg.arg1,
+                            null /*Session.Info*/);
+                    break;
+                case MSG_ON_RTT_REMOTELY_TERMINATED:
+                    mDelegate.onRttSessionRemotelyTerminated((String) msg.obj,
+                            null /*Session.Info*/);
+                    break;
+                case MSG_ON_RTT_UPGRADE_REQUEST:
+                    mDelegate.onRemoteRttRequest((String) msg.obj, null /*Session.Info*/);
+                    break;
             }
         }
     };
@@ -537,6 +555,32 @@
             args.arg3 = extras;
             mHandler.obtainMessage(MSG_ON_CONNECTION_EVENT, args).sendToTarget();
         }
+
+        @Override
+        public void onRttInitiationSuccess(String connectionId, Session.Info sessionInfo)
+                throws RemoteException {
+            mHandler.obtainMessage(MSG_ON_RTT_INITIATION_SUCCESS, connectionId).sendToTarget();
+        }
+
+        @Override
+        public void onRttInitiationFailure(String connectionId, int reason,
+                Session.Info sessionInfo)
+                throws RemoteException {
+            mHandler.obtainMessage(MSG_ON_RTT_INITIATION_FAILURE, reason, 0, connectionId)
+                    .sendToTarget();
+        }
+
+        @Override
+        public void onRttSessionRemotelyTerminated(String connectionId, Session.Info sessionInfo)
+                throws RemoteException {
+            mHandler.obtainMessage(MSG_ON_RTT_REMOTELY_TERMINATED, connectionId).sendToTarget();
+        }
+
+        @Override
+        public void onRemoteRttRequest(String connectionId, Session.Info sessionInfo)
+                throws RemoteException {
+            mHandler.obtainMessage(MSG_ON_RTT_UPGRADE_REQUEST, connectionId).sendToTarget();
+        }
     };
 
     public ConnectionServiceAdapterServant(IConnectionServiceAdapter delegate) {
diff --git a/telecomm/java/android/telecom/InCallAdapter.java b/telecomm/java/android/telecom/InCallAdapter.java
index 3f270d9..9559a28 100644
--- a/telecomm/java/android/telecom/InCallAdapter.java
+++ b/telecomm/java/android/telecom/InCallAdapter.java
@@ -34,7 +34,7 @@
  * <p>
  * The adapter will stop functioning when there are no more calls.
  *
- * {@hide}
+ * @hide
  */
 public final class InCallAdapter {
     private final IInCallAdapter mAdapter;
@@ -375,4 +375,48 @@
         } catch (RemoteException ignored) {
         }
     }
+
+    /**
+     * Sends an RTT upgrade request to the remote end of the connection.
+     */
+    public void sendRttRequest(String callId) {
+        try {
+            mAdapter.sendRttRequest(callId);
+        } catch (RemoteException ignored) {
+        }
+    }
+
+    /**
+     * Responds to an RTT upgrade request initiated from the remote end.
+     *
+     * @param id the ID of the request as specified by Telecom
+     * @param accept Whether the request should be accepted.
+     */
+    public void respondToRttRequest(String callId, int id, boolean accept) {
+        try {
+            mAdapter.respondToRttRequest(callId, id, accept);
+        } catch (RemoteException ignored) {
+        }
+    }
+
+    /**
+     * Instructs Telecom to shut down the RTT communication channel.
+     */
+    public void stopRtt(String callId) {
+        try {
+            mAdapter.stopRtt(callId);
+        } catch (RemoteException ignored) {
+        }
+    }
+
+    /**
+     * Sets the RTT audio mode.
+     * @param mode the desired RTT audio mode
+     */
+    public void setRttMode(String callId, int mode) {
+        try {
+            mAdapter.setRttMode(callId, mode);
+        } catch (RemoteException ignored) {
+        }
+    }
 }
diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java
index 5d68aae..e384d46 100644
--- a/telecomm/java/android/telecom/InCallService.java
+++ b/telecomm/java/android/telecom/InCallService.java
@@ -76,6 +76,8 @@
     private static final int MSG_ON_CAN_ADD_CALL_CHANGED = 7;
     private static final int MSG_SILENCE_RINGER = 8;
     private static final int MSG_ON_CONNECTION_EVENT = 9;
+    private static final int MSG_ON_RTT_UPGRADE_REQUEST = 10;
+    private static final int MSG_ON_RTT_INITIATION_FAILURE = 11;
 
     /** Default Handler used to consolidate binder method calls onto a single thread. */
     private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@@ -88,7 +90,8 @@
             switch (msg.what) {
                 case MSG_SET_IN_CALL_ADAPTER:
                     String callingPackage = getApplicationContext().getOpPackageName();
-                    mPhone = new Phone(new InCallAdapter((IInCallAdapter) msg.obj), callingPackage);
+                    mPhone = new Phone(new InCallAdapter((IInCallAdapter) msg.obj), callingPackage,
+                            getApplicationContext().getApplicationInfo().targetSdkVersion);
                     mPhone.addListener(mPhoneListener);
                     onPhoneCreated(mPhone);
                     break;
@@ -133,6 +136,18 @@
                     }
                     break;
                 }
+                case MSG_ON_RTT_UPGRADE_REQUEST: {
+                    String callId = (String) msg.obj;
+                    int requestId = msg.arg1;
+                    mPhone.internalOnRttUpgradeRequest(callId, requestId);
+                    break;
+                }
+                case MSG_ON_RTT_INITIATION_FAILURE: {
+                    String callId = (String) msg.obj;
+                    int reason = msg.arg1;
+                    mPhone.internalOnRttInitiationFailure(callId, reason);
+                    break;
+                }
                 default:
                     break;
             }
@@ -198,6 +213,16 @@
             args.arg3 = extras;
             mHandler.obtainMessage(MSG_ON_CONNECTION_EVENT, args).sendToTarget();
         }
+
+        @Override
+        public void onRttUpgradeRequest(String callId, int id) {
+            mHandler.obtainMessage(MSG_ON_RTT_UPGRADE_REQUEST, id, 0, callId).sendToTarget();
+        }
+
+        @Override
+        public void onRttInitiationFailure(String callId, int reason) {
+            mHandler.obtainMessage(MSG_ON_RTT_INITIATION_FAILURE, reason, 0, callId).sendToTarget();
+        }
     }
 
     private Phone.Listener mPhoneListener = new Phone.Listener() {
diff --git a/telecomm/java/android/telecom/ParcelableCall.java b/telecomm/java/android/telecom/ParcelableCall.java
index a3fce9c..85a92d1 100644
--- a/telecomm/java/android/telecom/ParcelableCall.java
+++ b/telecomm/java/android/telecom/ParcelableCall.java
@@ -50,6 +50,8 @@
     private final boolean mIsVideoCallProviderChanged;
     private final IVideoProvider mVideoCallProvider;
     private VideoCallImpl mVideoCall;
+    private final boolean mIsRttCallChanged;
+    private final ParcelableRttCall mRttCall;
     private final String mParentCallId;
     private final List<String> mChildCallIds;
     private final StatusHints mStatusHints;
@@ -75,6 +77,8 @@
             PhoneAccountHandle accountHandle,
             boolean isVideoCallProviderChanged,
             IVideoProvider videoCallProvider,
+            boolean isRttCallChanged,
+            ParcelableRttCall rttCall,
             String parentCallId,
             List<String> childCallIds,
             StatusHints statusHints,
@@ -98,6 +102,8 @@
         mAccountHandle = accountHandle;
         mIsVideoCallProviderChanged = isVideoCallProviderChanged;
         mVideoCallProvider = videoCallProvider;
+        mIsRttCallChanged = isRttCallChanged;
+        mRttCall = rttCall;
         mParentCallId = parentCallId;
         mChildCallIds = childCallIds;
         mStatusHints = statusHints;
@@ -187,13 +193,16 @@
 
     /**
      * Returns an object for remotely communicating through the video call provider's binder.
-
+     *
+     * @param callingPackageName the package name of the calling InCallService.
+     * @param targetSdkVersion the target SDK version of the calling InCallService.
      * @return The video call.
      */
-    public VideoCallImpl getVideoCallImpl(String callingPackageName) {
+    public VideoCallImpl getVideoCallImpl(String callingPackageName, int targetSdkVersion) {
         if (mVideoCall == null && mVideoCallProvider != null) {
             try {
-                mVideoCall = new VideoCallImpl(mVideoCallProvider, callingPackageName);
+                mVideoCall = new VideoCallImpl(mVideoCallProvider, callingPackageName,
+                        targetSdkVersion);
             } catch (RemoteException ignored) {
                 // Ignore RemoteException.
             }
@@ -202,6 +211,18 @@
         return mVideoCall;
     }
 
+    public boolean getIsRttCallChanged() {
+        return mIsRttCallChanged;
+    }
+
+    /**
+     * RTT communication channel information
+     * @return The ParcelableRttCall
+     */
+    public ParcelableRttCall getParcelableRttCall() {
+        return mRttCall;
+    }
+
     /**
      * The conference call to which this call is conferenced. Null if not conferenced.
      */
@@ -301,6 +322,8 @@
             Bundle intentExtras = source.readBundle(classLoader);
             Bundle extras = source.readBundle(classLoader);
             int supportedAudioRoutes = source.readInt();
+            boolean isRttCallChanged = source.readByte() == 1;
+            ParcelableRttCall rttCall = source.readParcelable(classLoader);
             return new ParcelableCall(
                     id,
                     state,
@@ -318,6 +341,8 @@
                     accountHandle,
                     isVideoCallProviderChanged,
                     videoCallProvider,
+                    isRttCallChanged,
+                    rttCall,
                     parentCallId,
                     childCallIds,
                     statusHints,
@@ -366,6 +391,8 @@
         destination.writeBundle(mIntentExtras);
         destination.writeBundle(mExtras);
         destination.writeInt(mSupportedAudioRoutes);
+        destination.writeByte((byte) (mIsRttCallChanged ? 1 : 0));
+        destination.writeParcelable(mRttCall, 0);
     }
 
     @Override
diff --git a/core/java/android/content/pm/ManifestDigest.aidl b/telecomm/java/android/telecom/ParcelableRttCall.aidl
similarity index 81%
copy from core/java/android/content/pm/ManifestDigest.aidl
copy to telecomm/java/android/telecom/ParcelableRttCall.aidl
index ebabab0..4480710 100644
--- a/core/java/android/content/pm/ManifestDigest.aidl
+++ b/telecomm/java/android/telecom/ParcelableRttCall.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright 2011, The Android Open Source Project
+ * 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.
@@ -14,6 +14,9 @@
  * limitations under the License.
  */
 
-package android.content.pm;
+package android.telecom;
 
-parcelable ManifestDigest;
+/**
+ * {@hide}
+ */
+parcelable ParcelableRttCall;
diff --git a/telecomm/java/android/telecom/ParcelableRttCall.java b/telecomm/java/android/telecom/ParcelableRttCall.java
new file mode 100644
index 0000000..763e48b
--- /dev/null
+++ b/telecomm/java/android/telecom/ParcelableRttCall.java
@@ -0,0 +1,88 @@
+/*
+ * 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 android.telecom;
+
+import android.os.Parcel;
+import android.os.ParcelFileDescriptor;
+import android.os.Parcelable;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * Data container for information associated with the RTT connection on a call.
+ * @hide
+ */
+public class ParcelableRttCall implements Parcelable {
+    private final int mRttMode;
+    private final ParcelFileDescriptor mTransmitStream;
+    private final ParcelFileDescriptor mReceiveStream;
+
+    public ParcelableRttCall(
+            int rttMode,
+            ParcelFileDescriptor transmitStream,
+            ParcelFileDescriptor receiveStream) {
+        mRttMode = rttMode;
+        mTransmitStream = transmitStream;
+        mReceiveStream = receiveStream;
+    }
+
+    protected ParcelableRttCall(Parcel in) {
+        mRttMode = in.readInt();
+        mTransmitStream = in.readParcelable(ParcelFileDescriptor.class.getClassLoader());
+        mReceiveStream = in.readParcelable(ParcelFileDescriptor.class.getClassLoader());
+    }
+
+    public static final Creator<ParcelableRttCall> CREATOR = new Creator<ParcelableRttCall>() {
+        @Override
+        public ParcelableRttCall createFromParcel(Parcel in) {
+            return new ParcelableRttCall(in);
+        }
+
+        @Override
+        public ParcelableRttCall[] newArray(int size) {
+            return new ParcelableRttCall[size];
+        }
+    };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mRttMode);
+        dest.writeParcelable(mTransmitStream, flags);
+        dest.writeParcelable(mReceiveStream, flags);
+    }
+
+    public int getRttMode() {
+        return mRttMode;
+    }
+
+    public ParcelFileDescriptor getReceiveStream() {
+        return mReceiveStream;
+    }
+
+    public ParcelFileDescriptor getTransmitStream() {
+        return mTransmitStream;
+    }
+}
diff --git a/telecomm/java/android/telecom/Phone.java b/telecomm/java/android/telecom/Phone.java
index 30ec5b3..066f6c2 100644
--- a/telecomm/java/android/telecom/Phone.java
+++ b/telecomm/java/android/telecom/Phone.java
@@ -127,14 +127,20 @@
 
     private final String mCallingPackage;
 
-    Phone(InCallAdapter adapter, String callingPackage) {
+    /**
+     * The Target SDK version of the InCallService implementation.
+     */
+    private final int mTargetSdkVersion;
+
+    Phone(InCallAdapter adapter, String callingPackage, int targetSdkVersion) {
         mInCallAdapter = adapter;
         mCallingPackage = callingPackage;
+        mTargetSdkVersion = targetSdkVersion;
     }
 
     final void internalAddCall(ParcelableCall parcelableCall) {
         Call call = new Call(this, parcelableCall.getId(), mInCallAdapter,
-                parcelableCall.getState(), mCallingPackage);
+                parcelableCall.getState(), mCallingPackage, mTargetSdkVersion);
         mCallByTelecomCallId.put(parcelableCall.getId(), call);
         mCalls.add(call);
         checkCallTree(parcelableCall);
@@ -201,6 +207,20 @@
         }
     }
 
+    final void internalOnRttUpgradeRequest(String callId, int requestId) {
+        Call call = mCallByTelecomCallId.get(callId);
+        if (call != null) {
+            call.internalOnRttUpgradeRequest(requestId);
+        }
+    }
+
+    final void internalOnRttInitiationFailure(String callId, int reason) {
+        Call call = mCallByTelecomCallId.get(callId);
+        if (call != null) {
+            call.internalOnRttInitiationFailure(reason);
+        }
+    }
+
     /**
      * Called to destroy the phone and cleanup any lingering calls.
      */
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index 845a103..3926e20 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -204,6 +204,18 @@
     public static final int CAPABILITY_SELF_MANAGED = 0x800;
 
     /**
+     * Flag indicating that this {@link PhoneAccount} is capable of making a call with an
+     * RTT (Real-time text) session.
+     * When set, Telecom will attempt to open an RTT session on outgoing calls that specify
+     * that they should be placed with an RTT session , and the in-call app will be displayed
+     * with text entry fields for RTT. Likewise, the in-call app can request that an RTT
+     * session be opened during a call if this bit is set.
+     */
+    public static final int CAPABILITY_RTT = 0x1000;
+
+    /* NEXT CAPABILITY: 0x2000 */
+
+    /**
      * URI scheme for telephone number URIs.
      */
     public static final String SCHEME_TEL = "tel";
diff --git a/telecomm/java/android/telecom/RemoteConnection.java b/telecomm/java/android/telecom/RemoteConnection.java
index 77e0e54..57fc9ce 100644
--- a/telecomm/java/android/telecom/RemoteConnection.java
+++ b/telecomm/java/android/telecom/RemoteConnection.java
@@ -20,6 +20,7 @@
 import com.android.internal.telecom.IVideoCallback;
 import com.android.internal.telecom.IVideoProvider;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.hardware.camera2.CameraManager;
@@ -231,6 +232,41 @@
          * @param extras Extras associated with the event.
          */
         public void onConnectionEvent(RemoteConnection connection, String event, Bundle extras) {}
+
+        /**
+         * Indicates that a RTT session was successfully established on this
+         * {@link RemoteConnection}. See {@link Connection#sendRttInitiationSuccess()}.
+         * @hide
+         * @param connection The {@code RemoteConnection} invoking this method.
+         */
+        public void onRttInitiationSuccess(RemoteConnection connection) {}
+
+        /**
+         * Indicates that a RTT session failed to be established on this
+         * {@link RemoteConnection}. See {@link Connection#sendRttInitiationFailure()}.
+         * @hide
+         * @param connection The {@code RemoteConnection} invoking this method.
+         * @param reason One of the reason codes defined in {@link Connection.RttModifyStatus},
+         *               with the exception of
+         *               {@link Connection.RttModifyStatus#SESSION_MODIFY_REQUEST_SUCCESS}.
+         */
+        public void onRttInitiationFailure(RemoteConnection connection, int reason) {}
+
+        /**
+         * Indicates that an established RTT session was terminated remotely on this
+         * {@link RemoteConnection}. See {@link Connection#sendRttSessionRemotelyTerminated()}
+         * @hide
+         * @param connection The {@code RemoteConnection} invoking this method.
+         */
+        public void onRttSessionRemotelyTerminated(RemoteConnection connection) {}
+
+        /**
+         * Indicates that the remote user on this {@link RemoteConnection} has requested an upgrade
+         * to an RTT session. See {@link Connection#sendRemoteRttRequest()}
+         * @hide
+         * @param connection The {@code RemoteConnection} invoking this method.
+         */
+        public void onRemoteRttRequest(RemoteConnection connection) {}
     }
 
     /**
@@ -410,6 +446,8 @@
 
         private final String mCallingPackage;
 
+        private final int mTargetSdkVersion;
+
         /**
          * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is
          * load factor before resizing, 1 means we only expect a single thread to
@@ -418,9 +456,12 @@
         private final Set<Callback> mCallbacks = Collections.newSetFromMap(
                 new ConcurrentHashMap<Callback, Boolean>(8, 0.9f, 1));
 
-        VideoProvider(IVideoProvider videoProviderBinder, String callingPackage) {
+        VideoProvider(IVideoProvider videoProviderBinder, String callingPackage,
+                      int targetSdkVersion) {
+
             mVideoProviderBinder = videoProviderBinder;
             mCallingPackage = callingPackage;
+            mTargetSdkVersion = targetSdkVersion;
             try {
                 mVideoProviderBinder.addVideoCallback(mVideoCallbackServant.getStub().asBinder());
             } catch (RemoteException e) {
@@ -455,7 +496,7 @@
          */
         public void setCamera(String cameraId) {
             try {
-                mVideoProviderBinder.setCamera(cameraId, mCallingPackage);
+                mVideoProviderBinder.setCamera(cameraId, mCallingPackage, mTargetSdkVersion);
             } catch (RemoteException e) {
             }
         }
@@ -631,7 +672,7 @@
      * @hide
      */
     RemoteConnection(String callId, IConnectionService connectionService,
-            ParcelableConnection connection, String callingPackage) {
+            ParcelableConnection connection, String callingPackage, int targetSdkVersion) {
         mConnectionId = callId;
         mConnectionService = connectionService;
         mConnected = true;
@@ -643,7 +684,8 @@
         mVideoState = connection.getVideoState();
         IVideoProvider videoProvider = connection.getVideoProvider();
         if (videoProvider != null) {
-            mVideoProvider = new RemoteConnection.VideoProvider(videoProvider, callingPackage);
+            mVideoProvider = new RemoteConnection.VideoProvider(videoProvider, callingPackage,
+                    targetSdkVersion);
         } else {
             mVideoProvider = null;
         }
@@ -1046,6 +1088,61 @@
     }
 
     /**
+     * Notifies this {@link RemoteConnection} that the user has requested an RTT session.
+     * @param rttTextStream The object that should be used to send text to or receive text from
+     *                      the in-call app.
+     * @hide
+     */
+    public void startRtt(@NonNull Connection.RttTextStream rttTextStream) {
+        try {
+            if (mConnected) {
+                mConnectionService.startRtt(mConnectionId, rttTextStream.getFdFromInCall(),
+                        rttTextStream.getFdToInCall(), null /*Session.Info*/);
+            }
+        } catch (RemoteException ignored) {
+        }
+    }
+
+    /**
+     * Notifies this {@link RemoteConnection} that it should terminate any existing RTT
+     * session. No response to Telecom is needed for this method.
+     * @hide
+     */
+    public void stopRtt() {
+        try {
+            if (mConnected) {
+                mConnectionService.stopRtt(mConnectionId, null /*Session.Info*/);
+            }
+        } catch (RemoteException ignored) {
+        }
+    }
+
+    /**
+     * Notifies this {@link RemoteConnection} of a response to a previous remotely-initiated RTT
+     * upgrade request sent via {@link Connection#sendRemoteRttRequest}.
+     * Acceptance of the request is indicated by the supplied {@link RttTextStream} being non-null,
+     * and rejection is indicated by {@code rttTextStream} being {@code null}
+     * @hide
+     * @param rttTextStream The object that should be used to send text to or receive text from
+     *                      the in-call app.
+     */
+    public void sendRttUpgradeResponse(@Nullable Connection.RttTextStream rttTextStream) {
+        try {
+            if (mConnected) {
+                if (rttTextStream == null) {
+                    mConnectionService.respondToRttUpgradeRequest(mConnectionId,
+                            null, null, null /*Session.Info*/);
+                } else {
+                    mConnectionService.respondToRttUpgradeRequest(mConnectionId,
+                            rttTextStream.getFdFromInCall(), rttTextStream.getFdToInCall(),
+                            null /*Session.Info*/);
+                }
+            }
+        } catch (RemoteException ignored) {
+        }
+    }
+
+    /**
      * Obtain the {@code RemoteConnection}s with which this {@code RemoteConnection} may be
      * successfully asked to create a conference with.
      *
@@ -1411,6 +1508,47 @@
         }
     }
 
+    /** @hide */
+    void onRttInitiationSuccess() {
+        for (CallbackRecord record : mCallbackRecords) {
+            final RemoteConnection connection = this;
+            final Callback callback = record.getCallback();
+            record.getHandler().post(
+                    () -> callback.onRttInitiationSuccess(connection));
+        }
+    }
+
+    /** @hide */
+    void onRttInitiationFailure(int reason) {
+        for (CallbackRecord record : mCallbackRecords) {
+            final RemoteConnection connection = this;
+            final Callback callback = record.getCallback();
+            record.getHandler().post(
+                    () -> callback.onRttInitiationFailure(connection, reason));
+        }
+    }
+
+    /** @hide */
+    void onRttSessionRemotelyTerminated() {
+        for (CallbackRecord record : mCallbackRecords) {
+            final RemoteConnection connection = this;
+            final Callback callback = record.getCallback();
+            record.getHandler().post(
+                    () -> callback.onRttSessionRemotelyTerminated(connection));
+        }
+    }
+
+    /** @hide */
+    void onRemoteRttRequest() {
+        for (CallbackRecord record : mCallbackRecords) {
+            final RemoteConnection connection = this;
+            final Callback callback = record.getCallback();
+            record.getHandler().post(
+                    () -> callback.onRemoteRttRequest(connection));
+        }
+    }
+
+    /**
     /**
      * Create a RemoteConnection represents a failure, and which will be in
      * {@link Connection#STATE_DISCONNECTED}. Attempting to use it for anything will almost
diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java
index 0c7404a..06cdd1a 100644
--- a/telecomm/java/android/telecom/RemoteConnectionService.java
+++ b/telecomm/java/android/telecom/RemoteConnectionService.java
@@ -286,10 +286,11 @@
 
             String callingPackage = mOurConnectionServiceImpl.getApplicationContext()
                     .getOpPackageName();
+            int targetSdkVersion = mOurConnectionServiceImpl.getApplicationInfo().targetSdkVersion;
             RemoteConnection.VideoProvider remoteVideoProvider = null;
             if (videoProvider != null) {
                 remoteVideoProvider = new RemoteConnection.VideoProvider(videoProvider,
-                        callingPackage);
+                        callingPackage, targetSdkVersion);
             }
             findConnectionForAction(callId, "setVideoProvider")
                     .setVideoProvider(remoteVideoProvider);
@@ -357,8 +358,11 @@
                 Session.Info sessionInfo) {
             String callingPackage = mOurConnectionServiceImpl.getApplicationContext().
                     getOpPackageName();
+            int callingTargetSdkVersion = mOurConnectionServiceImpl.getApplicationInfo()
+                    .targetSdkVersion;
             RemoteConnection remoteConnection = new RemoteConnection(callId,
-                    mOutgoingConnectionServiceRpc, connection, callingPackage);
+                    mOutgoingConnectionServiceRpc, connection, callingPackage,
+                    callingTargetSdkVersion);
             mConnectionById.put(callId, remoteConnection);
             remoteConnection.registerCallback(new RemoteConnection.Callback() {
                 @Override
@@ -405,6 +409,50 @@
                         extras);
             }
         }
+
+        @Override
+        public void onRttInitiationSuccess(String callId, Session.Info sessionInfo)
+                throws RemoteException {
+            if (hasConnection(callId)) {
+                findConnectionForAction(callId, "onRttInitiationSuccess")
+                        .onRttInitiationSuccess();
+            } else {
+                Log.w(this, "onRttInitiationSuccess called on a remote conference");
+            }
+        }
+
+        @Override
+        public void onRttInitiationFailure(String callId, int reason, Session.Info sessionInfo)
+                throws RemoteException {
+            if (hasConnection(callId)) {
+                findConnectionForAction(callId, "onRttInitiationFailure")
+                        .onRttInitiationFailure(reason);
+            } else {
+                Log.w(this, "onRttInitiationFailure called on a remote conference");
+            }
+        }
+
+        @Override
+        public void onRttSessionRemotelyTerminated(String callId, Session.Info sessionInfo)
+                throws RemoteException {
+            if (hasConnection(callId)) {
+                findConnectionForAction(callId, "onRttSessionRemotelyTerminated")
+                        .onRttSessionRemotelyTerminated();
+            } else {
+                Log.w(this, "onRttSessionRemotelyTerminated called on a remote conference");
+            }
+        }
+
+        @Override
+        public void onRemoteRttRequest(String callId, Session.Info sessionInfo)
+                throws RemoteException {
+            if (hasConnection(callId)) {
+                findConnectionForAction(callId, "onRemoteRttRequest")
+                        .onRemoteRttRequest();
+            } else {
+                Log.w(this, "onRemoteRttRequest called on a remote conference");
+            }
+        }
     };
 
     private final ConnectionServiceAdapterServant mServant =
@@ -450,11 +498,14 @@
             ConnectionRequest request,
             boolean isIncoming) {
         final String id = UUID.randomUUID().toString();
-        final ConnectionRequest newRequest = new ConnectionRequest(
-                request.getAccountHandle(),
-                request.getAddress(),
-                request.getExtras(),
-                request.getVideoState());
+        final ConnectionRequest newRequest = new ConnectionRequest.Builder()
+                .setAccountHandle(request.getAccountHandle())
+                .setAddress(request.getAddress())
+                .setExtras(request.getExtras())
+                .setVideoState(request.getVideoState())
+                .setRttPipeFromInCall(request.getRttPipeFromInCall())
+                .setRttPipeToInCall(request.getRttPipeToInCall())
+                .build();
         try {
             if (mConnectionById.isEmpty()) {
                 mOutgoingConnectionServiceRpc.addConnectionServiceAdapter(mServant.getStub(),
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 7964cf2..359dcb1 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -326,6 +326,14 @@
             "android.telecom.extra.NEW_OUTGOING_CALL_CANCEL_TIMEOUT";
 
     /**
+     * A boolean extra, which when set on the {@link Intent#ACTION_CALL} intent or on the bundle
+     * passed into {@link #placeCall(Uri, Bundle)}, indicates that the call should be initiated with
+     * an RTT session open. See {@link android.telecom.Call.RttCall} for more information on RTT.
+     */
+    public static final String EXTRA_START_CALL_WITH_RTT =
+            "android.telecom.extra.START_CALL_WITH_RTT";
+
+    /**
      * A boolean meta-data value indicating whether an {@link InCallService} implements an
      * in-call user interface. Dialer implementations (see {@link #getDefaultDialerPackage()}) which
      * would also like to replace the in-call interface should set this meta-data to {@code true} in
@@ -365,6 +373,24 @@
             "android.telecom.INCLUDE_EXTERNAL_CALLS";
 
     /**
+     * A boolean meta-data value indicating whether an {@link InCallService} wants to be informed of
+     * calls which have the {@link Call.Details#PROPERTY_SELF_MANAGED} property.  A self-managed
+     * call is one which originates from a self-managed {@link ConnectionService} which has chosen
+     * to implement its own call user interface.  An {@link InCallService} implementation which
+     * would like to be informed of external calls should set this meta-data to {@code true} in the
+     * manifest registration of their {@link InCallService}.  By default, the {@link InCallService}
+     * will NOT be informed about self-managed calls.
+     * <p>
+     * An {@link InCallService} which receives self-managed calls is free to view and control the
+     * state of calls in the self-managed {@link ConnectionService}.  An example use-case is
+     * exposing these calls to a wearable or automotive device via its companion app.
+     * <p>
+     * See also {@link Connection#PROPERTY_SELF_MANAGED}.
+     */
+    public static final String METADATA_INCLUDE_SELF_MANAGED_CALLS =
+            "android.telecom.INCLUDE_SELF_MANAGED_CALLS";
+
+    /**
      * The dual tone multi-frequency signaling character sent to indicate the dialing system should
      * pause for a predefined period.
      */
@@ -1043,10 +1069,12 @@
 
     /**
      * Returns whether there is an ongoing phone call (can be in dialing, ringing, active or holding
-     * states).
+     * states) originating from either a manager or self-managed {@link ConnectionService}.
      * <p>
      * Requires permission: {@link android.Manifest.permission#READ_PHONE_STATE}
-     * </p>
+     *
+     * @return {@code true} if there is an ongoing call in either a managed or self-managed
+     *      {@link ConnectionService}, {@code false} otherwise.
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public boolean isInCall() {
@@ -1061,6 +1089,31 @@
     }
 
     /**
+     * Returns whether there is an ongoing call originating from a managed
+     * {@link ConnectionService}.  An ongoing call can be in dialing, ringing, active or holding
+     * states.
+     * <p>
+     * If you also need to know if there are ongoing self-managed calls, use {@link #isInCall()}
+     * instead.
+     * <p>
+     * Requires permission: {@link android.Manifest.permission#READ_PHONE_STATE}
+     *
+     * @return {@code true} if there is an ongoing call in a managed {@link ConnectionService},
+     *      {@code false} otherwise.
+     */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    public boolean isInManagedCall() {
+        try {
+            if (isServiceConnected()) {
+                return getTelecomService().isInManagedCall(mContext.getOpPackageName());
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException calling isInManagedCall().", e);
+        }
+        return false;
+    }
+
+    /**
      * Returns one of the following constants that represents the current state of Telecom:
      *
      * {@link TelephonyManager#CALL_STATE_RINGING}
@@ -1071,6 +1124,9 @@
      * {@link android.Manifest.permission#READ_PHONE_STATE} permission. This is intentional, to
      * preserve the behavior of {@link TelephonyManager#getCallState()}, which also did not require
      * the permission.
+     *
+     * Takes into consideration both managed and self-managed calls.
+     *
      * @hide
      */
     @SystemApi
@@ -1088,6 +1144,7 @@
     /**
      * Returns whether there currently exists is a ringing incoming-call.
      *
+     * @return {@code true} if there is a managed or self-managed ringing call.
      * @hide
      */
     @SystemApi
@@ -1122,18 +1179,22 @@
 
     /**
      * If there is a ringing incoming call, this method accepts the call on behalf of the user.
-     * TODO: L-release - need to convert all invocation of ITelecmmService#answerRingingCall to use
-     * this method (clockwork & gearhead).
+     *
      * If the incoming call is a video call, the call will be answered with the same video state as
      * the incoming call requests.  This means, for example, that an incoming call requesting
      * {@link VideoProfile#STATE_BIDIRECTIONAL} will be answered, accepting that state.
-     * @hide
+     *
+     * Requires permission: {@link android.Manifest.permission#MODIFY_PHONE_STATE} or
+     * {@link android.Manifest.permission#ANSWER_PHONE_CALLS}
      */
-    @SystemApi
+    //TODO: L-release - need to convert all invocation of ITelecmmService#answerRingingCall to use
+    // this method (clockwork & gearhead).
+    @RequiresPermission(anyOf =
+            {Manifest.permission.ANSWER_PHONE_CALLS, Manifest.permission.MODIFY_PHONE_STATE})
     public void acceptRingingCall() {
         try {
             if (isServiceConnected()) {
-                getTelecomService().acceptRingingCall();
+                getTelecomService().acceptRingingCall(mContext.getPackageName());
             }
         } catch (RemoteException e) {
             Log.e(TAG, "Error calling ITelecomService#acceptRingingCall", e);
@@ -1144,14 +1205,18 @@
      * If there is a ringing incoming call, this method accepts the call on behalf of the user,
      * with the specified video state.
      *
+     * Requires permission: {@link android.Manifest.permission#MODIFY_PHONE_STATE} or
+     * {@link android.Manifest.permission#ANSWER_PHONE_CALLS}
+     *
      * @param videoState The desired video state to answer the call with.
-     * @hide
      */
-    @SystemApi
+    @RequiresPermission(anyOf =
+            {Manifest.permission.ANSWER_PHONE_CALLS, Manifest.permission.MODIFY_PHONE_STATE})
     public void acceptRingingCall(int videoState) {
         try {
             if (isServiceConnected()) {
-                getTelecomService().acceptRingingCallWithVideoState(videoState);
+                getTelecomService().acceptRingingCallWithVideoState(
+                        mContext.getPackageName(), videoState);
             }
         } catch (RemoteException e) {
             Log.e(TAG, "Error calling ITelecomService#acceptRingingCallWithVideoState", e);
diff --git a/telecomm/java/android/telecom/VideoCallImpl.java b/telecomm/java/android/telecom/VideoCallImpl.java
index d8ede5c..429a434 100644
--- a/telecomm/java/android/telecom/VideoCallImpl.java
+++ b/telecomm/java/android/telecom/VideoCallImpl.java
@@ -44,6 +44,7 @@
     private int mVideoQuality = VideoProfile.QUALITY_UNKNOWN;
     private int mVideoState = VideoProfile.STATE_AUDIO_ONLY;
     private final String mCallingPackageName;
+    private final int mTargetSdkVersion;
 
     private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
         @Override
@@ -198,13 +199,15 @@
 
     private Handler mHandler;
 
-    VideoCallImpl(IVideoProvider videoProvider, String callingPackageName) throws RemoteException {
+    VideoCallImpl(IVideoProvider videoProvider, String callingPackageName, int targetSdkVersion)
+            throws RemoteException {
         mVideoProvider = videoProvider;
         mVideoProvider.asBinder().linkToDeath(mDeathRecipient, 0);
 
         mBinder = new VideoCallListenerBinder();
         mVideoProvider.addVideoCallback(mBinder);
         mCallingPackageName = callingPackageName;
+        mTargetSdkVersion = targetSdkVersion;
     }
 
     public void destroy() {
@@ -243,7 +246,7 @@
     public void setCamera(String cameraId) {
         try {
             Log.w(this, "setCamera: cameraId=%s, calling=%s", cameraId, mCallingPackageName);
-            mVideoProvider.setCamera(cameraId, mCallingPackageName);
+            mVideoProvider.setCamera(cameraId, mCallingPackageName, mTargetSdkVersion);
         } catch (RemoteException e) {
         }
     }
diff --git a/telecomm/java/android/telecom/VideoProfile.java b/telecomm/java/android/telecom/VideoProfile.java
index 216603c..e0e3a08 100644
--- a/telecomm/java/android/telecom/VideoProfile.java
+++ b/telecomm/java/android/telecom/VideoProfile.java
@@ -235,7 +235,7 @@
         StringBuilder sb = new StringBuilder();
         sb.append("Audio");
 
-        if (isAudioOnly(videoState)) {
+        if (videoState == STATE_AUDIO_ONLY) {
             sb.append(" Only");
         } else {
             if (isTransmissionEnabled(videoState)) {
@@ -256,6 +256,9 @@
 
     /**
      * Indicates whether the video state is audio only.
+     * <p>
+     * Note: Considers only whether either both the {@link #STATE_RX_ENABLED} or
+     * {@link #STATE_TX_ENABLED} bits are off, but not {@link #STATE_PAUSED}.
      *
      * @param videoState The video state.
      * @return {@code True} if the video state is audio only, {@code false} otherwise.
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
index 20feba7..c631d08 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
@@ -17,6 +17,7 @@
 package com.android.internal.telecom;
 
 import android.os.Bundle;
+import android.os.ParcelFileDescriptor;
 import android.telecom.CallAudioState;
 import android.telecom.ConnectionRequest;
 import android.telecom.Logging.Session;
@@ -46,8 +47,8 @@
             boolean isUnknown,
             in Session.Info sessionInfo);
 
-    void createConnectionFailed(String callId, in ConnectionRequest request, boolean isIncoming,
-            in Session.Info sessionInfo);
+    void createConnectionFailed(in PhoneAccountHandle connectionManagerPhoneAccount, String callId,
+            in ConnectionRequest request, boolean isIncoming, in Session.Info sessionInfo);
 
     void abort(String callId, in Session.Info sessionInfo);
 
@@ -89,4 +90,12 @@
     void sendCallEvent(String callId, String event, in Bundle extras, in Session.Info sessionInfo);
 
     void onExtrasChanged(String callId, in Bundle extras, in Session.Info sessionInfo);
+
+    void startRtt(String callId, in ParcelFileDescriptor fromInCall,
+    in ParcelFileDescriptor toInCall, in Session.Info sessionInfo);
+
+    void stopRtt(String callId, in Session.Info sessionInfo);
+
+    void respondToRttUpgradeRequest(String callId, in ParcelFileDescriptor fromInCall,
+    in ParcelFileDescriptor toInCall, in Session.Info sessionInfo);
 }
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
index b58f8bc..ac9da2e 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
@@ -106,4 +106,12 @@
 
     void onConnectionEvent(String callId, String event, in Bundle extras,
     in Session.Info sessionInfo);
+
+    void onRttInitiationSuccess(String callId, in Session.Info sessionInfo);
+
+    void onRttInitiationFailure(String callId, int reason, in Session.Info sessionInfo);
+
+    void onRttSessionRemotelyTerminated(String callId, in Session.Info sessionInfo);
+
+    void onRemoteRttRequest(String callId, in Session.Info sessionInfo);
 }
diff --git a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
index 49f9b3b..73fa29a 100644
--- a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
@@ -69,4 +69,12 @@
     void putExtras(String callId, in Bundle extras);
 
     void removeExtras(String callId, in List<String> keys);
+
+    void sendRttRequest(String callId);
+
+    void respondToRttRequest(String callId, int id, boolean accept);
+
+    void stopRtt(String callId);
+
+    void setRttMode(String callId, int mode);
 }
diff --git a/telecomm/java/com/android/internal/telecom/IInCallService.aidl b/telecomm/java/com/android/internal/telecom/IInCallService.aidl
index 3e43fe2..e8cf8e9 100644
--- a/telecomm/java/com/android/internal/telecom/IInCallService.aidl
+++ b/telecomm/java/com/android/internal/telecom/IInCallService.aidl
@@ -50,4 +50,8 @@
     void silenceRinger();
 
     void onConnectionEvent(String callId, String event, in Bundle extras);
+
+    void onRttUpgradeRequest(String callId, int id);
+
+    void onRttInitiationFailure(String callId, int reason);
 }
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index d9465dc..8740224 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -165,6 +165,11 @@
     boolean isInCall(String callingPackage);
 
     /**
+     * @see TelecomServiceImpl#isInManagedCall
+     */
+    boolean isInManagedCall(String callingPackage);
+
+    /**
      * @see TelecomServiceImpl#isRinging
      */
     boolean isRinging(String callingPackage);
@@ -182,12 +187,12 @@
     /**
      * @see TelecomServiceImpl#acceptRingingCall
      */
-    void acceptRingingCall();
+    void acceptRingingCall(String callingPackage);
 
     /**
      * @see TelecomServiceImpl#acceptRingingCallWithVideoState(int)
      */
-    void acceptRingingCallWithVideoState(int videoState);
+    void acceptRingingCallWithVideoState(String callingPackage, int videoState);
 
     /**
      * @see TelecomServiceImpl#cancelMissedCallsNotification
diff --git a/telecomm/java/com/android/internal/telecom/IVideoProvider.aidl b/telecomm/java/com/android/internal/telecom/IVideoProvider.aidl
index a109e90..272b884 100644
--- a/telecomm/java/com/android/internal/telecom/IVideoProvider.aidl
+++ b/telecomm/java/com/android/internal/telecom/IVideoProvider.aidl
@@ -30,7 +30,7 @@
 
     void removeVideoCallback(IBinder videoCallbackBinder);
 
-    void setCamera(String cameraId, in String mCallingPackageName);
+    void setCamera(String cameraId, in String mCallingPackageName, int targetSdkVersion);
 
     void setPreviewSurface(in Surface surface);
 
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 70df69c..632a1d6 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -942,7 +942,7 @@
 
     /**
      * Defines carrier-specific actions which act upon
-     * android.intent.action.CARRIER_SIGNAL_REDIRECTED, used for customization of the
+     * com.android.internal.telephony.CARRIER_SIGNAL_REDIRECTED, used for customization of the
      * default carrier app
      * Format: "CARRIER_ACTION_IDX, ..."
      * Where {@code CARRIER_ACTION_IDX} is an integer defined in
@@ -957,7 +957,7 @@
 
     /**
      * Defines carrier-specific actions which act upon
-     * android.intent.action.CARRIER_SIGNAL_REQUEST_NETWORK_FAILED
+     * com.android.internal.telephony.CARRIER_SIGNAL_REQUEST_NETWORK_FAILED
      * and configured signal args:
      * {@link com.android.internal.telephony.TelephonyIntents#EXTRA_APN_TYPE_KEY apnType},
      * {@link com.android.internal.telephony.TelephonyIntents#EXTRA_ERROR_CODE_KEY errorCode}
@@ -998,11 +998,11 @@
      * @see com.android.internal.telephony.TelephonyIntents
      * Example:
      * <item>com.google.android.carrierAPK/.CarrierSignalReceiverA:
-     * android.intent.action.CARRIER_SIGNAL_REDIRECTED,
-     * android.intent.action.CARRIER_SIGNAL_PCO_VALUE
+     * com.android.internal.telephony.CARRIER_SIGNAL_REDIRECTED,
+     * com.android.internal.telephony.CARRIER_SIGNAL_PCO_VALUE
      * </item>
      * <item>com.google.android.carrierAPK/.CarrierSignalReceiverB:
-     * android.intent.action.CARRIER_SIGNAL_PCO_VALUE
+     * com.android.internal.telephony.CARRIER_SIGNAL_PCO_VALUE
      * </item>
      * @hide
      */
@@ -1017,11 +1017,11 @@
      * @see com.android.internal.telephony.TelephonyIntents
      * Example:
      * <item>com.google.android.carrierAPK/.CarrierSignalReceiverA:
-     * android.intent.action.CARRIER_SIGNAL_REQUEST_NETWORK_FAILED,
-     * android.intent.action.CARRIER_SIGNAL_PCO_VALUE
+     * com.android.internal.telephony.CARRIER_SIGNAL_REQUEST_NETWORK_FAILED,
+     * com.android.internal.telephony.CARRIER_SIGNAL_PCO_VALUE
      * </item>
      * <item>com.google.android.carrierAPK/.CarrierSignalReceiverB:
-     * android.intent.action.CARRIER_SIGNAL_REQUEST_NETWORK_FAILED
+     * com.android.internal.telephony.CARRIER_SIGNAL_REQUEST_NETWORK_FAILED
      * </item>
      * @hide
      */
@@ -1282,6 +1282,14 @@
         "support_3gpp_call_forwarding_while_roaming_bool";
 
     /**
+     * When {@code true}, the user will be notified when they attempt to place an international call
+     * when the call is placed using wifi calling.
+     * @hide
+     */
+    public static final String KEY_NOTIFY_INTERNATIONAL_CALL_ON_WFC_BOOL =
+            "notify_international_call_on_wfc_bool";
+
+    /**
      * Determine whether user edited tether APN (type dun) has effect
      * {@code false} - Default. APN with dun type in telephony database has no effect.
      *
@@ -1493,7 +1501,7 @@
         sDefaults.putStringArray(KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
                 new String[]{
                         "com.android.carrierdefaultapp/.CarrierDefaultBroadcastReceiver:" +
-                                "android.intent.action.CARRIER_SIGNAL_REDIRECTED"
+                                "com.android.internal.telephony.CARRIER_SIGNAL_REDIRECTED"
                 });
         sDefaults.putStringArray(KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY, null);
 
@@ -1529,6 +1537,7 @@
         sDefaults.putStringArray(KEY_CARRIER_WIFI_STRING_ARRAY, null);
         sDefaults.putInt(KEY_PREF_NETWORK_NOTIFICATION_DELAY_INT, -1);
         sDefaults.putBoolean(KEY_SUPPORT_3GPP_CALL_FORWARDING_WHILE_ROAMING_BOOL, true);
+        sDefaults.putBoolean(KEY_NOTIFY_INTERNATIONAL_CALL_ON_WFC_BOOL, false);
         sDefaults.putBoolean(KEY_EDITABLE_TETHER_APN_BOOL, false);
         sDefaults.putStringArray(KEY_CALL_FORWARDING_BLOCKS_WHILE_ROAMING_STRING_ARRAY,
                 null);
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 6f51c6e..a3e11c8 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -1140,6 +1140,8 @@
 
     private static final String KOREA_ISO_COUNTRY_CODE = "KR";
 
+    private static final String JAPAN_ISO_COUNTRY_CODE = "JP";
+
     /**
      * Breaks the given number down and formats it according to the rules
      * for the country the number is from.
@@ -1438,6 +1440,30 @@
     }
 
     /**
+     * Determines if a {@param phoneNumber} is international if dialed from
+     * {@param defaultCountryIso}.
+     *
+     * @param phoneNumber The phone number.
+     * @param defaultCountryIso The current country ISO.
+     * @return {@code true} if the number is international, {@code false} otherwise.
+     * @hide
+     */
+    public static boolean isInternationalNumber(String phoneNumber, String defaultCountryIso) {
+        // If it starts with # or * its not international.
+        if (phoneNumber.startsWith("#") || phoneNumber.startsWith("*")) {
+            return false;
+        }
+
+        PhoneNumberUtil util = PhoneNumberUtil.getInstance();
+        try {
+            PhoneNumber pn = util.parseAndKeepRawInput(phoneNumber, defaultCountryIso);
+            return pn.getCountryCode() != util.getCountryCodeForRegion(defaultCountryIso);
+        } catch (NumberParseException e) {
+            return false;
+        }
+    }
+
+    /**
      * Format a phone number.
      * <p>
      * If the given number doesn't have the country code, the phone will be
@@ -1460,15 +1486,25 @@
         String result = null;
         try {
             PhoneNumber pn = util.parseAndKeepRawInput(phoneNumber, defaultCountryIso);
-            /**
-             * Need to reformat any local Korean phone numbers (when the user is in Korea) with
-             * country code to corresponding national format which would replace the leading
-             * +82 with 0.
-             */
-            if (KOREA_ISO_COUNTRY_CODE.equals(defaultCountryIso) &&
+
+            if (KOREA_ISO_COUNTRY_CODE.equalsIgnoreCase(defaultCountryIso) &&
                     (pn.getCountryCode() == util.getCountryCodeForRegion(KOREA_ISO_COUNTRY_CODE)) &&
                     (pn.getCountryCodeSource() ==
                             PhoneNumber.CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN)) {
+                /**
+                 * Need to reformat any local Korean phone numbers (when the user is in Korea) with
+                 * country code to corresponding national format which would replace the leading
+                 * +82 with 0.
+                 */
+                result = util.format(pn, PhoneNumberUtil.PhoneNumberFormat.NATIONAL);
+            } else if (JAPAN_ISO_COUNTRY_CODE.equalsIgnoreCase(defaultCountryIso) &&
+                    pn.getCountryCode() == util.getCountryCodeForRegion(JAPAN_ISO_COUNTRY_CODE) &&
+                    (pn.getCountryCodeSource() ==
+                            PhoneNumber.CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN)) {
+                /**
+                 * Need to reformat Japanese phone numbers (when user is in Japan) with the national
+                 * dialing format.
+                 */
                 result = util.format(pn, PhoneNumberUtil.PhoneNumberFormat.NATIONAL);
             } else {
                 result = util.formatInOriginalFormat(pn, defaultCountryIso);
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index dd03305..afff6d5 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -208,7 +208,9 @@
      *
      * @see #onOemHookRawEvent
      * @hide
+     * @deprecated OEM needs a vendor-extension hal and their apps should use that instead
      */
+    @Deprecated
     public static final int LISTEN_OEM_HOOK_RAW_EVENT                       = 0x00008000;
 
     /**
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
new file mode 100644
index 0000000..8590482
--- /dev/null
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -0,0 +1,1707 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.annotation.SystemApi;
+import android.app.ActivityThread;
+import android.app.PendingIntent;
+import android.content.ActivityNotFoundException;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.BaseBundle;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import com.android.internal.telephony.IMms;
+import com.android.internal.telephony.ISms;
+import com.android.internal.telephony.SmsRawData;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+/*
+ * TODO(code review): Curious question... Why are a lot of these
+ * methods not declared as static, since they do not seem to require
+ * any local object state?  Presumably this cannot be changed without
+ * interfering with the API...
+ */
+
+/**
+ * Manages SMS operations such as sending data, text, and pdu SMS messages.
+ * Get this object by calling the static method {@link #getDefault()}.
+ *
+ * <p>For information about how to behave as the default SMS app on Android 4.4 (API level 19)
+ * and higher, see {@link android.provider.Telephony}.
+ */
+public final class SmsManager {
+    private static final String TAG = "SmsManager";
+    /**
+     * A psuedo-subId that represents the default subId at any given time. The actual subId it
+     * represents changes as the default subId is changed.
+     */
+    private static final int DEFAULT_SUBSCRIPTION_ID = -1002;
+
+    /** Singleton object constructed during class initialization. */
+    private static final SmsManager sInstance = new SmsManager(DEFAULT_SUBSCRIPTION_ID);
+    private static final Object sLockObject = new Object();
+
+    /** @hide */
+    public static final int CELL_BROADCAST_RAN_TYPE_GSM = 0;
+    /** @hide */
+    public static final int CELL_BROADCAST_RAN_TYPE_CDMA = 1;
+
+    /** SMS record length from TS 51.011 10.5.3
+     * @hide
+     */
+    public static final int SMS_RECORD_LENGTH = 176;
+
+    /** SMS record length from C.S0023 3.4.27
+     * @hide
+     */
+    public static final int CDMA_SMS_RECORD_LENGTH = 255;
+
+    private static final Map<Integer, SmsManager> sSubInstances =
+            new ArrayMap<Integer, SmsManager>();
+
+    /** A concrete subscription id, or the pseudo DEFAULT_SUBSCRIPTION_ID */
+    private int mSubId;
+
+    /*
+     * Key for the various carrier-dependent configuration values.
+     * Some of the values are used by the system in processing SMS or MMS messages. Others
+     * are provided for the convenience of SMS applications.
+     */
+
+    /**
+     * Whether to append transaction id to MMS WAP Push M-Notification.ind's content location URI
+     * when constructing the download URL of a new MMS (boolean type)
+     */
+    public static final String MMS_CONFIG_APPEND_TRANSACTION_ID =
+            CarrierConfigManager.KEY_MMS_APPEND_TRANSACTION_ID_BOOL;
+    /**
+     * Whether MMS is enabled for the current carrier (boolean type)
+     */
+    public static final String
+        MMS_CONFIG_MMS_ENABLED = CarrierConfigManager.KEY_MMS_MMS_ENABLED_BOOL;
+    /**
+     * Whether group MMS is enabled for the current carrier (boolean type)
+     */
+    public static final String
+            MMS_CONFIG_GROUP_MMS_ENABLED = CarrierConfigManager.KEY_MMS_GROUP_MMS_ENABLED_BOOL;
+    /**
+     * If this is enabled, M-NotifyResp.ind should be sent to the WAP Push content location instead
+     * of the default MMSC (boolean type)
+     */
+    public static final String MMS_CONFIG_NOTIFY_WAP_MMSC_ENABLED =
+            CarrierConfigManager.KEY_MMS_NOTIFY_WAP_MMSC_ENABLED_BOOL;
+    /**
+     * Whether alias is enabled (boolean type)
+     */
+    public static final String
+            MMS_CONFIG_ALIAS_ENABLED = CarrierConfigManager.KEY_MMS_ALIAS_ENABLED_BOOL;
+    /**
+     * Whether audio is allowed to be attached for MMS messages (boolean type)
+     */
+    public static final String
+            MMS_CONFIG_ALLOW_ATTACH_AUDIO = CarrierConfigManager.KEY_MMS_ALLOW_ATTACH_AUDIO_BOOL;
+    /**
+     * Whether multipart SMS is enabled (boolean type)
+     */
+    public static final String MMS_CONFIG_MULTIPART_SMS_ENABLED =
+            CarrierConfigManager.KEY_MMS_MULTIPART_SMS_ENABLED_BOOL;
+    /**
+     * Whether SMS delivery report is enabled (boolean type)
+     */
+    public static final String MMS_CONFIG_SMS_DELIVERY_REPORT_ENABLED =
+            CarrierConfigManager.KEY_MMS_SMS_DELIVERY_REPORT_ENABLED_BOOL;
+    /**
+     * Whether content-disposition field should be expected in an MMS PDU (boolean type)
+     */
+    public static final String MMS_CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION =
+            CarrierConfigManager.KEY_MMS_SUPPORT_MMS_CONTENT_DISPOSITION_BOOL;
+    /**
+     * Whether multipart SMS should be sent as separate messages
+     */
+    public static final String MMS_CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES =
+            CarrierConfigManager.KEY_MMS_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES_BOOL;
+    /**
+     * Whether MMS read report is enabled (boolean type)
+     */
+    public static final String MMS_CONFIG_MMS_READ_REPORT_ENABLED =
+            CarrierConfigManager.KEY_MMS_MMS_READ_REPORT_ENABLED_BOOL;
+    /**
+     * Whether MMS delivery report is enabled (boolean type)
+     */
+    public static final String MMS_CONFIG_MMS_DELIVERY_REPORT_ENABLED =
+            CarrierConfigManager.KEY_MMS_MMS_DELIVERY_REPORT_ENABLED_BOOL;
+    /**
+     * Max MMS message size in bytes (int type)
+     */
+    public static final String
+            MMS_CONFIG_MAX_MESSAGE_SIZE = CarrierConfigManager.KEY_MMS_MAX_MESSAGE_SIZE_INT;
+    /**
+     * Max MMS image width (int type)
+     */
+    public static final String
+            MMS_CONFIG_MAX_IMAGE_WIDTH = CarrierConfigManager.KEY_MMS_MAX_IMAGE_WIDTH_INT;
+    /**
+     * Max MMS image height (int type)
+     */
+    public static final String
+            MMS_CONFIG_MAX_IMAGE_HEIGHT = CarrierConfigManager.KEY_MMS_MAX_IMAGE_HEIGHT_INT;
+    /**
+     * Limit of recipients of MMS messages (int type)
+     */
+    public static final String
+            MMS_CONFIG_RECIPIENT_LIMIT = CarrierConfigManager.KEY_MMS_RECIPIENT_LIMIT_INT;
+    /**
+     * Min alias character count (int type)
+     */
+    public static final String
+            MMS_CONFIG_ALIAS_MIN_CHARS = CarrierConfigManager.KEY_MMS_ALIAS_MIN_CHARS_INT;
+    /**
+     * Max alias character count (int type)
+     */
+    public static final String
+            MMS_CONFIG_ALIAS_MAX_CHARS = CarrierConfigManager.KEY_MMS_ALIAS_MAX_CHARS_INT;
+    /**
+     * When the number of parts of a multipart SMS reaches this threshold, it should be converted
+     * into an MMS (int type)
+     */
+    public static final String MMS_CONFIG_SMS_TO_MMS_TEXT_THRESHOLD =
+            CarrierConfigManager.KEY_MMS_SMS_TO_MMS_TEXT_THRESHOLD_INT;
+    /**
+     * Some carriers require SMS to be converted into MMS when text length reaches this threshold
+     * (int type)
+     */
+    public static final String MMS_CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD =
+            CarrierConfigManager.KEY_MMS_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD_INT;
+    /**
+     * Max message text size (int type)
+     */
+    public static final String MMS_CONFIG_MESSAGE_TEXT_MAX_SIZE =
+            CarrierConfigManager.KEY_MMS_MESSAGE_TEXT_MAX_SIZE_INT;
+    /**
+     * Max message subject length (int type)
+     */
+    public static final String
+            MMS_CONFIG_SUBJECT_MAX_LENGTH = CarrierConfigManager.KEY_MMS_SUBJECT_MAX_LENGTH_INT;
+    /**
+     * MMS HTTP socket timeout in milliseconds (int type)
+     */
+    public static final String
+            MMS_CONFIG_HTTP_SOCKET_TIMEOUT = CarrierConfigManager.KEY_MMS_HTTP_SOCKET_TIMEOUT_INT;
+    /**
+     * The name of the UA Prof URL HTTP header for MMS HTTP request (String type)
+     */
+    public static final String
+            MMS_CONFIG_UA_PROF_TAG_NAME = CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING;
+    /**
+     * The User-Agent header value for MMS HTTP request (String type)
+     */
+    public static final String
+            MMS_CONFIG_USER_AGENT = CarrierConfigManager.KEY_MMS_USER_AGENT_STRING;
+    /**
+     * The UA Profile URL header value for MMS HTTP request (String type)
+     */
+    public static final String
+            MMS_CONFIG_UA_PROF_URL = CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING;
+    /**
+     * A list of HTTP headers to add to MMS HTTP request, separated by "|" (String type)
+     */
+    public static final String
+            MMS_CONFIG_HTTP_PARAMS = CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING;
+    /**
+     * Email gateway number (String type)
+     */
+    public static final String MMS_CONFIG_EMAIL_GATEWAY_NUMBER =
+            CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING;
+    /**
+     * The suffix to append to the NAI header value for MMS HTTP request (String type)
+     */
+    public static final String
+            MMS_CONFIG_NAI_SUFFIX = CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING;
+    /**
+     * If true, show the cell broadcast (amber alert) in the SMS settings. Some carriers don't want
+     * this shown. (Boolean type)
+     */
+    public static final String MMS_CONFIG_SHOW_CELL_BROADCAST_APP_LINKS =
+            CarrierConfigManager.KEY_MMS_SHOW_CELL_BROADCAST_APP_LINKS_BOOL;
+    /**
+     * Whether the carrier MMSC supports charset field in Content-Type header. If this is false,
+     * then we don't add "charset" to "Content-Type"
+     */
+    public static final String MMS_CONFIG_SUPPORT_HTTP_CHARSET_HEADER =
+            CarrierConfigManager.KEY_MMS_SUPPORT_HTTP_CHARSET_HEADER_BOOL;
+    /**
+     * If true, add "Connection: close" header to MMS HTTP requests so the connection
+     * is immediately closed (disabling keep-alive). (Boolean type)
+     * @hide
+     */
+    public static final String MMS_CONFIG_CLOSE_CONNECTION =
+            CarrierConfigManager.KEY_MMS_CLOSE_CONNECTION_BOOL;
+
+    /*
+     * Forwarded constants from SimDialogActivity.
+     */
+    private static String DIALOG_TYPE_KEY = "dialog_type";
+    private static final int SMS_PICK = 2;
+
+    /**
+     * Send a text based SMS.
+     *
+     * <p class="note"><strong>Note:</strong> Using this method requires that your app has the
+     * {@link android.Manifest.permission#SEND_SMS} permission.</p>
+     *
+     * <p class="note"><strong>Note:</strong> Beginning with Android 4.4 (API level 19), if
+     * <em>and only if</em> an app is not selected as the default SMS app, the system automatically
+     * writes messages sent using this method to the SMS Provider (the default SMS app is always
+     * responsible for writing its sent messages to the SMS Provider). For information about
+     * how to behave as the default SMS app, see {@link android.provider.Telephony}.</p>
+     *
+     *
+     * @param destinationAddress the address to send the message to
+     * @param scAddress is the service center address or null to use
+     *  the current default SMSC
+     * @param text the body of the message to send
+     * @param sentIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is successfully sent, or failed.
+     *  The result code will be <code>Activity.RESULT_OK</code> for success,
+     *  or one of these errors:<br>
+     *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
+     *  <code>RESULT_ERROR_RADIO_OFF</code><br>
+     *  <code>RESULT_ERROR_NULL_PDU</code><br>
+     *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
+     *  the extra "errorCode" containing a radio technology specific value,
+     *  generally only useful for troubleshooting.<br>
+     *  The per-application based SMS control checks sentIntent. If sentIntent
+     *  is NULL the caller will be checked against all unknown applications,
+     *  which cause smaller number of SMS to be sent in checking period.
+     * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is delivered to the recipient.  The
+     *  raw pdu of the status report is in the extended data ("pdu").
+     *
+     * @throws IllegalArgumentException if destinationAddress or text are empty
+     */
+    public void sendTextMessage(
+            String destinationAddress, String scAddress, String text,
+            PendingIntent sentIntent, PendingIntent deliveryIntent) {
+        sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent,
+                true /* persistMessage*/);
+    }
+
+    private void sendTextMessageInternal(String destinationAddress, String scAddress,
+            String text, PendingIntent sentIntent, PendingIntent deliveryIntent,
+            boolean persistMessage) {
+        if (TextUtils.isEmpty(destinationAddress)) {
+            throw new IllegalArgumentException("Invalid destinationAddress");
+        }
+
+        if (TextUtils.isEmpty(text)) {
+            throw new IllegalArgumentException("Invalid message body");
+        }
+
+        try {
+            ISms iccISms = getISmsServiceOrThrow();
+            iccISms.sendTextForSubscriber(getSubscriptionId(), ActivityThread.currentPackageName(),
+                    destinationAddress,
+                    scAddress, text, sentIntent, deliveryIntent,
+                    persistMessage);
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+    }
+
+    /**
+     * Send a text based SMS without writing it into the SMS Provider.
+     *
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE} or the calling app has carrier
+     * privileges.
+     * </p>
+     *
+     * @see #sendTextMessage(String, String, String, PendingIntent, PendingIntent)
+     * @hide
+     */
+    @SystemApi
+    public void sendTextMessageWithoutPersisting(
+            String destinationAddress, String scAddress, String text,
+            PendingIntent sentIntent, PendingIntent deliveryIntent) {
+        sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent,
+                false /* persistMessage */);
+    }
+
+    /**
+     * A variant of {@link SmsManager#sendTextMessage} that allows self to be the caller. This is
+     * for internal use only.
+     *
+     * @param persistMessage whether to persist the sent message in the SMS app. the caller must be
+     * the Phone process if set to false.
+     *
+     * @hide
+     */
+    public void sendTextMessageWithSelfPermissions(
+            String destinationAddress, String scAddress, String text,
+            PendingIntent sentIntent, PendingIntent deliveryIntent, boolean persistMessage) {
+        if (TextUtils.isEmpty(destinationAddress)) {
+            throw new IllegalArgumentException("Invalid destinationAddress");
+        }
+
+        if (TextUtils.isEmpty(text)) {
+            throw new IllegalArgumentException("Invalid message body");
+        }
+
+        try {
+            ISms iccISms = getISmsServiceOrThrow();
+            iccISms.sendTextForSubscriberWithSelfPermissions(getSubscriptionId(),
+                    ActivityThread.currentPackageName(),
+                    destinationAddress,
+                    scAddress, text, sentIntent, deliveryIntent, persistMessage);
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+    }
+
+    /**
+     * Inject an SMS PDU into the android application framework.
+     *
+     * The caller should have carrier privileges.
+     * @see android.telephony.TelephonyManager#hasCarrierPrivileges
+     *
+     * @param pdu is the byte array of pdu to be injected into android application framework
+     * @param format is the format of SMS pdu (3gpp or 3gpp2)
+     * @param receivedIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is successfully received by the
+     *  android application framework, or failed. This intent is broadcasted at
+     *  the same time an SMS received from radio is acknowledged back.
+     *  The result code will be <code>RESULT_SMS_HANDLED</code> for success, or
+     *  <code>RESULT_SMS_GENERIC_ERROR</code> for error.
+     *
+     * @throws IllegalArgumentException if format is not one of 3gpp and 3gpp2.
+     */
+    public void injectSmsPdu(byte[] pdu, String format, PendingIntent receivedIntent) {
+        if (!format.equals(SmsMessage.FORMAT_3GPP) && !format.equals(SmsMessage.FORMAT_3GPP2)) {
+            // Format must be either 3gpp or 3gpp2.
+            throw new IllegalArgumentException(
+                    "Invalid pdu format. format must be either 3gpp or 3gpp2");
+        }
+        try {
+            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
+            if (iccISms != null) {
+                iccISms.injectSmsPduForSubscriber(
+                        getSubscriptionId(), pdu, format, receivedIntent);
+            }
+        } catch (RemoteException ex) {
+          // ignore it
+        }
+    }
+
+    /**
+     * Divide a message text into several fragments, none bigger than
+     * the maximum SMS message size.
+     *
+     * @param text the original message.  Must not be null.
+     * @return an <code>ArrayList</code> of strings that, in order,
+     *   comprise the original message
+     *
+     * @throws IllegalArgumentException if text is null
+     */
+    public ArrayList<String> divideMessage(String text) {
+        if (null == text) {
+            throw new IllegalArgumentException("text is null");
+        }
+        return SmsMessage.fragmentText(text);
+    }
+
+    /**
+     * Send a multi-part text based SMS.  The callee should have already
+     * divided the message into correctly sized parts by calling
+     * <code>divideMessage</code>.
+     *
+     * <p class="note"><strong>Note:</strong> Using this method requires that your app has the
+     * {@link android.Manifest.permission#SEND_SMS} permission.</p>
+     *
+     * <p class="note"><strong>Note:</strong> Beginning with Android 4.4 (API level 19), if
+     * <em>and only if</em> an app is not selected as the default SMS app, the system automatically
+     * writes messages sent using this method to the SMS Provider (the default SMS app is always
+     * responsible for writing its sent messages to the SMS Provider). For information about
+     * how to behave as the default SMS app, see {@link android.provider.Telephony}.</p>
+     *
+     * @param destinationAddress the address to send the message to
+     * @param scAddress is the service center address or null to use
+     *   the current default SMSC
+     * @param parts an <code>ArrayList</code> of strings that, in order,
+     *   comprise the original message
+     * @param sentIntents if not null, an <code>ArrayList</code> of
+     *   <code>PendingIntent</code>s (one for each message part) that is
+     *   broadcast when the corresponding message part has been sent.
+     *   The result code will be <code>Activity.RESULT_OK</code> for success,
+     *   or one of these errors:<br>
+     *   <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
+     *   <code>RESULT_ERROR_RADIO_OFF</code><br>
+     *   <code>RESULT_ERROR_NULL_PDU</code><br>
+     *   For <code>RESULT_ERROR_GENERIC_FAILURE</code> each sentIntent may include
+     *   the extra "errorCode" containing a radio technology specific value,
+     *   generally only useful for troubleshooting.<br>
+     *   The per-application based SMS control checks sentIntent. If sentIntent
+     *   is NULL the caller will be checked against all unknown applications,
+     *   which cause smaller number of SMS to be sent in checking period.
+     * @param deliveryIntents if not null, an <code>ArrayList</code> of
+     *   <code>PendingIntent</code>s (one for each message part) that is
+     *   broadcast when the corresponding message part has been delivered
+     *   to the recipient.  The raw pdu of the status report is in the
+     *   extended data ("pdu").
+     *
+     * @throws IllegalArgumentException if destinationAddress or data are empty
+     */
+    public void sendMultipartTextMessage(
+            String destinationAddress, String scAddress, ArrayList<String> parts,
+            ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) {
+        sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents,
+                deliveryIntents, true /* persistMessage*/);
+    }
+
+    private void sendMultipartTextMessageInternal(
+            String destinationAddress, String scAddress, List<String> parts,
+            List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents,
+            boolean persistMessage) {
+        if (TextUtils.isEmpty(destinationAddress)) {
+            throw new IllegalArgumentException("Invalid destinationAddress");
+        }
+        if (parts == null || parts.size() < 1) {
+            throw new IllegalArgumentException("Invalid message body");
+        }
+
+        if (parts.size() > 1) {
+            try {
+                ISms iccISms = getISmsServiceOrThrow();
+                iccISms.sendMultipartTextForSubscriber(getSubscriptionId(),
+                        ActivityThread.currentPackageName(),
+                        destinationAddress, scAddress, parts,
+                        sentIntents, deliveryIntents, persistMessage);
+            } catch (RemoteException ex) {
+                // ignore it
+            }
+        } else {
+            PendingIntent sentIntent = null;
+            PendingIntent deliveryIntent = null;
+            if (sentIntents != null && sentIntents.size() > 0) {
+                sentIntent = sentIntents.get(0);
+            }
+            if (deliveryIntents != null && deliveryIntents.size() > 0) {
+                deliveryIntent = deliveryIntents.get(0);
+            }
+            sendTextMessage(destinationAddress, scAddress, parts.get(0),
+                    sentIntent, deliveryIntent);
+        }
+    }
+
+    /**
+     * Send a multi-part text based SMS without writing it into the SMS Provider.
+     *
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE} or the calling app has carrier
+     * privileges.
+     * </p>
+     *
+     * @see #sendMultipartTextMessage(String, String, ArrayList, ArrayList, ArrayList)
+     * @hide
+     **/
+    @SystemApi
+    public void sendMultipartTextMessageWithoutPersisting(
+            String destinationAddress, String scAddress, List<String> parts,
+            List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents) {
+        sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents,
+                deliveryIntents, false /* persistMessage*/);
+    }
+
+    /**
+     * Send a data based SMS to a specific application port.
+     *
+     * <p class="note"><strong>Note:</strong> Using this method requires that your app has the
+     * {@link android.Manifest.permission#SEND_SMS} permission.</p>
+     *
+     * @param destinationAddress the address to send the message to
+     * @param scAddress is the service center address or null to use
+     *  the current default SMSC
+     * @param destinationPort the port to deliver the message to
+     * @param data the body of the message to send
+     * @param sentIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is successfully sent, or failed.
+     *  The result code will be <code>Activity.RESULT_OK</code> for success,
+     *  or one of these errors:<br>
+     *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
+     *  <code>RESULT_ERROR_RADIO_OFF</code><br>
+     *  <code>RESULT_ERROR_NULL_PDU</code><br>
+     *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
+     *  the extra "errorCode" containing a radio technology specific value,
+     *  generally only useful for troubleshooting.<br>
+     *  The per-application based SMS control checks sentIntent. If sentIntent
+     *  is NULL the caller will be checked against all unknown applications,
+     *  which cause smaller number of SMS to be sent in checking period.
+     * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is delivered to the recipient.  The
+     *  raw pdu of the status report is in the extended data ("pdu").
+     *
+     * @throws IllegalArgumentException if destinationAddress or data are empty
+     */
+    public void sendDataMessage(
+            String destinationAddress, String scAddress, short destinationPort,
+            byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
+        if (TextUtils.isEmpty(destinationAddress)) {
+            throw new IllegalArgumentException("Invalid destinationAddress");
+        }
+
+        if (data == null || data.length == 0) {
+            throw new IllegalArgumentException("Invalid message data");
+        }
+
+        try {
+            ISms iccISms = getISmsServiceOrThrow();
+            iccISms.sendDataForSubscriber(getSubscriptionId(), ActivityThread.currentPackageName(),
+                    destinationAddress, scAddress, destinationPort & 0xFFFF,
+                    data, sentIntent, deliveryIntent);
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+    }
+
+    /**
+     * A variant of {@link SmsManager#sendDataMessage} that allows self to be the caller. This is
+     * for internal use only.
+     *
+     * @hide
+     */
+    public void sendDataMessageWithSelfPermissions(
+            String destinationAddress, String scAddress, short destinationPort,
+            byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
+        if (TextUtils.isEmpty(destinationAddress)) {
+            throw new IllegalArgumentException("Invalid destinationAddress");
+        }
+
+        if (data == null || data.length == 0) {
+            throw new IllegalArgumentException("Invalid message data");
+        }
+
+        try {
+            ISms iccISms = getISmsServiceOrThrow();
+            iccISms.sendDataForSubscriberWithSelfPermissions(getSubscriptionId(),
+                    ActivityThread.currentPackageName(), destinationAddress, scAddress,
+                    destinationPort & 0xFFFF, data, sentIntent, deliveryIntent);
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+    }
+
+
+
+    /**
+     * Get the SmsManager associated with the default subscription id. The instance will always be
+     * associated with the default subscription id, even if the default subscription id is changed.
+     *
+     * @return the SmsManager associated with the default subscription id
+     */
+    public static SmsManager getDefault() {
+        return sInstance;
+    }
+
+    /**
+     * Get the the instance of the SmsManager associated with a particular subscription id
+     *
+     * @param subId an SMS subscription id, typically accessed using
+     *   {@link android.telephony.SubscriptionManager}
+     * @return the instance of the SmsManager associated with subId
+     */
+    public static SmsManager getSmsManagerForSubscriptionId(int subId) {
+        // TODO(shri): Add javadoc link once SubscriptionManager is made public api
+        synchronized(sLockObject) {
+            SmsManager smsManager = sSubInstances.get(subId);
+            if (smsManager == null) {
+                smsManager = new SmsManager(subId);
+                sSubInstances.put(subId, smsManager);
+            }
+            return smsManager;
+        }
+    }
+
+    private SmsManager(int subId) {
+        mSubId = subId;
+    }
+
+    /**
+     * Get the associated subscription id. If the instance was returned by {@link #getDefault()},
+     * then this method may return different values at different points in time (if the user
+     * changes the default subscription id). It will return < 0 if the default subscription id
+     * cannot be determined.
+     *
+     * Additionally, to support legacy applications that are not multi-SIM aware,
+     * if the following are true:
+     *     - We are using a multi-SIM device
+     *     - A default SMS SIM has not been selected
+     *     - At least one SIM subscription is available
+     * then ask the user to set the default SMS SIM.
+     *
+     * @return associated subscription id
+     */
+    public int getSubscriptionId() {
+        final int subId = (mSubId == DEFAULT_SUBSCRIPTION_ID)
+                ? getDefaultSmsSubscriptionId() : mSubId;
+        boolean isSmsSimPickActivityNeeded = false;
+        final Context context = ActivityThread.currentApplication().getApplicationContext();
+        try {
+            ISms iccISms = getISmsService();
+            if (iccISms != null) {
+                isSmsSimPickActivityNeeded = iccISms.isSmsSimPickActivityNeeded(subId);
+            }
+        } catch (RemoteException ex) {
+            Log.e(TAG, "Exception in getSubscriptionId");
+        }
+
+        if (isSmsSimPickActivityNeeded) {
+            Log.d(TAG, "getSubscriptionId isSmsSimPickActivityNeeded is true");
+            // ask the user for a default SMS SIM.
+            Intent intent = new Intent();
+            intent.setClassName("com.android.settings",
+                    "com.android.settings.sim.SimDialogActivity");
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            intent.putExtra(DIALOG_TYPE_KEY, SMS_PICK);
+            try {
+                context.startActivity(intent);
+            } catch (ActivityNotFoundException anfe) {
+                // If Settings is not installed, only log the error as we do not want to break
+                // legacy applications.
+                Log.e(TAG, "Unable to launch Settings application.");
+            }
+        }
+
+        return subId;
+    }
+
+    /**
+     * Returns the ISms service, or throws an UnsupportedOperationException if
+     * the service does not exist.
+     */
+    private static ISms getISmsServiceOrThrow() {
+        ISms iccISms = getISmsService();
+        if (iccISms == null) {
+            throw new UnsupportedOperationException("Sms is not supported");
+        }
+        return iccISms;
+    }
+
+    private static ISms getISmsService() {
+        return ISms.Stub.asInterface(ServiceManager.getService("isms"));
+    }
+
+    /**
+     * Copy a raw SMS PDU to the ICC.
+     * ICC (Integrated Circuit Card) is the card of the device.
+     * For example, this can be the SIM or USIM for GSM.
+     *
+     * @param smsc the SMSC for this message, or NULL for the default SMSC
+     * @param pdu the raw PDU to store
+     * @param status message status (STATUS_ON_ICC_READ, STATUS_ON_ICC_UNREAD,
+     *               STATUS_ON_ICC_SENT, STATUS_ON_ICC_UNSENT)
+     * @return true for success
+     *
+     * @throws IllegalArgumentException if pdu is NULL
+     * {@hide}
+     */
+    public boolean copyMessageToIcc(byte[] smsc, byte[] pdu,int status) {
+        boolean success = false;
+
+        if (null == pdu) {
+            throw new IllegalArgumentException("pdu is NULL");
+        }
+        try {
+            ISms iccISms = getISmsService();
+            if (iccISms != null) {
+                success = iccISms.copyMessageToIccEfForSubscriber(getSubscriptionId(),
+                        ActivityThread.currentPackageName(),
+                        status, pdu, smsc);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+
+        return success;
+    }
+
+    /**
+     * Delete the specified message from the ICC.
+     * ICC (Integrated Circuit Card) is the card of the device.
+     * For example, this can be the SIM or USIM for GSM.
+     *
+     * @param messageIndex is the record index of the message on ICC
+     * @return true for success
+     *
+     * {@hide}
+     */
+    public boolean
+    deleteMessageFromIcc(int messageIndex) {
+        boolean success = false;
+        byte[] pdu = new byte[SMS_RECORD_LENGTH-1];
+        Arrays.fill(pdu, (byte)0xff);
+
+        try {
+            ISms iccISms = getISmsService();
+            if (iccISms != null) {
+                success = iccISms.updateMessageOnIccEfForSubscriber(getSubscriptionId(),
+                        ActivityThread.currentPackageName(),
+                        messageIndex, STATUS_ON_ICC_FREE, pdu);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+
+        return success;
+    }
+
+    /**
+     * Update the specified message on the ICC.
+     * ICC (Integrated Circuit Card) is the card of the device.
+     * For example, this can be the SIM or USIM for GSM.
+     *
+     * @param messageIndex record index of message to update
+     * @param newStatus new message status (STATUS_ON_ICC_READ,
+     *                  STATUS_ON_ICC_UNREAD, STATUS_ON_ICC_SENT,
+     *                  STATUS_ON_ICC_UNSENT, STATUS_ON_ICC_FREE)
+     * @param pdu the raw PDU to store
+     * @return true for success
+     *
+     * {@hide}
+     */
+    public boolean updateMessageOnIcc(int messageIndex, int newStatus, byte[] pdu) {
+        boolean success = false;
+
+        try {
+            ISms iccISms = getISmsService();
+            if (iccISms != null) {
+                success = iccISms.updateMessageOnIccEfForSubscriber(getSubscriptionId(),
+                        ActivityThread.currentPackageName(),
+                        messageIndex, newStatus, pdu);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+
+        return success;
+    }
+
+    /**
+     * Retrieves all messages currently stored on ICC.
+     * ICC (Integrated Circuit Card) is the card of the device.
+     * For example, this can be the SIM or USIM for GSM.
+     *
+     * @return <code>ArrayList</code> of <code>SmsMessage</code> objects
+     *
+     * {@hide}
+     */
+    public ArrayList<SmsMessage> getAllMessagesFromIcc() {
+        List<SmsRawData> records = null;
+
+        try {
+            ISms iccISms = getISmsService();
+            if (iccISms != null) {
+                records = iccISms.getAllMessagesFromIccEfForSubscriber(
+                        getSubscriptionId(),
+                        ActivityThread.currentPackageName());
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+
+        return createMessageListFromRawRecords(records);
+    }
+
+    /**
+     * Enable reception of cell broadcast (SMS-CB) messages with the given
+     * message identifier and RAN type. The RAN type specify this message ID
+     * belong to 3GPP (GSM) or 3GPP2(CDMA).Note that if two different clients
+     * enable the same message identifier, they must both disable it for the device to stop
+     * receiving those messages. All received messages will be broadcast in an
+     * intent with the action "android.provider.Telephony.SMS_CB_RECEIVED".
+     * Note: This call is blocking, callers may want to avoid calling it from
+     * the main thread of an application.
+     *
+     * @param messageIdentifier Message identifier as specified in TS 23.041 (3GPP)
+     * or C.R1001-G (3GPP2)
+     * @param ranType as defined in class SmsManager, the value can be one of these:
+     *    android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_GSM
+     *    android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_CDMA
+     * @return true if successful, false otherwise
+     * @see #disableCellBroadcast(int, int)
+     *
+     * {@hide}
+     */
+    public boolean enableCellBroadcast(int messageIdentifier, int ranType) {
+        boolean success = false;
+
+        try {
+            ISms iccISms = getISmsService();
+            if (iccISms != null) {
+                success = iccISms.enableCellBroadcastForSubscriber(
+                        getSubscriptionId(), messageIdentifier, ranType);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+
+        return success;
+    }
+
+    /**
+     * Disable reception of cell broadcast (SMS-CB) messages with the given
+     * message identifier and RAN type. The RAN type specify this message ID
+     * belong to 3GPP (GSM) or 3GPP2(CDMA). Note that if two different clients
+     * enable the same message identifier, they must both disable it for the
+     * device to stop receiving those messages.
+     * Note: This call is blocking, callers may want to avoid calling it from
+     * the main thread of an application.
+     *
+     * @param messageIdentifier Message identifier as specified in TS 23.041 (3GPP)
+     * or C.R1001-G (3GPP2)
+     * @param ranType as defined in class SmsManager, the value can be one of these:
+     *    android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_GSM
+     *    android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_CDMA
+     * @return true if successful, false otherwise
+     *
+     * @see #enableCellBroadcast(int, int)
+     *
+     * {@hide}
+     */
+    public boolean disableCellBroadcast(int messageIdentifier, int ranType) {
+        boolean success = false;
+
+        try {
+            ISms iccISms = getISmsService();
+            if (iccISms != null) {
+                success = iccISms.disableCellBroadcastForSubscriber(
+                        getSubscriptionId(), messageIdentifier, ranType);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+
+        return success;
+    }
+
+    /**
+     * Enable reception of cell broadcast (SMS-CB) messages with the given
+     * message identifier range and RAN type. The RAN type specify this message ID
+     * belong to 3GPP (GSM) or 3GPP2(CDMA). Note that if two different clients enable
+     * the same message identifier, they must both disable it for the device to stop
+     * receiving those messages. All received messages will be broadcast in an
+     * intent with the action "android.provider.Telephony.SMS_CB_RECEIVED".
+     * Note: This call is blocking, callers may want to avoid calling it from
+     * the main thread of an application.
+     *
+     * @param startMessageId first message identifier as specified in TS 23.041 (3GPP)
+     * or C.R1001-G (3GPP2)
+     * @param endMessageId last message identifier as specified in TS 23.041 (3GPP)
+     * or C.R1001-G (3GPP2)
+     * @param ranType as defined in class SmsManager, the value can be one of these:
+     *    android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_GSM
+     *    android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_CDMA
+     * @return true if successful, false otherwise
+     * @see #disableCellBroadcastRange(int, int, int)
+     *
+     * @throws IllegalArgumentException if endMessageId < startMessageId
+     * {@hide}
+     */
+    public boolean enableCellBroadcastRange(int startMessageId, int endMessageId, int ranType) {
+        boolean success = false;
+
+        if (endMessageId < startMessageId) {
+            throw new IllegalArgumentException("endMessageId < startMessageId");
+        }
+        try {
+            ISms iccISms = getISmsService();
+            if (iccISms != null) {
+                success = iccISms.enableCellBroadcastRangeForSubscriber(getSubscriptionId(),
+                        startMessageId, endMessageId, ranType);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+
+        return success;
+    }
+
+    /**
+     * Disable reception of cell broadcast (SMS-CB) messages with the given
+     * message identifier range and RAN type. The RAN type specify this message
+     * ID range belong to 3GPP (GSM) or 3GPP2(CDMA). Note that if two different
+     * clients enable the same message identifier, they must both disable it for
+     * the device to stop receiving those messages.
+     * Note: This call is blocking, callers may want to avoid calling it from
+     * the main thread of an application.
+     *
+     * @param startMessageId first message identifier as specified in TS 23.041 (3GPP)
+     * or C.R1001-G (3GPP2)
+     * @param endMessageId last message identifier as specified in TS 23.041 (3GPP)
+     * or C.R1001-G (3GPP2)
+     * @param ranType as defined in class SmsManager, the value can be one of these:
+     *    android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_GSM
+     *    android.telephony.SmsMessage.CELL_BROADCAST_RAN_TYPE_CDMA
+     * @return true if successful, false otherwise
+     *
+     * @see #enableCellBroadcastRange(int, int, int)
+     *
+     * @throws IllegalArgumentException if endMessageId < startMessageId
+     * {@hide}
+     */
+    public boolean disableCellBroadcastRange(int startMessageId, int endMessageId, int ranType) {
+        boolean success = false;
+
+        if (endMessageId < startMessageId) {
+            throw new IllegalArgumentException("endMessageId < startMessageId");
+        }
+        try {
+            ISms iccISms = getISmsService();
+            if (iccISms != null) {
+                success = iccISms.disableCellBroadcastRangeForSubscriber(getSubscriptionId(),
+                        startMessageId, endMessageId, ranType);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+
+        return success;
+    }
+
+    /**
+     * Create a list of <code>SmsMessage</code>s from a list of RawSmsData
+     * records returned by <code>getAllMessagesFromIcc()</code>
+     *
+     * @param records SMS EF records, returned by
+     *   <code>getAllMessagesFromIcc</code>
+     * @return <code>ArrayList</code> of <code>SmsMessage</code> objects.
+     */
+    private static ArrayList<SmsMessage> createMessageListFromRawRecords(List<SmsRawData> records) {
+        ArrayList<SmsMessage> messages = new ArrayList<SmsMessage>();
+        if (records != null) {
+            int count = records.size();
+            for (int i = 0; i < count; i++) {
+                SmsRawData data = records.get(i);
+                // List contains all records, including "free" records (null)
+                if (data != null) {
+                    SmsMessage sms = SmsMessage.createFromEfRecord(i+1, data.getBytes());
+                    if (sms != null) {
+                        messages.add(sms);
+                    }
+                }
+            }
+        }
+        return messages;
+    }
+
+    /**
+     * SMS over IMS is supported if IMS is registered and SMS is supported
+     * on IMS.
+     *
+     * @return true if SMS over IMS is supported, false otherwise
+     *
+     * @see #getImsSmsFormat()
+     *
+     * @hide
+     */
+    public boolean isImsSmsSupported() {
+        boolean boSupported = false;
+        try {
+            ISms iccISms = getISmsService();
+            if (iccISms != null) {
+                boSupported = iccISms.isImsSmsSupportedForSubscriber(getSubscriptionId());
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+        return boSupported;
+    }
+
+    /**
+     * Gets SMS format supported on IMS.  SMS over IMS format is
+     * either 3GPP or 3GPP2.
+     *
+     * @return SmsMessage.FORMAT_3GPP,
+     *         SmsMessage.FORMAT_3GPP2
+     *      or SmsMessage.FORMAT_UNKNOWN
+     *
+     * @see #isImsSmsSupported()
+     *
+     * @hide
+     */
+    public String getImsSmsFormat() {
+        String format = com.android.internal.telephony.SmsConstants.FORMAT_UNKNOWN;
+        try {
+            ISms iccISms = getISmsService();
+            if (iccISms != null) {
+                format = iccISms.getImsSmsFormatForSubscriber(getSubscriptionId());
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+        return format;
+    }
+
+    /**
+     * Get default sms subscription id
+     *
+     * @return the default SMS subscription id
+     */
+    public static int getDefaultSmsSubscriptionId() {
+        ISms iccISms = null;
+        try {
+            iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
+            return iccISms.getPreferredSmsSubscription();
+        } catch (RemoteException ex) {
+            return -1;
+        } catch (NullPointerException ex) {
+            return -1;
+        }
+    }
+
+    /**
+     * Get SMS prompt property,  enabled or not
+     *
+     * @return true if enabled, false otherwise
+     * @hide
+     */
+    public boolean isSMSPromptEnabled() {
+        ISms iccISms = null;
+        try {
+            iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
+            return iccISms.isSMSPromptEnabled();
+        } catch (RemoteException ex) {
+            return false;
+        } catch (NullPointerException ex) {
+            return false;
+        }
+    }
+
+    // see SmsMessage.getStatusOnIcc
+
+    /** Free space (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
+    static public final int STATUS_ON_ICC_FREE      = 0;
+
+    /** Received and read (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
+    static public final int STATUS_ON_ICC_READ      = 1;
+
+    /** Received and unread (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
+    static public final int STATUS_ON_ICC_UNREAD    = 3;
+
+    /** Stored and sent (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
+    static public final int STATUS_ON_ICC_SENT      = 5;
+
+    /** Stored and unsent (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
+    static public final int STATUS_ON_ICC_UNSENT    = 7;
+
+    // SMS send failure result codes
+
+    /** Generic failure cause */
+    static public final int RESULT_ERROR_GENERIC_FAILURE    = 1;
+    /** Failed because radio was explicitly turned off */
+    static public final int RESULT_ERROR_RADIO_OFF          = 2;
+    /** Failed because no pdu provided */
+    static public final int RESULT_ERROR_NULL_PDU           = 3;
+    /** Failed because service is currently unavailable */
+    static public final int RESULT_ERROR_NO_SERVICE         = 4;
+    /** Failed because we reached the sending queue limit.  {@hide} */
+    static public final int RESULT_ERROR_LIMIT_EXCEEDED     = 5;
+    /** Failed because FDN is enabled. {@hide} */
+    static public final int RESULT_ERROR_FDN_CHECK_FAILURE  = 6;
+
+    static private final String PHONE_PACKAGE_NAME = "com.android.phone";
+
+    /**
+     * Send an MMS message
+     *
+     * @param context application context
+     * @param contentUri the content Uri from which the message pdu will be read
+     * @param locationUrl the optional location url where message should be sent to
+     * @param configOverrides the carrier-specific messaging configuration values to override for
+     *  sending the message.
+     * @param sentIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is successfully sent, or failed
+     * @throws IllegalArgumentException if contentUri is empty
+     */
+    public void sendMultimediaMessage(Context context, Uri contentUri, String locationUrl,
+            Bundle configOverrides, PendingIntent sentIntent) {
+        if (contentUri == null) {
+            throw new IllegalArgumentException("Uri contentUri null");
+        }
+        try {
+            final IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));
+            if (iMms == null) {
+                return;
+            }
+
+            iMms.sendMessage(getSubscriptionId(), ActivityThread.currentPackageName(), contentUri,
+                    locationUrl, configOverrides, sentIntent);
+        } catch (RemoteException e) {
+            // Ignore it
+        }
+    }
+
+    /**
+     * Download an MMS message from carrier by a given location URL
+     *
+     * @param context application context
+     * @param locationUrl the location URL of the MMS message to be downloaded, usually obtained
+     *  from the MMS WAP push notification
+     * @param contentUri the content uri to which the downloaded pdu will be written
+     * @param configOverrides the carrier-specific messaging configuration values to override for
+     *  downloading the message.
+     * @param downloadedIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is downloaded, or the download is failed
+     * @throws IllegalArgumentException if locationUrl or contentUri is empty
+     */
+    public void downloadMultimediaMessage(Context context, String locationUrl, Uri contentUri,
+            Bundle configOverrides, PendingIntent downloadedIntent) {
+        if (TextUtils.isEmpty(locationUrl)) {
+            throw new IllegalArgumentException("Empty MMS location URL");
+        }
+        if (contentUri == null) {
+            throw new IllegalArgumentException("Uri contentUri null");
+        }
+        try {
+            final IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));
+            if (iMms == null) {
+                return;
+            }
+            iMms.downloadMessage(
+                    getSubscriptionId(), ActivityThread.currentPackageName(), locationUrl,
+                    contentUri, configOverrides, downloadedIntent);
+        } catch (RemoteException e) {
+            // Ignore it
+        }
+    }
+
+    // MMS send/download failure result codes
+    public static final int MMS_ERROR_UNSPECIFIED = 1;
+    public static final int MMS_ERROR_INVALID_APN = 2;
+    public static final int MMS_ERROR_UNABLE_CONNECT_MMS = 3;
+    public static final int MMS_ERROR_HTTP_FAILURE = 4;
+    public static final int MMS_ERROR_IO_ERROR = 5;
+    public static final int MMS_ERROR_RETRY = 6;
+    public static final int MMS_ERROR_CONFIGURATION_ERROR = 7;
+    public static final int MMS_ERROR_NO_DATA_NETWORK = 8;
+
+    /** Intent extra name for MMS sending result data in byte array type */
+    public static final String EXTRA_MMS_DATA = "android.telephony.extra.MMS_DATA";
+    /** Intent extra name for HTTP status code for MMS HTTP failure in integer type */
+    public static final String EXTRA_MMS_HTTP_STATUS = "android.telephony.extra.MMS_HTTP_STATUS";
+
+    /**
+     * Import a text message into system's SMS store
+     *
+     * Only default SMS apps can import SMS
+     *
+     * @param address the destination(source) address of the sent(received) message
+     * @param type the type of the message
+     * @param text the message text
+     * @param timestampMillis the message timestamp in milliseconds
+     * @param seen if the message is seen
+     * @param read if the message is read
+     * @return the message URI, null if failed
+     * @hide
+     */
+    public Uri importTextMessage(String address, int type, String text, long timestampMillis,
+            boolean seen, boolean read) {
+        try {
+            IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));
+            if (iMms != null) {
+                return iMms.importTextMessage(ActivityThread.currentPackageName(),
+                        address, type, text, timestampMillis, seen, read);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+        return null;
+    }
+
+    /** Represents the received SMS message for importing {@hide} */
+    public static final int SMS_TYPE_INCOMING = 0;
+    /** Represents the sent SMS message for importing {@hide} */
+    public static final int SMS_TYPE_OUTGOING = 1;
+
+    /**
+     * Import a multimedia message into system's MMS store. Only the following PDU type is
+     * supported: Retrieve.conf, Send.req, Notification.ind, Delivery.ind, Read-Orig.ind
+     *
+     * Only default SMS apps can import MMS
+     *
+     * @param contentUri the content uri from which to read the PDU of the message to import
+     * @param messageId the optional message id. Use null if not specifying
+     * @param timestampSecs the optional message timestamp. Use -1 if not specifying
+     * @param seen if the message is seen
+     * @param read if the message is read
+     * @return the message URI, null if failed
+     * @throws IllegalArgumentException if pdu is empty
+     * {@hide}
+     */
+    public Uri importMultimediaMessage(Uri contentUri, String messageId, long timestampSecs,
+            boolean seen, boolean read) {
+        if (contentUri == null) {
+            throw new IllegalArgumentException("Uri contentUri null");
+        }
+        try {
+            IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));
+            if (iMms != null) {
+                return iMms.importMultimediaMessage(ActivityThread.currentPackageName(),
+                        contentUri, messageId, timestampSecs, seen, read);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+        return null;
+    }
+
+    /**
+     * Delete a system stored SMS or MMS message
+     *
+     * Only default SMS apps can delete system stored SMS and MMS messages
+     *
+     * @param messageUri the URI of the stored message
+     * @return true if deletion is successful, false otherwise
+     * @throws IllegalArgumentException if messageUri is empty
+     * {@hide}
+     */
+    public boolean deleteStoredMessage(Uri messageUri) {
+        if (messageUri == null) {
+            throw new IllegalArgumentException("Empty message URI");
+        }
+        try {
+            IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));
+            if (iMms != null) {
+                return iMms.deleteStoredMessage(ActivityThread.currentPackageName(), messageUri);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+        return false;
+    }
+
+    /**
+     * Delete a system stored SMS or MMS thread
+     *
+     * Only default SMS apps can delete system stored SMS and MMS conversations
+     *
+     * @param conversationId the ID of the message conversation
+     * @return true if deletion is successful, false otherwise
+     * {@hide}
+     */
+    public boolean deleteStoredConversation(long conversationId) {
+        try {
+            IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));
+            if (iMms != null) {
+                return iMms.deleteStoredConversation(
+                        ActivityThread.currentPackageName(), conversationId);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+        return false;
+    }
+
+    /**
+     * Update the status properties of a system stored SMS or MMS message, e.g.
+     * the read status of a message, etc.
+     *
+     * @param messageUri the URI of the stored message
+     * @param statusValues a list of status properties in key-value pairs to update
+     * @return true if update is successful, false otherwise
+     * @throws IllegalArgumentException if messageUri is empty
+     * {@hide}
+     */
+    public boolean updateStoredMessageStatus(Uri messageUri, ContentValues statusValues) {
+        if (messageUri == null) {
+            throw new IllegalArgumentException("Empty message URI");
+        }
+        try {
+            IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));
+            if (iMms != null) {
+                return iMms.updateStoredMessageStatus(ActivityThread.currentPackageName(),
+                        messageUri, statusValues);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+        return false;
+    }
+
+    /** Message status property: whether the message has been seen. 1 means seen, 0 not {@hide} */
+    public static final String MESSAGE_STATUS_SEEN = "seen";
+    /** Message status property: whether the message has been read. 1 means read, 0 not {@hide} */
+    public static final String MESSAGE_STATUS_READ = "read";
+
+    /**
+     * Archive or unarchive a stored conversation
+     *
+     * @param conversationId the ID of the message conversation
+     * @param archived true to archive the conversation, false to unarchive
+     * @return true if update is successful, false otherwise
+     * {@hide}
+     */
+    public boolean archiveStoredConversation(long conversationId, boolean archived) {
+        try {
+            IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));
+            if (iMms != null) {
+                return iMms.archiveStoredConversation(ActivityThread.currentPackageName(),
+                        conversationId, archived);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+        return false;
+    }
+
+    /**
+     * Add a text message draft to system SMS store
+     *
+     * Only default SMS apps can add SMS draft
+     *
+     * @param address the destination address of message
+     * @param text the body of the message to send
+     * @return the URI of the stored draft message
+     * {@hide}
+     */
+    public Uri addTextMessageDraft(String address, String text) {
+        try {
+            IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));
+            if (iMms != null) {
+                return iMms.addTextMessageDraft(ActivityThread.currentPackageName(), address, text);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+        return null;
+    }
+
+    /**
+     * Add a multimedia message draft to system MMS store
+     *
+     * Only default SMS apps can add MMS draft
+     *
+     * @param contentUri the content uri from which to read the PDU data of the draft MMS
+     * @return the URI of the stored draft message
+     * @throws IllegalArgumentException if pdu is empty
+     * {@hide}
+     */
+    public Uri addMultimediaMessageDraft(Uri contentUri) {
+        if (contentUri == null) {
+            throw new IllegalArgumentException("Uri contentUri null");
+        }
+        try {
+            IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));
+            if (iMms != null) {
+                return iMms.addMultimediaMessageDraft(ActivityThread.currentPackageName(),
+                        contentUri);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+        return null;
+    }
+
+    /**
+     * Send a system stored text message.
+     *
+     * You can only send a failed text message or a draft text message.
+     *
+     * @param messageUri the URI of the stored message
+     * @param scAddress is the service center address or null to use the current default SMSC
+     * @param sentIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is successfully sent, or failed.
+     *  The result code will be <code>Activity.RESULT_OK</code> for success,
+     *  or one of these errors:<br>
+     *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
+     *  <code>RESULT_ERROR_RADIO_OFF</code><br>
+     *  <code>RESULT_ERROR_NULL_PDU</code><br>
+     *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
+     *  the extra "errorCode" containing a radio technology specific value,
+     *  generally only useful for troubleshooting.<br>
+     *  The per-application based SMS control checks sentIntent. If sentIntent
+     *  is NULL the caller will be checked against all unknown applications,
+     *  which cause smaller number of SMS to be sent in checking period.
+     * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is delivered to the recipient.  The
+     *  raw pdu of the status report is in the extended data ("pdu").
+     *
+     * @throws IllegalArgumentException if messageUri is empty
+     * {@hide}
+     */
+    public void sendStoredTextMessage(Uri messageUri, String scAddress, PendingIntent sentIntent,
+            PendingIntent deliveryIntent) {
+        if (messageUri == null) {
+            throw new IllegalArgumentException("Empty message URI");
+        }
+        try {
+            ISms iccISms = getISmsServiceOrThrow();
+            iccISms.sendStoredText(
+                    getSubscriptionId(), ActivityThread.currentPackageName(), messageUri,
+                    scAddress, sentIntent, deliveryIntent);
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+    }
+
+    /**
+     * Send a system stored multi-part text message.
+     *
+     * You can only send a failed text message or a draft text message.
+     * The provided <code>PendingIntent</code> lists should match the part number of the
+     * divided text of the stored message by using <code>divideMessage</code>
+     *
+     * @param messageUri the URI of the stored message
+     * @param scAddress is the service center address or null to use
+     *   the current default SMSC
+     * @param sentIntents if not null, an <code>ArrayList</code> of
+     *   <code>PendingIntent</code>s (one for each message part) that is
+     *   broadcast when the corresponding message part has been sent.
+     *   The result code will be <code>Activity.RESULT_OK</code> for success,
+     *   or one of these errors:<br>
+     *   <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
+     *   <code>RESULT_ERROR_RADIO_OFF</code><br>
+     *   <code>RESULT_ERROR_NULL_PDU</code><br>
+     *   For <code>RESULT_ERROR_GENERIC_FAILURE</code> each sentIntent may include
+     *   the extra "errorCode" containing a radio technology specific value,
+     *   generally only useful for troubleshooting.<br>
+     *   The per-application based SMS control checks sentIntent. If sentIntent
+     *   is NULL the caller will be checked against all unknown applications,
+     *   which cause smaller number of SMS to be sent in checking period.
+     * @param deliveryIntents if not null, an <code>ArrayList</code> of
+     *   <code>PendingIntent</code>s (one for each message part) that is
+     *   broadcast when the corresponding message part has been delivered
+     *   to the recipient.  The raw pdu of the status report is in the
+     *   extended data ("pdu").
+     *
+     * @throws IllegalArgumentException if messageUri is empty
+     * {@hide}
+     */
+    public void sendStoredMultipartTextMessage(Uri messageUri, String scAddress,
+            ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) {
+        if (messageUri == null) {
+            throw new IllegalArgumentException("Empty message URI");
+        }
+        try {
+            ISms iccISms = getISmsServiceOrThrow();
+            iccISms.sendStoredMultipartText(
+                    getSubscriptionId(), ActivityThread.currentPackageName(), messageUri,
+                    scAddress, sentIntents, deliveryIntents);
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+    }
+
+    /**
+     * Send a system stored MMS message
+     *
+     * This is used for sending a previously sent, but failed-to-send, message or
+     * for sending a text message that has been stored as a draft.
+     *
+     * @param messageUri the URI of the stored message
+     * @param configOverrides the carrier-specific messaging configuration values to override for
+     *  sending the message.
+     * @param sentIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is successfully sent, or failed
+     * @throws IllegalArgumentException if messageUri is empty
+     * {@hide}
+     */
+    public void sendStoredMultimediaMessage(Uri messageUri, Bundle configOverrides,
+            PendingIntent sentIntent) {
+        if (messageUri == null) {
+            throw new IllegalArgumentException("Empty message URI");
+        }
+        try {
+            IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));
+            if (iMms != null) {
+                iMms.sendStoredMessage(
+                        getSubscriptionId(), ActivityThread.currentPackageName(), messageUri,
+                        configOverrides, sentIntent);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+    }
+
+    /**
+     * Turns on/off the flag to automatically write sent/received SMS/MMS messages into system
+     *
+     * When this flag is on, all SMS/MMS sent/received are stored by system automatically
+     * When this flag is off, only SMS/MMS sent by non-default SMS apps are stored by system
+     * automatically
+     *
+     * This flag can only be changed by default SMS apps
+     *
+     * @param enabled Whether to enable message auto persisting
+     * {@hide}
+     */
+    public void setAutoPersisting(boolean enabled) {
+        try {
+            IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));
+            if (iMms != null) {
+                iMms.setAutoPersisting(ActivityThread.currentPackageName(), enabled);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+    }
+
+    /**
+     * Get the value of the flag to automatically write sent/received SMS/MMS messages into system
+     *
+     * When this flag is on, all SMS/MMS sent/received are stored by system automatically
+     * When this flag is off, only SMS/MMS sent by non-default SMS apps are stored by system
+     * automatically
+     *
+     * @return the current value of the auto persist flag
+     * {@hide}
+     */
+    public boolean getAutoPersisting() {
+        try {
+            IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));
+            if (iMms != null) {
+                return iMms.getAutoPersisting();
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+        return false;
+    }
+
+    /**
+     * Get carrier-dependent configuration values.
+     *
+     * @return bundle key/values pairs of configuration values
+     */
+    public Bundle getCarrierConfigValues() {
+        try {
+            IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));
+            if (iMms != null) {
+                return iMms.getCarrierConfigValues(getSubscriptionId());
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+        return null;
+    }
+
+    /**
+     * Create a single use app specific incoming SMS request for the the calling package.
+     *
+     * This method returns a token that if included in a subsequent incoming SMS message will cause
+     * {@code intent} to be sent with the SMS data.
+     *
+     * The token is only good for one use, after an SMS has been received containing the token all
+     * subsequent SMS messages with the token will be routed as normal.
+     *
+     * An app can only have one request at a time, if the app already has a request pending it will
+     * be replaced with a new request.
+     *
+     * @return Token to include in an SMS message. The token will be 11 characters long.
+     * @see android.provider.Telephony.Sms.Intents#getMessagesFromIntent
+     */
+    public String createAppSpecificSmsToken(PendingIntent intent) {
+        try {
+            ISms iccSms = getISmsServiceOrThrow();
+            return iccSms.createAppSpecificSmsToken(getSubscriptionId(),
+                    ActivityThread.currentPackageName(), intent);
+
+        } catch (RemoteException ex) {
+            ex.rethrowFromSystemServer();
+            return null;
+        }
+    }
+
+    /**
+     * Filters a bundle to only contain MMS config variables.
+     *
+     * This is for use with bundles returned by {@link CarrierConfigManager} which contain MMS
+     * config and unrelated config. It is assumed that all MMS_CONFIG_* keys are present in the
+     * supplied bundle.
+     *
+     * @param config a Bundle that contains MMS config variables and possibly more.
+     * @return a new Bundle that only contains the MMS_CONFIG_* keys defined above.
+     * @hide
+     */
+    public static Bundle getMmsConfig(BaseBundle config) {
+        Bundle filtered = new Bundle();
+        filtered.putBoolean(MMS_CONFIG_APPEND_TRANSACTION_ID,
+                config.getBoolean(MMS_CONFIG_APPEND_TRANSACTION_ID));
+        filtered.putBoolean(MMS_CONFIG_MMS_ENABLED, config.getBoolean(MMS_CONFIG_MMS_ENABLED));
+        filtered.putBoolean(MMS_CONFIG_GROUP_MMS_ENABLED,
+                config.getBoolean(MMS_CONFIG_GROUP_MMS_ENABLED));
+        filtered.putBoolean(MMS_CONFIG_NOTIFY_WAP_MMSC_ENABLED,
+                config.getBoolean(MMS_CONFIG_NOTIFY_WAP_MMSC_ENABLED));
+        filtered.putBoolean(MMS_CONFIG_ALIAS_ENABLED, config.getBoolean(MMS_CONFIG_ALIAS_ENABLED));
+        filtered.putBoolean(MMS_CONFIG_ALLOW_ATTACH_AUDIO,
+                config.getBoolean(MMS_CONFIG_ALLOW_ATTACH_AUDIO));
+        filtered.putBoolean(MMS_CONFIG_MULTIPART_SMS_ENABLED,
+                config.getBoolean(MMS_CONFIG_MULTIPART_SMS_ENABLED));
+        filtered.putBoolean(MMS_CONFIG_SMS_DELIVERY_REPORT_ENABLED,
+                config.getBoolean(MMS_CONFIG_SMS_DELIVERY_REPORT_ENABLED));
+        filtered.putBoolean(MMS_CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION,
+                config.getBoolean(MMS_CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION));
+        filtered.putBoolean(MMS_CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES,
+                config.getBoolean(MMS_CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES));
+        filtered.putBoolean(MMS_CONFIG_MMS_READ_REPORT_ENABLED,
+                config.getBoolean(MMS_CONFIG_MMS_READ_REPORT_ENABLED));
+        filtered.putBoolean(MMS_CONFIG_MMS_DELIVERY_REPORT_ENABLED,
+                config.getBoolean(MMS_CONFIG_MMS_DELIVERY_REPORT_ENABLED));
+        filtered.putBoolean(MMS_CONFIG_CLOSE_CONNECTION,
+                config.getBoolean(MMS_CONFIG_CLOSE_CONNECTION));
+        filtered.putInt(MMS_CONFIG_MAX_MESSAGE_SIZE, config.getInt(MMS_CONFIG_MAX_MESSAGE_SIZE));
+        filtered.putInt(MMS_CONFIG_MAX_IMAGE_WIDTH, config.getInt(MMS_CONFIG_MAX_IMAGE_WIDTH));
+        filtered.putInt(MMS_CONFIG_MAX_IMAGE_HEIGHT, config.getInt(MMS_CONFIG_MAX_IMAGE_HEIGHT));
+        filtered.putInt(MMS_CONFIG_RECIPIENT_LIMIT, config.getInt(MMS_CONFIG_RECIPIENT_LIMIT));
+        filtered.putInt(MMS_CONFIG_ALIAS_MIN_CHARS, config.getInt(MMS_CONFIG_ALIAS_MIN_CHARS));
+        filtered.putInt(MMS_CONFIG_ALIAS_MAX_CHARS, config.getInt(MMS_CONFIG_ALIAS_MAX_CHARS));
+        filtered.putInt(MMS_CONFIG_SMS_TO_MMS_TEXT_THRESHOLD,
+                config.getInt(MMS_CONFIG_SMS_TO_MMS_TEXT_THRESHOLD));
+        filtered.putInt(MMS_CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD,
+                config.getInt(MMS_CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD));
+        filtered.putInt(MMS_CONFIG_MESSAGE_TEXT_MAX_SIZE,
+                config.getInt(MMS_CONFIG_MESSAGE_TEXT_MAX_SIZE));
+        filtered.putInt(MMS_CONFIG_SUBJECT_MAX_LENGTH,
+                config.getInt(MMS_CONFIG_SUBJECT_MAX_LENGTH));
+        filtered.putInt(MMS_CONFIG_HTTP_SOCKET_TIMEOUT,
+                config.getInt(MMS_CONFIG_HTTP_SOCKET_TIMEOUT));
+        filtered.putString(MMS_CONFIG_UA_PROF_TAG_NAME,
+                config.getString(MMS_CONFIG_UA_PROF_TAG_NAME));
+        filtered.putString(MMS_CONFIG_USER_AGENT, config.getString(MMS_CONFIG_USER_AGENT));
+        filtered.putString(MMS_CONFIG_UA_PROF_URL, config.getString(MMS_CONFIG_UA_PROF_URL));
+        filtered.putString(MMS_CONFIG_HTTP_PARAMS, config.getString(MMS_CONFIG_HTTP_PARAMS));
+        filtered.putString(MMS_CONFIG_EMAIL_GATEWAY_NUMBER,
+                config.getString(MMS_CONFIG_EMAIL_GATEWAY_NUMBER));
+        filtered.putString(MMS_CONFIG_NAI_SUFFIX, config.getString(MMS_CONFIG_NAI_SUFFIX));
+        filtered.putBoolean(MMS_CONFIG_SHOW_CELL_BROADCAST_APP_LINKS,
+                config.getBoolean(MMS_CONFIG_SHOW_CELL_BROADCAST_APP_LINKS));
+        filtered.putBoolean(MMS_CONFIG_SUPPORT_HTTP_CHARSET_HEADER,
+                config.getBoolean(MMS_CONFIG_SUPPORT_HTTP_CHARSET_HEADER));
+        return filtered;
+    }
+
+}
diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java
new file mode 100644
index 0000000..d6e74cf
--- /dev/null
+++ b/telephony/java/android/telephony/SmsMessage.java
@@ -0,0 +1,884 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.os.Binder;
+import android.os.Parcel;
+import android.content.res.Resources;
+import android.text.TextUtils;
+
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
+import com.android.internal.telephony.SmsConstants;
+import com.android.internal.telephony.SmsMessageBase;
+import com.android.internal.telephony.SmsMessageBase.SubmitPduBase;
+import com.android.internal.telephony.Sms7BitEncodingTranslator;
+
+import java.lang.Math;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import static android.telephony.TelephonyManager.PHONE_TYPE_CDMA;
+
+
+/**
+ * A Short Message Service message.
+ * @see android.provider.Telephony.Sms.Intents#getMessagesFromIntent
+ */
+public class SmsMessage {
+    private static final String LOG_TAG = "SmsMessage";
+
+    /**
+     * SMS Class enumeration.
+     * See TS 23.038.
+     *
+     */
+    public enum MessageClass{
+        UNKNOWN, CLASS_0, CLASS_1, CLASS_2, CLASS_3;
+    }
+
+    /** User data text encoding code unit size */
+    public static final int ENCODING_UNKNOWN = 0;
+    public static final int ENCODING_7BIT = 1;
+    public static final int ENCODING_8BIT = 2;
+    public static final int ENCODING_16BIT = 3;
+    /**
+     * @hide This value is not defined in global standard. Only in Korea, this is used.
+     */
+    public static final int ENCODING_KSC5601 = 4;
+
+    /** The maximum number of payload bytes per message */
+    public static final int MAX_USER_DATA_BYTES = 140;
+
+    /**
+     * The maximum number of payload bytes per message if a user data header
+     * is present.  This assumes the header only contains the
+     * CONCATENATED_8_BIT_REFERENCE element.
+     */
+    public static final int MAX_USER_DATA_BYTES_WITH_HEADER = 134;
+
+    /** The maximum number of payload septets per message */
+    public static final int MAX_USER_DATA_SEPTETS = 160;
+
+    /**
+     * The maximum number of payload septets per message if a user data header
+     * is present.  This assumes the header only contains the
+     * CONCATENATED_8_BIT_REFERENCE element.
+     */
+    public static final int MAX_USER_DATA_SEPTETS_WITH_HEADER = 153;
+
+    /**
+     * Indicates a 3GPP format SMS message.
+     * @hide pending API council approval
+     */
+    public static final String FORMAT_3GPP = "3gpp";
+
+    /**
+     * Indicates a 3GPP2 format SMS message.
+     * @hide pending API council approval
+     */
+    public static final String FORMAT_3GPP2 = "3gpp2";
+
+    /** Contains actual SmsMessage. Only public for debugging and for framework layer.
+     *
+     * @hide
+     */
+    public SmsMessageBase mWrappedSmsMessage;
+
+    /** Indicates the subId
+     *
+     * @hide
+     */
+    private int mSubId = 0;
+
+    /** set Subscription information
+     *
+     * @hide
+     */
+    public void setSubId(int subId) {
+        mSubId = subId;
+    }
+
+    /** get Subscription information
+     *
+     * @hide
+     */
+    public int getSubId() {
+        return mSubId;
+    }
+
+    public static class SubmitPdu {
+
+        public byte[] encodedScAddress; // Null if not applicable.
+        public byte[] encodedMessage;
+
+        @Override
+        public String toString() {
+            return "SubmitPdu: encodedScAddress = "
+                    + Arrays.toString(encodedScAddress)
+                    + ", encodedMessage = "
+                    + Arrays.toString(encodedMessage);
+        }
+
+        /**
+         * @hide
+         */
+        protected SubmitPdu(SubmitPduBase spb) {
+            this.encodedMessage = spb.encodedMessage;
+            this.encodedScAddress = spb.encodedScAddress;
+        }
+
+    }
+
+    /**
+     * @hide
+     */
+    public SmsMessage(SmsMessageBase smb) {
+        mWrappedSmsMessage = smb;
+    }
+
+    /**
+     * Create an SmsMessage from a raw PDU. Guess format based on Voice
+     * technology first, if it fails use other format.
+     * All applications which handle
+     * incoming SMS messages by processing the {@code SMS_RECEIVED_ACTION} broadcast
+     * intent <b>must</b> now pass the new {@code format} String extra from the intent
+     * into the new method {@code createFromPdu(byte[], String)} which takes an
+     * extra format parameter. This is required in order to correctly decode the PDU on
+     * devices that require support for both 3GPP and 3GPP2 formats at the same time,
+     * such as dual-mode GSM/CDMA and CDMA/LTE phones.
+     * @deprecated Use {@link #createFromPdu(byte[], String)} instead.
+     */
+    @Deprecated
+    public static SmsMessage createFromPdu(byte[] pdu) {
+         SmsMessage message = null;
+
+        // cdma(3gpp2) vs gsm(3gpp) format info was not given,
+        // guess from active voice phone type
+        int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
+        String format = (PHONE_TYPE_CDMA == activePhone) ?
+                SmsConstants.FORMAT_3GPP2 : SmsConstants.FORMAT_3GPP;
+        message = createFromPdu(pdu, format);
+
+        if (null == message || null == message.mWrappedSmsMessage) {
+            // decoding pdu failed based on activePhone type, must be other format
+            format = (PHONE_TYPE_CDMA == activePhone) ?
+                    SmsConstants.FORMAT_3GPP : SmsConstants.FORMAT_3GPP2;
+            message = createFromPdu(pdu, format);
+        }
+        return message;
+    }
+
+    /**
+     * Create an SmsMessage from a raw PDU with the specified message format. The
+     * message format is passed in the
+     * {@link android.provider.Telephony.Sms.Intents#SMS_RECEIVED_ACTION} as the {@code format}
+     * String extra, and will be either "3gpp" for GSM/UMTS/LTE messages in 3GPP format
+     * or "3gpp2" for CDMA/LTE messages in 3GPP2 format.
+     *
+     * @param pdu the message PDU from the
+     * {@link android.provider.Telephony.Sms.Intents#SMS_RECEIVED_ACTION} intent
+     * @param format the format extra from the
+     * {@link android.provider.Telephony.Sms.Intents#SMS_RECEIVED_ACTION} intent
+     */
+    public static SmsMessage createFromPdu(byte[] pdu, String format) {
+        SmsMessageBase wrappedMessage;
+
+        if (SmsConstants.FORMAT_3GPP2.equals(format)) {
+            wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.createFromPdu(pdu);
+        } else if (SmsConstants.FORMAT_3GPP.equals(format)) {
+            wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.createFromPdu(pdu);
+        } else {
+            Rlog.e(LOG_TAG, "createFromPdu(): unsupported message format " + format);
+            return null;
+        }
+
+        if (wrappedMessage != null) {
+            return new SmsMessage(wrappedMessage);
+        } else {
+            Rlog.e(LOG_TAG, "createFromPdu(): wrappedMessage is null");
+            return null;
+        }
+    }
+
+    /**
+     * TS 27.005 3.4.1 lines[0] and lines[1] are the two lines read from the
+     * +CMT unsolicited response (PDU mode, of course)
+     *  +CMT: [&lt;alpha>],<length><CR><LF><pdu>
+     *
+     * Only public for debugging and for RIL
+     *
+     * {@hide}
+     */
+    public static SmsMessage newFromCMT(byte[] pdu) {
+        // received SMS in 3GPP format
+        SmsMessageBase wrappedMessage =
+                com.android.internal.telephony.gsm.SmsMessage.newFromCMT(pdu);
+
+        if (wrappedMessage != null) {
+            return new SmsMessage(wrappedMessage);
+        } else {
+            Rlog.e(LOG_TAG, "newFromCMT(): wrappedMessage is null");
+            return null;
+        }
+    }
+
+    /**
+     * Create an SmsMessage from an SMS EF record.
+     *
+     * @param index Index of SMS record. This should be index in ArrayList
+     *              returned by SmsManager.getAllMessagesFromSim + 1.
+     * @param data Record data.
+     * @return An SmsMessage representing the record.
+     *
+     * @hide
+     */
+    public static SmsMessage createFromEfRecord(int index, byte[] data) {
+        SmsMessageBase wrappedMessage;
+
+        if (isCdmaVoice()) {
+            wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.createFromEfRecord(
+                    index, data);
+        } else {
+            wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.createFromEfRecord(
+                    index, data);
+        }
+
+        if (wrappedMessage != null) {
+            return new SmsMessage(wrappedMessage);
+        } else {
+            Rlog.e(LOG_TAG, "createFromEfRecord(): wrappedMessage is null");
+            return null;
+        }
+    }
+
+    /**
+     * Get the TP-Layer-Length for the given SMS-SUBMIT PDU Basically, the
+     * length in bytes (not hex chars) less the SMSC header
+     *
+     * FIXME: This method is only used by a CTS test case that isn't run on CDMA devices.
+     * We should probably deprecate it and remove the obsolete test case.
+     */
+    public static int getTPLayerLengthForPDU(String pdu) {
+        if (isCdmaVoice()) {
+            return com.android.internal.telephony.cdma.SmsMessage.getTPLayerLengthForPDU(pdu);
+        } else {
+            return com.android.internal.telephony.gsm.SmsMessage.getTPLayerLengthForPDU(pdu);
+        }
+    }
+
+    /*
+     * TODO(cleanup): It would make some sense if the result of
+     * preprocessing a message to determine the proper encoding (i.e.
+     * the resulting data structure from calculateLength) could be
+     * passed as an argument to the actual final encoding function.
+     * This would better ensure that the logic behind size calculation
+     * actually matched the encoding.
+     */
+
+    /**
+     * Calculates the number of SMS's required to encode the message body and
+     * the number of characters remaining until the next message.
+     *
+     * @param msgBody the message to encode
+     * @param use7bitOnly if true, characters that are not part of the
+     *         radio-specific 7-bit encoding are counted as single
+     *         space chars.  If false, and if the messageBody contains
+     *         non-7-bit encodable characters, length is calculated
+     *         using a 16-bit encoding.
+     * @return an int[4] with int[0] being the number of SMS's
+     *         required, int[1] the number of code units used, and
+     *         int[2] is the number of code units remaining until the
+     *         next message. int[3] is an indicator of the encoding
+     *         code unit size (see the ENCODING_* definitions in SmsConstants)
+     */
+    public static int[] calculateLength(CharSequence msgBody, boolean use7bitOnly) {
+        // this function is for MO SMS
+        TextEncodingDetails ted = (useCdmaFormatForMoSms()) ?
+            com.android.internal.telephony.cdma.SmsMessage.calculateLength(msgBody, use7bitOnly,
+                    true) :
+            com.android.internal.telephony.gsm.SmsMessage.calculateLength(msgBody, use7bitOnly);
+        int ret[] = new int[4];
+        ret[0] = ted.msgCount;
+        ret[1] = ted.codeUnitCount;
+        ret[2] = ted.codeUnitsRemaining;
+        ret[3] = ted.codeUnitSize;
+        return ret;
+    }
+
+    /**
+     * Divide a message text into several fragments, none bigger than
+     * the maximum SMS message text size.
+     *
+     * @param text text, must not be null.
+     * @return an <code>ArrayList</code> of strings that, in order,
+     *   comprise the original msg text
+     *
+     * @hide
+     */
+    public static ArrayList<String> fragmentText(String text) {
+        // This function is for MO SMS
+        TextEncodingDetails ted = (useCdmaFormatForMoSms()) ?
+            com.android.internal.telephony.cdma.SmsMessage.calculateLength(text, false, true) :
+            com.android.internal.telephony.gsm.SmsMessage.calculateLength(text, false);
+
+        // TODO(cleanup): The code here could be rolled into the logic
+        // below cleanly if these MAX_* constants were defined more
+        // flexibly...
+
+        int limit;
+        if (ted.codeUnitSize == SmsConstants.ENCODING_7BIT) {
+            int udhLength;
+            if (ted.languageTable != 0 && ted.languageShiftTable != 0) {
+                udhLength = GsmAlphabet.UDH_SEPTET_COST_TWO_SHIFT_TABLES;
+            } else if (ted.languageTable != 0 || ted.languageShiftTable != 0) {
+                udhLength = GsmAlphabet.UDH_SEPTET_COST_ONE_SHIFT_TABLE;
+            } else {
+                udhLength = 0;
+            }
+
+            if (ted.msgCount > 1) {
+                udhLength += GsmAlphabet.UDH_SEPTET_COST_CONCATENATED_MESSAGE;
+            }
+
+            if (udhLength != 0) {
+                udhLength += GsmAlphabet.UDH_SEPTET_COST_LENGTH;
+            }
+
+            limit = SmsConstants.MAX_USER_DATA_SEPTETS - udhLength;
+        } else {
+            if (ted.msgCount > 1) {
+                limit = SmsConstants.MAX_USER_DATA_BYTES_WITH_HEADER;
+                // If EMS is not supported, break down EMS into single segment SMS
+                // and add page info " x/y".
+                // In the case of UCS2 encoding, we need 8 bytes for this,
+                // but we only have 6 bytes from UDH, so truncate the limit for
+                // each segment by 2 bytes (1 char).
+                // Make sure total number of segments is less than 10.
+                if (!hasEmsSupport() && ted.msgCount < 10) {
+                    limit -= 2;
+                }
+            } else {
+                limit = SmsConstants.MAX_USER_DATA_BYTES;
+            }
+        }
+
+        String newMsgBody = null;
+        Resources r = Resources.getSystem();
+        if (r.getBoolean(com.android.internal.R.bool.config_sms_force_7bit_encoding)) {
+            newMsgBody  = Sms7BitEncodingTranslator.translate(text);
+        }
+        if (TextUtils.isEmpty(newMsgBody)) {
+            newMsgBody = text;
+        }
+        int pos = 0;  // Index in code units.
+        int textLen = newMsgBody.length();
+        ArrayList<String> result = new ArrayList<String>(ted.msgCount);
+        while (pos < textLen) {
+            int nextPos = 0;  // Counts code units.
+            if (ted.codeUnitSize == SmsConstants.ENCODING_7BIT) {
+                if (useCdmaFormatForMoSms() && ted.msgCount == 1) {
+                    // For a singleton CDMA message, the encoding must be ASCII...
+                    nextPos = pos + Math.min(limit, textLen - pos);
+                } else {
+                    // For multi-segment messages, CDMA 7bit equals GSM 7bit encoding (EMS mode).
+                    nextPos = GsmAlphabet.findGsmSeptetLimitIndex(newMsgBody, pos, limit,
+                            ted.languageTable, ted.languageShiftTable);
+                }
+            } else {  // Assume unicode.
+                nextPos = SmsMessageBase.findNextUnicodePosition(pos, limit, newMsgBody);
+            }
+            if ((nextPos <= pos) || (nextPos > textLen)) {
+                Rlog.e(LOG_TAG, "fragmentText failed (" + pos + " >= " + nextPos + " or " +
+                          nextPos + " >= " + textLen + ")");
+                break;
+            }
+            result.add(newMsgBody.substring(pos, nextPos));
+            pos = nextPos;
+        }
+        return result;
+    }
+
+    /**
+     * Calculates the number of SMS's required to encode the message body and
+     * the number of characters remaining until the next message, given the
+     * current encoding.
+     *
+     * @param messageBody the message to encode
+     * @param use7bitOnly if true, characters that are not part of the radio
+     *         specific (GSM / CDMA) alphabet encoding are converted to as a
+     *         single space characters. If false, a messageBody containing
+     *         non-GSM or non-CDMA alphabet characters are encoded using
+     *         16-bit encoding.
+     * @return an int[4] with int[0] being the number of SMS's required, int[1]
+     *         the number of code units used, and int[2] is the number of code
+     *         units remaining until the next message. int[3] is the encoding
+     *         type that should be used for the message.
+     */
+    public static int[] calculateLength(String messageBody, boolean use7bitOnly) {
+        return calculateLength((CharSequence)messageBody, use7bitOnly);
+    }
+
+    /*
+     * TODO(cleanup): It looks like there is now no useful reason why
+     * apps should generate pdus themselves using these routines,
+     * instead of handing the raw data to SMSDispatcher (and thereby
+     * have the phone process do the encoding).  Moreover, CDMA now
+     * has shared state (in the form of the msgId system property)
+     * which can only be modified by the phone process, and hence
+     * makes the output of these routines incorrect.  Since they now
+     * serve no purpose, they should probably just return null
+     * directly, and be deprecated.  Going further in that direction,
+     * the above parsers of serialized pdu data should probably also
+     * be gotten rid of, hiding all but the necessarily visible
+     * structured data from client apps.  A possible concern with
+     * doing this is that apps may be using these routines to generate
+     * pdus that are then sent elsewhere, some network server, for
+     * example, and that always returning null would thereby break
+     * otherwise useful apps.
+     */
+
+    /**
+     * Get an SMS-SUBMIT PDU for a destination address and a message.
+     * This method will not attempt to use any GSM national language 7 bit encodings.
+     *
+     * @param scAddress Service Centre address.  Null means use default.
+     * @return a <code>SubmitPdu</code> containing the encoded SC
+     *         address, if applicable, and the encoded message.
+     *         Returns null on encode error.
+     */
+    public static SubmitPdu getSubmitPdu(String scAddress,
+            String destinationAddress, String message, boolean statusReportRequested) {
+        SubmitPduBase spb;
+
+        if (useCdmaFormatForMoSms()) {
+            spb = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(scAddress,
+                    destinationAddress, message, statusReportRequested, null);
+        } else {
+            spb = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(scAddress,
+                    destinationAddress, message, statusReportRequested);
+        }
+
+        return new SubmitPdu(spb);
+    }
+
+    /**
+     * Get an SMS-SUBMIT PDU for a data message to a destination address &amp; port.
+     * This method will not attempt to use any GSM national language 7 bit encodings.
+     *
+     * @param scAddress Service Centre address. null == use default
+     * @param destinationAddress the address of the destination for the message
+     * @param destinationPort the port to deliver the message to at the
+     *        destination
+     * @param data the data for the message
+     * @return a <code>SubmitPdu</code> containing the encoded SC
+     *         address, if applicable, and the encoded message.
+     *         Returns null on encode error.
+     */
+    public static SubmitPdu getSubmitPdu(String scAddress,
+            String destinationAddress, short destinationPort, byte[] data,
+            boolean statusReportRequested) {
+        SubmitPduBase spb;
+
+        if (useCdmaFormatForMoSms()) {
+            spb = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(scAddress,
+                    destinationAddress, destinationPort, data, statusReportRequested);
+        } else {
+            spb = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(scAddress,
+                    destinationAddress, destinationPort, data, statusReportRequested);
+        }
+
+        return new SubmitPdu(spb);
+    }
+
+    /**
+     * Returns the address of the SMS service center that relayed this message
+     * or null if there is none.
+     */
+    public String getServiceCenterAddress() {
+        return mWrappedSmsMessage.getServiceCenterAddress();
+    }
+
+    /**
+     * Returns the originating address (sender) of this SMS message in String
+     * form or null if unavailable
+     */
+    public String getOriginatingAddress() {
+        return mWrappedSmsMessage.getOriginatingAddress();
+    }
+
+    /**
+     * Returns the originating address, or email from address if this message
+     * was from an email gateway. Returns null if originating address
+     * unavailable.
+     */
+    public String getDisplayOriginatingAddress() {
+        return mWrappedSmsMessage.getDisplayOriginatingAddress();
+    }
+
+    /**
+     * Returns the message body as a String, if it exists and is text based.
+     * @return message body is there is one, otherwise null
+     */
+    public String getMessageBody() {
+        return mWrappedSmsMessage.getMessageBody();
+    }
+
+    /**
+     * Returns the class of this message.
+     */
+    public MessageClass getMessageClass() {
+        switch(mWrappedSmsMessage.getMessageClass()) {
+            case CLASS_0: return MessageClass.CLASS_0;
+            case CLASS_1: return MessageClass.CLASS_1;
+            case CLASS_2: return MessageClass.CLASS_2;
+            case CLASS_3: return MessageClass.CLASS_3;
+            default: return MessageClass.UNKNOWN;
+
+        }
+    }
+
+    /**
+     * Returns the message body, or email message body if this message was from
+     * an email gateway. Returns null if message body unavailable.
+     */
+    public String getDisplayMessageBody() {
+        return mWrappedSmsMessage.getDisplayMessageBody();
+    }
+
+    /**
+     * Unofficial convention of a subject line enclosed in parens empty string
+     * if not present
+     */
+    public String getPseudoSubject() {
+        return mWrappedSmsMessage.getPseudoSubject();
+    }
+
+    /**
+     * Returns the service centre timestamp in currentTimeMillis() format
+     */
+    public long getTimestampMillis() {
+        return mWrappedSmsMessage.getTimestampMillis();
+    }
+
+    /**
+     * Returns true if message is an email.
+     *
+     * @return true if this message came through an email gateway and email
+     *         sender / subject / parsed body are available
+     */
+    public boolean isEmail() {
+        return mWrappedSmsMessage.isEmail();
+    }
+
+     /**
+     * @return if isEmail() is true, body of the email sent through the gateway.
+     *         null otherwise
+     */
+    public String getEmailBody() {
+        return mWrappedSmsMessage.getEmailBody();
+    }
+
+    /**
+     * @return if isEmail() is true, email from address of email sent through
+     *         the gateway. null otherwise
+     */
+    public String getEmailFrom() {
+        return mWrappedSmsMessage.getEmailFrom();
+    }
+
+    /**
+     * Get protocol identifier.
+     */
+    public int getProtocolIdentifier() {
+        return mWrappedSmsMessage.getProtocolIdentifier();
+    }
+
+    /**
+     * See TS 23.040 9.2.3.9 returns true if this is a "replace short message"
+     * SMS
+     */
+    public boolean isReplace() {
+        return mWrappedSmsMessage.isReplace();
+    }
+
+    /**
+     * Returns true for CPHS MWI toggle message.
+     *
+     * @return true if this is a CPHS MWI toggle message See CPHS 4.2 section
+     *         B.4.2
+     */
+    public boolean isCphsMwiMessage() {
+        return mWrappedSmsMessage.isCphsMwiMessage();
+    }
+
+    /**
+     * returns true if this message is a CPHS voicemail / message waiting
+     * indicator (MWI) clear message
+     */
+    public boolean isMWIClearMessage() {
+        return mWrappedSmsMessage.isMWIClearMessage();
+    }
+
+    /**
+     * returns true if this message is a CPHS voicemail / message waiting
+     * indicator (MWI) set message
+     */
+    public boolean isMWISetMessage() {
+        return mWrappedSmsMessage.isMWISetMessage();
+    }
+
+    /**
+     * returns true if this message is a "Message Waiting Indication Group:
+     * Discard Message" notification and should not be stored.
+     */
+    public boolean isMwiDontStore() {
+        return mWrappedSmsMessage.isMwiDontStore();
+    }
+
+    /**
+     * returns the user data section minus the user data header if one was
+     * present.
+     */
+    public byte[] getUserData() {
+        return mWrappedSmsMessage.getUserData();
+    }
+
+    /**
+     * Returns the raw PDU for the message.
+     *
+     * @return the raw PDU for the message.
+     */
+    public byte[] getPdu() {
+        return mWrappedSmsMessage.getPdu();
+    }
+
+    /**
+     * Returns the status of the message on the SIM (read, unread, sent, unsent).
+     *
+     * @return the status of the message on the SIM.  These are:
+     *         SmsManager.STATUS_ON_SIM_FREE
+     *         SmsManager.STATUS_ON_SIM_READ
+     *         SmsManager.STATUS_ON_SIM_UNREAD
+     *         SmsManager.STATUS_ON_SIM_SEND
+     *         SmsManager.STATUS_ON_SIM_UNSENT
+     * @deprecated Use getStatusOnIcc instead.
+     */
+    @Deprecated public int getStatusOnSim() {
+        return mWrappedSmsMessage.getStatusOnIcc();
+    }
+
+    /**
+     * Returns the status of the message on the ICC (read, unread, sent, unsent).
+     *
+     * @return the status of the message on the ICC.  These are:
+     *         SmsManager.STATUS_ON_ICC_FREE
+     *         SmsManager.STATUS_ON_ICC_READ
+     *         SmsManager.STATUS_ON_ICC_UNREAD
+     *         SmsManager.STATUS_ON_ICC_SEND
+     *         SmsManager.STATUS_ON_ICC_UNSENT
+     */
+    public int getStatusOnIcc() {
+        return mWrappedSmsMessage.getStatusOnIcc();
+    }
+
+    /**
+     * Returns the record index of the message on the SIM (1-based index).
+     * @return the record index of the message on the SIM, or -1 if this
+     *         SmsMessage was not created from a SIM SMS EF record.
+     * @deprecated Use getIndexOnIcc instead.
+     */
+    @Deprecated public int getIndexOnSim() {
+        return mWrappedSmsMessage.getIndexOnIcc();
+    }
+
+    /**
+     * Returns the record index of the message on the ICC (1-based index).
+     * @return the record index of the message on the ICC, or -1 if this
+     *         SmsMessage was not created from a ICC SMS EF record.
+     */
+    public int getIndexOnIcc() {
+        return mWrappedSmsMessage.getIndexOnIcc();
+    }
+
+    /**
+     * GSM:
+     * For an SMS-STATUS-REPORT message, this returns the status field from
+     * the status report.  This field indicates the status of a previously
+     * submitted SMS, if requested.  See TS 23.040, 9.2.3.15 TP-Status for a
+     * description of values.
+     * CDMA:
+     * For not interfering with status codes from GSM, the value is
+     * shifted to the bits 31-16.
+     * The value is composed of an error class (bits 25-24) and a status code (bits 23-16).
+     * Possible codes are described in C.S0015-B, v2.0, 4.5.21.
+     *
+     * @return 0 indicates the previously sent message was received.
+     *         See TS 23.040, 9.9.2.3.15 and C.S0015-B, v2.0, 4.5.21
+     *         for a description of other possible values.
+     */
+    public int getStatus() {
+        return mWrappedSmsMessage.getStatus();
+    }
+
+    /**
+     * Return true iff the message is a SMS-STATUS-REPORT message.
+     */
+    public boolean isStatusReportMessage() {
+        return mWrappedSmsMessage.isStatusReportMessage();
+    }
+
+    /**
+     * Returns true iff the <code>TP-Reply-Path</code> bit is set in
+     * this message.
+     */
+    public boolean isReplyPathPresent() {
+        return mWrappedSmsMessage.isReplyPathPresent();
+    }
+
+    /**
+     * Determines whether or not to use CDMA format for MO SMS.
+     * If SMS over IMS is supported, then format is based on IMS SMS format,
+     * otherwise format is based on current phone type.
+     *
+     * @return true if Cdma format should be used for MO SMS, false otherwise.
+     */
+    private static boolean useCdmaFormatForMoSms() {
+        if (!SmsManager.getDefault().isImsSmsSupported()) {
+            // use Voice technology to determine SMS format.
+            return isCdmaVoice();
+        }
+        // IMS is registered with SMS support, check the SMS format supported
+        return (SmsConstants.FORMAT_3GPP2.equals(SmsManager.getDefault().getImsSmsFormat()));
+    }
+
+    /**
+     * Determines whether or not to current phone type is cdma.
+     *
+     * @return true if current phone type is cdma, false otherwise.
+     */
+    private static boolean isCdmaVoice() {
+        int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
+        return (PHONE_TYPE_CDMA == activePhone);
+    }
+
+    /**
+     * Decide if the carrier supports long SMS.
+     * {@hide}
+     */
+    public static boolean hasEmsSupport() {
+        if (!isNoEmsSupportConfigListExisted()) {
+            return true;
+        }
+
+        String simOperator;
+        String gid;
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            simOperator = TelephonyManager.getDefault().getSimOperatorNumeric();
+            gid = TelephonyManager.getDefault().getGroupIdLevel1();
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+
+        if (!TextUtils.isEmpty(simOperator)) {
+            for (NoEmsSupportConfig currentConfig : mNoEmsSupportConfigList) {
+                if (simOperator.startsWith(currentConfig.mOperatorNumber) &&
+                        (TextUtils.isEmpty(currentConfig.mGid1) ||
+                                (!TextUtils.isEmpty(currentConfig.mGid1) &&
+                                        currentConfig.mGid1.equalsIgnoreCase(gid)))) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Check where to add " x/y" in each SMS segment, begin or end.
+     * {@hide}
+     */
+    public static boolean shouldAppendPageNumberAsPrefix() {
+        if (!isNoEmsSupportConfigListExisted()) {
+            return false;
+        }
+
+        String simOperator;
+        String gid;
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            simOperator = TelephonyManager.getDefault().getSimOperatorNumeric();
+            gid = TelephonyManager.getDefault().getGroupIdLevel1();
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+
+        for (NoEmsSupportConfig currentConfig : mNoEmsSupportConfigList) {
+            if (simOperator.startsWith(currentConfig.mOperatorNumber) &&
+                (TextUtils.isEmpty(currentConfig.mGid1) ||
+                (!TextUtils.isEmpty(currentConfig.mGid1)
+                && currentConfig.mGid1.equalsIgnoreCase(gid)))) {
+                return currentConfig.mIsPrefix;
+            }
+        }
+        return false;
+    }
+
+    private static class NoEmsSupportConfig {
+        String mOperatorNumber;
+        String mGid1;
+        boolean mIsPrefix;
+
+        public NoEmsSupportConfig(String[] config) {
+            mOperatorNumber = config[0];
+            mIsPrefix = "prefix".equals(config[1]);
+            mGid1 = config.length > 2 ? config[2] : null;
+        }
+
+        @Override
+        public String toString() {
+            return "NoEmsSupportConfig { mOperatorNumber = " + mOperatorNumber
+                    + ", mIsPrefix = " + mIsPrefix + ", mGid1 = " + mGid1 + " }";
+        }
+    }
+
+    private static NoEmsSupportConfig[] mNoEmsSupportConfigList = null;
+    private static boolean mIsNoEmsSupportConfigListLoaded = false;
+
+    private static boolean isNoEmsSupportConfigListExisted() {
+        if (!mIsNoEmsSupportConfigListLoaded) {
+            Resources r = Resources.getSystem();
+            if (r != null) {
+                String[] listArray = r.getStringArray(
+                        com.android.internal.R.array.no_ems_support_sim_operators);
+                if ((listArray != null) && (listArray.length > 0)) {
+                    mNoEmsSupportConfigList = new NoEmsSupportConfig[listArray.length];
+                    for (int i=0; i<listArray.length; i++) {
+                        mNoEmsSupportConfigList[i] = new NoEmsSupportConfig(listArray[i].split(";"));
+                    }
+                }
+                mIsNoEmsSupportConfigListLoaded = true;
+            }
+        }
+
+        if (mNoEmsSupportConfigList != null && mNoEmsSupportConfigList.length != 0) {
+            return true;
+        }
+
+        return false;
+    }
+}
diff --git a/telephony/java/android/telephony/Telephony.java b/telephony/java/android/telephony/Telephony.java
new file mode 100644
index 0000000..943a6ca
--- /dev/null
+++ b/telephony/java/android/telephony/Telephony.java
@@ -0,0 +1,2975 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider;
+
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.TestApi;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import android.database.sqlite.SqliteWrapper;
+import android.net.Uri;
+import android.telephony.SmsMessage;
+import android.telephony.SubscriptionManager;
+import android.text.TextUtils;
+import android.telephony.Rlog;
+import android.util.Patterns;
+
+import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.SmsApplication;
+
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * The Telephony provider contains data related to phone operation, specifically SMS and MMS
+ * messages and access to the APN list, including the MMSC to use.
+ *
+ * <p class="note"><strong>Note:</strong> These APIs are not available on all Android-powered
+ * devices. If your app depends on telephony features such as for managing SMS messages, include
+ * a <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code <uses-feature>}
+ * </a> element in your manifest that declares the {@code "android.hardware.telephony"} hardware
+ * feature. Alternatively, you can check for telephony availability at runtime using either
+ * {@link android.content.pm.PackageManager#hasSystemFeature
+ * hasSystemFeature(PackageManager.FEATURE_TELEPHONY)} or {@link
+ * android.telephony.TelephonyManager#getPhoneType}.</p>
+ *
+ * <h3>Creating an SMS app</h3>
+ *
+ * <p>Only the default SMS app (selected by the user in system settings) is able to write to the
+ * SMS Provider (the tables defined within the {@code Telephony} class) and only the default SMS
+ * app receives the {@link android.provider.Telephony.Sms.Intents#SMS_DELIVER_ACTION} broadcast
+ * when the user receives an SMS or the {@link
+ * android.provider.Telephony.Sms.Intents#WAP_PUSH_DELIVER_ACTION} broadcast when the user
+ * receives an MMS.</p>
+ *
+ * <p>Any app that wants to behave as the user's default SMS app must handle the following intents:
+ * <ul>
+ * <li>In a broadcast receiver, include an intent filter for {@link Sms.Intents#SMS_DELIVER_ACTION}
+ * (<code>"android.provider.Telephony.SMS_DELIVER"</code>). The broadcast receiver must also
+ * require the {@link android.Manifest.permission#BROADCAST_SMS} permission.
+ * <p>This allows your app to directly receive incoming SMS messages.</p></li>
+ * <li>In a broadcast receiver, include an intent filter for {@link
+ * Sms.Intents#WAP_PUSH_DELIVER_ACTION}} ({@code "android.provider.Telephony.WAP_PUSH_DELIVER"})
+ * with the MIME type <code>"application/vnd.wap.mms-message"</code>.
+ * The broadcast receiver must also require the {@link
+ * android.Manifest.permission#BROADCAST_WAP_PUSH} permission.
+ * <p>This allows your app to directly receive incoming MMS messages.</p></li>
+ * <li>In your activity that delivers new messages, include an intent filter for
+ * {@link android.content.Intent#ACTION_SENDTO} (<code>"android.intent.action.SENDTO"
+ * </code>) with schemas, <code>sms:</code>, <code>smsto:</code>, <code>mms:</code>, and
+ * <code>mmsto:</code>.
+ * <p>This allows your app to receive intents from other apps that want to deliver a
+ * message.</p></li>
+ * <li>In a service, include an intent filter for {@link
+ * android.telephony.TelephonyManager#ACTION_RESPOND_VIA_MESSAGE}
+ * (<code>"android.intent.action.RESPOND_VIA_MESSAGE"</code>) with schemas,
+ * <code>sms:</code>, <code>smsto:</code>, <code>mms:</code>, and <code>mmsto:</code>.
+ * This service must also require the {@link
+ * android.Manifest.permission#SEND_RESPOND_VIA_MESSAGE} permission.
+ * <p>This allows users to respond to incoming phone calls with an immediate text message
+ * using your app.</p></li>
+ * </ul>
+ *
+ * <p>Other apps that are not selected as the default SMS app can only <em>read</em> the SMS
+ * Provider, but may also be notified when a new SMS arrives by listening for the {@link
+ * Sms.Intents#SMS_RECEIVED_ACTION}
+ * broadcast, which is a non-abortable broadcast that may be delivered to multiple apps. This
+ * broadcast is intended for apps that&mdash;while not selected as the default SMS app&mdash;need to
+ * read special incoming messages such as to perform phone number verification.</p>
+ *
+ * <p>For more information about building SMS apps, read the blog post, <a
+ * href="http://android-developers.blogspot.com/2013/10/getting-your-sms-apps-ready-for-kitkat.html"
+ * >Getting Your SMS Apps Ready for KitKat</a>.</p>
+ *
+ */
+public final class Telephony {
+    private static final String TAG = "Telephony";
+
+    /**
+     * Not instantiable.
+     * @hide
+     */
+    private Telephony() {
+    }
+
+    /**
+     * Base columns for tables that contain text-based SMSs.
+     */
+    public interface TextBasedSmsColumns {
+
+        /** Message type: all messages. */
+        public static final int MESSAGE_TYPE_ALL    = 0;
+
+        /** Message type: inbox. */
+        public static final int MESSAGE_TYPE_INBOX  = 1;
+
+        /** Message type: sent messages. */
+        public static final int MESSAGE_TYPE_SENT   = 2;
+
+        /** Message type: drafts. */
+        public static final int MESSAGE_TYPE_DRAFT  = 3;
+
+        /** Message type: outbox. */
+        public static final int MESSAGE_TYPE_OUTBOX = 4;
+
+        /** Message type: failed outgoing message. */
+        public static final int MESSAGE_TYPE_FAILED = 5;
+
+        /** Message type: queued to send later. */
+        public static final int MESSAGE_TYPE_QUEUED = 6;
+
+        /**
+         * The type of message.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String TYPE = "type";
+
+        /**
+         * The thread ID of the message.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String THREAD_ID = "thread_id";
+
+        /**
+         * The address of the other party.
+         * <P>Type: TEXT</P>
+         */
+        public static final String ADDRESS = "address";
+
+        /**
+         * The date the message was received.
+         * <P>Type: INTEGER (long)</P>
+         */
+        public static final String DATE = "date";
+
+        /**
+         * The date the message was sent.
+         * <P>Type: INTEGER (long)</P>
+         */
+        public static final String DATE_SENT = "date_sent";
+
+        /**
+         * Has the message been read?
+         * <P>Type: INTEGER (boolean)</P>
+         */
+        public static final String READ = "read";
+
+        /**
+         * Has the message been seen by the user? The "seen" flag determines
+         * whether we need to show a notification.
+         * <P>Type: INTEGER (boolean)</P>
+         */
+        public static final String SEEN = "seen";
+
+        /**
+         * {@code TP-Status} value for the message, or -1 if no status has been received.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String STATUS = "status";
+
+        /** TP-Status: no status received. */
+        public static final int STATUS_NONE = -1;
+        /** TP-Status: complete. */
+        public static final int STATUS_COMPLETE = 0;
+        /** TP-Status: pending. */
+        public static final int STATUS_PENDING = 32;
+        /** TP-Status: failed. */
+        public static final int STATUS_FAILED = 64;
+
+        /**
+         * The subject of the message, if present.
+         * <P>Type: TEXT</P>
+         */
+        public static final String SUBJECT = "subject";
+
+        /**
+         * The body of the message.
+         * <P>Type: TEXT</P>
+         */
+        public static final String BODY = "body";
+
+        /**
+         * The ID of the sender of the conversation, if present.
+         * <P>Type: INTEGER (reference to item in {@code content://contacts/people})</P>
+         */
+        public static final String PERSON = "person";
+
+        /**
+         * The protocol identifier code.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String PROTOCOL = "protocol";
+
+        /**
+         * Is the {@code TP-Reply-Path} flag set?
+         * <P>Type: BOOLEAN</P>
+         */
+        public static final String REPLY_PATH_PRESENT = "reply_path_present";
+
+        /**
+         * The service center (SC) through which to send the message, if present.
+         * <P>Type: TEXT</P>
+         */
+        public static final String SERVICE_CENTER = "service_center";
+
+        /**
+         * Is the message locked?
+         * <P>Type: INTEGER (boolean)</P>
+         */
+        public static final String LOCKED = "locked";
+
+        /**
+         * The subscription to which the message belongs to. Its value will be
+         * < 0 if the sub id cannot be determined.
+         * <p>Type: INTEGER (long) </p>
+         */
+        public static final String SUBSCRIPTION_ID = "sub_id";
+
+        /**
+         * The MTU size of the mobile interface to which the APN connected
+         * @hide
+         */
+        public static final String MTU = "mtu";
+
+        /**
+         * Error code associated with sending or receiving this message
+         * <P>Type: INTEGER</P>
+         */
+        public static final String ERROR_CODE = "error_code";
+
+        /**
+         * The identity of the sender of a sent message. It is
+         * usually the package name of the app which sends the message.
+         * <p class="note"><strong>Note:</strong>
+         * This column is read-only. It is set by the provider and can not be changed by apps.
+         * <p>Type: TEXT</p>
+         */
+        public static final String CREATOR = "creator";
+    }
+
+    /**
+     * Contains all text-based SMS messages.
+     */
+    public static final class Sms implements BaseColumns, TextBasedSmsColumns {
+
+        /**
+         * Not instantiable.
+         * @hide
+         */
+        private Sms() {
+        }
+
+        /**
+         * Used to determine the currently configured default SMS package.
+         * @param context context of the requesting application
+         * @return package name for the default SMS package or null
+         */
+        public static String getDefaultSmsPackage(Context context) {
+            ComponentName component = SmsApplication.getDefaultSmsApplication(context, false);
+            if (component != null) {
+                return component.getPackageName();
+            }
+            return null;
+        }
+
+        /**
+         * Return cursor for table query.
+         * @hide
+         */
+        public static Cursor query(ContentResolver cr, String[] projection) {
+            return cr.query(CONTENT_URI, projection, null, null, DEFAULT_SORT_ORDER);
+        }
+
+        /**
+         * Return cursor for table query.
+         * @hide
+         */
+        public static Cursor query(ContentResolver cr, String[] projection,
+                String where, String orderBy) {
+            return cr.query(CONTENT_URI, projection, where,
+                    null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
+        }
+
+        /**
+         * The {@code content://} style URL for this table.
+         */
+        public static final Uri CONTENT_URI = Uri.parse("content://sms");
+
+        /**
+         * The default sort order for this table.
+         */
+        public static final String DEFAULT_SORT_ORDER = "date DESC";
+
+        /**
+         * Add an SMS to the given URI.
+         *
+         * @param resolver the content resolver to use
+         * @param uri the URI to add the message to
+         * @param address the address of the sender
+         * @param body the body of the message
+         * @param subject the pseudo-subject of the message
+         * @param date the timestamp for the message
+         * @param read true if the message has been read, false if not
+         * @param deliveryReport true if a delivery report was requested, false if not
+         * @return the URI for the new message
+         * @hide
+         */
+        public static Uri addMessageToUri(ContentResolver resolver,
+                Uri uri, String address, String body, String subject,
+                Long date, boolean read, boolean deliveryReport) {
+            return addMessageToUri(SubscriptionManager.getDefaultSmsSubscriptionId(),
+                    resolver, uri, address, body, subject, date, read, deliveryReport, -1L);
+        }
+
+        /**
+         * Add an SMS to the given URI.
+         *
+         * @param resolver the content resolver to use
+         * @param uri the URI to add the message to
+         * @param address the address of the sender
+         * @param body the body of the message
+         * @param subject the psuedo-subject of the message
+         * @param date the timestamp for the message
+         * @param read true if the message has been read, false if not
+         * @param deliveryReport true if a delivery report was requested, false if not
+         * @param subId the subscription which the message belongs to
+         * @return the URI for the new message
+         * @hide
+         */
+        public static Uri addMessageToUri(int subId, ContentResolver resolver,
+                Uri uri, String address, String body, String subject,
+                Long date, boolean read, boolean deliveryReport) {
+            return addMessageToUri(subId, resolver, uri, address, body, subject,
+                    date, read, deliveryReport, -1L);
+        }
+
+        /**
+         * Add an SMS to the given URI with the specified thread ID.
+         *
+         * @param resolver the content resolver to use
+         * @param uri the URI to add the message to
+         * @param address the address of the sender
+         * @param body the body of the message
+         * @param subject the pseudo-subject of the message
+         * @param date the timestamp for the message
+         * @param read true if the message has been read, false if not
+         * @param deliveryReport true if a delivery report was requested, false if not
+         * @param threadId the thread_id of the message
+         * @return the URI for the new message
+         * @hide
+         */
+        public static Uri addMessageToUri(ContentResolver resolver,
+                Uri uri, String address, String body, String subject,
+                Long date, boolean read, boolean deliveryReport, long threadId) {
+            return addMessageToUri(SubscriptionManager.getDefaultSmsSubscriptionId(),
+                    resolver, uri, address, body, subject,
+                    date, read, deliveryReport, threadId);
+        }
+
+        /**
+         * Add an SMS to the given URI with thread_id specified.
+         *
+         * @param resolver the content resolver to use
+         * @param uri the URI to add the message to
+         * @param address the address of the sender
+         * @param body the body of the message
+         * @param subject the psuedo-subject of the message
+         * @param date the timestamp for the message
+         * @param read true if the message has been read, false if not
+         * @param deliveryReport true if a delivery report was requested, false if not
+         * @param threadId the thread_id of the message
+         * @param subId the subscription which the message belongs to
+         * @return the URI for the new message
+         * @hide
+         */
+        public static Uri addMessageToUri(int subId, ContentResolver resolver,
+                Uri uri, String address, String body, String subject,
+                Long date, boolean read, boolean deliveryReport, long threadId) {
+            ContentValues values = new ContentValues(8);
+            Rlog.v(TAG,"Telephony addMessageToUri sub id: " + subId);
+
+            values.put(SUBSCRIPTION_ID, subId);
+            values.put(ADDRESS, address);
+            if (date != null) {
+                values.put(DATE, date);
+            }
+            values.put(READ, read ? Integer.valueOf(1) : Integer.valueOf(0));
+            values.put(SUBJECT, subject);
+            values.put(BODY, body);
+            if (deliveryReport) {
+                values.put(STATUS, STATUS_PENDING);
+            }
+            if (threadId != -1L) {
+                values.put(THREAD_ID, threadId);
+            }
+            return resolver.insert(uri, values);
+        }
+
+        /**
+         * Move a message to the given folder.
+         *
+         * @param context the context to use
+         * @param uri the message to move
+         * @param folder the folder to move to
+         * @return true if the operation succeeded
+         * @hide
+         */
+        public static boolean moveMessageToFolder(Context context,
+                Uri uri, int folder, int error) {
+            if (uri == null) {
+                return false;
+            }
+
+            boolean markAsUnread = false;
+            boolean markAsRead = false;
+            switch(folder) {
+            case MESSAGE_TYPE_INBOX:
+            case MESSAGE_TYPE_DRAFT:
+                break;
+            case MESSAGE_TYPE_OUTBOX:
+            case MESSAGE_TYPE_SENT:
+                markAsRead = true;
+                break;
+            case MESSAGE_TYPE_FAILED:
+            case MESSAGE_TYPE_QUEUED:
+                markAsUnread = true;
+                break;
+            default:
+                return false;
+            }
+
+            ContentValues values = new ContentValues(3);
+
+            values.put(TYPE, folder);
+            if (markAsUnread) {
+                values.put(READ, 0);
+            } else if (markAsRead) {
+                values.put(READ, 1);
+            }
+            values.put(ERROR_CODE, error);
+
+            return 1 == SqliteWrapper.update(context, context.getContentResolver(),
+                            uri, values, null, null);
+        }
+
+        /**
+         * Returns true iff the folder (message type) identifies an
+         * outgoing message.
+         * @hide
+         */
+        public static boolean isOutgoingFolder(int messageType) {
+            return  (messageType == MESSAGE_TYPE_FAILED)
+                    || (messageType == MESSAGE_TYPE_OUTBOX)
+                    || (messageType == MESSAGE_TYPE_SENT)
+                    || (messageType == MESSAGE_TYPE_QUEUED);
+        }
+
+        /**
+         * Contains all text-based SMS messages in the SMS app inbox.
+         */
+        public static final class Inbox implements BaseColumns, TextBasedSmsColumns {
+
+            /**
+             * Not instantiable.
+             * @hide
+             */
+            private Inbox() {
+            }
+
+            /**
+             * The {@code content://} style URL for this table.
+             */
+            public static final Uri CONTENT_URI = Uri.parse("content://sms/inbox");
+
+            /**
+             * The default sort order for this table.
+             */
+            public static final String DEFAULT_SORT_ORDER = "date DESC";
+
+            /**
+             * Add an SMS to the Draft box.
+             *
+             * @param resolver the content resolver to use
+             * @param address the address of the sender
+             * @param body the body of the message
+             * @param subject the pseudo-subject of the message
+             * @param date the timestamp for the message
+             * @param read true if the message has been read, false if not
+             * @return the URI for the new message
+             * @hide
+             */
+            public static Uri addMessage(ContentResolver resolver,
+                    String address, String body, String subject, Long date,
+                    boolean read) {
+                return addMessageToUri(SubscriptionManager.getDefaultSmsSubscriptionId(),
+                        resolver, CONTENT_URI, address, body, subject, date, read, false);
+            }
+
+            /**
+             * Add an SMS to the Draft box.
+             *
+             * @param resolver the content resolver to use
+             * @param address the address of the sender
+             * @param body the body of the message
+             * @param subject the psuedo-subject of the message
+             * @param date the timestamp for the message
+             * @param read true if the message has been read, false if not
+             * @param subId the subscription which the message belongs to
+             * @return the URI for the new message
+             * @hide
+             */
+            public static Uri addMessage(int subId, ContentResolver resolver,
+                    String address, String body, String subject, Long date, boolean read) {
+                return addMessageToUri(subId, resolver, CONTENT_URI, address, body,
+                        subject, date, read, false);
+            }
+        }
+
+        /**
+         * Contains all sent text-based SMS messages in the SMS app.
+         */
+        public static final class Sent implements BaseColumns, TextBasedSmsColumns {
+
+            /**
+             * Not instantiable.
+             * @hide
+             */
+            private Sent() {
+            }
+
+            /**
+             * The {@code content://} style URL for this table.
+             */
+            public static final Uri CONTENT_URI = Uri.parse("content://sms/sent");
+
+            /**
+             * The default sort order for this table.
+             */
+            public static final String DEFAULT_SORT_ORDER = "date DESC";
+
+            /**
+             * Add an SMS to the Draft box.
+             *
+             * @param resolver the content resolver to use
+             * @param address the address of the sender
+             * @param body the body of the message
+             * @param subject the pseudo-subject of the message
+             * @param date the timestamp for the message
+             * @return the URI for the new message
+             * @hide
+             */
+            public static Uri addMessage(ContentResolver resolver,
+                    String address, String body, String subject, Long date) {
+                return addMessageToUri(SubscriptionManager.getDefaultSmsSubscriptionId(),
+                        resolver, CONTENT_URI, address, body, subject, date, true, false);
+            }
+
+            /**
+             * Add an SMS to the Draft box.
+             *
+             * @param resolver the content resolver to use
+             * @param address the address of the sender
+             * @param body the body of the message
+             * @param subject the psuedo-subject of the message
+             * @param date the timestamp for the message
+             * @param subId the subscription which the message belongs to
+             * @return the URI for the new message
+             * @hide
+             */
+            public static Uri addMessage(int subId, ContentResolver resolver,
+                    String address, String body, String subject, Long date) {
+                return addMessageToUri(subId, resolver, CONTENT_URI, address, body,
+                        subject, date, true, false);
+            }
+        }
+
+        /**
+         * Contains all sent text-based SMS messages in the SMS app.
+         */
+        public static final class Draft implements BaseColumns, TextBasedSmsColumns {
+
+            /**
+             * Not instantiable.
+             * @hide
+             */
+            private Draft() {
+            }
+
+            /**
+             * The {@code content://} style URL for this table.
+             */
+            public static final Uri CONTENT_URI = Uri.parse("content://sms/draft");
+
+           /**
+            * @hide
+            */
+            public static Uri addMessage(ContentResolver resolver,
+                    String address, String body, String subject, Long date) {
+                return addMessageToUri(SubscriptionManager.getDefaultSmsSubscriptionId(),
+                        resolver, CONTENT_URI, address, body, subject, date, true, false);
+            }
+
+            /**
+             * Add an SMS to the Draft box.
+             *
+             * @param resolver the content resolver to use
+             * @param address the address of the sender
+             * @param body the body of the message
+             * @param subject the psuedo-subject of the message
+             * @param date the timestamp for the message
+             * @param subId the subscription which the message belongs to
+             * @return the URI for the new message
+             * @hide
+             */
+            public static Uri addMessage(int subId, ContentResolver resolver,
+                    String address, String body, String subject, Long date) {
+                return addMessageToUri(subId, resolver, CONTENT_URI, address, body,
+                        subject, date, true, false);
+            }
+
+            /**
+             * The default sort order for this table.
+             */
+            public static final String DEFAULT_SORT_ORDER = "date DESC";
+        }
+
+        /**
+         * Contains all pending outgoing text-based SMS messages.
+         */
+        public static final class Outbox implements BaseColumns, TextBasedSmsColumns {
+
+            /**
+             * Not instantiable.
+             * @hide
+             */
+            private Outbox() {
+            }
+
+            /**
+             * The {@code content://} style URL for this table.
+             */
+            public static final Uri CONTENT_URI = Uri.parse("content://sms/outbox");
+
+            /**
+             * The default sort order for this table.
+             */
+            public static final String DEFAULT_SORT_ORDER = "date DESC";
+
+            /**
+             * Add an SMS to the outbox.
+             *
+             * @param resolver the content resolver to use
+             * @param address the address of the sender
+             * @param body the body of the message
+             * @param subject the pseudo-subject of the message
+             * @param date the timestamp for the message
+             * @param deliveryReport whether a delivery report was requested for the message
+             * @return the URI for the new message
+             * @hide
+             */
+            public static Uri addMessage(ContentResolver resolver,
+                    String address, String body, String subject, Long date,
+                    boolean deliveryReport, long threadId) {
+                return addMessageToUri(SubscriptionManager.getDefaultSmsSubscriptionId(),
+                        resolver, CONTENT_URI, address, body, subject, date,
+                        true, deliveryReport, threadId);
+            }
+
+            /**
+             * Add an SMS to the Out box.
+             *
+             * @param resolver the content resolver to use
+             * @param address the address of the sender
+             * @param body the body of the message
+             * @param subject the psuedo-subject of the message
+             * @param date the timestamp for the message
+             * @param deliveryReport whether a delivery report was requested for the message
+             * @param subId the subscription which the message belongs to
+             * @return the URI for the new message
+             * @hide
+             */
+            public static Uri addMessage(int subId, ContentResolver resolver,
+                    String address, String body, String subject, Long date,
+                    boolean deliveryReport, long threadId) {
+                return addMessageToUri(subId, resolver, CONTENT_URI, address, body,
+                        subject, date, true, deliveryReport, threadId);
+            }
+        }
+
+        /**
+         * Contains all sent text-based SMS messages in the SMS app.
+         */
+        public static final class Conversations
+                implements BaseColumns, TextBasedSmsColumns {
+
+            /**
+             * Not instantiable.
+             * @hide
+             */
+            private Conversations() {
+            }
+
+            /**
+             * The {@code content://} style URL for this table.
+             */
+            public static final Uri CONTENT_URI = Uri.parse("content://sms/conversations");
+
+            /**
+             * The default sort order for this table.
+             */
+            public static final String DEFAULT_SORT_ORDER = "date DESC";
+
+            /**
+             * The first 45 characters of the body of the message.
+             * <P>Type: TEXT</P>
+             */
+            public static final String SNIPPET = "snippet";
+
+            /**
+             * The number of messages in the conversation.
+             * <P>Type: INTEGER</P>
+             */
+            public static final String MESSAGE_COUNT = "msg_count";
+        }
+
+        /**
+         * Contains constants for SMS related Intents that are broadcast.
+         */
+        public static final class Intents {
+
+            /**
+             * Not instantiable.
+             * @hide
+             */
+            private Intents() {
+            }
+
+            /**
+             * Set by BroadcastReceiver to indicate that the message was handled
+             * successfully.
+             */
+            public static final int RESULT_SMS_HANDLED = 1;
+
+            /**
+             * Set by BroadcastReceiver to indicate a generic error while
+             * processing the message.
+             */
+            public static final int RESULT_SMS_GENERIC_ERROR = 2;
+
+            /**
+             * Set by BroadcastReceiver to indicate insufficient memory to store
+             * the message.
+             */
+            public static final int RESULT_SMS_OUT_OF_MEMORY = 3;
+
+            /**
+             * Set by BroadcastReceiver to indicate that the message, while
+             * possibly valid, is of a format or encoding that is not
+             * supported.
+             */
+            public static final int RESULT_SMS_UNSUPPORTED = 4;
+
+            /**
+             * Set by BroadcastReceiver to indicate a duplicate incoming message.
+             */
+            public static final int RESULT_SMS_DUPLICATED = 5;
+
+            /**
+             * Activity action: Ask the user to change the default
+             * SMS application. This will show a dialog that asks the
+             * user whether they want to replace the current default
+             * SMS application with the one specified in
+             * {@link #EXTRA_PACKAGE_NAME}.
+             */
+            @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+            public static final String ACTION_CHANGE_DEFAULT =
+                    "android.provider.Telephony.ACTION_CHANGE_DEFAULT";
+
+            /**
+             * The PackageName string passed in as an
+             * extra for {@link #ACTION_CHANGE_DEFAULT}
+             *
+             * @see #ACTION_CHANGE_DEFAULT
+             */
+            public static final String EXTRA_PACKAGE_NAME = "package";
+
+            /**
+             * Broadcast Action: A new text-based SMS message has been received
+             * by the device. This intent will only be delivered to the default
+             * sms app. That app is responsible for writing the message and notifying
+             * the user. The intent will have the following extra values:</p>
+             *
+             * <ul>
+             *   <li><em>"pdus"</em> - An Object[] of byte[]s containing the PDUs
+             *   that make up the message.</li>
+             *   <li><em>"format"</em> - A String describing the format of the PDUs. It can
+             *   be either "3gpp" or "3gpp2".</li>
+             *   <li><em>"subscription"</em> - An optional long value of the subscription id which
+             *   received the message.</li>
+             *   <li><em>"slot"</em> - An optional int value of the SIM slot containing the
+             *   subscription.</li>
+             *   <li><em>"phone"</em> - An optional int value of the phone id associated with the
+             *   subscription.</li>
+             *   <li><em>"errorCode"</em> - An optional int error code associated with receiving
+             *   the message.</li>
+             * </ul>
+             *
+             * <p>The extra values can be extracted using
+             * {@link #getMessagesFromIntent(Intent)}.</p>
+             *
+             * <p>If a BroadcastReceiver encounters an error while processing
+             * this intent it should set the result code appropriately.</p>
+             *
+             * <p class="note"><strong>Note:</strong>
+             * The broadcast receiver that filters for this intent must declare
+             * {@link android.Manifest.permission#BROADCAST_SMS} as a required permission in
+             * the <a href="{@docRoot}guide/topics/manifest/receiver-element.html">{@code
+             * <receiver>}</a> tag.
+             *
+             * <p>Requires {@link android.Manifest.permission#RECEIVE_SMS} to receive.</p>
+             */
+            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+            public static final String SMS_DELIVER_ACTION =
+                    "android.provider.Telephony.SMS_DELIVER";
+
+            /**
+             * Broadcast Action: A new text-based SMS message has been received
+             * by the device. This intent will be delivered to all registered
+             * receivers as a notification. These apps are not expected to write the
+             * message or notify the user. The intent will have the following extra
+             * values:</p>
+             *
+             * <ul>
+             *   <li><em>"pdus"</em> - An Object[] of byte[]s containing the PDUs
+             *   that make up the message.</li>
+             * </ul>
+             *
+             * <p>The extra values can be extracted using
+             * {@link #getMessagesFromIntent(Intent)}.</p>
+             *
+             * <p>If a BroadcastReceiver encounters an error while processing
+             * this intent it should set the result code appropriately.</p>
+             *
+             * <p>Requires {@link android.Manifest.permission#RECEIVE_SMS} to receive.</p>
+             */
+            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+            public static final String SMS_RECEIVED_ACTION =
+                    "android.provider.Telephony.SMS_RECEIVED";
+
+            /**
+             * Broadcast Action: A new data based SMS message has been received
+             * by the device. This intent will be delivered to all registered
+             * receivers as a notification. The intent will have the following extra
+             * values:</p>
+             *
+             * <ul>
+             *   <li><em>"pdus"</em> - An Object[] of byte[]s containing the PDUs
+             *   that make up the message.</li>
+             * </ul>
+             *
+             * <p>The extra values can be extracted using
+             * {@link #getMessagesFromIntent(Intent)}.</p>
+             *
+             * <p>If a BroadcastReceiver encounters an error while processing
+             * this intent it should set the result code appropriately.</p>
+             *
+             * <p>Requires {@link android.Manifest.permission#RECEIVE_SMS} to receive.</p>
+             */
+            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+            public static final String DATA_SMS_RECEIVED_ACTION =
+                    "android.intent.action.DATA_SMS_RECEIVED";
+
+            /**
+             * Broadcast Action: A new WAP PUSH message has been received by the
+             * device. This intent will only be delivered to the default
+             * sms app. That app is responsible for writing the message and notifying
+             * the user. The intent will have the following extra values:</p>
+             *
+             * <ul>
+             *   <li><em>"transactionId"</em> - (Integer) The WAP transaction ID</li>
+             *   <li><em>"pduType"</em> - (Integer) The WAP PDU type</li>
+             *   <li><em>"header"</em> - (byte[]) The header of the message</li>
+             *   <li><em>"data"</em> - (byte[]) The data payload of the message</li>
+             *   <li><em>"contentTypeParameters" </em>
+             *   -(HashMap&lt;String,String&gt;) Any parameters associated with the content type
+             *   (decoded from the WSP Content-Type header)</li>
+             *   <li><em>"subscription"</em> - An optional long value of the subscription id which
+             *   received the message.</li>
+             *   <li><em>"slot"</em> - An optional int value of the SIM slot containing the
+             *   subscription.</li>
+             *   <li><em>"phone"</em> - An optional int value of the phone id associated with the
+             *   subscription.</li>
+             * </ul>
+             *
+             * <p>If a BroadcastReceiver encounters an error while processing
+             * this intent it should set the result code appropriately.</p>
+             *
+             * <p>The contentTypeParameters extra value is map of content parameters keyed by
+             * their names.</p>
+             *
+             * <p>If any unassigned well-known parameters are encountered, the key of the map will
+             * be 'unassigned/0x...', where '...' is the hex value of the unassigned parameter.  If
+             * a parameter has No-Value the value in the map will be null.</p>
+             *
+             * <p>Requires {@link android.Manifest.permission#RECEIVE_MMS} or
+             * {@link android.Manifest.permission#RECEIVE_WAP_PUSH} (depending on WAP PUSH type) to
+             * receive.</p>
+             *
+             * <p class="note"><strong>Note:</strong>
+             * The broadcast receiver that filters for this intent must declare
+             * {@link android.Manifest.permission#BROADCAST_WAP_PUSH} as a required permission in
+             * the <a href="{@docRoot}guide/topics/manifest/receiver-element.html">{@code
+             * <receiver>}</a> tag.
+             */
+            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+            public static final String WAP_PUSH_DELIVER_ACTION =
+                    "android.provider.Telephony.WAP_PUSH_DELIVER";
+
+            /**
+             * Broadcast Action: A new WAP PUSH message has been received by the
+             * device. This intent will be delivered to all registered
+             * receivers as a notification. These apps are not expected to write the
+             * message or notify the user. The intent will have the following extra
+             * values:</p>
+             *
+             * <ul>
+             *   <li><em>"transactionId"</em> - (Integer) The WAP transaction ID</li>
+             *   <li><em>"pduType"</em> - (Integer) The WAP PDU type</li>
+             *   <li><em>"header"</em> - (byte[]) The header of the message</li>
+             *   <li><em>"data"</em> - (byte[]) The data payload of the message</li>
+             *   <li><em>"contentTypeParameters"</em>
+             *   - (HashMap&lt;String,String&gt;) Any parameters associated with the content type
+             *   (decoded from the WSP Content-Type header)</li>
+             * </ul>
+             *
+             * <p>If a BroadcastReceiver encounters an error while processing
+             * this intent it should set the result code appropriately.</p>
+             *
+             * <p>The contentTypeParameters extra value is map of content parameters keyed by
+             * their names.</p>
+             *
+             * <p>If any unassigned well-known parameters are encountered, the key of the map will
+             * be 'unassigned/0x...', where '...' is the hex value of the unassigned parameter.  If
+             * a parameter has No-Value the value in the map will be null.</p>
+             *
+             * <p>Requires {@link android.Manifest.permission#RECEIVE_MMS} or
+             * {@link android.Manifest.permission#RECEIVE_WAP_PUSH} (depending on WAP PUSH type) to
+             * receive.</p>
+             */
+            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+            public static final String WAP_PUSH_RECEIVED_ACTION =
+                    "android.provider.Telephony.WAP_PUSH_RECEIVED";
+
+            /**
+             * Broadcast Action: A new Cell Broadcast message has been received
+             * by the device. The intent will have the following extra
+             * values:</p>
+             *
+             * <ul>
+             *   <li><em>"message"</em> - An SmsCbMessage object containing the broadcast message
+             *   data. This is not an emergency alert, so ETWS and CMAS data will be null.</li>
+             * </ul>
+             *
+             * <p>The extra values can be extracted using
+             * {@link #getMessagesFromIntent(Intent)}.</p>
+             *
+             * <p>If a BroadcastReceiver encounters an error while processing
+             * this intent it should set the result code appropriately.</p>
+             *
+             * <p>Requires {@link android.Manifest.permission#RECEIVE_SMS} to receive.</p>
+             */
+            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+            public static final String SMS_CB_RECEIVED_ACTION =
+                    "android.provider.Telephony.SMS_CB_RECEIVED";
+
+            /**
+             * Action: A SMS based carrier provision intent. Used to identify default
+             * carrier provisioning app on the device.
+             * @hide
+             */
+            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+            @TestApi
+            public static final String SMS_CARRIER_PROVISION_ACTION =
+                    "android.provider.Telephony.SMS_CARRIER_PROVISION";
+
+            /**
+             * Broadcast Action: A new Emergency Broadcast message has been received
+             * by the device. The intent will have the following extra
+             * values:</p>
+             *
+             * <ul>
+             *   <li><em>"message"</em> - An SmsCbMessage object containing the broadcast message
+             *   data, including ETWS or CMAS warning notification info if present.</li>
+             * </ul>
+             *
+             * <p>The extra values can be extracted using
+             * {@link #getMessagesFromIntent(Intent)}.</p>
+             *
+             * <p>If a BroadcastReceiver encounters an error while processing
+             * this intent it should set the result code appropriately.</p>
+             *
+             * <p>Requires {@link android.Manifest.permission#RECEIVE_EMERGENCY_BROADCAST} to
+             * receive.</p>
+             * @removed
+             */
+            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+            public static final String SMS_EMERGENCY_CB_RECEIVED_ACTION =
+                    "android.provider.Telephony.SMS_EMERGENCY_CB_RECEIVED";
+
+            /**
+             * Broadcast Action: A new CDMA SMS has been received containing Service Category
+             * Program Data (updates the list of enabled broadcast channels). The intent will
+             * have the following extra values:</p>
+             *
+             * <ul>
+             *   <li><em>"operations"</em> - An array of CdmaSmsCbProgramData objects containing
+             *   the service category operations (add/delete/clear) to perform.</li>
+             * </ul>
+             *
+             * <p>The extra values can be extracted using
+             * {@link #getMessagesFromIntent(Intent)}.</p>
+             *
+             * <p>If a BroadcastReceiver encounters an error while processing
+             * this intent it should set the result code appropriately.</p>
+             *
+             * <p>Requires {@link android.Manifest.permission#RECEIVE_SMS} to receive.</p>
+             */
+            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+            public static final String SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED_ACTION =
+                    "android.provider.Telephony.SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED";
+
+            /**
+             * Broadcast Action: The SIM storage for SMS messages is full.  If
+             * space is not freed, messages targeted for the SIM (class 2) may
+             * not be saved.
+             *
+             * <p>Requires {@link android.Manifest.permission#RECEIVE_SMS} to receive.</p>
+             */
+            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+            public static final String SIM_FULL_ACTION =
+                    "android.provider.Telephony.SIM_FULL";
+
+            /**
+             * Broadcast Action: An incoming SMS has been rejected by the
+             * telephony framework.  This intent is sent in lieu of any
+             * of the RECEIVED_ACTION intents.  The intent will have the
+             * following extra value:</p>
+             *
+             * <ul>
+             *   <li><em>"result"</em> - An int result code, e.g. {@link #RESULT_SMS_OUT_OF_MEMORY}
+             *   indicating the error returned to the network.</li>
+             * </ul>
+             *
+             * <p>Requires {@link android.Manifest.permission#RECEIVE_SMS} to receive.</p>
+             */
+            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+            public static final String SMS_REJECTED_ACTION =
+                "android.provider.Telephony.SMS_REJECTED";
+
+            /**
+             * Broadcast Action: An incoming MMS has been downloaded. The intent is sent to all
+             * users, except for secondary users where SMS has been disabled and to managed
+             * profiles.
+             * @hide
+             */
+            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+            public static final String MMS_DOWNLOADED_ACTION =
+                "android.provider.Telephony.MMS_DOWNLOADED";
+
+            /**
+             * Broadcast action: When the default SMS package changes,
+             * the previous default SMS package and the new default SMS
+             * package are sent this broadcast to notify them of the change.
+             * A boolean is specified in {@link #EXTRA_IS_DEFAULT_SMS_APP} to
+             * indicate whether the package is the new default SMS package.
+            */
+            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+            public static final String ACTION_DEFAULT_SMS_PACKAGE_CHANGED =
+                            "android.provider.action.DEFAULT_SMS_PACKAGE_CHANGED";
+
+            /**
+             * The IsDefaultSmsApp boolean passed as an
+             * extra for {@link #ACTION_DEFAULT_SMS_PACKAGE_CHANGED} to indicate whether the
+             * SMS app is becoming the default SMS app or is no longer the default.
+             *
+             * @see #ACTION_DEFAULT_SMS_PACKAGE_CHANGED
+             */
+            public static final String EXTRA_IS_DEFAULT_SMS_APP =
+                    "android.provider.extra.IS_DEFAULT_SMS_APP";
+
+            /**
+             * Broadcast action: When a change is made to the SmsProvider or
+             * MmsProvider by a process other than the default SMS application,
+             * this intent is broadcast to the default SMS application so it can
+             * re-sync or update the change. The uri that was used to call the provider
+             * can be retrieved from the intent with getData(). The actual affected uris
+             * (which would depend on the selection specified) are not included.
+            */
+            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+            public static final String ACTION_EXTERNAL_PROVIDER_CHANGE =
+                          "android.provider.action.EXTERNAL_PROVIDER_CHANGE";
+
+            /**
+             * Read the PDUs out of an {@link #SMS_RECEIVED_ACTION} or a
+             * {@link #DATA_SMS_RECEIVED_ACTION} intent.
+             *
+             * @param intent the intent to read from
+             * @return an array of SmsMessages for the PDUs
+             */
+            public static SmsMessage[] getMessagesFromIntent(Intent intent) {
+                Object[] messages;
+                try {
+                    messages = (Object[]) intent.getSerializableExtra("pdus");
+                }
+                catch (ClassCastException e) {
+                    Rlog.e(TAG, "getMessagesFromIntent: " + e);
+                    return null;
+                }
+
+                if (messages == null) {
+                    Rlog.e(TAG, "pdus does not exist in the intent");
+                    return null;
+                }
+
+                String format = intent.getStringExtra("format");
+                int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
+                        SubscriptionManager.getDefaultSmsSubscriptionId());
+
+                Rlog.v(TAG, " getMessagesFromIntent sub_id : " + subId);
+
+                int pduCount = messages.length;
+                SmsMessage[] msgs = new SmsMessage[pduCount];
+
+                for (int i = 0; i < pduCount; i++) {
+                    byte[] pdu = (byte[]) messages[i];
+                    msgs[i] = SmsMessage.createFromPdu(pdu, format);
+                    if (msgs[i] != null) msgs[i].setSubId(subId);
+                }
+                return msgs;
+            }
+        }
+    }
+
+    /**
+     * Base columns for tables that contain MMSs.
+     */
+    public interface BaseMmsColumns extends BaseColumns {
+
+        /** Message box: all messages. */
+        public static final int MESSAGE_BOX_ALL    = 0;
+        /** Message box: inbox. */
+        public static final int MESSAGE_BOX_INBOX  = 1;
+        /** Message box: sent messages. */
+        public static final int MESSAGE_BOX_SENT   = 2;
+        /** Message box: drafts. */
+        public static final int MESSAGE_BOX_DRAFTS = 3;
+        /** Message box: outbox. */
+        public static final int MESSAGE_BOX_OUTBOX = 4;
+        /** Message box: failed. */
+        public static final int MESSAGE_BOX_FAILED = 5;
+
+        /**
+         * The thread ID of the message.
+         * <P>Type: INTEGER (long)</P>
+         */
+        public static final String THREAD_ID = "thread_id";
+
+        /**
+         * The date the message was received.
+         * <P>Type: INTEGER (long)</P>
+         */
+        public static final String DATE = "date";
+
+        /**
+         * The date the message was sent.
+         * <P>Type: INTEGER (long)</P>
+         */
+        public static final String DATE_SENT = "date_sent";
+
+        /**
+         * The box which the message belongs to, e.g. {@link #MESSAGE_BOX_INBOX}.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String MESSAGE_BOX = "msg_box";
+
+        /**
+         * Has the message been read?
+         * <P>Type: INTEGER (boolean)</P>
+         */
+        public static final String READ = "read";
+
+        /**
+         * Has the message been seen by the user? The "seen" flag determines
+         * whether we need to show a new message notification.
+         * <P>Type: INTEGER (boolean)</P>
+         */
+        public static final String SEEN = "seen";
+
+        /**
+         * Does the message have only a text part (can also have a subject) with
+         * no picture, slideshow, sound, etc. parts?
+         * <P>Type: INTEGER (boolean)</P>
+         */
+        public static final String TEXT_ONLY = "text_only";
+
+        /**
+         * The {@code Message-ID} of the message.
+         * <P>Type: TEXT</P>
+         */
+        public static final String MESSAGE_ID = "m_id";
+
+        /**
+         * The subject of the message, if present.
+         * <P>Type: TEXT</P>
+         */
+        public static final String SUBJECT = "sub";
+
+        /**
+         * The character set of the subject, if present.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String SUBJECT_CHARSET = "sub_cs";
+
+        /**
+         * The {@code Content-Type} of the message.
+         * <P>Type: TEXT</P>
+         */
+        public static final String CONTENT_TYPE = "ct_t";
+
+        /**
+         * The {@code Content-Location} of the message.
+         * <P>Type: TEXT</P>
+         */
+        public static final String CONTENT_LOCATION = "ct_l";
+
+        /**
+         * The expiry time of the message.
+         * <P>Type: INTEGER (long)</P>
+         */
+        public static final String EXPIRY = "exp";
+
+        /**
+         * The class of the message.
+         * <P>Type: TEXT</P>
+         */
+        public static final String MESSAGE_CLASS = "m_cls";
+
+        /**
+         * The type of the message defined by MMS spec.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String MESSAGE_TYPE = "m_type";
+
+        /**
+         * The version of the specification that this message conforms to.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String MMS_VERSION = "v";
+
+        /**
+         * The size of the message.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String MESSAGE_SIZE = "m_size";
+
+        /**
+         * The priority of the message.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String PRIORITY = "pri";
+
+        /**
+         * The {@code read-report} of the message.
+         * <P>Type: INTEGER (boolean)</P>
+         */
+        public static final String READ_REPORT = "rr";
+
+        /**
+         * Is read report allowed?
+         * <P>Type: INTEGER (boolean)</P>
+         */
+        public static final String REPORT_ALLOWED = "rpt_a";
+
+        /**
+         * The {@code response-status} of the message.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String RESPONSE_STATUS = "resp_st";
+
+        /**
+         * The {@code status} of the message.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String STATUS = "st";
+
+        /**
+         * The {@code transaction-id} of the message.
+         * <P>Type: TEXT</P>
+         */
+        public static final String TRANSACTION_ID = "tr_id";
+
+        /**
+         * The {@code retrieve-status} of the message.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String RETRIEVE_STATUS = "retr_st";
+
+        /**
+         * The {@code retrieve-text} of the message.
+         * <P>Type: TEXT</P>
+         */
+        public static final String RETRIEVE_TEXT = "retr_txt";
+
+        /**
+         * The character set of the retrieve-text.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String RETRIEVE_TEXT_CHARSET = "retr_txt_cs";
+
+        /**
+         * The {@code read-status} of the message.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String READ_STATUS = "read_status";
+
+        /**
+         * The {@code content-class} of the message.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String CONTENT_CLASS = "ct_cls";
+
+        /**
+         * The {@code delivery-report} of the message.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String DELIVERY_REPORT = "d_rpt";
+
+        /**
+         * The {@code delivery-time-token} of the message.
+         * <P>Type: INTEGER</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String DELIVERY_TIME_TOKEN = "d_tm_tok";
+
+        /**
+         * The {@code delivery-time} of the message.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String DELIVERY_TIME = "d_tm";
+
+        /**
+         * The {@code response-text} of the message.
+         * <P>Type: TEXT</P>
+         */
+        public static final String RESPONSE_TEXT = "resp_txt";
+
+        /**
+         * The {@code sender-visibility} of the message.
+         * <P>Type: TEXT</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String SENDER_VISIBILITY = "s_vis";
+
+        /**
+         * The {@code reply-charging} of the message.
+         * <P>Type: INTEGER</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String REPLY_CHARGING = "r_chg";
+
+        /**
+         * The {@code reply-charging-deadline-token} of the message.
+         * <P>Type: INTEGER</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String REPLY_CHARGING_DEADLINE_TOKEN = "r_chg_dl_tok";
+
+        /**
+         * The {@code reply-charging-deadline} of the message.
+         * <P>Type: INTEGER</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String REPLY_CHARGING_DEADLINE = "r_chg_dl";
+
+        /**
+         * The {@code reply-charging-id} of the message.
+         * <P>Type: TEXT</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String REPLY_CHARGING_ID = "r_chg_id";
+
+        /**
+         * The {@code reply-charging-size} of the message.
+         * <P>Type: INTEGER</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String REPLY_CHARGING_SIZE = "r_chg_sz";
+
+        /**
+         * The {@code previously-sent-by} of the message.
+         * <P>Type: TEXT</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String PREVIOUSLY_SENT_BY = "p_s_by";
+
+        /**
+         * The {@code previously-sent-date} of the message.
+         * <P>Type: INTEGER</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String PREVIOUSLY_SENT_DATE = "p_s_d";
+
+        /**
+         * The {@code store} of the message.
+         * <P>Type: TEXT</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String STORE = "store";
+
+        /**
+         * The {@code mm-state} of the message.
+         * <P>Type: INTEGER</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String MM_STATE = "mm_st";
+
+        /**
+         * The {@code mm-flags-token} of the message.
+         * <P>Type: INTEGER</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String MM_FLAGS_TOKEN = "mm_flg_tok";
+
+        /**
+         * The {@code mm-flags} of the message.
+         * <P>Type: TEXT</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String MM_FLAGS = "mm_flg";
+
+        /**
+         * The {@code store-status} of the message.
+         * <P>Type: TEXT</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String STORE_STATUS = "store_st";
+
+        /**
+         * The {@code store-status-text} of the message.
+         * <P>Type: TEXT</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String STORE_STATUS_TEXT = "store_st_txt";
+
+        /**
+         * The {@code stored} of the message.
+         * <P>Type: TEXT</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String STORED = "stored";
+
+        /**
+         * The {@code totals} of the message.
+         * <P>Type: TEXT</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String TOTALS = "totals";
+
+        /**
+         * The {@code mbox-totals} of the message.
+         * <P>Type: TEXT</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String MBOX_TOTALS = "mb_t";
+
+        /**
+         * The {@code mbox-totals-token} of the message.
+         * <P>Type: INTEGER</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String MBOX_TOTALS_TOKEN = "mb_t_tok";
+
+        /**
+         * The {@code quotas} of the message.
+         * <P>Type: TEXT</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String QUOTAS = "qt";
+
+        /**
+         * The {@code mbox-quotas} of the message.
+         * <P>Type: TEXT</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String MBOX_QUOTAS = "mb_qt";
+
+        /**
+         * The {@code mbox-quotas-token} of the message.
+         * <P>Type: INTEGER</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String MBOX_QUOTAS_TOKEN = "mb_qt_tok";
+
+        /**
+         * The {@code message-count} of the message.
+         * <P>Type: INTEGER</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String MESSAGE_COUNT = "m_cnt";
+
+        /**
+         * The {@code start} of the message.
+         * <P>Type: INTEGER</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String START = "start";
+
+        /**
+         * The {@code distribution-indicator} of the message.
+         * <P>Type: TEXT</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String DISTRIBUTION_INDICATOR = "d_ind";
+
+        /**
+         * The {@code element-descriptor} of the message.
+         * <P>Type: TEXT</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String ELEMENT_DESCRIPTOR = "e_des";
+
+        /**
+         * The {@code limit} of the message.
+         * <P>Type: INTEGER</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String LIMIT = "limit";
+
+        /**
+         * The {@code recommended-retrieval-mode} of the message.
+         * <P>Type: INTEGER</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String RECOMMENDED_RETRIEVAL_MODE = "r_r_mod";
+
+        /**
+         * The {@code recommended-retrieval-mode-text} of the message.
+         * <P>Type: TEXT</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String RECOMMENDED_RETRIEVAL_MODE_TEXT = "r_r_mod_txt";
+
+        /**
+         * The {@code status-text} of the message.
+         * <P>Type: TEXT</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String STATUS_TEXT = "st_txt";
+
+        /**
+         * The {@code applic-id} of the message.
+         * <P>Type: TEXT</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String APPLIC_ID = "apl_id";
+
+        /**
+         * The {@code reply-applic-id} of the message.
+         * <P>Type: TEXT</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String REPLY_APPLIC_ID = "r_apl_id";
+
+        /**
+         * The {@code aux-applic-id} of the message.
+         * <P>Type: TEXT</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String AUX_APPLIC_ID = "aux_apl_id";
+
+        /**
+         * The {@code drm-content} of the message.
+         * <P>Type: TEXT</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String DRM_CONTENT = "drm_c";
+
+        /**
+         * The {@code adaptation-allowed} of the message.
+         * <P>Type: TEXT</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String ADAPTATION_ALLOWED = "adp_a";
+
+        /**
+         * The {@code replace-id} of the message.
+         * <P>Type: TEXT</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String REPLACE_ID = "repl_id";
+
+        /**
+         * The {@code cancel-id} of the message.
+         * <P>Type: TEXT</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String CANCEL_ID = "cl_id";
+
+        /**
+         * The {@code cancel-status} of the message.
+         * <P>Type: INTEGER</P>
+         * @deprecated this column is no longer supported.
+         * @hide
+         */
+        @Deprecated
+        public static final String CANCEL_STATUS = "cl_st";
+
+        /**
+         * Is the message locked?
+         * <P>Type: INTEGER (boolean)</P>
+         */
+        public static final String LOCKED = "locked";
+
+        /**
+         * The subscription to which the message belongs to. Its value will be
+         * < 0 if the sub id cannot be determined.
+         * <p>Type: INTEGER (long)</p>
+         */
+        public static final String SUBSCRIPTION_ID = "sub_id";
+
+        /**
+         * The identity of the sender of a sent message. It is
+         * usually the package name of the app which sends the message.
+         * <p class="note"><strong>Note:</strong>
+         * This column is read-only. It is set by the provider and can not be changed by apps.
+         * <p>Type: TEXT</p>
+         */
+        public static final String CREATOR = "creator";
+    }
+
+    /**
+     * Columns for the "canonical_addresses" table used by MMS and SMS.
+     */
+    public interface CanonicalAddressesColumns extends BaseColumns {
+        /**
+         * An address used in MMS or SMS.  Email addresses are
+         * converted to lower case and are compared by string
+         * equality.  Other addresses are compared using
+         * PHONE_NUMBERS_EQUAL.
+         * <P>Type: TEXT</P>
+         */
+        public static final String ADDRESS = "address";
+    }
+
+    /**
+     * Columns for the "threads" table used by MMS and SMS.
+     */
+    public interface ThreadsColumns extends BaseColumns {
+
+        /**
+         * The date at which the thread was created.
+         * <P>Type: INTEGER (long)</P>
+         */
+        public static final String DATE = "date";
+
+        /**
+         * A string encoding of the recipient IDs of the recipients of
+         * the message, in numerical order and separated by spaces.
+         * <P>Type: TEXT</P>
+         */
+        public static final String RECIPIENT_IDS = "recipient_ids";
+
+        /**
+         * The message count of the thread.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String MESSAGE_COUNT = "message_count";
+
+        /**
+         * Indicates whether all messages of the thread have been read.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String READ = "read";
+
+        /**
+         * The snippet of the latest message in the thread.
+         * <P>Type: TEXT</P>
+         */
+        public static final String SNIPPET = "snippet";
+
+        /**
+         * The charset of the snippet.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String SNIPPET_CHARSET = "snippet_cs";
+
+        /**
+         * Type of the thread, either {@link Threads#COMMON_THREAD} or
+         * {@link Threads#BROADCAST_THREAD}.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String TYPE = "type";
+
+        /**
+         * Indicates whether there is a transmission error in the thread.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String ERROR = "error";
+
+        /**
+         * Indicates whether this thread contains any attachments.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String HAS_ATTACHMENT = "has_attachment";
+
+        /**
+         * If the thread is archived
+         * <P>Type: INTEGER (boolean)</P>
+         */
+        public static final String ARCHIVED = "archived";
+    }
+
+    /**
+     * Helper functions for the "threads" table used by MMS and SMS.
+     */
+    public static final class Threads implements ThreadsColumns {
+
+        private static final String[] ID_PROJECTION = { BaseColumns._ID };
+
+        /**
+         * Private {@code content://} style URL for this table. Used by
+         * {@link #getOrCreateThreadId(android.content.Context, java.util.Set)}.
+         */
+        private static final Uri THREAD_ID_CONTENT_URI = Uri.parse(
+                "content://mms-sms/threadID");
+
+        /**
+         * The {@code content://} style URL for this table, by conversation.
+         */
+        public static final Uri CONTENT_URI = Uri.withAppendedPath(
+                MmsSms.CONTENT_URI, "conversations");
+
+        /**
+         * The {@code content://} style URL for this table, for obsolete threads.
+         */
+        public static final Uri OBSOLETE_THREADS_URI = Uri.withAppendedPath(
+                CONTENT_URI, "obsolete");
+
+        /** Thread type: common thread. */
+        public static final int COMMON_THREAD    = 0;
+
+        /** Thread type: broadcast thread. */
+        public static final int BROADCAST_THREAD = 1;
+
+        /**
+         * Not instantiable.
+         * @hide
+         */
+        private Threads() {
+        }
+
+        /**
+         * This is a single-recipient version of {@code getOrCreateThreadId}.
+         * It's convenient for use with SMS messages.
+         * @param context the context object to use.
+         * @param recipient the recipient to send to.
+         */
+        public static long getOrCreateThreadId(Context context, String recipient) {
+            Set<String> recipients = new HashSet<String>();
+
+            recipients.add(recipient);
+            return getOrCreateThreadId(context, recipients);
+        }
+
+        /**
+         * Given the recipients list and subject of an unsaved message,
+         * return its thread ID.  If the message starts a new thread,
+         * allocate a new thread ID.  Otherwise, use the appropriate
+         * existing thread ID.
+         *
+         * <p>Find the thread ID of the same set of recipients (in any order,
+         * without any additions). If one is found, return it. Otherwise,
+         * return a unique thread ID.</p>
+         */
+        public static long getOrCreateThreadId(
+                Context context, Set<String> recipients) {
+            Uri.Builder uriBuilder = THREAD_ID_CONTENT_URI.buildUpon();
+
+            for (String recipient : recipients) {
+                if (Mms.isEmailAddress(recipient)) {
+                    recipient = Mms.extractAddrSpec(recipient);
+                }
+
+                uriBuilder.appendQueryParameter("recipient", recipient);
+            }
+
+            Uri uri = uriBuilder.build();
+            //if (DEBUG) Rlog.v(TAG, "getOrCreateThreadId uri: " + uri);
+
+            Cursor cursor = SqliteWrapper.query(context, context.getContentResolver(),
+                    uri, ID_PROJECTION, null, null, null);
+            if (cursor != null) {
+                try {
+                    if (cursor.moveToFirst()) {
+                        return cursor.getLong(0);
+                    } else {
+                        Rlog.e(TAG, "getOrCreateThreadId returned no rows!");
+                    }
+                } finally {
+                    cursor.close();
+                }
+            }
+
+            Rlog.e(TAG, "getOrCreateThreadId failed with " + recipients.size() + " recipients");
+            throw new IllegalArgumentException("Unable to find or allocate a thread ID.");
+        }
+    }
+
+    /**
+     * Contains all MMS messages.
+     */
+    public static final class Mms implements BaseMmsColumns {
+
+        /**
+         * Not instantiable.
+         * @hide
+         */
+        private Mms() {
+        }
+
+        /**
+         * The {@code content://} URI for this table.
+         */
+        public static final Uri CONTENT_URI = Uri.parse("content://mms");
+
+        /**
+         * Content URI for getting MMS report requests.
+         */
+        public static final Uri REPORT_REQUEST_URI = Uri.withAppendedPath(
+                                            CONTENT_URI, "report-request");
+
+        /**
+         * Content URI for getting MMS report status.
+         */
+        public static final Uri REPORT_STATUS_URI = Uri.withAppendedPath(
+                                            CONTENT_URI, "report-status");
+
+        /**
+         * The default sort order for this table.
+         */
+        public static final String DEFAULT_SORT_ORDER = "date DESC";
+
+        /**
+         * Regex pattern for names and email addresses.
+         * <ul>
+         *     <li><em>mailbox</em> = {@code name-addr}</li>
+         *     <li><em>name-addr</em> = {@code [display-name] angle-addr}</li>
+         *     <li><em>angle-addr</em> = {@code [CFWS] "<" addr-spec ">" [CFWS]}</li>
+         * </ul>
+         * @hide
+         */
+        public static final Pattern NAME_ADDR_EMAIL_PATTERN =
+                Pattern.compile("\\s*(\"[^\"]*\"|[^<>\"]+)\\s*<([^<>]+)>\\s*");
+
+        /**
+         * Helper method to query this table.
+         * @hide
+         */
+        public static Cursor query(
+                ContentResolver cr, String[] projection) {
+            return cr.query(CONTENT_URI, projection, null, null, DEFAULT_SORT_ORDER);
+        }
+
+        /**
+         * Helper method to query this table.
+         * @hide
+         */
+        public static Cursor query(
+                ContentResolver cr, String[] projection,
+                String where, String orderBy) {
+            return cr.query(CONTENT_URI, projection,
+                    where, null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
+        }
+
+        /**
+         * Helper method to extract email address from address string.
+         * @hide
+         */
+        public static String extractAddrSpec(String address) {
+            Matcher match = NAME_ADDR_EMAIL_PATTERN.matcher(address);
+
+            if (match.matches()) {
+                return match.group(2);
+            }
+            return address;
+        }
+
+        /**
+         * Is the specified address an email address?
+         *
+         * @param address the input address to test
+         * @return true if address is an email address; false otherwise.
+         * @hide
+         */
+        public static boolean isEmailAddress(String address) {
+            if (TextUtils.isEmpty(address)) {
+                return false;
+            }
+
+            String s = extractAddrSpec(address);
+            Matcher match = Patterns.EMAIL_ADDRESS.matcher(s);
+            return match.matches();
+        }
+
+        /**
+         * Is the specified number a phone number?
+         *
+         * @param number the input number to test
+         * @return true if number is a phone number; false otherwise.
+         * @hide
+         */
+        public static boolean isPhoneNumber(String number) {
+            if (TextUtils.isEmpty(number)) {
+                return false;
+            }
+
+            Matcher match = Patterns.PHONE.matcher(number);
+            return match.matches();
+        }
+
+        /**
+         * Contains all MMS messages in the MMS app inbox.
+         */
+        public static final class Inbox implements BaseMmsColumns {
+
+            /**
+             * Not instantiable.
+             * @hide
+             */
+            private Inbox() {
+            }
+
+            /**
+             * The {@code content://} style URL for this table.
+             */
+            public static final Uri
+                    CONTENT_URI = Uri.parse("content://mms/inbox");
+
+            /**
+             * The default sort order for this table.
+             */
+            public static final String DEFAULT_SORT_ORDER = "date DESC";
+        }
+
+        /**
+         * Contains all MMS messages in the MMS app sent folder.
+         */
+        public static final class Sent implements BaseMmsColumns {
+
+            /**
+             * Not instantiable.
+             * @hide
+             */
+            private Sent() {
+            }
+
+            /**
+             * The {@code content://} style URL for this table.
+             */
+            public static final Uri
+                    CONTENT_URI = Uri.parse("content://mms/sent");
+
+            /**
+             * The default sort order for this table.
+             */
+            public static final String DEFAULT_SORT_ORDER = "date DESC";
+        }
+
+        /**
+         * Contains all MMS messages in the MMS app drafts folder.
+         */
+        public static final class Draft implements BaseMmsColumns {
+
+            /**
+             * Not instantiable.
+             * @hide
+             */
+            private Draft() {
+            }
+
+            /**
+             * The {@code content://} style URL for this table.
+             */
+            public static final Uri
+                    CONTENT_URI = Uri.parse("content://mms/drafts");
+
+            /**
+             * The default sort order for this table.
+             */
+            public static final String DEFAULT_SORT_ORDER = "date DESC";
+        }
+
+        /**
+         * Contains all MMS messages in the MMS app outbox.
+         */
+        public static final class Outbox implements BaseMmsColumns {
+
+            /**
+             * Not instantiable.
+             * @hide
+             */
+            private Outbox() {
+            }
+
+            /**
+             * The {@code content://} style URL for this table.
+             */
+            public static final Uri
+                    CONTENT_URI = Uri.parse("content://mms/outbox");
+
+            /**
+             * The default sort order for this table.
+             */
+            public static final String DEFAULT_SORT_ORDER = "date DESC";
+        }
+
+        /**
+         * Contains address information for an MMS message.
+         */
+        public static final class Addr implements BaseColumns {
+
+            /**
+             * Not instantiable.
+             * @hide
+             */
+            private Addr() {
+            }
+
+            /**
+             * The ID of MM which this address entry belongs to.
+             * <P>Type: INTEGER (long)</P>
+             */
+            public static final String MSG_ID = "msg_id";
+
+            /**
+             * The ID of contact entry in Phone Book.
+             * <P>Type: INTEGER (long)</P>
+             */
+            public static final String CONTACT_ID = "contact_id";
+
+            /**
+             * The address text.
+             * <P>Type: TEXT</P>
+             */
+            public static final String ADDRESS = "address";
+
+            /**
+             * Type of address: must be one of {@code PduHeaders.BCC},
+             * {@code PduHeaders.CC}, {@code PduHeaders.FROM}, {@code PduHeaders.TO}.
+             * <P>Type: INTEGER</P>
+             */
+            public static final String TYPE = "type";
+
+            /**
+             * Character set of this entry (MMS charset value).
+             * <P>Type: INTEGER</P>
+             */
+            public static final String CHARSET = "charset";
+        }
+
+        /**
+         * Contains message parts.
+         */
+        public static final class Part implements BaseColumns {
+
+            /**
+             * Not instantiable.
+             * @hide
+             */
+            private Part() {
+            }
+
+            /**
+             * The identifier of the message which this part belongs to.
+             * <P>Type: INTEGER</P>
+             */
+            public static final String MSG_ID = "mid";
+
+            /**
+             * The order of the part.
+             * <P>Type: INTEGER</P>
+             */
+            public static final String SEQ = "seq";
+
+            /**
+             * The content type of the part.
+             * <P>Type: TEXT</P>
+             */
+            public static final String CONTENT_TYPE = "ct";
+
+            /**
+             * The name of the part.
+             * <P>Type: TEXT</P>
+             */
+            public static final String NAME = "name";
+
+            /**
+             * The charset of the part.
+             * <P>Type: TEXT</P>
+             */
+            public static final String CHARSET = "chset";
+
+            /**
+             * The file name of the part.
+             * <P>Type: TEXT</P>
+             */
+            public static final String FILENAME = "fn";
+
+            /**
+             * The content disposition of the part.
+             * <P>Type: TEXT</P>
+             */
+            public static final String CONTENT_DISPOSITION = "cd";
+
+            /**
+             * The content ID of the part.
+             * <P>Type: INTEGER</P>
+             */
+            public static final String CONTENT_ID = "cid";
+
+            /**
+             * The content location of the part.
+             * <P>Type: INTEGER</P>
+             */
+            public static final String CONTENT_LOCATION = "cl";
+
+            /**
+             * The start of content-type of the message.
+             * <P>Type: INTEGER</P>
+             */
+            public static final String CT_START = "ctt_s";
+
+            /**
+             * The type of content-type of the message.
+             * <P>Type: TEXT</P>
+             */
+            public static final String CT_TYPE = "ctt_t";
+
+            /**
+             * The location (on filesystem) of the binary data of the part.
+             * <P>Type: INTEGER</P>
+             */
+            public static final String _DATA = "_data";
+
+            /**
+             * The message text.
+             * <P>Type: TEXT</P>
+             */
+            public static final String TEXT = "text";
+        }
+
+        /**
+         * Message send rate table.
+         */
+        public static final class Rate {
+
+            /**
+             * Not instantiable.
+             * @hide
+             */
+            private Rate() {
+            }
+
+            /**
+             * The {@code content://} style URL for this table.
+             */
+            public static final Uri CONTENT_URI = Uri.withAppendedPath(
+                    Mms.CONTENT_URI, "rate");
+
+            /**
+             * When a message was successfully sent.
+             * <P>Type: INTEGER (long)</P>
+             */
+            public static final String SENT_TIME = "sent_time";
+        }
+
+        /**
+         * Intents class.
+         */
+        public static final class Intents {
+
+            /**
+             * Not instantiable.
+             * @hide
+             */
+            private Intents() {
+            }
+
+            /**
+             * Indicates that the contents of specified URIs were changed.
+             * The application which is showing or caching these contents
+             * should be updated.
+             */
+            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+            public static final String CONTENT_CHANGED_ACTION
+                    = "android.intent.action.CONTENT_CHANGED";
+
+            /**
+             * An extra field which stores the URI of deleted contents.
+             */
+            public static final String DELETED_CONTENTS = "deleted_contents";
+        }
+    }
+
+    /**
+     * Contains all MMS and SMS messages.
+     */
+    public static final class MmsSms implements BaseColumns {
+
+        /**
+         * Not instantiable.
+         * @hide
+         */
+        private MmsSms() {
+        }
+
+        /**
+         * The column to distinguish SMS and MMS messages in query results.
+         */
+        public static final String TYPE_DISCRIMINATOR_COLUMN =
+                "transport_type";
+
+        /**
+         * The {@code content://} style URL for this table.
+         */
+        public static final Uri CONTENT_URI = Uri.parse("content://mms-sms/");
+
+        /**
+         * The {@code content://} style URL for this table, by conversation.
+         */
+        public static final Uri CONTENT_CONVERSATIONS_URI = Uri.parse(
+                "content://mms-sms/conversations");
+
+        /**
+         * The {@code content://} style URL for this table, by phone number.
+         */
+        public static final Uri CONTENT_FILTER_BYPHONE_URI = Uri.parse(
+                "content://mms-sms/messages/byphone");
+
+        /**
+         * The {@code content://} style URL for undelivered messages in this table.
+         */
+        public static final Uri CONTENT_UNDELIVERED_URI = Uri.parse(
+                "content://mms-sms/undelivered");
+
+        /**
+         * The {@code content://} style URL for draft messages in this table.
+         */
+        public static final Uri CONTENT_DRAFT_URI = Uri.parse(
+                "content://mms-sms/draft");
+
+        /**
+         * The {@code content://} style URL for locked messages in this table.
+         */
+        public static final Uri CONTENT_LOCKED_URI = Uri.parse(
+                "content://mms-sms/locked");
+
+        /**
+         * Pass in a query parameter called "pattern" which is the text to search for.
+         * The sort order is fixed to be: {@code thread_id ASC, date DESC}.
+         */
+        public static final Uri SEARCH_URI = Uri.parse(
+                "content://mms-sms/search");
+
+        // Constants for message protocol types.
+
+        /** SMS protocol type. */
+        public static final int SMS_PROTO = 0;
+
+        /** MMS protocol type. */
+        public static final int MMS_PROTO = 1;
+
+        // Constants for error types of pending messages.
+
+        /** Error type: no error. */
+        public static final int NO_ERROR                      = 0;
+
+        /** Error type: generic transient error. */
+        public static final int ERR_TYPE_GENERIC              = 1;
+
+        /** Error type: SMS protocol transient error. */
+        public static final int ERR_TYPE_SMS_PROTO_TRANSIENT  = 2;
+
+        /** Error type: MMS protocol transient error. */
+        public static final int ERR_TYPE_MMS_PROTO_TRANSIENT  = 3;
+
+        /** Error type: transport failure. */
+        public static final int ERR_TYPE_TRANSPORT_FAILURE    = 4;
+
+        /** Error type: permanent error (along with all higher error values). */
+        public static final int ERR_TYPE_GENERIC_PERMANENT    = 10;
+
+        /** Error type: SMS protocol permanent error. */
+        public static final int ERR_TYPE_SMS_PROTO_PERMANENT  = 11;
+
+        /** Error type: MMS protocol permanent error. */
+        public static final int ERR_TYPE_MMS_PROTO_PERMANENT  = 12;
+
+        /**
+         * Contains pending messages info.
+         */
+        public static final class PendingMessages implements BaseColumns {
+
+            /**
+             * Not instantiable.
+             * @hide
+             */
+            private PendingMessages() {
+            }
+
+            public static final Uri CONTENT_URI = Uri.withAppendedPath(
+                    MmsSms.CONTENT_URI, "pending");
+
+            /**
+             * The type of transport protocol (MMS or SMS).
+             * <P>Type: INTEGER</P>
+             */
+            public static final String PROTO_TYPE = "proto_type";
+
+            /**
+             * The ID of the message to be sent or downloaded.
+             * <P>Type: INTEGER (long)</P>
+             */
+            public static final String MSG_ID = "msg_id";
+
+            /**
+             * The type of the message to be sent or downloaded.
+             * This field is only valid for MM. For SM, its value is always set to 0.
+             * <P>Type: INTEGER</P>
+             */
+            public static final String MSG_TYPE = "msg_type";
+
+            /**
+             * The type of the error code.
+             * <P>Type: INTEGER</P>
+             */
+            public static final String ERROR_TYPE = "err_type";
+
+            /**
+             * The error code of sending/retrieving process.
+             * <P>Type: INTEGER</P>
+             */
+            public static final String ERROR_CODE = "err_code";
+
+            /**
+             * How many times we tried to send or download the message.
+             * <P>Type: INTEGER</P>
+             */
+            public static final String RETRY_INDEX = "retry_index";
+
+            /**
+             * The time to do next retry.
+             * <P>Type: INTEGER (long)</P>
+             */
+            public static final String DUE_TIME = "due_time";
+
+            /**
+             * The time we last tried to send or download the message.
+             * <P>Type: INTEGER (long)</P>
+             */
+            public static final String LAST_TRY = "last_try";
+
+            /**
+             * The subscription to which the message belongs to. Its value will be
+             * < 0 if the sub id cannot be determined.
+             * <p>Type: INTEGER (long) </p>
+             */
+            public static final String SUBSCRIPTION_ID = "pending_sub_id";
+        }
+
+        /**
+         * Words table used by provider for full-text searches.
+         * @hide
+         */
+        public static final class WordsTable {
+
+            /**
+             * Not instantiable.
+             * @hide
+             */
+            private WordsTable() {}
+
+            /**
+             * Primary key.
+             * <P>Type: INTEGER (long)</P>
+             */
+            public static final String ID = "_id";
+
+            /**
+             * Source row ID.
+             * <P>Type: INTEGER (long)</P>
+             */
+            public static final String SOURCE_ROW_ID = "source_id";
+
+            /**
+             * Table ID (either 1 or 2).
+             * <P>Type: INTEGER</P>
+             */
+            public static final String TABLE_ID = "table_to_use";
+
+            /**
+             * The words to index.
+             * <P>Type: TEXT</P>
+             */
+            public static final String INDEXED_TEXT = "index_text";
+        }
+    }
+
+    /**
+     * Carriers class contains information about APNs, including MMSC information.
+     */
+    public static final class Carriers implements BaseColumns {
+
+        /**
+         * Not instantiable.
+         * @hide
+         */
+        private Carriers() {}
+
+        /**
+         * The {@code content://} style URL for this table.
+         */
+        public static final Uri CONTENT_URI = Uri.parse("content://telephony/carriers");
+
+        /**
+         * The default sort order for this table.
+         */
+        public static final String DEFAULT_SORT_ORDER = "name ASC";
+
+        /**
+         * Entry name.
+         * <P>Type: TEXT</P>
+         */
+        public static final String NAME = "name";
+
+        /**
+         * APN name.
+         * <P>Type: TEXT</P>
+         */
+        public static final String APN = "apn";
+
+        /**
+         * Proxy address.
+         * <P>Type: TEXT</P>
+         */
+        public static final String PROXY = "proxy";
+
+        /**
+         * Proxy port.
+         * <P>Type: TEXT</P>
+         */
+        public static final String PORT = "port";
+
+        /**
+         * MMS proxy address.
+         * <P>Type: TEXT</P>
+         */
+        public static final String MMSPROXY = "mmsproxy";
+
+        /**
+         * MMS proxy port.
+         * <P>Type: TEXT</P>
+         */
+        public static final String MMSPORT = "mmsport";
+
+        /**
+         * Server address.
+         * <P>Type: TEXT</P>
+         */
+        public static final String SERVER = "server";
+
+        /**
+         * APN username.
+         * <P>Type: TEXT</P>
+         */
+        public static final String USER = "user";
+
+        /**
+         * APN password.
+         * <P>Type: TEXT</P>
+         */
+        public static final String PASSWORD = "password";
+
+        /**
+         * MMSC URL.
+         * <P>Type: TEXT</P>
+         */
+        public static final String MMSC = "mmsc";
+
+        /**
+         * Mobile Country Code (MCC).
+         * <P>Type: TEXT</P>
+         */
+        public static final String MCC = "mcc";
+
+        /**
+         * Mobile Network Code (MNC).
+         * <P>Type: TEXT</P>
+         */
+        public static final String MNC = "mnc";
+
+        /**
+         * Numeric operator ID (as String). Usually {@code MCC + MNC}.
+         * <P>Type: TEXT</P>
+         */
+        public static final String NUMERIC = "numeric";
+
+        /**
+         * Authentication type.
+         * <P>Type:  INTEGER</P>
+         */
+        public static final String AUTH_TYPE = "authtype";
+
+        /**
+         * Comma-delimited list of APN types.
+         * <P>Type: TEXT</P>
+         */
+        public static final String TYPE = "type";
+
+        /**
+         * The protocol to use to connect to this APN.
+         *
+         * One of the {@code PDP_type} values in TS 27.007 section 10.1.1.
+         * For example: {@code IP}, {@code IPV6}, {@code IPV4V6}, or {@code PPP}.
+         * <P>Type: TEXT</P>
+         */
+        public static final String PROTOCOL = "protocol";
+
+        /**
+         * The protocol to use to connect to this APN when roaming.
+         * The syntax is the same as protocol.
+         * <P>Type: TEXT</P>
+         */
+        public static final String ROAMING_PROTOCOL = "roaming_protocol";
+
+        /**
+         * Is this the current APN?
+         * <P>Type: INTEGER (boolean)</P>
+         */
+        public static final String CURRENT = "current";
+
+        /**
+         * Is this APN enabled?
+         * <P>Type: INTEGER (boolean)</P>
+         */
+        public static final String CARRIER_ENABLED = "carrier_enabled";
+
+        /**
+         * Radio Access Technology info.
+         * To check what values are allowed, refer to {@link android.telephony.ServiceState}.
+         * This should be spread to other technologies,
+         * but is currently only used for LTE (14) and eHRPD (13).
+         * <P>Type: INTEGER</P>
+         */
+        public static final String BEARER = "bearer";
+
+        /**
+         * Radio Access Technology bitmask.
+         * To check what values can be contained, refer to {@link android.telephony.ServiceState}.
+         * 0 indicates all techs otherwise first bit refers to RAT/bearer 1, second bit refers to
+         * RAT/bearer 2 and so on.
+         * Bitmask for a radio tech R is (1 << (R - 1))
+         * <P>Type: INTEGER</P>
+         * @hide
+         */
+        public static final String BEARER_BITMASK = "bearer_bitmask";
+
+        /**
+         * MVNO type:
+         * {@code SPN (Service Provider Name), IMSI, GID (Group Identifier Level 1)}.
+         * <P>Type: TEXT</P>
+         */
+        public static final String MVNO_TYPE = "mvno_type";
+
+        /**
+         * MVNO data.
+         * Use the following examples.
+         * <ul>
+         *     <li>SPN: A MOBILE, BEN NL, ...</li>
+         *     <li>IMSI: 302720x94, 2060188, ...</li>
+         *     <li>GID: 4E, 33, ...</li>
+         * </ul>
+         * <P>Type: TEXT</P>
+         */
+        public static final String MVNO_MATCH_DATA = "mvno_match_data";
+
+        /**
+         * The subscription to which the APN belongs to
+         * <p>Type: INTEGER (long) </p>
+         */
+        public static final String SUBSCRIPTION_ID = "sub_id";
+
+        /**
+         * The profile_id to which the APN saved in modem
+         * <p>Type: INTEGER</p>
+         *@hide
+         */
+        public static final String PROFILE_ID = "profile_id";
+
+        /**
+         * Is the apn setting to be set in modem
+         * <P>Type: INTEGER (boolean)</P>
+         *@hide
+         */
+        public static final String MODEM_COGNITIVE = "modem_cognitive";
+
+        /**
+         * The max connections of this apn
+         * <p>Type: INTEGER</p>
+         *@hide
+         */
+        public static final String MAX_CONNS = "max_conns";
+
+        /**
+         * The wait time for retry of the apn
+         * <p>Type: INTEGER</p>
+         *@hide
+         */
+        public static final String WAIT_TIME = "wait_time";
+
+        /**
+         * The time to limit max connection for the apn
+         * <p>Type: INTEGER</p>
+         *@hide
+         */
+        public static final String MAX_CONNS_TIME = "max_conns_time";
+
+        /**
+         * The MTU size of the mobile interface to  which the APN connected
+         * <p>Type: INTEGER </p>
+         * @hide
+         */
+        public static final String MTU = "mtu";
+
+        /**
+         * Is this APN added/edited/deleted by a user or carrier?
+         * <p>Type: INTEGER </p>
+         * @hide
+         */
+        public static final String EDITED = "edited";
+
+        /**
+         * Is this APN visible to the user?
+         * <p>Type: INTEGER (boolean) </p>
+         * @hide
+         */
+        public static final String USER_VISIBLE = "user_visible";
+
+        /**
+         * Following are possible values for the EDITED field
+         * @hide
+         */
+        public static final int UNEDITED = 0;
+        /**
+         *  @hide
+         */
+        public static final int USER_EDITED = 1;
+        /**
+         *  @hide
+         */
+        public static final int USER_DELETED = 2;
+        /**
+         * DELETED_BUT_PRESENT is an intermediate value used to indicate that an entry deleted
+         * by the user is still present in the new APN database and therefore must remain tagged
+         * as user deleted rather than completely removed from the database
+         * @hide
+         */
+        public static final int USER_DELETED_BUT_PRESENT_IN_XML = 3;
+        /**
+         *  @hide
+         */
+        public static final int CARRIER_EDITED = 4;
+        /**
+         * CARRIER_DELETED values are currently not used as there is no usecase. If they are used,
+         * delete() will have to change accordingly. Currently it is hardcoded to USER_DELETED.
+         * @hide
+         */
+        public static final int CARRIER_DELETED = 5;
+        /**
+         *  @hide
+         */
+        public static final int CARRIER_DELETED_BUT_PRESENT_IN_XML = 6;
+    }
+
+    /**
+     * Contains received SMS cell broadcast messages.
+     * @hide
+     */
+    public static final class CellBroadcasts implements BaseColumns {
+
+        /**
+         * Not instantiable.
+         * @hide
+         */
+        private CellBroadcasts() {}
+
+        /**
+         * The {@code content://} URI for this table.
+         */
+        public static final Uri CONTENT_URI = Uri.parse("content://cellbroadcasts");
+
+        /**
+         * Message geographical scope.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String GEOGRAPHICAL_SCOPE = "geo_scope";
+
+        /**
+         * Message serial number.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String SERIAL_NUMBER = "serial_number";
+
+        /**
+         * PLMN of broadcast sender. {@code SERIAL_NUMBER + PLMN + LAC + CID} uniquely identifies
+         * a broadcast for duplicate detection purposes.
+         * <P>Type: TEXT</P>
+         */
+        public static final String PLMN = "plmn";
+
+        /**
+         * Location Area (GSM) or Service Area (UMTS) of broadcast sender. Unused for CDMA.
+         * Only included if Geographical Scope of message is not PLMN wide (01).
+         * <P>Type: INTEGER</P>
+         */
+        public static final String LAC = "lac";
+
+        /**
+         * Cell ID of message sender (GSM/UMTS). Unused for CDMA. Only included when the
+         * Geographical Scope of message is cell wide (00 or 11).
+         * <P>Type: INTEGER</P>
+         */
+        public static final String CID = "cid";
+
+        /**
+         * Message code. <em>OBSOLETE: merged into SERIAL_NUMBER.</em>
+         * <P>Type: INTEGER</P>
+         */
+        public static final String V1_MESSAGE_CODE = "message_code";
+
+        /**
+         * Message identifier. <em>OBSOLETE: renamed to SERVICE_CATEGORY.</em>
+         * <P>Type: INTEGER</P>
+         */
+        public static final String V1_MESSAGE_IDENTIFIER = "message_id";
+
+        /**
+         * Service category (GSM/UMTS: message identifier; CDMA: service category).
+         * <P>Type: INTEGER</P>
+         */
+        public static final String SERVICE_CATEGORY = "service_category";
+
+        /**
+         * Message language code.
+         * <P>Type: TEXT</P>
+         */
+        public static final String LANGUAGE_CODE = "language";
+
+        /**
+         * Message body.
+         * <P>Type: TEXT</P>
+         */
+        public static final String MESSAGE_BODY = "body";
+
+        /**
+         * Message delivery time.
+         * <P>Type: INTEGER (long)</P>
+         */
+        public static final String DELIVERY_TIME = "date";
+
+        /**
+         * Has the message been viewed?
+         * <P>Type: INTEGER (boolean)</P>
+         */
+        public static final String MESSAGE_READ = "read";
+
+        /**
+         * Message format (3GPP or 3GPP2).
+         * <P>Type: INTEGER</P>
+         */
+        public static final String MESSAGE_FORMAT = "format";
+
+        /**
+         * Message priority (including emergency).
+         * <P>Type: INTEGER</P>
+         */
+        public static final String MESSAGE_PRIORITY = "priority";
+
+        /**
+         * ETWS warning type (ETWS alerts only).
+         * <P>Type: INTEGER</P>
+         */
+        public static final String ETWS_WARNING_TYPE = "etws_warning_type";
+
+        /**
+         * CMAS message class (CMAS alerts only).
+         * <P>Type: INTEGER</P>
+         */
+        public static final String CMAS_MESSAGE_CLASS = "cmas_message_class";
+
+        /**
+         * CMAS category (CMAS alerts only).
+         * <P>Type: INTEGER</P>
+         */
+        public static final String CMAS_CATEGORY = "cmas_category";
+
+        /**
+         * CMAS response type (CMAS alerts only).
+         * <P>Type: INTEGER</P>
+         */
+        public static final String CMAS_RESPONSE_TYPE = "cmas_response_type";
+
+        /**
+         * CMAS severity (CMAS alerts only).
+         * <P>Type: INTEGER</P>
+         */
+        public static final String CMAS_SEVERITY = "cmas_severity";
+
+        /**
+         * CMAS urgency (CMAS alerts only).
+         * <P>Type: INTEGER</P>
+         */
+        public static final String CMAS_URGENCY = "cmas_urgency";
+
+        /**
+         * CMAS certainty (CMAS alerts only).
+         * <P>Type: INTEGER</P>
+         */
+        public static final String CMAS_CERTAINTY = "cmas_certainty";
+
+        /** The default sort order for this table. */
+        public static final String DEFAULT_SORT_ORDER = DELIVERY_TIME + " DESC";
+
+        /**
+         * Query columns for instantiating {@link android.telephony.CellBroadcastMessage} objects.
+         */
+        public static final String[] QUERY_COLUMNS = {
+                _ID,
+                GEOGRAPHICAL_SCOPE,
+                PLMN,
+                LAC,
+                CID,
+                SERIAL_NUMBER,
+                SERVICE_CATEGORY,
+                LANGUAGE_CODE,
+                MESSAGE_BODY,
+                DELIVERY_TIME,
+                MESSAGE_READ,
+                MESSAGE_FORMAT,
+                MESSAGE_PRIORITY,
+                ETWS_WARNING_TYPE,
+                CMAS_MESSAGE_CLASS,
+                CMAS_CATEGORY,
+                CMAS_RESPONSE_TYPE,
+                CMAS_SEVERITY,
+                CMAS_URGENCY,
+                CMAS_CERTAINTY
+        };
+    }
+}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index c2c724f..92197d6 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -21,9 +21,9 @@
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
-import android.annotation.SystemApi;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemApi;
 import android.app.ActivityThread;
 import android.app.PendingIntent;
 import android.content.ContentResolver;
@@ -32,9 +32,6 @@
 import android.net.ConnectivityManager;
 import android.net.Uri;
 import android.os.BatteryStats;
-import android.os.Binder;
-import android.provider.Settings;
-import android.provider.Settings.SettingNotFoundException;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.PersistableBundle;
@@ -42,11 +39,11 @@
 import android.os.ResultReceiver;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
 import android.service.carrier.CarrierIdentifier;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
-import android.telephony.ClientRequestStats;
-import android.telephony.TelephonyHistogram;
 import android.telephony.ims.feature.ImsFeature;
 import android.util.Log;
 
@@ -64,7 +61,6 @@
 
 import java.io.FileInputStream;
 import java.io.IOException;
-import java.io.UnsupportedEncodingException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
@@ -124,6 +120,20 @@
         static final int NEVER_USE = 2;
     }
 
+    /** The otaspMode passed to PhoneStateListener#onOtaspChanged */
+    /** @hide */
+    static public final int OTASP_UNINITIALIZED = 0;
+    /** @hide */
+    static public final int OTASP_UNKNOWN = 1;
+    /** @hide */
+    static public final int OTASP_NEEDED = 2;
+    /** @hide */
+    static public final int OTASP_NOT_NEEDED = 3;
+    /* OtaUtil has conflict enum 4: OtaUtils.OTASP_FAILURE_SPC_RETRIES */
+    /** @hide */
+    static public final int OTASP_SIM_UNPROVISIONED = 5;
+
+
     private final Context mContext;
     private final int mSubId;
     private SubscriptionManager mSubscriptionManager;
@@ -733,6 +743,8 @@
      * notification.
      *
      * <p>
+     * The {@link #EXTRA_PHONE_ACCOUNT_HANDLE} extra indicates which {@link PhoneAccountHandle} the
+     * voicemail is received on.
      * The {@link #EXTRA_NOTIFICATION_COUNT} extra indicates the total numbers of unheard
      * voicemails.
      * The {@link #EXTRA_VOICEMAIL_NUMBER} extra indicates the voicemail number if available.
@@ -743,6 +755,7 @@
      * {@link android.app.PendingIntent} that will launch the voicemail settings. This extra is only
      * available when the voicemail number is not set.
      *
+     * @see #EXTRA_PHONE_ACCOUNT_HANDLE
      * @see #EXTRA_NOTIFICATION_COUNT
      * @see #EXTRA_VOICEMAIL_NUMBER
      * @see #EXTRA_CALL_VOICEMAIL_INTENT
@@ -752,6 +765,15 @@
             "android.telephony.action.SHOW_VOICEMAIL_NOTIFICATION";
 
     /**
+     * The extra used with an {@link #ACTION_SHOW_VOICEMAIL_NOTIFICATION} {@code Intent} to specify
+     * the {@link PhoneAccountHandle} the notification is for.
+     * <p class="note">
+     * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}.
+     */
+    public static final String EXTRA_PHONE_ACCOUNT_HANDLE =
+            "android.telephony.extra.PHONE_ACCOUNT_HANDLE";
+
+    /**
      * The number of voice messages associated with the notification.
      */
     public static final String EXTRA_NOTIFICATION_COUNT =
@@ -819,6 +841,21 @@
     public static final String EVENT_DOWNGRADE_DATA_DISABLED =
             "android.telephony.event.EVENT_DOWNGRADE_DATA_DISABLED";
 
+    /**
+     * {@link android.telecom.Connection} event used to indicate that the InCall UI should notify
+     * the user when an international call is placed while on WFC only.
+     * <p>
+     * Used when the carrier config value
+     * {@link CarrierConfigManager#KEY_NOTIFY_INTERNATIONAL_CALL_ON_WFC_BOOL} is true, the device
+     * is on WFC (VoLTE not available) and an international number is dialed.
+     * <p>
+     * Sent via {@link android.telecom.Connection#sendConnectionEvent(String, Bundle)}.
+     * The {@link Bundle} parameter is expected to be null when this connection event is used.
+     * @hide
+     */
+    public static final String EVENT_NOTIFY_INTERNATIONAL_CALL_ON_WFC =
+            "android.telephony.event.EVENT_NOTIFY_INTERNATIONAL_CALL_ON_WFC";
+
     /* Visual voicemail protocols */
 
     /**
@@ -4026,9 +4063,8 @@
             }
         }
 
-        if (property.length() > SystemProperties.PROP_NAME_MAX
-                || propVal.length() > SystemProperties.PROP_VALUE_MAX) {
-            Rlog.d(TAG, "setTelephonyProperty: property to long phoneId=" + phoneId +
+        if (propVal.length() > SystemProperties.PROP_VALUE_MAX) {
+            Rlog.d(TAG, "setTelephonyProperty: property too long phoneId=" + phoneId +
                     " property=" + property + " value: " + value + " propVal=" + propVal);
             return;
         }
@@ -4285,6 +4321,45 @@
     }
 
     /**
+     * Returns an array of Forbidden PLMNs from the USIM App
+     * Returns null if the query fails.
+     *
+     *
+     * <p>Requires that the caller has READ_PRIVILEGED_PHONE_STATE
+     *
+     * @return an array of forbidden PLMNs or null if not available
+     */
+    public String[] getForbiddenPlmns() {
+      return getForbiddenPlmns(getSubId(), APPTYPE_USIM);
+    }
+
+    /**
+     * Returns an array of Forbidden PLMNs from the specified SIM App
+     * Returns null if the query fails.
+     *
+     *
+     * <p>Requires that the calling app has READ_PRIVILEGED_PHONE_STATE
+     *
+     * @param subId subscription ID used for authentication
+     * @param appType the icc application type, like {@link #APPTYPE_USIM}
+     * @return fplmns an array of forbidden PLMNs
+     * @hide
+     */
+    public String[] getForbiddenPlmns(int subId, int appType) {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony == null)
+                return null;
+            return telephony.getForbiddenPlmns(subId, appType);
+        } catch (RemoteException ex) {
+            return null;
+        } catch (NullPointerException ex) {
+            // This could happen before phone starts
+            return null;
+        }
+    }
+
+    /**
      * Get P-CSCF address from PCO after data connection is established or modified.
      * @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN
      * @return array of P-CSCF address
@@ -5229,7 +5304,9 @@
      *         0 request was handled succesfully, but no response data
      *         positive value success, data length of response
      * @hide
+     * @deprecated OEM needs a vendor-extension hal and their apps should use that instead
      */
+    @Deprecated
     public int invokeOemRilRequestRaw(byte[] oemReq, byte[] oemResp) {
         try {
             ITelephony telephony = getITelephony();
@@ -5522,6 +5599,44 @@
     }
 
     /**
+     * Set SIM card power state. Request is equivalent to inserting or removing the card.
+     *
+     * @param powerUp True if powering up the SIM, otherwise powering down
+     *
+     * <p>Requires Permission:
+     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+     *
+     * @hide
+     **/
+    public void setSimPowerState(boolean powerUp) {
+        setSimPowerStateForSlot(getDefaultSim(), powerUp);
+    }
+
+    /**
+     * Set SIM card power state. Request is equivalent to inserting or removing the card.
+     *
+     * @param slotId SIM slot id
+     * @param powerUp True if powering up the SIM, otherwise powering down
+     *
+     * <p>Requires Permission:
+     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+     *
+     * @hide
+     **/
+    public void setSimPowerStateForSlot(int slotId, boolean powerUp) {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                telephony.setSimPowerStateForSlot(slotId, powerUp);
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling ITelephony#setSimPowerStateForSlot", e);
+        } catch (SecurityException e) {
+            Log.e(TAG, "Permission error calling ITelephony#setSimPowerStateForSlot", e);
+        }
+    }
+
+    /**
      * Set baseband version for the default phone.
      *
      * @param version baseband version
@@ -6106,7 +6221,7 @@
      * android.content.pm.PackageManager#FEATURE_TELEPHONY_CARRIERLOCK} enabled.
      *
      * @return The number of carriers set successfully. Should be length of
-     * carrierList on success; -1 on error.
+     * carrierList on success; -1 if carrierList null or on error.
      * @hide
      */
     @SystemApi
diff --git a/telephony/java/android/telephony/VisualVoicemailService.java b/telephony/java/android/telephony/VisualVoicemailService.java
index 84833e3..e211f76 100644
--- a/telephony/java/android/telephony/VisualVoicemailService.java
+++ b/telephony/java/android/telephony/VisualVoicemailService.java
@@ -41,6 +41,10 @@
  * the SMS filtering chain and may intercept the visual voicemail SMS before it reaches this
  * service.
  * <p>
+ * To extend this class, The service must be declared in the manifest file with
+ * the {@link android.Manifest.permission#BIND_VISUAL_VOICEMAIL_SERVICE} permission and include an
+ * intent filter with the {@link #SERVICE_INTERFACE} action.
+ * <p>
  * Below is an example manifest registration for a {@code VisualVoicemailService}.
  * <pre>
  * {@code
@@ -260,6 +264,9 @@
      * @param port The destination port for data SMS, or 0 for text SMS.
      * @param text The message content. For data sms, it will be encoded as a UTF-8 byte stream.
      * @param sentIntent The sent intent passed to the {@link SmsManager}
+     *
+     * @throws SecurityException if the caller is not the current default dialer
+     *
      * @see SmsManager#sendDataMessage(String, String, short, byte[], PendingIntent, PendingIntent)
      * @see SmsManager#sendTextMessage(String, String, String, PendingIntent, PendingIntent)
      */
diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java
index 0f865a8..f1f683c 100644
--- a/telephony/java/android/telephony/ims/ImsService.java
+++ b/telephony/java/android/telephony/ims/ImsService.java
@@ -18,6 +18,7 @@
 
 import android.app.PendingIntent;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.os.IBinder;
 import android.os.Message;
 import android.os.RemoteException;
@@ -41,6 +42,10 @@
 import com.android.ims.internal.IImsUt;
 import com.android.internal.annotations.VisibleForTesting;
 
+import static android.Manifest.permission.MODIFY_PHONE_STATE;
+import static android.Manifest.permission.READ_PHONE_STATE;
+import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE;
+
 /**
  * Main ImsService implementation, which binds via the Telephony ImsResolver. Services that extend
  * ImsService must register the service in their AndroidManifest to be detected by the framework.
@@ -94,6 +99,7 @@
         public void createImsFeature(int slotId, int feature, IImsFeatureStatusCallback c)
                 throws RemoteException {
             synchronized (mFeatures) {
+                enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, "createImsFeature");
                 onCreateImsFeatureInternal(slotId, feature, c);
             }
         }
@@ -101,6 +107,7 @@
         @Override
         public void removeImsFeature(int slotId, int feature) throws RemoteException {
             synchronized (mFeatures) {
+                enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, "removeImsFeature");
                 onRemoveImsFeatureInternal(slotId, feature);
             }
         }
@@ -108,6 +115,7 @@
         @Override
         public int startSession(int slotId, int featureType, PendingIntent incomingCallIntent,
                 IImsRegistrationListener listener) throws RemoteException {
+            enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, "startSession");
             synchronized (mFeatures) {
                 MMTelFeature feature = resolveMMTelFeature(slotId, featureType);
                 if (feature != null) {
@@ -120,6 +128,7 @@
         @Override
         public void endSession(int slotId, int featureType, int sessionId) throws RemoteException {
             synchronized (mFeatures) {
+                enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, "endSession");
                 MMTelFeature feature = resolveMMTelFeature(slotId, featureType);
                 if (feature != null) {
                     feature.endSession(sessionId);
@@ -128,23 +137,25 @@
         }
 
         @Override
-        public boolean isConnected(int slotId, int featureType, int sessionId, int callSessionType,
-                int callType) throws RemoteException {
+        public boolean isConnected(int slotId, int featureType, int callSessionType, int callType)
+                throws RemoteException {
+            enforceReadPhoneStatePermission("isConnected");
             synchronized (mFeatures) {
                 MMTelFeature feature = resolveMMTelFeature(slotId, featureType);
                 if (feature != null) {
-                    return feature.isConnected(sessionId, callSessionType, callType);
+                    return feature.isConnected(callSessionType, callType);
                 }
             }
             return false;
         }
 
         @Override
-        public boolean isOpened(int slotId, int featureType, int sessionId) throws RemoteException {
+        public boolean isOpened(int slotId, int featureType) throws RemoteException {
+            enforceReadPhoneStatePermission("isOpened");
             synchronized (mFeatures) {
                 MMTelFeature feature = resolveMMTelFeature(slotId, featureType);
                 if (feature != null) {
-                    return feature.isOpened(sessionId);
+                    return feature.isOpened();
                 }
             }
             return false;
@@ -152,6 +163,7 @@
 
         @Override
         public int getFeatureStatus(int slotId, int featureType) throws RemoteException {
+            enforceReadPhoneStatePermission("getFeatureStatus");
             int status = ImsFeature.STATE_NOT_AVAILABLE;
             synchronized (mFeatures) {
                 SparseArray<ImsFeature> featureMap = mFeatures.get(slotId);
@@ -166,23 +178,25 @@
         }
 
         @Override
-        public void addRegistrationListener(int slotId, int featureType, int sessionId,
+        public void addRegistrationListener(int slotId, int featureType,
                 IImsRegistrationListener listener) throws RemoteException {
+            enforceReadPhoneStatePermission("addRegistrationListener");
             synchronized (mFeatures) {
                 MMTelFeature feature = resolveMMTelFeature(slotId, featureType);
                 if (feature != null) {
-                    feature.addRegistrationListener(sessionId, listener);
+                    feature.addRegistrationListener(listener);
                 }
             }
         }
 
         @Override
-        public void removeRegistrationListener(int slotId, int featureType, int sessionId,
+        public void removeRegistrationListener(int slotId, int featureType,
                 IImsRegistrationListener listener) throws RemoteException {
+            enforceReadPhoneStatePermission("removeRegistrationListener");
             synchronized (mFeatures) {
                 MMTelFeature feature = resolveMMTelFeature(slotId, featureType);
                 if (feature != null) {
-                    feature.removeRegistrationListener(sessionId, listener);
+                    feature.removeRegistrationListener(listener);
                 }
             }
         }
@@ -190,6 +204,7 @@
         @Override
         public ImsCallProfile createCallProfile(int slotId, int featureType, int sessionId,
                 int callSessionType, int callType) throws RemoteException {
+            enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, "createCallProfile");
             synchronized (mFeatures) {
                 MMTelFeature feature = resolveMMTelFeature(slotId, featureType);
                 if (feature != null) {
@@ -202,6 +217,7 @@
         @Override
         public IImsCallSession createCallSession(int slotId, int featureType, int sessionId,
                 ImsCallProfile profile, IImsCallSessionListener listener) throws RemoteException {
+            enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, "createCallSession");
             synchronized (mFeatures) {
                 MMTelFeature feature = resolveMMTelFeature(slotId, featureType);
                 if (feature != null) {
@@ -214,6 +230,7 @@
         @Override
         public IImsCallSession getPendingCallSession(int slotId, int featureType, int sessionId,
                 String callId) throws RemoteException {
+            enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, "getPendingCallSession");
             synchronized (mFeatures) {
                 MMTelFeature feature = resolveMMTelFeature(slotId, featureType);
                 if (feature != null) {
@@ -224,79 +241,86 @@
         }
 
         @Override
-        public IImsUt getUtInterface(int slotId, int featureType, int sessionId)
+        public IImsUt getUtInterface(int slotId, int featureType)
                 throws RemoteException {
+            enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, "getUtInterface");
             synchronized (mFeatures) {
                 MMTelFeature feature = resolveMMTelFeature(slotId, featureType);
                 if (feature != null) {
-                    return feature.getUtInterface(sessionId);
+                    return feature.getUtInterface();
                 }
             }
             return null;
         }
 
         @Override
-        public IImsConfig getConfigInterface(int slotId, int featureType, int sessionId)
+        public IImsConfig getConfigInterface(int slotId, int featureType)
                 throws RemoteException {
+            enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, "getConfigInterface");
             synchronized (mFeatures) {
                 MMTelFeature feature = resolveMMTelFeature(slotId, featureType);
                 if (feature != null) {
-                    return feature.getConfigInterface(sessionId);
+                    return feature.getConfigInterface();
                 }
             }
             return null;
         }
 
         @Override
-        public void turnOnIms(int slotId, int featureType, int sessionId) throws RemoteException {
+        public void turnOnIms(int slotId, int featureType) throws RemoteException {
+            enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, "turnOnIms");
             synchronized (mFeatures) {
                 MMTelFeature feature = resolveMMTelFeature(slotId, featureType);
                 if (feature != null) {
-                    feature.turnOnIms(sessionId);
+                    feature.turnOnIms();
                 }
             }
         }
 
         @Override
-        public void turnOffIms(int slotId, int featureType, int sessionId) throws RemoteException {
+        public void turnOffIms(int slotId, int featureType) throws RemoteException {
+            enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, "turnOffIms");
             synchronized (mFeatures) {
                 MMTelFeature feature = resolveMMTelFeature(slotId, featureType);
                 if (feature != null) {
-                    feature.turnOffIms(sessionId);
+                    feature.turnOffIms();
                 }
             }
         }
 
         @Override
-        public IImsEcbm getEcbmInterface(int slotId, int featureType, int sessionId)
+        public IImsEcbm getEcbmInterface(int slotId, int featureType)
                 throws RemoteException {
+            enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, "getEcbmInterface");
             synchronized (mFeatures) {
                 MMTelFeature feature = resolveMMTelFeature(slotId, featureType);
                 if (feature != null) {
-                    return feature.getEcbmInterface(sessionId);
+                    return feature.getEcbmInterface();
                 }
             }
             return null;
         }
 
         @Override
-        public void setUiTTYMode(int slotId, int featureType, int sessionId, int uiTtyMode,
-                Message onComplete) throws RemoteException {
+        public void setUiTTYMode(int slotId, int featureType, int uiTtyMode, Message onComplete)
+                throws RemoteException {
+            enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, "setUiTTYMode");
             synchronized (mFeatures) {
                 MMTelFeature feature = resolveMMTelFeature(slotId, featureType);
                 if (feature != null) {
-                    feature.setUiTTYMode(sessionId, uiTtyMode, onComplete);
+                    feature.setUiTTYMode(uiTtyMode, onComplete);
                 }
             }
         }
 
         @Override
-        public IImsMultiEndpoint getMultiEndpointInterface(int slotId, int featureType,
-                int sessionId) throws RemoteException {
+        public IImsMultiEndpoint getMultiEndpointInterface(int slotId, int featureType)
+                throws RemoteException {
+            enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, "getMultiEndpointInterface");
             synchronized (mFeatures) {
                 MMTelFeature feature = resolveMMTelFeature(slotId, featureType);
                 if (feature != null) {
-                    return feature.getMultiEndpointInterface(sessionId);
+                    return feature.getMultiEndpointInterface();
                 }
             }
             return null;
@@ -329,6 +353,8 @@
         }
         ImsFeature f = makeImsFeature(slotId, featureType);
         if (f != null) {
+            f.setContext(this);
+            f.setSlotId(slotId);
             f.setImsFeatureStatusCallback(c);
             featureMap.put(featureType, f);
         }
@@ -412,6 +438,17 @@
     }
 
     /**
+     * Check for both READ_PHONE_STATE and READ_PRIVILEGED_PHONE_STATE. READ_PHONE_STATE is a
+     * public permission and READ_PRIVILEGED_PHONE_STATE is only granted to system apps.
+     */
+    private void enforceReadPhoneStatePermission(String fn) {
+        if (checkCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE)
+                != PackageManager.PERMISSION_GRANTED) {
+            enforceCallingOrSelfPermission(READ_PHONE_STATE, fn);
+        }
+    }
+
+    /**
      * @return An implementation of MMTelFeature that will be used by the system for MMTel
      * functionality. Must be able to handle emergency calls at any time as well.
      */
diff --git a/telephony/java/android/telephony/ims/ImsServiceBase.java b/telephony/java/android/telephony/ims/ImsServiceBase.java
index 0878db8..bb36862 100644
--- a/telephony/java/android/telephony/ims/ImsServiceBase.java
+++ b/telephony/java/android/telephony/ims/ImsServiceBase.java
@@ -19,6 +19,7 @@
 import android.annotation.SystemApi;
 import android.app.Service;
 import android.content.Intent;
+import android.os.Binder;
 import android.os.IBinder;
 
 /**
@@ -30,8 +31,15 @@
 @SystemApi
 public class ImsServiceBase extends Service {
 
+    /**
+     * Binder connection that does nothing but keep the connection between this Service and the
+     * framework active. If this service crashes, the framework will be notified.
+     */
+    private IBinder mConnection = new Binder();
+
     @Override
     public IBinder onBind(Intent intent) {
-        return null;
+        return mConnection;
     }
+
 }
diff --git a/telephony/java/android/telephony/ims/ImsServiceProxy.java b/telephony/java/android/telephony/ims/ImsServiceProxy.java
index b2cdba2..38ea6e6f 100644
--- a/telephony/java/android/telephony/ims/ImsServiceProxy.java
+++ b/telephony/java/android/telephony/ims/ImsServiceProxy.java
@@ -135,40 +135,40 @@
     }
 
     @Override
-    public boolean isConnected(int sessionId, int callServiceType, int callType)
+    public boolean isConnected(int callServiceType, int callType)
             throws RemoteException {
         synchronized (mLock) {
             checkBinderConnection();
-            return getServiceInterface(mBinder).isConnected(mSlotId, mSupportedFeature, sessionId,
+            return getServiceInterface(mBinder).isConnected(mSlotId, mSupportedFeature,
                     callServiceType, callType);
         }
     }
 
     @Override
-    public boolean isOpened(int sessionId) throws RemoteException {
+    public boolean isOpened() throws RemoteException {
         synchronized (mLock) {
             checkBinderConnection();
-            return getServiceInterface(mBinder).isOpened(mSlotId, mSupportedFeature, sessionId);
+            return getServiceInterface(mBinder).isOpened(mSlotId, mSupportedFeature);
         }
     }
 
     @Override
-    public void addRegistrationListener(int sessionId, IImsRegistrationListener listener)
+    public void addRegistrationListener(IImsRegistrationListener listener)
     throws RemoteException {
         synchronized (mLock) {
             checkBinderConnection();
             getServiceInterface(mBinder).addRegistrationListener(mSlotId, mSupportedFeature,
-                    sessionId, listener);
+                    listener);
         }
     }
 
     @Override
-    public void removeRegistrationListener(int sessionId, IImsRegistrationListener listener)
+    public void removeRegistrationListener(IImsRegistrationListener listener)
             throws RemoteException {
         synchronized (mLock) {
             checkBinderConnection();
             getServiceInterface(mBinder).removeRegistrationListener(mSlotId, mSupportedFeature,
-                    sessionId, listener);
+                    listener);
         }
     }
 
@@ -203,64 +203,61 @@
     }
 
     @Override
-    public IImsUt getUtInterface(int sessionId) throws RemoteException {
+    public IImsUt getUtInterface() throws RemoteException {
         synchronized (mLock) {
             checkBinderConnection();
-            return getServiceInterface(mBinder).getUtInterface(mSlotId, mSupportedFeature,
-                    sessionId);
+            return getServiceInterface(mBinder).getUtInterface(mSlotId, mSupportedFeature);
         }
     }
 
     @Override
-    public IImsConfig getConfigInterface(int sessionId) throws RemoteException {
+    public IImsConfig getConfigInterface() throws RemoteException {
         synchronized (mLock) {
             checkBinderConnection();
-            return getServiceInterface(mBinder).getConfigInterface(mSlotId, mSupportedFeature,
-                    sessionId);
+            return getServiceInterface(mBinder).getConfigInterface(mSlotId, mSupportedFeature);
         }
     }
 
     @Override
-    public void turnOnIms(int sessionId) throws RemoteException {
+    public void turnOnIms() throws RemoteException {
         synchronized (mLock) {
             checkBinderConnection();
-            getServiceInterface(mBinder).turnOnIms(mSlotId, mSupportedFeature, sessionId);
+            getServiceInterface(mBinder).turnOnIms(mSlotId, mSupportedFeature);
         }
     }
 
     @Override
-    public void turnOffIms(int sessionId) throws RemoteException {
+    public void turnOffIms() throws RemoteException {
         synchronized (mLock) {
             checkBinderConnection();
-            getServiceInterface(mBinder).turnOffIms(mSlotId, mSupportedFeature, sessionId);
+            getServiceInterface(mBinder).turnOffIms(mSlotId, mSupportedFeature);
         }
     }
 
     @Override
-    public IImsEcbm getEcbmInterface(int sessionId) throws RemoteException {
+    public IImsEcbm getEcbmInterface() throws RemoteException {
         synchronized (mLock) {
             checkBinderConnection();
-            return getServiceInterface(mBinder).getEcbmInterface(mSlotId, mSupportedFeature,
-                    sessionId);
+            return getServiceInterface(mBinder).getEcbmInterface(mSlotId, mSupportedFeature);
         }
     }
 
     @Override
-    public void setUiTTYMode(int sessionId, int uiTtyMode, Message onComplete)
+    public void setUiTTYMode(int uiTtyMode, Message onComplete)
             throws RemoteException {
         synchronized (mLock) {
             checkBinderConnection();
-            getServiceInterface(mBinder).setUiTTYMode(mSlotId, mSupportedFeature, sessionId,
-                    uiTtyMode, onComplete);
+            getServiceInterface(mBinder).setUiTTYMode(mSlotId, mSupportedFeature, uiTtyMode,
+                    onComplete);
         }
     }
 
     @Override
-    public IImsMultiEndpoint getMultiEndpointInterface(int sessionId) throws RemoteException {
+    public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException {
         synchronized (mLock) {
             checkBinderConnection();
             return getServiceInterface(mBinder).getMultiEndpointInterface(mSlotId,
-                    mSupportedFeature, sessionId);
+                    mSupportedFeature);
         }
     }
 
diff --git a/telephony/java/android/telephony/ims/ImsServiceProxyCompat.java b/telephony/java/android/telephony/ims/ImsServiceProxyCompat.java
index ff53858..bbd5f02 100644
--- a/telephony/java/android/telephony/ims/ImsServiceProxyCompat.java
+++ b/telephony/java/android/telephony/ims/ImsServiceProxyCompat.java
@@ -42,6 +42,8 @@
 
 public class ImsServiceProxyCompat implements IMMTelFeature {
 
+    private static final int SERVICE_ID = ImsFeature.MMTEL;
+
     protected final int mSlotId;
     protected IBinder mBinder;
 
@@ -65,29 +67,28 @@
     }
 
     @Override
-    public boolean isConnected(int sessionId, int callServiceType, int callType)
+    public boolean isConnected(int callServiceType, int callType)
             throws RemoteException {
         checkBinderConnection();
-        return getServiceInterface(mBinder).isConnected(sessionId,  callServiceType, callType);
+        return getServiceInterface(mBinder).isConnected(SERVICE_ID,  callServiceType, callType);
     }
 
     @Override
-    public boolean isOpened(int sessionId) throws RemoteException {
+    public boolean isOpened() throws RemoteException {
         checkBinderConnection();
-        return getServiceInterface(mBinder).isOpened(sessionId);
+        return getServiceInterface(mBinder).isOpened(SERVICE_ID);
     }
 
     @Override
-    public void addRegistrationListener(int sessionId, IImsRegistrationListener listener)
+    public void addRegistrationListener(IImsRegistrationListener listener)
             throws RemoteException {
         checkBinderConnection();
         getServiceInterface(mBinder).addRegistrationListener(mSlotId, ImsFeature.MMTEL, listener);
     }
 
     @Override
-    public void removeRegistrationListener(int sessionId, IImsRegistrationListener listener)
+    public void removeRegistrationListener(IImsRegistrationListener listener)
             throws RemoteException {
-        checkBinderConnection();
         // Not Implemented in old ImsService. If the registration listener becomes invalid, the
         // ImsService will remove.
     }
@@ -114,46 +115,46 @@
     }
 
     @Override
-    public IImsUt getUtInterface(int sessionId) throws RemoteException {
+    public IImsUt getUtInterface() throws RemoteException {
         checkBinderConnection();
-        return getServiceInterface(mBinder).getUtInterface(sessionId);
+        return getServiceInterface(mBinder).getUtInterface(SERVICE_ID);
     }
 
     @Override
-    public IImsConfig getConfigInterface(int sessionId) throws RemoteException {
+    public IImsConfig getConfigInterface() throws RemoteException {
         checkBinderConnection();
         return getServiceInterface(mBinder).getConfigInterface(mSlotId);
     }
 
     @Override
-    public void turnOnIms(int sessionId) throws RemoteException {
+    public void turnOnIms() throws RemoteException {
         checkBinderConnection();
         getServiceInterface(mBinder).turnOnIms(mSlotId);
     }
 
     @Override
-    public void turnOffIms(int sessionId) throws RemoteException {
+    public void turnOffIms() throws RemoteException {
         checkBinderConnection();
         getServiceInterface(mBinder).turnOffIms(mSlotId);
     }
 
     @Override
-    public IImsEcbm getEcbmInterface(int sessionId) throws RemoteException {
+    public IImsEcbm getEcbmInterface() throws RemoteException {
         checkBinderConnection();
-        return getServiceInterface(mBinder).getEcbmInterface(sessionId);
+        return getServiceInterface(mBinder).getEcbmInterface(SERVICE_ID);
     }
 
     @Override
-    public void setUiTTYMode(int sessionId, int uiTtyMode, Message onComplete)
+    public void setUiTTYMode(int uiTtyMode, Message onComplete)
             throws RemoteException {
         checkBinderConnection();
-        getServiceInterface(mBinder).setUiTTYMode(sessionId, uiTtyMode, onComplete);
+        getServiceInterface(mBinder).setUiTTYMode(SERVICE_ID, uiTtyMode, onComplete);
     }
 
     @Override
-    public IImsMultiEndpoint getMultiEndpointInterface(int sessionId) throws RemoteException {
+    public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException {
         checkBinderConnection();
-        return getServiceInterface(mBinder).getMultiEndpointInterface(sessionId);
+        return getServiceInterface(mBinder).getMultiEndpointInterface(SERVICE_ID);
     }
 
     /**
diff --git a/telephony/java/android/telephony/ims/feature/IMMTelFeature.java b/telephony/java/android/telephony/ims/feature/IMMTelFeature.java
index e180843..d65e27e 100644
--- a/telephony/java/android/telephony/ims/feature/IMMTelFeature.java
+++ b/telephony/java/android/telephony/ims/feature/IMMTelFeature.java
@@ -68,7 +68,6 @@
      * Checks if the IMS service has successfully registered to the IMS network with the specified
      * service & call type.
      *
-     * @param sessionId a session id which is obtained from {@link #startSession}
      * @param callServiceType a service type that is specified in {@link ImsCallProfile}
      *        {@link ImsCallProfile#SERVICE_TYPE_NORMAL}
      *        {@link ImsCallProfile#SERVICE_TYPE_EMERGENCY}
@@ -80,31 +79,28 @@
      * @return true if the specified service id is connected to the IMS network; false otherwise
      * @throws RemoteException
      */
-    boolean isConnected(int sessionId, int callServiceType, int callType) throws RemoteException;
+    boolean isConnected(int callServiceType, int callType) throws RemoteException;
 
     /**
      * Checks if the specified IMS service is opened.
      *
-     * @param sessionId a service id which is obtained from {@link #startSession}
      * @return true if the specified service id is opened; false otherwise
      */
-    boolean isOpened(int sessionId) throws RemoteException;
+    boolean isOpened() throws RemoteException;
 
     /**
      * Add a new registration listener for the client associated with the session Id.
-     * @param sessionId a session id which is obtained from {@link #startSession}
      * @param listener An implementation of IImsRegistrationListener.
      */
-    void addRegistrationListener(int sessionId, IImsRegistrationListener listener)
+    void addRegistrationListener(IImsRegistrationListener listener)
             throws RemoteException;
 
     /**
      * Remove a previously registered listener using {@link #addRegistrationListener} for the client
      * associated with the session Id.
-     * @param sessionId a session id which is obtained from {@link #startSession}
      * @param listener A previously registered IImsRegistrationListener
      */
-    void removeRegistrationListener(int sessionId, IImsRegistrationListener listener)
+    void removeRegistrationListener(IImsRegistrationListener listener)
             throws RemoteException;
 
     /**
@@ -152,41 +148,40 @@
     /**
      * @return The Ut interface for the supplementary service configuration.
      */
-    IImsUt getUtInterface(int sessionId) throws RemoteException;
+    IImsUt getUtInterface() throws RemoteException;
 
     /**
      * @return The config interface for IMS Configuration
      */
-    IImsConfig getConfigInterface(int sessionId) throws RemoteException;
+    IImsConfig getConfigInterface() throws RemoteException;
 
     /**
      * Signal the MMTelFeature to turn on IMS when it has been turned off using {@link #turnOffIms}
      * @param sessionId a session id which is obtained from {@link #startSession}
      */
-    void turnOnIms(int sessionId) throws RemoteException;
+    void turnOnIms() throws RemoteException;
 
     /**
      * Signal the MMTelFeature to turn off IMS when it has been turned on using {@link #turnOnIms}
      * @param sessionId a session id which is obtained from {@link #startSession}
      */
-    void turnOffIms(int sessionId) throws RemoteException;
+    void turnOffIms() throws RemoteException;
 
     /**
      * @return The Emergency call-back mode interface for emergency VoLTE calls that support it.
      */
-    IImsEcbm getEcbmInterface(int sessionId) throws RemoteException;
+    IImsEcbm getEcbmInterface() throws RemoteException;
 
     /**
      * Sets the current UI TTY mode for the MMTelFeature.
-     * @param sessionId a session id which is obtained from {@link #startSession}
      * @param uiTtyMode An integer containing the new UI TTY Mode.
      * @param onComplete A {@link Message} to be used when the mode has been set.
      * @throws RemoteException
      */
-    void setUiTTYMode(int sessionId, int uiTtyMode, Message onComplete) throws RemoteException;
+    void setUiTTYMode(int uiTtyMode, Message onComplete) throws RemoteException;
 
     /**
      * @return MultiEndpoint interface for DEP notifications
      */
-    IImsMultiEndpoint getMultiEndpointInterface(int sessionId) throws RemoteException;
+    IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException;
 }
diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java
index 8d7d260..988dd58 100644
--- a/telephony/java/android/telephony/ims/feature/ImsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java
@@ -17,7 +17,10 @@
 package android.telephony.ims.feature;
 
 import android.annotation.IntDef;
+import android.content.Context;
+import android.content.Intent;
 import android.os.RemoteException;
+import android.telephony.SubscriptionManager;
 import android.util.Log;
 
 import com.android.ims.internal.IImsFeatureStatusCallback;
@@ -35,6 +38,32 @@
 
     private static final String LOG_TAG = "ImsFeature";
 
+    /**
+     * Action to broadcast when ImsService is up.
+     * Internal use only.
+     * Only defined here separately compatibility purposes with the old ImsService.
+     * @hide
+     */
+    public static final String ACTION_IMS_SERVICE_UP =
+            "com.android.ims.IMS_SERVICE_UP";
+
+    /**
+     * Action to broadcast when ImsService is down.
+     * Internal use only.
+     * Only defined here separately for compatibility purposes with the old ImsService.
+     * @hide
+     */
+    public static final String ACTION_IMS_SERVICE_DOWN =
+            "com.android.ims.IMS_SERVICE_DOWN";
+
+    /**
+     * Part of the ACTION_IMS_SERVICE_UP or _DOWN intents.
+     * A long value; the phone ID corresponding to the IMS service coming up or down.
+     * Only defined here separately for compatibility purposes with the old ImsService.
+     * @hide
+     */
+    public static final String EXTRA_PHONE_ID = "android:phone_id";
+
     // Invalid feature value
     public static final int INVALID = -1;
     // ImsFeatures that are defined in the Manifests. Ensure that these values match the previously
@@ -61,11 +90,21 @@
     private List<INotifyFeatureRemoved> mRemovedListeners = new ArrayList<>();
     private IImsFeatureStatusCallback mStatusCallback;
     private @ImsState int mState = STATE_NOT_AVAILABLE;
+    private int mSlotId = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
+    private Context mContext;
 
     public interface INotifyFeatureRemoved {
         void onFeatureRemoved(int slotId);
     }
 
+    public void setContext(Context context) {
+        mContext = context;
+    }
+
+    public void setSlotId(int slotId) {
+        mSlotId = slotId;
+    }
+
     public void addFeatureRemovedListener(INotifyFeatureRemoved listener) {
         synchronized (mRemovedListeners) {
             mRemovedListeners.add(listener);
@@ -118,6 +157,30 @@
                 Log.w(LOG_TAG, "Couldn't notify feature state: " + e.getMessage());
             }
         }
+        sendImsServiceIntent(state);
+    }
+
+    /**
+     * Provide backwards compatibility using deprecated service UP/DOWN intents.
+     */
+    private void sendImsServiceIntent(@ImsState int state) {
+        if(mContext == null || mSlotId == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
+            return;
+        }
+        Intent intent;
+        switch (state) {
+            case ImsFeature.STATE_NOT_AVAILABLE:
+            case ImsFeature.STATE_INITIALIZING:
+                intent = new Intent(ACTION_IMS_SERVICE_DOWN);
+                break;
+            case ImsFeature.STATE_READY:
+                intent = new Intent(ACTION_IMS_SERVICE_UP);
+                break;
+            default:
+                intent = new Intent(ACTION_IMS_SERVICE_DOWN);
+        }
+        intent.putExtra(EXTRA_PHONE_ID, mSlotId);
+        mContext.sendBroadcast(intent);
     }
 
     /**
diff --git a/telephony/java/android/telephony/ims/feature/MMTelFeature.java b/telephony/java/android/telephony/ims/feature/MMTelFeature.java
index 570cd65..a71f0bf 100644
--- a/telephony/java/android/telephony/ims/feature/MMTelFeature.java
+++ b/telephony/java/android/telephony/ims/feature/MMTelFeature.java
@@ -50,21 +50,21 @@
     }
 
     @Override
-    public boolean isConnected(int sessionId, int callSessionType, int callType) {
+    public boolean isConnected(int callSessionType, int callType) {
         return false;
     }
 
     @Override
-    public boolean isOpened(int sessionId) {
+    public boolean isOpened() {
         return false;
     }
 
     @Override
-    public void addRegistrationListener(int sessionId, IImsRegistrationListener listener) {
+    public void addRegistrationListener(IImsRegistrationListener listener) {
     }
 
     @Override
-    public void removeRegistrationListener(int sessionId, IImsRegistrationListener listener) {
+    public void removeRegistrationListener(IImsRegistrationListener listener) {
     }
 
     @Override
@@ -84,34 +84,34 @@
     }
 
     @Override
-    public IImsUt getUtInterface(int sessionId) {
+    public IImsUt getUtInterface() {
         return null;
     }
 
     @Override
-    public IImsConfig getConfigInterface(int sessionId) {
+    public IImsConfig getConfigInterface() {
         return null;
     }
 
     @Override
-    public void turnOnIms(int sessionId) {
+    public void turnOnIms() {
     }
 
     @Override
-    public void turnOffIms(int sessionId) {
+    public void turnOffIms() {
     }
 
     @Override
-    public IImsEcbm getEcbmInterface(int sessionId) {
+    public IImsEcbm getEcbmInterface() {
         return null;
     }
 
     @Override
-    public void setUiTTYMode(int sessionId, int uiTtyMode, Message onComplete) {
+    public void setUiTTYMode(int uiTtyMode, Message onComplete) {
     }
 
     @Override
-    public IImsMultiEndpoint getMultiEndpointInterface(int sessionId) {
+    public IImsMultiEndpoint getMultiEndpointInterface() {
         return null;
     }
 
diff --git a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
new file mode 100644
index 0000000..69b8acc
--- /dev/null
+++ b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
@@ -0,0 +1,348 @@
+/*
+ * 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 android.telephony.ims.stub;
+
+import android.os.Message;
+import android.os.RemoteException;
+
+import com.android.ims.ImsCallProfile;
+import com.android.ims.ImsStreamMediaProfile;
+import com.android.ims.internal.ImsCallSession;
+import com.android.ims.internal.IImsCallSession;
+import com.android.ims.internal.IImsCallSessionListener;
+import com.android.ims.internal.IImsVideoCallProvider;
+
+/**
+ * Base implementation of IImsCallSession, which implements stub versions of the methods in the
+ * IImsCallSession AIDL. Override the methods that your implementation of ImsCallSession supports.
+ *
+ * DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
+ * will break other implementations of ImsCallSession maintained by other ImsServices.
+ *
+ * @hide
+ */
+
+public class ImsCallSessionImplBase extends IImsCallSession.Stub {
+
+    /**
+     * Closes the object. This object is not usable after being closed.
+     */
+    @Override
+    public void close() throws RemoteException {
+
+    }
+
+    /**
+     * Gets the call ID of the session.
+     *
+     * @return the call ID
+     */
+    @Override
+    public String getCallId() throws RemoteException {
+        return null;
+    }
+
+    /**
+     * Gets the call profile that this session is associated with
+     *
+     * @return the {@link ImsCallProfile} that this session is associated with
+     */
+    @Override
+    public ImsCallProfile getCallProfile() throws RemoteException {
+        return null;
+    }
+
+    /**
+     * Gets the local call profile that this session is associated with
+     *
+     * @return the local {@link ImsCallProfile} that this session is associated with
+     */
+    @Override
+    public ImsCallProfile getLocalCallProfile() throws RemoteException {
+        return null;
+    }
+
+    /**
+     * Gets the remote call profile that this session is associated with
+     *
+     * @return the remote {@link ImsCallProfile} that this session is associated with
+     */
+    @Override
+    public ImsCallProfile getRemoteCallProfile() throws RemoteException {
+        return null;
+    }
+
+    /**
+     * Gets the value associated with the specified property of this session.
+     *
+     * @return the string value associated with the specified property
+     */
+    @Override
+    public String getProperty(String name) throws RemoteException {
+        return null;
+    }
+
+    /**
+     * Gets the session state.
+     * The value returned must be one of the states in {@link ImsCallSession.State}.
+     *
+     * @return the session state
+     */
+    @Override
+    public int getState() throws RemoteException {
+        return ImsCallSession.State.INVALID;
+    }
+
+    /**
+     * Checks if the session is in call.
+     *
+     * @return true if the session is in call, false otherwise
+     */
+    @Override
+    public boolean isInCall() throws RemoteException {
+        return false;
+    }
+
+    /**
+     * Sets the listener to listen to the session events. An {@link ImsCallSession}
+     * can only hold one listener at a time. Subsequent calls to this method
+     * override the previous listener.
+     *
+     * @param listener to listen to the session events of this object
+     */
+    @Override
+    public void setListener(IImsCallSessionListener listener) throws RemoteException {
+    }
+
+    /**
+     * Mutes or unmutes the mic for the active call.
+     *
+     * @param muted true if the call is muted, false otherwise
+     */
+    @Override
+    public void setMute(boolean muted) throws RemoteException {
+    }
+
+    /**
+     * Initiates an IMS call with the specified target and call profile.
+     * The session listener set in {@link #setListener} is called back upon defined session events.
+     * The method is only valid to call when the session state is in
+     * {@link ImsCallSession.State#IDLE}.
+     *
+     * @param callee dialed string to make the call to
+     * @param profile call profile to make the call with the specified service type,
+     *      call type and media information
+     * @see {@link ImsCallSession.Listener#callSessionStarted},
+     * {@link ImsCallSession.Listener#callSessionStartFailed}
+     */
+    @Override
+    public void start(String callee, ImsCallProfile profile) throws RemoteException {
+    }
+
+    /**
+     * Initiates an IMS call with the specified participants and call profile.
+     * The session listener set in {@link #setListener} is called back upon defined session events.
+     * The method is only valid to call when the session state is in
+     * {@link ImsCallSession.State#IDLE}.
+     *
+     * @param participants participant list to initiate an IMS conference call
+     * @param profile call profile to make the call with the specified service type,
+     *      call type and media information
+     * @see {@link ImsCallSession.Listener#callSessionStarted},
+     * {@link ImsCallSession.Listener#callSessionStartFailed}
+     */
+    @Override
+    public void startConference(String[] participants, ImsCallProfile profile)
+            throws RemoteException {
+    }
+
+    /**
+     * Accepts an incoming call or session update.
+     *
+     * @param callType call type specified in {@link ImsCallProfile} to be answered
+     * @param profile stream media profile {@link ImsStreamMediaProfile} to be answered
+     * @see {@link ImsCallSession.Listener#callSessionStarted}
+     */
+    @Override
+    public void accept(int callType, ImsStreamMediaProfile profile) throws RemoteException {
+    }
+
+    /**
+     * Rejects an incoming call or session update.
+     *
+     * @param reason reason code to reject an incoming call, defined in
+     *         com.android.ims.ImsReasonInfo
+     * {@link ImsCallSession.Listener#callSessionStartFailed}
+     */
+    @Override
+    public void reject(int reason) throws RemoteException {
+    }
+
+    /**
+     * Terminates a call.
+     *
+     * @param reason reason code to terminate a call, defined in
+     *         com.android.ims.ImsReasonInfo
+     *
+     * @see {@link ImsCallSession.Listener#callSessionTerminated}
+     */
+    @Override
+    public void terminate(int reason) throws RemoteException {
+    }
+
+    /**
+     * Puts a call on hold. When it succeeds, {@link ImsCallSession.Listener#callSessionHeld} is
+     * called.
+     *
+     * @param profile stream media profile {@link ImsStreamMediaProfile} to hold the call
+     * @see {@link ImsCallSession.Listener#callSessionHeld},
+     * {@link ImsCallSession.Listener#callSessionHoldFailed}
+     */
+    @Override
+    public void hold(ImsStreamMediaProfile profile) throws RemoteException {
+    }
+
+    /**
+     * Continues a call that's on hold. When it succeeds,
+     * {@link ImsCallSession.Listener#callSessionResumed} is called.
+     *
+     * @param profile stream media profile with {@link ImsStreamMediaProfile} to resume the call
+     * @see {@link ImsCallSession.Listener#callSessionResumed},
+     * {@link ImsCallSession.Listener#callSessionResumeFailed}
+     */
+    @Override
+    public void resume(ImsStreamMediaProfile profile) throws RemoteException {
+    }
+
+    /**
+     * Merges the active & hold call. When the merge starts,
+     * {@link ImsCallSession.Listener#callSessionMergeStarted} is called.
+     * {@link ImsCallSession.Listener#callSessionMergeComplete} is called if the merge is
+     * successful, and {@link ImsCallSession.Listener#callSessionMergeFailed} is called if the merge
+     * fails.
+     *
+     * @see {@link ImsCallSession.Listener#callSessionMergeStarted},
+     * {@link ImsCallSession.Listener#callSessionMergeComplete},
+     *      {@link ImsCallSession.Listener#callSessionMergeFailed}
+     */
+    @Override
+    public void merge() throws RemoteException {
+    }
+
+    /**
+     * Updates the current call's properties (ex. call mode change: video upgrade / downgrade).
+     *
+     * @param callType call type specified in {@link ImsCallProfile} to be updated
+     * @param profile stream media profile {@link ImsStreamMediaProfile} to be updated
+     * @see {@link ImsCallSession.Listener#callSessionUpdated},
+     * {@link ImsCallSession.Listener#callSessionUpdateFailed}
+     */
+    @Override
+    public void update(int callType, ImsStreamMediaProfile profile) throws RemoteException {
+    }
+
+    /**
+     * Extends this call to the conference call with the specified recipients.
+     *
+     * @param participants participant list to be invited to the conference call after extending the
+     * call
+     * @see {@link ImsCallSession.Listener#callSessionConferenceExtended},
+     * {@link ImsCallSession.Listener#callSessionConferenceExtendFailed}
+     */
+    @Override
+    public void extendToConference(String[] participants) throws RemoteException {
+    }
+
+    /**
+     * Requests the conference server to invite an additional participants to the conference.
+     *
+     * @param participants participant list to be invited to the conference call
+     * @see {@link ImsCallSession.Listener#callSessionInviteParticipantsRequestDelivered},
+     *      {@link ImsCallSession.Listener#callSessionInviteParticipantsRequestFailed}
+     */
+    @Override
+    public void inviteParticipants(String[] participants) throws RemoteException {
+    }
+
+    /**
+     * Requests the conference server to remove the specified participants from the conference.
+     *
+     * @param participants participant list to be removed from the conference call
+     * @see {@link ImsCallSession.Listener#callSessionRemoveParticipantsRequestDelivered},
+     *      {@link ImsCallSession.Listener#callSessionRemoveParticipantsRequestFailed}
+     */
+    @Override
+    public void removeParticipants(String[] participants) throws RemoteException {
+    }
+
+    /**
+     * Sends a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>,
+     * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15,
+     * and event flash to 16. Currently, event flash is not supported.
+     *
+     * @param c the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs.
+     */
+    @Override
+    public void sendDtmf(char c, Message result) throws RemoteException {
+    }
+
+    /**
+     * Start a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>,
+     * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15,
+     * and event flash to 16. Currently, event flash is not supported.
+     *
+     * @param c the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs.
+     */
+    @Override
+    public void startDtmf(char c) throws RemoteException {
+    }
+
+    /**
+     * Stop a DTMF code.
+     */
+    @Override
+    public void stopDtmf() throws RemoteException {
+    }
+
+    /**
+     * Sends an USSD message.
+     *
+     * @param ussdMessage USSD message to send
+     */
+    @Override
+    public void sendUssd(String ussdMessage) throws RemoteException {
+    }
+
+    /**
+     * Returns a binder for the video call provider implementation contained within the IMS service
+     * process. This binder is used by the VideoCallProvider subclass in Telephony which
+     * intermediates between the propriety implementation and Telecomm/InCall.
+     */
+    @Override
+    public IImsVideoCallProvider getVideoCallProvider() throws RemoteException {
+        return null;
+    }
+
+    /**
+     * Determines if the current session is multiparty.
+     * @return {@code True} if the session is multiparty.
+     */
+    @Override
+    public boolean isMultiparty() throws RemoteException {
+        return false;
+    }
+}
diff --git a/telephony/java/android/telephony/ims/stub/ImsCallSessionListenerImplBase.java b/telephony/java/android/telephony/ims/stub/ImsCallSessionListenerImplBase.java
new file mode 100644
index 0000000..46f8f80
--- /dev/null
+++ b/telephony/java/android/telephony/ims/stub/ImsCallSessionListenerImplBase.java
@@ -0,0 +1,251 @@
+/*
+ * 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 android.telephony.ims.stub;
+
+import com.android.ims.ImsCallProfile;
+import com.android.ims.ImsConferenceState;
+import com.android.ims.ImsReasonInfo;
+import com.android.ims.ImsStreamMediaProfile;
+import com.android.ims.ImsSuppServiceNotification;
+import com.android.ims.internal.IImsCallSession;
+import com.android.ims.internal.IImsCallSessionListener;
+
+/**
+ * Base implementation of ImsCallSessionListenerBase, which implements stub versions of the methods
+ * in the IImsCallSessionListener AIDL. Override the methods that your implementation of
+ * ImsCallSessionListener supports.
+ *
+ * DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
+ * will break other implementations of ImsCallSessionListener maintained by other ImsServices.
+ *
+ * @hide
+ */
+public class ImsCallSessionListenerImplBase extends IImsCallSessionListener.Stub {
+    /**
+     * Notifies the result of the basic session operation (setup / terminate).
+     */
+    @Override
+    public void callSessionProgressing(IImsCallSession session, ImsStreamMediaProfile profile) {
+        // no-op
+    }
+
+    @Override
+    public void callSessionStarted(IImsCallSession session, ImsCallProfile profile) {
+        // no-op
+    }
+
+    @Override
+    public void callSessionStartFailed(IImsCallSession session, ImsReasonInfo reasonInfo) {
+        // no-op
+    }
+
+    @Override
+    public void callSessionTerminated(IImsCallSession session, ImsReasonInfo reasonInfo) {
+        // no-op
+    }
+
+    /**
+     * Notifies the result of the call hold/resume operation.
+     */
+    @Override
+    public void callSessionHeld(IImsCallSession session, ImsCallProfile profile) {
+        // no-op
+    }
+
+    @Override
+    public void callSessionHoldFailed(IImsCallSession session, ImsReasonInfo reasonInfo) {
+        // no-op
+    }
+
+    @Override
+    public void callSessionHoldReceived(IImsCallSession session, ImsCallProfile profile) {
+        // no-op
+    }
+
+    @Override
+    public void callSessionResumed(IImsCallSession session, ImsCallProfile profile) {
+        // no-op
+    }
+
+    @Override
+    public void callSessionResumeFailed(IImsCallSession session, ImsReasonInfo reasonInfo) {
+        // no-op
+    }
+
+    @Override
+    public void callSessionResumeReceived(IImsCallSession session, ImsCallProfile profile) {
+        // no-op
+    }
+
+    /**
+     * Notifies the result of call merge operation.
+     */
+    @Override
+    public void callSessionMergeStarted(IImsCallSession session, IImsCallSession newSession,
+            ImsCallProfile profile) {
+        // no-op
+    }
+
+    @Override
+    public void callSessionMergeComplete(IImsCallSession session) {
+        // no-op
+    }
+
+    @Override
+    public void callSessionMergeFailed(IImsCallSession session, ImsReasonInfo reasonInfo) {
+        // no-op
+    }
+
+    /**
+     * Notifies the result of call upgrade / downgrade or any other call
+     * updates.
+     */
+    @Override
+    public void callSessionUpdated(IImsCallSession session, ImsCallProfile profile) {
+        // no-op
+    }
+
+    @Override
+    public void callSessionUpdateFailed(IImsCallSession session, ImsReasonInfo reasonInfo) {
+        // no-op
+    }
+
+    @Override
+    public void callSessionUpdateReceived(IImsCallSession session, ImsCallProfile profile) {
+        // no-op
+    }
+
+    /**
+     * Notifies the result of conference extension.
+     */
+    @Override
+    public void callSessionConferenceExtended(IImsCallSession session, IImsCallSession newSession,
+            ImsCallProfile profile) {
+        // no-op
+    }
+
+    @Override
+    public void callSessionConferenceExtendFailed(IImsCallSession session,
+            ImsReasonInfo reasonInfo) {
+        // no-op
+    }
+
+    @Override
+    public void callSessionConferenceExtendReceived(IImsCallSession session,
+            IImsCallSession newSession,
+            ImsCallProfile profile) {
+        // no-op
+    }
+
+    /**
+     * Notifies the result of the participant invitation / removal to/from the
+     * conference session.
+     */
+    @Override
+    public void callSessionInviteParticipantsRequestDelivered(IImsCallSession session) {
+        // no-op
+    }
+
+    @Override
+    public void callSessionInviteParticipantsRequestFailed(IImsCallSession session,
+            ImsReasonInfo reasonInfo) {
+        // no-op
+    }
+
+    @Override
+    public void callSessionRemoveParticipantsRequestDelivered(IImsCallSession session) {
+        // no-op
+    }
+
+    @Override
+    public void callSessionRemoveParticipantsRequestFailed(IImsCallSession session,
+            ImsReasonInfo reasonInfo) {
+        // no-op
+    }
+
+    /**
+     * Notifies the changes of the conference info. the conference session.
+     */
+    @Override
+    public void callSessionConferenceStateUpdated(IImsCallSession session,
+            ImsConferenceState state) {
+        // no-op
+    }
+
+    /**
+     * Notifies the incoming USSD message.
+     */
+    @Override
+    public void callSessionUssdMessageReceived(IImsCallSession session, int mode,
+            String ussdMessage) {
+        // no-op
+    }
+
+    /**
+     * Notifies of handover information for this call
+     */
+    @Override
+    public void callSessionHandover(IImsCallSession session, int srcAccessTech,
+            int targetAccessTech,
+            ImsReasonInfo reasonInfo) {
+        // no-op
+    }
+
+    @Override
+    public void callSessionHandoverFailed(IImsCallSession session, int srcAccessTech,
+            int targetAccessTech,
+            ImsReasonInfo reasonInfo) {
+        // no-op
+    }
+
+    /**
+     * Notifies the TTY mode change by remote party.
+     *
+     * @param mode one of the following: -
+     *            {@link com.android.internal.telephony.Phone#TTY_MODE_OFF} -
+     *            {@link com.android.internal.telephony.Phone#TTY_MODE_FULL} -
+     *            {@link com.android.internal.telephony.Phone#TTY_MODE_HCO} -
+     *            {@link com.android.internal.telephony.Phone#TTY_MODE_VCO}
+     */
+    @Override
+    public void callSessionTtyModeReceived(IImsCallSession session, int mode) {
+        // no-op
+    }
+
+    /**
+     * Notifies of a change to the multiparty state for this
+     * {@code ImsCallSession}.
+     *
+     * @param session The call session.
+     * @param isMultiParty {@code true} if the session became multiparty,
+     *            {@code false} otherwise.
+     */
+    @Override
+    public void callSessionMultipartyStateChanged(IImsCallSession session, boolean isMultiParty) {
+        // no-op
+    }
+
+    /**
+     * Notifies the supplementary service information for the current session.
+     */
+    @Override
+    public void callSessionSuppServiceReceived(IImsCallSession session,
+            ImsSuppServiceNotification suppSrvNotification) {
+        // no-op
+    }
+}
+
diff --git a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
new file mode 100644
index 0000000..5a4db99
--- /dev/null
+++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
@@ -0,0 +1,150 @@
+/*
+ * 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 android.telephony.ims.stub;
+
+import android.os.RemoteException;
+
+import com.android.ims.ImsConfig;
+import com.android.ims.ImsConfigListener;
+import com.android.ims.internal.IImsConfig;
+
+/**
+ * Base implementation of ImsConfig, which implements stub versions of the methods
+ * in the IImsConfig AIDL. Override the methods that your implementation of ImsConfig supports.
+ *
+ * DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
+ * will break other implementations of ImsConfig maintained by other ImsServices.
+ *
+ * Provides APIs to get/set the IMS service feature/capability/parameters.
+ * The config items include:
+ * 1) Items provisioned by the operator.
+ * 2) Items configured by user. Mainly service feature class.
+ *
+ * @hide
+ */
+
+public class ImsConfigImplBase extends IImsConfig.Stub {
+
+    /**
+     * Gets the value for ims service/capabilities parameters from the provisioned
+     * value storage. Synchronous blocking call.
+     *
+     * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+     * @return value in Integer format.
+     */
+    @Override
+    public int getProvisionedValue(int item) throws RemoteException {
+        return -1;
+    }
+
+    /**
+     * Gets the value for ims service/capabilities parameters from the provisioned
+     * value storage. Synchronous blocking call.
+     *
+     * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+     * @return value in String format.
+     */
+    @Override
+    public String getProvisionedStringValue(int item) throws RemoteException {
+        return null;
+    }
+
+    /**
+     * Sets the value for IMS service/capabilities parameters by the operator device
+     * management entity. It sets the config item value in the provisioned storage
+     * from which the master value is derived. Synchronous blocking call.
+     *
+     * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+     * @param value in Integer format.
+     * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants.
+     */
+    @Override
+    public int setProvisionedValue(int item, int value) throws RemoteException {
+        return ImsConfig.OperationStatusConstants.FAILED;
+    }
+
+    /**
+     * Sets the value for IMS service/capabilities parameters by the operator device
+     * management entity. It sets the config item value in the provisioned storage
+     * from which the master value is derived.  Synchronous blocking call.
+     *
+     * @param item as defined in com.android.ims.ImsConfig#ConfigConstants.
+     * @param value in String format.
+     * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants.
+     */
+    @Override
+    public int setProvisionedStringValue(int item, String value) throws RemoteException {
+        return ImsConfig.OperationStatusConstants.FAILED;
+    }
+
+    /**
+     * Gets the value of the specified IMS feature item for specified network type.
+     * This operation gets the feature config value from the master storage (i.e. final
+     * value). Asynchronous non-blocking call.
+     *
+     * @param feature as defined in com.android.ims.ImsConfig#FeatureConstants.
+     * @param network as defined in android.telephony.TelephonyManager#NETWORK_TYPE_XXX.
+     * @param listener feature value returned asynchronously through listener.
+     */
+    @Override
+    public void getFeatureValue(int feature, int network, ImsConfigListener listener)
+            throws RemoteException {
+    }
+
+    /**
+     * Sets the value for IMS feature item for specified network type.
+     * This operation stores the user setting in setting db from which master db
+     * is derived.
+     *
+     * @param feature as defined in com.android.ims.ImsConfig#FeatureConstants.
+     * @param network as defined in android.telephony.TelephonyManager#NETWORK_TYPE_XXX.
+     * @param value as defined in com.android.ims.ImsConfig#FeatureValueConstants.
+     * @param listener, provided if caller needs to be notified for set result.
+     */
+    @Override
+    public void setFeatureValue(int feature, int network, int value, ImsConfigListener listener)
+            throws RemoteException {
+    }
+
+    /**
+     * Gets the value for IMS VoLTE provisioned.
+     * This should be the same as the operator provisioned value if applies.
+     */
+    @Override
+    public boolean getVolteProvisioned() throws RemoteException {
+        return false;
+    }
+
+    /**
+     * Gets the value for IMS feature item video quality.
+     *
+     * @param listener Video quality value returned asynchronously through listener.
+     */
+    @Override
+    public void getVideoQuality(ImsConfigListener listener) throws RemoteException {
+    }
+
+    /**
+     * Sets the value for IMS feature item video quality.
+     *
+     * @param quality, defines the value of video quality.
+     * @param listener, provided if caller needs to be notified for set result.
+     */
+    @Override
+    public void setVideoQuality(int quality, ImsConfigListener listener) throws RemoteException {
+    }
+}
diff --git a/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java b/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
new file mode 100644
index 0000000..89f95ff
--- /dev/null
+++ b/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
@@ -0,0 +1,51 @@
+/*
+ * 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 android.telephony.ims.stub;
+
+import android.os.RemoteException;
+
+import com.android.ims.internal.IImsEcbm;
+import com.android.ims.internal.IImsEcbmListener;
+
+/**
+ * Base implementation of ImsEcbm, which implements stub versions of the methods
+ * in the IImsEcbm AIDL. Override the methods that your implementation of ImsEcbm supports.
+ *
+ * DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
+ * will break other implementations of ImsEcbm maintained by other ImsServices.
+ *
+ * @hide
+ */
+
+public class ImsEcbmImplBase extends IImsEcbm.Stub {
+
+    /**
+     * Sets the listener.
+     */
+    @Override
+    public void setListener(IImsEcbmListener listener) throws RemoteException {
+
+    }
+
+    /**
+     * Requests Modem to come out of ECBM mode
+     */
+    @Override
+    public void exitEmergencyCallbackMode() throws RemoteException {
+
+    }
+}
diff --git a/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java b/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
new file mode 100644
index 0000000..05da9da
--- /dev/null
+++ b/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
@@ -0,0 +1,53 @@
+/*
+ * 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 android.telephony.ims.stub;
+
+import android.os.RemoteException;
+
+import com.android.ims.internal.IImsExternalCallStateListener;
+import com.android.ims.internal.IImsMultiEndpoint;
+
+/**
+ * Base implementation of ImsMultiEndpoint, which implements stub versions of the methods
+ * in the IImsMultiEndpoint AIDL. Override the methods that your implementation of
+ * ImsMultiEndpoint supports.
+ *
+ * DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
+ * will break other implementations of ImsMultiEndpoint maintained by other ImsServices.
+ *
+ * @hide
+ */
+
+public class ImsMultiEndpointImplBase extends IImsMultiEndpoint.Stub {
+
+    /**
+     * Sets the listener.
+     */
+    @Override
+    public void setListener(IImsExternalCallStateListener listener) throws RemoteException {
+
+    }
+
+    /**
+     * Query API to get the latest Dialog Event Package information
+     * Should be invoked only after setListener is done
+     */
+    @Override
+    public void requestImsExternalCallStateInfo() throws RemoteException {
+
+    }
+}
diff --git a/telephony/java/android/telephony/ims/stub/ImsStreamMediaSessionImplBase.java b/telephony/java/android/telephony/ims/stub/ImsStreamMediaSessionImplBase.java
new file mode 100644
index 0000000..92f1a01
--- /dev/null
+++ b/telephony/java/android/telephony/ims/stub/ImsStreamMediaSessionImplBase.java
@@ -0,0 +1,40 @@
+/*
+ * 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 android.telephony.ims.stub;
+
+import android.os.RemoteException;
+
+import com.android.ims.internal.IImsStreamMediaSession;
+
+/**
+ * Base implementation of ImsStreamMediaSession, which implements stub versions of the methods
+ * in the IImsStreamMediaSession AIDL. Override the methods that your implementation of
+ * ImsStreamMediaSession supports.
+ *
+ * DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
+ * will break other implementations of ImsStreamMediaSession maintained by other ImsServices.
+ *
+ * @hide
+ */
+
+public class ImsStreamMediaSessionImplBase extends IImsStreamMediaSession.Stub {
+
+    @Override
+    public void close() throws RemoteException {
+
+    }
+}
diff --git a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
new file mode 100644
index 0000000..dc74094
--- /dev/null
+++ b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
@@ -0,0 +1,174 @@
+/*
+ * 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 android.telephony.ims.stub;
+
+import android.os.Bundle;
+import android.os.RemoteException;
+
+import com.android.ims.internal.IImsUt;
+import com.android.ims.internal.IImsUtListener;
+
+/**
+ * Base implementation of ImsUt, which implements stub versions of the methods
+ * in the IImsUt AIDL. Override the methods that your implementation of ImsUt supports.
+ *
+ * DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
+ * will break other implementations of ImsUt maintained by other ImsServices.
+ *
+ * Provides the Ut interface interworking to get/set the supplementary service configuration.
+ *
+ * @hide
+ */
+
+public class ImsUtImplBase extends IImsUt.Stub {
+
+    /**
+     * Closes the object. This object is not usable after being closed.
+     */
+    @Override
+    public void close() throws RemoteException {
+
+    }
+
+    /**
+     * Retrieves the configuration of the call barring.
+     */
+    @Override
+    public int queryCallBarring(int cbType) throws RemoteException {
+        return -1;
+    }
+
+    /**
+     * Retrieves the configuration of the call forward.
+     */
+    @Override
+    public int queryCallForward(int condition, String number) throws RemoteException {
+        return -1;
+    }
+
+    /**
+     * Retrieves the configuration of the call waiting.
+     */
+    @Override
+    public int queryCallWaiting() throws RemoteException {
+        return -1;
+    }
+
+    /**
+     * Retrieves the default CLIR setting.
+     */
+    @Override
+    public int queryCLIR() throws RemoteException {
+        return -1;
+    }
+
+    /**
+     * Retrieves the CLIP call setting.
+     */
+    @Override
+    public int queryCLIP() throws RemoteException {
+        return -1;
+    }
+
+    /**
+     * Retrieves the COLR call setting.
+     */
+    @Override
+    public int queryCOLR() throws RemoteException {
+        return -1;
+    }
+
+    /**
+     * Retrieves the COLP call setting.
+     */
+    @Override
+    public int queryCOLP() throws RemoteException {
+        return -1;
+    }
+
+    /**
+     * Updates or retrieves the supplementary service configuration.
+     */
+    @Override
+    public int transact(Bundle ssInfo) throws RemoteException {
+        return -1;
+    }
+
+    /**
+     * Updates the configuration of the call barring.
+     */
+    @Override
+    public int updateCallBarring(int cbType, int action, String[] barrList) throws RemoteException {
+        return -1;
+    }
+
+    /**
+     * Updates the configuration of the call forward.
+     */
+    @Override
+    public int updateCallForward(int action, int condition, String number, int serviceClass,
+            int timeSeconds) throws RemoteException {
+        return 0;
+    }
+
+    /**
+     * Updates the configuration of the call waiting.
+     */
+    @Override
+    public int updateCallWaiting(boolean enable, int serviceClass) throws RemoteException {
+        return -1;
+    }
+
+    /**
+     * Updates the configuration of the CLIR supplementary service.
+     */
+    @Override
+    public int updateCLIR(int clirMode) throws RemoteException {
+        return -1;
+    }
+
+    /**
+     * Updates the configuration of the CLIP supplementary service.
+     */
+    @Override
+    public int updateCLIP(boolean enable) throws RemoteException {
+        return -1;
+    }
+
+    /**
+     * Updates the configuration of the COLR supplementary service.
+     */
+    @Override
+    public int updateCOLR(int presentation) throws RemoteException {
+        return -1;
+    }
+
+    /**
+     * Updates the configuration of the COLP supplementary service.
+     */
+    @Override
+    public int updateCOLP(boolean enable) throws RemoteException {
+        return -1;
+    }
+
+    /**
+     * Sets the listener.
+     */
+    @Override
+    public void setListener(IImsUtListener listener) throws RemoteException {
+    }
+}
diff --git a/telephony/java/android/telephony/ims/stub/ImsUtListenerImplBase.java b/telephony/java/android/telephony/ims/stub/ImsUtListenerImplBase.java
new file mode 100644
index 0000000..b371efb
--- /dev/null
+++ b/telephony/java/android/telephony/ims/stub/ImsUtListenerImplBase.java
@@ -0,0 +1,88 @@
+/*
+ * 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 android.telephony.ims.stub;
+
+import android.os.Bundle;
+import android.os.RemoteException;
+
+import com.android.ims.ImsCallForwardInfo;
+import com.android.ims.ImsReasonInfo;
+import com.android.ims.ImsSsInfo;
+import com.android.ims.internal.IImsUt;
+import com.android.ims.internal.IImsUtListener;
+
+/**
+ * Base implementation of ImsUtListener, which implements stub versions of the methods
+ * in the IImsUtListener AIDL. Override the methods that your implementation of
+ * ImsUtListener supports.
+ *
+ * DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
+ * will break other implementations of ImsUtListener maintained by other ImsServices.
+ *
+ * @hide
+ */
+
+public class ImsUtListenerImplBase extends IImsUtListener.Stub {
+
+    /**
+     * Notifies the result of the supplementary service configuration udpate.
+     */
+    @Override
+    public void utConfigurationUpdated(IImsUt ut, int id) throws RemoteException {
+    }
+
+    @Override
+    public void utConfigurationUpdateFailed(IImsUt ut, int id, ImsReasonInfo error)
+            throws RemoteException {
+    }
+
+    /**
+     * Notifies the result of the supplementary service configuration query.
+     */
+    @Override
+    public void utConfigurationQueried(IImsUt ut, int id, Bundle ssInfo) throws RemoteException {
+    }
+
+    @Override
+    public void utConfigurationQueryFailed(IImsUt ut, int id, ImsReasonInfo error)
+            throws RemoteException {
+    }
+
+    /**
+     * Notifies the status of the call barring supplementary service.
+     */
+    @Override
+    public void utConfigurationCallBarringQueried(IImsUt ut, int id, ImsSsInfo[] cbInfo)
+            throws RemoteException {
+    }
+
+    /**
+     * Notifies the status of the call forwarding supplementary service.
+     */
+    @Override
+    public void utConfigurationCallForwardQueried(IImsUt ut, int id, ImsCallForwardInfo[] cfInfo)
+            throws RemoteException {
+    }
+
+    /**
+     * Notifies the status of the call waiting supplementary service.
+     */
+    @Override
+    public void utConfigurationCallWaitingQueried(IImsUt ut, int id, ImsSsInfo[] cwInfo)
+            throws RemoteException {
+    }
+}
diff --git a/telephony/java/com/android/ims/ImsConfig.java b/telephony/java/com/android/ims/ImsConfig.java
new file mode 100644
index 0000000..cd076b1
--- /dev/null
+++ b/telephony/java/com/android/ims/ImsConfig.java
@@ -0,0 +1,694 @@
+/*
+ * 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.ims;
+
+import android.content.Context;
+import android.os.RemoteException;
+import android.telephony.Rlog;
+
+import com.android.ims.internal.IImsConfig;
+
+/**
+ * Provides APIs to get/set the IMS service feature/capability/parameters.
+ * The config items include:
+ * 1) Items provisioned by the operator.
+ * 2) Items configured by user. Mainly service feature class.
+ *
+ * @hide
+ */
+public class ImsConfig {
+    private static final String TAG = "ImsConfig";
+    private boolean DBG = true;
+    private final IImsConfig miConfig;
+    private Context mContext;
+
+    /**
+     * Broadcast action: the feature enable status was changed
+     *
+     * @hide
+     */
+    public static final String ACTION_IMS_FEATURE_CHANGED =
+            "com.android.intent.action.IMS_FEATURE_CHANGED";
+
+    /**
+     * Broadcast action: the configuration was changed
+     *
+     * @hide
+     */
+    public static final String ACTION_IMS_CONFIG_CHANGED =
+            "com.android.intent.action.IMS_CONFIG_CHANGED";
+
+    /**
+     * Extra parameter "item" of intent ACTION_IMS_FEATURE_CHANGED and ACTION_IMS_CONFIG_CHANGED.
+     * It is the value of FeatureConstants or ConfigConstants.
+     *
+     * @hide
+     */
+    public static final String EXTRA_CHANGED_ITEM = "item";
+
+    /**
+     * Extra parameter "value" of intent ACTION_IMS_FEATURE_CHANGED and ACTION_IMS_CONFIG_CHANGED.
+     * It is the new value of "item".
+     *
+     * @hide
+     */
+    public static final String EXTRA_NEW_VALUE = "value";
+
+    /**
+    * Defines IMS service/capability feature constants.
+    */
+    public static class FeatureConstants {
+        public static final int FEATURE_TYPE_UNKNOWN = -1;
+
+        /**
+         * FEATURE_TYPE_VOLTE supports features defined in 3GPP and
+         * GSMA IR.92 over LTE.
+         */
+        public static final int FEATURE_TYPE_VOICE_OVER_LTE = 0;
+
+        /**
+         * FEATURE_TYPE_LVC supports features defined in 3GPP and
+         * GSMA IR.94 over LTE.
+         */
+        public static final int FEATURE_TYPE_VIDEO_OVER_LTE = 1;
+
+        /**
+         * FEATURE_TYPE_VOICE_OVER_WIFI supports features defined in 3GPP and
+         * GSMA IR.92 over WiFi.
+         */
+        public static final int FEATURE_TYPE_VOICE_OVER_WIFI = 2;
+
+        /**
+         * FEATURE_TYPE_VIDEO_OVER_WIFI supports features defined in 3GPP and
+         * GSMA IR.94 over WiFi.
+         */
+        public static final int FEATURE_TYPE_VIDEO_OVER_WIFI = 3;
+
+        /**
+         * FEATURE_TYPE_UT supports features defined in 3GPP and
+         * GSMA IR.92 over LTE.
+         */
+        public static final int FEATURE_TYPE_UT_OVER_LTE = 4;
+
+       /**
+         * FEATURE_TYPE_UT_OVER_WIFI supports features defined in 3GPP and
+         * GSMA IR.92 over WiFi.
+         */
+        public static final int FEATURE_TYPE_UT_OVER_WIFI = 5;
+    }
+
+    /**
+    * Defines IMS service/capability parameters.
+    */
+    public static class ConfigConstants {
+
+        // Define IMS config items
+        public static final int CONFIG_START = 0;
+
+        // Define operator provisioned config items
+        public static final int PROVISIONED_CONFIG_START = CONFIG_START;
+
+        /**
+         * AMR CODEC Mode Value set, 0-7 in comma separated sequence.
+         * Value is in String format.
+         */
+        public static final int VOCODER_AMRMODESET = CONFIG_START;
+
+        /**
+         * Wide Band AMR CODEC Mode Value set,0-7 in comma separated sequence.
+         * Value is in String format.
+         */
+        public static final int VOCODER_AMRWBMODESET = 1;
+
+        /**
+         * SIP Session Timer value (seconds).
+         * Value is in Integer format.
+         */
+        public static final int SIP_SESSION_TIMER = 2;
+
+        /**
+         * Minimum SIP Session Expiration Timer in (seconds).
+         * Value is in Integer format.
+         */
+        public static final int MIN_SE = 3;
+
+        /**
+         * SIP_INVITE cancellation time out value (in milliseconds). Integer format.
+         * Value is in Integer format.
+         */
+        public static final int CANCELLATION_TIMER = 4;
+
+        /**
+         * Delay time when an iRAT transition from eHRPD/HRPD/1xRTT to LTE.
+         * Value is in Integer format.
+         */
+        public static final int TDELAY = 5;
+
+        /**
+         * Silent redial status of Enabled (True), or Disabled (False).
+         * Value is in Integer format.
+         */
+        public static final int SILENT_REDIAL_ENABLE = 6;
+
+        /**
+         * SIP T1 timer value in milliseconds. See RFC 3261 for define.
+         * Value is in Integer format.
+         */
+        public static final int SIP_T1_TIMER = 7;
+
+        /**
+         * SIP T2 timer value in milliseconds.  See RFC 3261 for define.
+         * Value is in Integer format.
+         */
+        public static final int SIP_T2_TIMER  = 8;
+
+         /**
+         * SIP TF timer value in milliseconds.  See RFC 3261 for define.
+         * Value is in Integer format.
+         */
+        public static final int SIP_TF_TIMER = 9;
+
+        /**
+         * VoLTE status for VLT/s status of Enabled (1), or Disabled (0).
+         * Value is in Integer format.
+         */
+        public static final int VLT_SETTING_ENABLED = 10;
+
+        /**
+         * VoLTE status for LVC/s status of Enabled (1), or Disabled (0).
+         * Value is in Integer format.
+         */
+        public static final int LVC_SETTING_ENABLED = 11;
+        /**
+         * Domain Name for the device to populate the request URI for REGISTRATION.
+         * Value is in String format.
+         */
+        public static final int DOMAIN_NAME = 12;
+         /**
+         * Device Outgoing SMS based on either 3GPP or 3GPP2 standards.
+         * Value is in Integer format. 3GPP2(0), 3GPP(1)
+         */
+        public static final int SMS_FORMAT = 13;
+         /**
+         * Turns IMS ON/OFF on the device.
+         * Value is in Integer format. ON (1), OFF(0).
+         */
+        public static final int SMS_OVER_IP = 14;
+        /**
+         * Requested expiration for Published Online availability.
+         * Value is in Integer format.
+         */
+        public static final int PUBLISH_TIMER = 15;
+        /**
+         * Requested expiration for Published Offline availability.
+         * Value is in Integer format.
+         */
+        public static final int PUBLISH_TIMER_EXTENDED = 16;
+        /**
+         *
+         * Value is in Integer format.
+         */
+        public static final int CAPABILITY_DISCOVERY_ENABLED = 17;
+        /**
+         * Period of time the capability information of the  contact is cached on handset.
+         * Value is in Integer format.
+         */
+        public static final int CAPABILITIES_CACHE_EXPIRATION = 18;
+        /**
+         * Peiod of time the availability information of a contact is cached on device.
+         * Value is in Integer format.
+         */
+        public static final int AVAILABILITY_CACHE_EXPIRATION = 19;
+        /**
+         * Interval between successive capabilities polling.
+         * Value is in Integer format.
+         */
+        public static final int CAPABILITIES_POLL_INTERVAL = 20;
+        /**
+         * Minimum time between two published messages from the device.
+         * Value is in Integer format.
+         */
+        public static final int SOURCE_THROTTLE_PUBLISH = 21;
+        /**
+         * The Maximum number of MDNs contained in one Request Contained List.
+         * Value is in Integer format.
+         */
+        public static final int MAX_NUMENTRIES_IN_RCL = 22;
+        /**
+         * Expiration timer for subscription of a Request Contained List, used in capability
+         * polling.
+         * Value is in Integer format.
+         */
+        public static final int CAPAB_POLL_LIST_SUB_EXP = 23;
+        /**
+         * Applies compression to LIST Subscription.
+         * Value is in Integer format. Enable (1), Disable(0).
+         */
+        public static final int GZIP_FLAG = 24;
+        /**
+         * VOLTE Status for EAB/s status of Enabled (1), or Disabled (0).
+         * Value is in Integer format.
+         */
+        public static final int EAB_SETTING_ENABLED = 25;
+        /**
+         * Wi-Fi calling roaming status.
+         * Value is in Integer format. ON (1), OFF(0).
+         */
+        public static final int VOICE_OVER_WIFI_ROAMING = 26;
+        /**
+         * Wi-Fi calling modem - WfcModeFeatureValueConstants.
+         * Value is in Integer format.
+         */
+        public static final int VOICE_OVER_WIFI_MODE = 27;
+        /**
+         * VOLTE Status for voice over wifi status of Enabled (1), or Disabled (0).
+         * Value is in Integer format.
+         */
+        public static final int VOICE_OVER_WIFI_SETTING_ENABLED = 28;
+        /**
+         * Mobile data enabled.
+         * Value is in Integer format. On (1), OFF(0).
+         */
+        public static final int MOBILE_DATA_ENABLED = 29;
+        /**
+         * VoLTE user opted in status.
+         * Value is in Integer format. Opted-in (1) Opted-out (0).
+         */
+        public static final int VOLTE_USER_OPT_IN_STATUS = 30;
+        /**
+         * Proxy for Call Session Control Function(P-CSCF) address for Local-BreakOut(LBO).
+         * Value is in String format.
+         */
+        public static final int LBO_PCSCF_ADDRESS = 31;
+        /**
+         * Keep Alive Enabled for SIP.
+         * Value is in Integer format. On(1), OFF(0).
+         */
+        public static final int KEEP_ALIVE_ENABLED = 32;
+        /**
+         * Registration retry Base Time value in seconds.
+         * Value is in Integer format.
+         */
+        public static final int REGISTRATION_RETRY_BASE_TIME_SEC = 33;
+        /**
+         * Registration retry Max Time value in seconds.
+         * Value is in Integer format.
+         */
+        public static final int REGISTRATION_RETRY_MAX_TIME_SEC = 34;
+        /**
+         * Smallest RTP port for speech codec.
+         * Value is in integer format.
+         */
+        public static final int SPEECH_START_PORT = 35;
+        /**
+         * Largest RTP port for speech code.
+         * Value is in Integer format.
+         */
+        public static final int SPEECH_END_PORT = 36;
+        /**
+         * SIP Timer A's value in milliseconds. Timer A is the INVITE request
+         * retransmit interval, for UDP only.
+         * Value is in Integer format.
+         */
+        public static final int SIP_INVITE_REQ_RETX_INTERVAL_MSEC = 37;
+        /**
+         * SIP Timer B's value in milliseconds. Timer B is the wait time for
+         * INVITE message to be acknowledged.
+         * Value is in Integer format.
+         */
+        public static final int SIP_INVITE_RSP_WAIT_TIME_MSEC = 38;
+        /**
+         * SIP Timer D's value in milliseconds. Timer D is the wait time for
+         * response retransmits of the invite client transactions.
+         * Value is in Integer format.
+         */
+        public static final int SIP_INVITE_RSP_RETX_WAIT_TIME_MSEC = 39;
+        /**
+         * SIP Timer E's value in milliseconds. Timer E is the value Non-INVITE
+         * request retransmit interval, for UDP only.
+         * Value is in Integer format.
+         */
+        public static final int SIP_NON_INVITE_REQ_RETX_INTERVAL_MSEC = 40;
+        /**
+         * SIP Timer F's value in milliseconds. Timer F is the Non-INVITE transaction
+         * timeout timer.
+         * Value is in Integer format.
+         */
+        public static final int SIP_NON_INVITE_TXN_TIMEOUT_TIMER_MSEC = 41;
+        /**
+         * SIP Timer G's value in milliseconds. Timer G is the value of INVITE response
+         * retransmit interval.
+         * Value is in Integer format.
+         */
+        public static final int SIP_INVITE_RSP_RETX_INTERVAL_MSEC = 42;
+        /**
+         * SIP Timer H's value in milliseconds. Timer H is the value of wait time for
+         * ACK receipt.
+         * Value is in Integer format.
+         */
+        public static final int SIP_ACK_RECEIPT_WAIT_TIME_MSEC = 43;
+        /**
+         * SIP Timer I's value in milliseconds. Timer I is the value of wait time for
+         * ACK retransmits.
+         * Value is in Integer format.
+         */
+        public static final int SIP_ACK_RETX_WAIT_TIME_MSEC = 44;
+        /**
+         * SIP Timer J's value in milliseconds. Timer J is the value of wait time for
+         * non-invite request retransmission.
+         * Value is in Integer format.
+         */
+        public static final int SIP_NON_INVITE_REQ_RETX_WAIT_TIME_MSEC = 45;
+        /**
+         * SIP Timer K's value in milliseconds. Timer K is the value of wait time for
+         * non-invite response retransmits.
+         * Value is in Integer format.
+         */
+        public static final int SIP_NON_INVITE_RSP_RETX_WAIT_TIME_MSEC = 46;
+        /**
+         * AMR WB octet aligned dynamic payload type.
+         * Value is in Integer format.
+         */
+        public static final int AMR_WB_OCTET_ALIGNED_PT = 47;
+        /**
+         * AMR WB bandwidth efficient payload type.
+         * Value is in Integer format.
+         */
+        public static final int AMR_WB_BANDWIDTH_EFFICIENT_PT = 48;
+        /**
+         * AMR octet aligned dynamic payload type.
+         * Value is in Integer format.
+         */
+        public static final int AMR_OCTET_ALIGNED_PT = 49;
+        /**
+         * AMR bandwidth efficient payload type.
+         * Value is in Integer format.
+         */
+        public static final int AMR_BANDWIDTH_EFFICIENT_PT = 50;
+        /**
+         * DTMF WB payload type.
+         * Value is in Integer format.
+         */
+        public static final int DTMF_WB_PT = 51;
+        /**
+         * DTMF NB payload type.
+         * Value is in Integer format.
+         */
+        public static final int DTMF_NB_PT = 52;
+        /**
+         * AMR Default encoding mode.
+         * Value is in Integer format.
+         */
+        public static final int AMR_DEFAULT_MODE = 53;
+        /**
+         * SMS Public Service Identity.
+         * Value is in String format.
+         */
+        public static final int SMS_PSI = 54;
+        /**
+         * Video Quality - VideoQualityFeatureValuesConstants.
+         * Value is in Integer format.
+         */
+        public static final int VIDEO_QUALITY = 55;
+        /**
+         * LTE threshold.
+         * Handover from LTE to WiFi if LTE < THLTE1 and WiFi >= VOWT_A.
+         */
+        public static final int TH_LTE1 = 56;
+        /**
+         * LTE threshold.
+         * Handover from WiFi to LTE if LTE >= THLTE3 or (WiFi < VOWT_B and LTE >= THLTE2).
+         */
+        public static final int TH_LTE2 = 57;
+        /**
+         * LTE threshold.
+         * Handover from WiFi to LTE if LTE >= THLTE3 or (WiFi < VOWT_B and LTE >= THLTE2).
+         */
+        public static final int TH_LTE3 = 58;
+        /**
+         * 1x threshold.
+         * Handover from 1x to WiFi if 1x < TH1x
+         */
+        public static final int TH_1x = 59;
+        /**
+         * WiFi threshold.
+         * Handover from LTE to WiFi if LTE < THLTE1 and WiFi >= VOWT_A.
+         */
+        public static final int VOWT_A = 60;
+        /**
+         * WiFi threshold.
+         * Handover from WiFi to LTE if LTE >= THLTE3 or (WiFi < VOWT_B and LTE >= THLTE2).
+         */
+        public static final int VOWT_B = 61;
+        /**
+         * LTE ePDG timer.
+         * Device shall not handover back to LTE until the T_ePDG_LTE timer expires.
+         */
+        public static final int T_EPDG_LTE = 62;
+        /**
+         * WiFi ePDG timer.
+         * Device shall not handover back to WiFi until the T_ePDG_WiFi timer expires.
+         */
+        public static final int T_EPDG_WIFI = 63;
+        /**
+         * 1x ePDG timer.
+         * Device shall not re-register on 1x until the T_ePDG_1x timer expires.
+         */
+        public static final int T_EPDG_1X = 64;
+        /**
+         * MultiEndpoint status: Enabled (1), or Disabled (0).
+         * Value is in Integer format.
+         */
+        public static final int VICE_SETTING_ENABLED = 65;
+
+        // Expand the operator config items as needed here, need to change
+        // PROVISIONED_CONFIG_END after that.
+        public static final int PROVISIONED_CONFIG_END = VICE_SETTING_ENABLED;
+
+        // Expand the operator config items as needed here.
+    }
+
+    /**
+    * Defines IMS set operation status.
+    */
+    public static class OperationStatusConstants {
+        public static final int UNKNOWN = -1;
+        public static final int SUCCESS = 0;
+        public static final int FAILED =  1;
+        public static final int UNSUPPORTED_CAUSE_NONE = 2;
+        public static final int UNSUPPORTED_CAUSE_RAT = 3;
+        public static final int UNSUPPORTED_CAUSE_DISABLED = 4;
+    }
+
+    /**
+     * Defines IMS get operation values.
+     */
+    public static class OperationValuesConstants {
+        /**
+         * Values related to Video Quality
+         */
+        public static final int VIDEO_QUALITY_UNKNOWN = -1;
+        public static final int VIDEO_QUALITY_LOW = 0;
+        public static final int VIDEO_QUALITY_HIGH = 1;
+    }
+
+    /**
+     * Defines IMS video quality feature value.
+     */
+    public static class VideoQualityFeatureValuesConstants {
+        public static final int LOW = 0;
+        public static final int HIGH = 1;
+    }
+
+   /**
+    * Defines IMS feature value.
+    */
+    public static class FeatureValueConstants {
+        public static final int OFF = 0;
+        public static final int ON = 1;
+    }
+
+    /**
+     * Defines IMS feature value.
+     */
+    public static class WfcModeFeatureValueConstants {
+        public static final int WIFI_ONLY = 0;
+        public static final int CELLULAR_PREFERRED = 1;
+        public static final int WIFI_PREFERRED = 2;
+    }
+
+    public ImsConfig(IImsConfig iconfig, Context context) {
+        if (DBG) Rlog.d(TAG, "ImsConfig creates");
+        miConfig = iconfig;
+        mContext = context;
+    }
+
+    /**
+     * Gets the provisioned value for IMS service/capabilities parameters used by IMS stack.
+     * This function should not be called from the mainthread as it could block the
+     * mainthread.
+     *
+     * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+     * @return the value in Integer format.
+     *
+     * @throws ImsException if calling the IMS service results in an error.
+     */
+    public int getProvisionedValue(int item) throws ImsException {
+        int ret = 0;
+        try {
+            ret = miConfig.getProvisionedValue(item);
+        }  catch (RemoteException e) {
+            throw new ImsException("getValue()", e,
+                    ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
+        }
+        if (DBG) Rlog.d(TAG, "getProvisionedValue(): item = " + item + ", ret =" + ret);
+
+        return ret;
+    }
+
+    /**
+     * Gets the provisioned value for IMS service/capabilities parameters used by IMS stack.
+     * This function should not be called from the mainthread as it could block the
+     * mainthread.
+     *
+     * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+     * @return value in String format.
+     *
+     * @throws ImsException if calling the IMS service results in an error.
+     */
+    public String getProvisionedStringValue(int item) throws ImsException {
+        String ret = "Unknown";
+        try {
+            ret = miConfig.getProvisionedStringValue(item);
+        }  catch (RemoteException e) {
+            throw new ImsException("getProvisionedStringValue()", e,
+                    ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
+        }
+        if (DBG) Rlog.d(TAG, "getProvisionedStringValue(): item = " + item + ", ret =" + ret);
+
+        return ret;
+    }
+
+    /**
+     * Sets the value for IMS service/capabilities parameters by
+     * the operator device management entity.
+     * This function should not be called from main thread as it could block
+     * mainthread.
+     *
+     * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+     * @param value in Integer format.
+     * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants
+     *
+     * @throws ImsException if calling the IMS service results in an error.
+     */
+    public int setProvisionedValue(int item, int value)
+            throws ImsException {
+        int ret = OperationStatusConstants.UNKNOWN;
+        if (DBG) {
+            Rlog.d(TAG, "setProvisionedValue(): item = " + item +
+                    "value = " + value);
+        }
+        try {
+            ret = miConfig.setProvisionedValue(item, value);
+        }  catch (RemoteException e) {
+            throw new ImsException("setProvisionedValue()", e,
+                    ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
+        }
+        if (DBG) {
+            Rlog.d(TAG, "setProvisionedValue(): item = " + item +
+                    " value = " + value + " ret = " + ret);
+        }
+        return ret;
+    }
+
+    /**
+     * Sets the value for IMS service/capabilities parameters by
+     * the operator device management entity.
+     * This function should not be called from main thread as it could block
+     * mainthread.
+     *
+     * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
+     * @param value in String format.
+     * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants
+     *
+     * @throws ImsException if calling the IMS service results in an error.
+     */
+    public int setProvisionedStringValue(int item, String value)
+            throws ImsException {
+        int ret = OperationStatusConstants.UNKNOWN;
+        try {
+            ret = miConfig.setProvisionedStringValue(item, value);
+        }  catch (RemoteException e) {
+            throw new ImsException("setProvisionedStringValue()", e,
+                    ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
+        }
+        if (DBG) {
+            Rlog.d(TAG, "setProvisionedStringValue(): item = " + item +
+                    ", value =" + value);
+        }
+        return ret;
+    }
+
+    /**
+     * Gets the value for IMS feature item for specified network type.
+     *
+     * @param feature, defined as in FeatureConstants.
+     * @param network, defined as in android.telephony.TelephonyManager#NETWORK_TYPE_XXX.
+     * @param listener, provided to be notified for the feature on/off status.
+     * @return void
+     *
+     * @throws ImsException if calling the IMS service results in an error.
+     */
+    public void getFeatureValue(int feature, int network,
+            ImsConfigListener listener) throws ImsException {
+        if (DBG) {
+            Rlog.d(TAG, "getFeatureValue: feature = " + feature + ", network =" + network +
+                    ", listener =" + listener);
+        }
+        try {
+            miConfig.getFeatureValue(feature, network, listener);
+        } catch (RemoteException e) {
+            throw new ImsException("getFeatureValue()", e,
+                    ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
+        }
+    }
+
+    /**
+     * Sets the value for IMS feature item for specified network type.
+     *
+     * @param feature, as defined in FeatureConstants.
+     * @param network, as defined in android.telephony.TelephonyManager#NETWORK_TYPE_XXX.
+     * @param value, as defined in FeatureValueConstants.
+     * @param listener, provided if caller needs to be notified for set result.
+     * @return void
+     *
+     * @throws ImsException if calling the IMS service results in an error.
+     */
+    public void setFeatureValue(int feature, int network, int value,
+            ImsConfigListener listener) throws ImsException {
+        if (DBG) {
+            Rlog.d(TAG, "setFeatureValue: feature = " + feature + ", network =" + network +
+                    ", value =" + value + ", listener =" + listener);
+        }
+        try {
+            miConfig.setFeatureValue(feature, network, value, listener);
+        } catch (RemoteException e) {
+            throw new ImsException("setFeatureValue()", e,
+                    ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
+        }
+    }
+}
diff --git a/telephony/java/com/android/ims/ImsException.java b/telephony/java/com/android/ims/ImsException.java
new file mode 100644
index 0000000..74b20f4
--- /dev/null
+++ b/telephony/java/com/android/ims/ImsException.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.ims;
+
+/**
+ * This class defines a general IMS-related exception.
+ *
+ * @hide
+ */
+public class ImsException extends Exception {
+
+    /**
+     * Refer to CODE_LOCAL_* in {@link ImsReasonInfo}
+     */
+    private int mCode;
+
+    public ImsException() {
+    }
+
+    public ImsException(String message, int code) {
+        super(message + ", code = " + code);
+        mCode = code;
+    }
+
+    public ImsException(String message, Throwable cause, int code) {
+        super(message, cause);
+        mCode = code;
+    }
+
+    /**
+     * Gets the detailed exception code when ImsException is throwed
+     *
+     * @return the exception code in {@link ImsReasonInfo}
+     */
+    public int getCode() {
+        return mCode;
+    }
+}
diff --git a/telephony/java/com/android/ims/ImsReasonInfo.java b/telephony/java/com/android/ims/ImsReasonInfo.java
index c71808c..e4f380f 100644
--- a/telephony/java/com/android/ims/ImsReasonInfo.java
+++ b/telephony/java/com/android/ims/ImsReasonInfo.java
@@ -313,6 +313,12 @@
     public static final int CODE_WIFI_LOST = 1407;
 
     /**
+     * Indicates the registration attempt on IWLAN failed due to IKEv2 authetication failure
+     * during tunnel establishment.
+     */
+    public static final int CODE_IKEV2_AUTH_FAILURE = 1408;
+
+    /**
      * Network string error messages.
      * mExtraMessage may have these values.
      */
diff --git a/telephony/java/com/android/ims/ImsUtInterface.java b/telephony/java/com/android/ims/ImsUtInterface.java
new file mode 100644
index 0000000..5984e78
--- /dev/null
+++ b/telephony/java/com/android/ims/ImsUtInterface.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.ims;
+
+import android.os.Message;
+
+/**
+ * Provides APIs for the supplementary service settings using IMS (Ut interface).
+ * It is created from 3GPP TS 24.623 (XCAP(XML Configuration Access Protocol)
+ * over the Ut interface for manipulating supplementary services).
+ *
+ * @hide
+ */
+public interface ImsUtInterface {
+    /**
+     * Actions
+     * @hide
+     */
+    public static final int ACTION_DEACTIVATION = 0;
+    public static final int ACTION_ACTIVATION = 1;
+    public static final int ACTION_REGISTRATION = 3;
+    public static final int ACTION_ERASURE = 4;
+    public static final int ACTION_INTERROGATION = 5;
+
+    /**
+     * OIR (Originating Identification Restriction, 3GPP TS 24.607)
+     * OIP (Originating Identification Presentation, 3GPP TS 24.607)
+     * TIR (Terminating Identification Restriction, 3GPP TS 24.608)
+     * TIP (Terminating Identification Presentation, 3GPP TS 24.608)
+     */
+    public static final int OIR_DEFAULT = 0;    // "user subscription default value"
+    public static final int OIR_PRESENTATION_RESTRICTED = 1;
+    public static final int OIR_PRESENTATION_NOT_RESTRICTED = 2;
+
+    /**
+     * CW (Communication Waiting, 3GPP TS 24.615)
+     */
+
+    /**
+     * CDIV (Communication Diversion, 3GPP TS 24.604)
+     *     actions: target, no reply timer
+     */
+    public static final int CDIV_CF_UNCONDITIONAL = 0;
+    public static final int CDIV_CF_BUSY = 1;
+    public static final int CDIV_CF_NO_REPLY = 2;
+    public static final int CDIV_CF_NOT_REACHABLE = 3;
+    // For CS service code: 002
+    public static final int CDIV_CF_ALL = 4;
+    // For CS service code: 004
+    public static final int CDIV_CF_ALL_CONDITIONAL = 5;
+    // It's only supported in the IMS service (CS does not define it).
+    // IR.92 recommends that an UE activates both the CFNRc and the CFNL
+    // (CDIV using condition not-registered) to the same target.
+    public static final int CDIV_CF_NOT_LOGGED_IN = 6;
+
+    /**
+     * CB (Communication Barring, 3GPP TS 24.611)
+     */
+    // Barring of All Incoming Calls
+    public static final int CB_BAIC = 1;
+    // Barring of All Outgoing Calls
+    public static final int CB_BAOC = 2;
+    // Barring of Outgoing International Calls
+    public static final int CB_BOIC = 3;
+    // Barring of Outgoing International Calls - excluding Home Country
+    public static final int CB_BOIC_EXHC = 4;
+    // Barring of Incoming Calls - when roaming
+    public static final int CB_BIC_WR = 5;
+    // Barring of Anonymous Communication Rejection (ACR) - a particular case of ICB service
+    public static final int CB_BIC_ACR = 6;
+    // Barring of All Calls
+    public static final int CB_BA_ALL = 7;
+    // Barring of Outgoing Services (Service Code 333 - 3GPP TS 22.030 Table B-1)
+    public static final int CB_BA_MO = 8;
+    // Barring of Incoming Services (Service Code 353 - 3GPP TS 22.030 Table B-1)
+    public static final int CB_BA_MT = 9;
+    // Barring of Specific Incoming calls
+    public static final int CB_BS_MT = 10;
+
+    /**
+     * Invalid result value.
+     */
+    public static final int INVALID = (-1);
+
+
+
+    /**
+     * Operations for the supplementary service configuration
+     */
+
+    /**
+     * Retrieves the configuration of the call barring.
+     * The return value of ((AsyncResult)result.obj) is an array of {@link ImsSsInfo}.
+     */
+    public void queryCallBarring(int cbType, Message result);
+
+    /**
+     * Retrieves the configuration of the call forward.
+     * The return value of ((AsyncResult)result.obj) is an array of {@link ImsCallForwardInfo}.
+     */
+    public void queryCallForward(int condition, String number, Message result);
+
+    /**
+     * Retrieves the configuration of the call waiting.
+     * The return value of ((AsyncResult)result.obj) is an array of {@link ImsSsInfo}.
+     */
+    public void queryCallWaiting(Message result);
+
+    /**
+     * Retrieves the default CLIR setting.
+     */
+    public void queryCLIR(Message result);
+
+    /**
+     * Retrieves the CLIP call setting.
+     */
+    public void queryCLIP(Message result);
+
+    /**
+     * Retrieves the COLR call setting.
+     */
+    public void queryCOLR(Message result);
+
+    /**
+     * Retrieves the COLP call setting.
+     */
+    public void queryCOLP(Message result);
+
+    /**
+     * Modifies the configuration of the call barring.
+     */
+    public void updateCallBarring(int cbType, int action,
+            Message result, String[] barrList);
+
+    /**
+     * Modifies the configuration of the call forward.
+     */
+    public void updateCallForward(int action, int condition, String number,
+            int serviceClass, int timeSeconds, Message result);
+
+    /**
+     * Modifies the configuration of the call waiting.
+     */
+    public void updateCallWaiting(boolean enable, int serviceClass, Message result);
+
+    /**
+     * Updates the configuration of the CLIR supplementary service.
+     */
+    public void updateCLIR(int clirMode, Message result);
+
+    /**
+     * Updates the configuration of the CLIP supplementary service.
+     */
+    public void updateCLIP(boolean enable, Message result);
+
+    /**
+     * Updates the configuration of the COLR supplementary service.
+     */
+    public void updateCOLR(int presentation, Message result);
+
+    /**
+     * Updates the configuration of the COLP supplementary service.
+     */
+    public void updateCOLP(boolean enable, Message result);
+}
diff --git a/telephony/java/com/android/ims/internal/IImsServiceController.aidl b/telephony/java/com/android/ims/internal/IImsServiceController.aidl
index b700f49..712816f 100644
--- a/telephony/java/com/android/ims/internal/IImsServiceController.aidl
+++ b/telephony/java/com/android/ims/internal/IImsServiceController.aidl
@@ -42,24 +42,23 @@
     int startSession(int slotId, int featureType, in PendingIntent incomingCallIntent,
             in IImsRegistrationListener listener);
     void endSession(int slotId, int featureType, int sessionId);
-    boolean isConnected(int slotId, int featureType, int sessionId, int callSessionType, int callType);
-    boolean isOpened(int slotId, int featureType, int sessionId);
+    boolean isConnected(int slotId, int featureType, int callSessionType, int callType);
+    boolean isOpened(int slotId, int featureType);
     int getFeatureStatus(int slotId, int featureType);
-    void addRegistrationListener(int slotId, int featureType, int sessionId,
+    void addRegistrationListener(int slotId, int featureType, in IImsRegistrationListener listener);
+    void removeRegistrationListener(int slotId, int featureType,
             in IImsRegistrationListener listener);
-    void removeRegistrationListener(int slotId, int featureType, int sessionId,
-            in IImsRegistrationListener listener);
-    ImsCallProfile createCallProfile(int slotId, int featureType, int sessionId, int callSessionType, int callType);
+    ImsCallProfile createCallProfile(int slotId, int featureType, int sessionId,
+            int callSessionType, int callType);
     IImsCallSession createCallSession(int slotId, int featureType, int sessionId,
             in ImsCallProfile profile, IImsCallSessionListener listener);
     IImsCallSession getPendingCallSession(int slotId, int featureType, int sessionId,
             String callId);
-    IImsUt getUtInterface(int slotId, int featureType, int sessionId);
-    IImsConfig getConfigInterface(int slotId, int featureType, int sessionId);
-    void turnOnIms(int slotId, int featureType, int sessionId);
-    void turnOffIms(int slotId, int featureType, int sessionId);
-    IImsEcbm getEcbmInterface(int slotId, int featureType, int sessionId);
-    void setUiTTYMode(int slotId, int featureType, int sessionId, int uiTtyMode,
-            in Message onComplete);
-    IImsMultiEndpoint getMultiEndpointInterface(int slotId, int featureType, int sessionId);
+    IImsUt getUtInterface(int slotId, int featureType);
+    IImsConfig getConfigInterface(int slotId, int featureType);
+    void turnOnIms(int slotId, int featureType);
+    void turnOffIms(int slotId, int featureType);
+    IImsEcbm getEcbmInterface(int slotId, int featureType);
+    void setUiTTYMode(int slotId, int featureType, int uiTtyMode, in Message onComplete);
+    IImsMultiEndpoint getMultiEndpointInterface(int slotId, int featureType);
 }
diff --git a/telephony/java/com/android/ims/internal/IImsServiceFeatureListener.aidl b/telephony/java/com/android/ims/internal/IImsServiceFeatureListener.aidl
index 82a13dc..df10700 100644
--- a/telephony/java/com/android/ims/internal/IImsServiceFeatureListener.aidl
+++ b/telephony/java/com/android/ims/internal/IImsServiceFeatureListener.aidl
@@ -17,7 +17,8 @@
 package com.android.ims.internal;
 
 /**
-*  Interface from ImsResolver to ImsServiceProxy in ImsManager.
+ *  Interface from ImsResolver to ImsServiceProxy in ImsManager.
+ * Callback to ImsManager when a feature changes in the ImsServiceController.
  * {@hide}
  */
 oneway interface IImsServiceFeatureListener {
diff --git a/telephony/java/com/android/ims/internal/ImsCallSession.java b/telephony/java/com/android/ims/internal/ImsCallSession.java
new file mode 100644
index 0000000..8196b23
--- /dev/null
+++ b/telephony/java/com/android/ims/internal/ImsCallSession.java
@@ -0,0 +1,1290 @@
+/*
+ * Copyright (c) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.ims.internal;
+
+import android.os.Message;
+import android.os.RemoteException;
+
+import java.util.Objects;
+
+import android.telephony.ims.stub.ImsCallSessionListenerImplBase;
+import android.util.Log;
+import com.android.ims.ImsCallProfile;
+import com.android.ims.ImsConferenceState;
+import com.android.ims.ImsReasonInfo;
+import com.android.ims.ImsStreamMediaProfile;
+import com.android.ims.ImsSuppServiceNotification;
+
+/**
+ * Provides the call initiation/termination, and media exchange between two IMS endpoints.
+ * It directly communicates with IMS service which implements the IMS protocol behavior.
+ *
+ * @hide
+ */
+public class ImsCallSession {
+    private static final String TAG = "ImsCallSession";
+
+    /**
+     * Defines IMS call session state.
+     */
+    public static class State {
+        public static final int IDLE = 0;
+        public static final int INITIATED = 1;
+        public static final int NEGOTIATING = 2;
+        public static final int ESTABLISHING = 3;
+        public static final int ESTABLISHED = 4;
+
+        public static final int RENEGOTIATING = 5;
+        public static final int REESTABLISHING = 6;
+
+        public static final int TERMINATING = 7;
+        public static final int TERMINATED = 8;
+
+        public static final int INVALID = (-1);
+
+        /**
+         * Converts the state to string.
+         */
+        public static String toString(int state) {
+            switch (state) {
+                case IDLE:
+                    return "IDLE";
+                case INITIATED:
+                    return "INITIATED";
+                case NEGOTIATING:
+                    return "NEGOTIATING";
+                case ESTABLISHING:
+                    return "ESTABLISHING";
+                case ESTABLISHED:
+                    return "ESTABLISHED";
+                case RENEGOTIATING:
+                    return "RENEGOTIATING";
+                case REESTABLISHING:
+                    return "REESTABLISHING";
+                case TERMINATING:
+                    return "TERMINATING";
+                case TERMINATED:
+                    return "TERMINATED";
+                default:
+                    return "UNKNOWN";
+            }
+        }
+
+        private State() {
+        }
+    }
+
+    /**
+     * Listener for events relating to an IMS session, such as when a session is being
+     * recieved ("on ringing") or a call is outgoing ("on calling").
+     * <p>Many of these events are also received by {@link ImsCall.Listener}.</p>
+     */
+    public static class Listener {
+        /**
+         * Called when a request is sent out to initiate a new session
+         * and 1xx response is received from the network.
+         *
+         * @param session the session object that carries out the IMS session
+         */
+        public void callSessionProgressing(ImsCallSession session,
+                ImsStreamMediaProfile profile) {
+            // no-op
+        }
+
+        /**
+         * Called when the session is established.
+         *
+         * @param session the session object that carries out the IMS session
+         */
+        public void callSessionStarted(ImsCallSession session,
+                ImsCallProfile profile) {
+            // no-op
+        }
+
+        /**
+         * Called when the session establishment is failed.
+         *
+         * @param session the session object that carries out the IMS session
+         * @param reasonInfo detailed reason of the session establishment failure
+         */
+        public void callSessionStartFailed(ImsCallSession session,
+                ImsReasonInfo reasonInfo) {
+        }
+
+        /**
+         * Called when the session is terminated.
+         *
+         * @param session the session object that carries out the IMS session
+         * @param reasonInfo detailed reason of the session termination
+         */
+        public void callSessionTerminated(ImsCallSession session,
+                ImsReasonInfo reasonInfo) {
+        }
+
+        /**
+         * Called when the session is in hold.
+         *
+         * @param session the session object that carries out the IMS session
+         */
+        public void callSessionHeld(ImsCallSession session,
+                ImsCallProfile profile) {
+        }
+
+        /**
+         * Called when the session hold is failed.
+         *
+         * @param session the session object that carries out the IMS session
+         * @param reasonInfo detailed reason of the session hold failure
+         */
+        public void callSessionHoldFailed(ImsCallSession session,
+                ImsReasonInfo reasonInfo) {
+        }
+
+        /**
+         * Called when the session hold is received from the remote user.
+         *
+         * @param session the session object that carries out the IMS session
+         */
+        public void callSessionHoldReceived(ImsCallSession session,
+                ImsCallProfile profile) {
+        }
+
+        /**
+         * Called when the session resume is done.
+         *
+         * @param session the session object that carries out the IMS session
+         */
+        public void callSessionResumed(ImsCallSession session,
+                ImsCallProfile profile) {
+        }
+
+        /**
+         * Called when the session resume is failed.
+         *
+         * @param session the session object that carries out the IMS session
+         * @param reasonInfo detailed reason of the session resume failure
+         */
+        public void callSessionResumeFailed(ImsCallSession session,
+                ImsReasonInfo reasonInfo) {
+        }
+
+        /**
+         * Called when the session resume is received from the remote user.
+         *
+         * @param session the session object that carries out the IMS session
+         */
+        public void callSessionResumeReceived(ImsCallSession session,
+                ImsCallProfile profile) {
+        }
+
+        /**
+         * Called when the session merge has been started.  At this point, the {@code newSession}
+         * represents the session which has been initiated to the IMS conference server for the
+         * new merged conference.
+         *
+         * @param session the session object that carries out the IMS session
+         * @param newSession the session object that is merged with an active & hold session
+         */
+        public void callSessionMergeStarted(ImsCallSession session,
+                ImsCallSession newSession, ImsCallProfile profile) {
+        }
+
+        /**
+         * Called when the session merge is successful and the merged session is active.
+         *
+         * @param session the session object that carries out the IMS session
+         */
+        public void callSessionMergeComplete(ImsCallSession session) {
+        }
+
+        /**
+         * Called when the session merge has failed.
+         *
+         * @param session the session object that carries out the IMS session
+         * @param reasonInfo detailed reason of the call merge failure
+         */
+        public void callSessionMergeFailed(ImsCallSession session,
+                ImsReasonInfo reasonInfo) {
+        }
+
+        /**
+         * Called when the session is updated (except for hold/unhold).
+         *
+         * @param session the session object that carries out the IMS session
+         */
+        public void callSessionUpdated(ImsCallSession session,
+                ImsCallProfile profile) {
+        }
+
+        /**
+         * Called when the session update is failed.
+         *
+         * @param session the session object that carries out the IMS session
+         * @param reasonInfo detailed reason of the session update failure
+         */
+        public void callSessionUpdateFailed(ImsCallSession session,
+                ImsReasonInfo reasonInfo) {
+        }
+
+        /**
+         * Called when the session update is received from the remote user.
+         *
+         * @param session the session object that carries out the IMS session
+         */
+        public void callSessionUpdateReceived(ImsCallSession session,
+                ImsCallProfile profile) {
+            // no-op
+        }
+
+        /**
+         * Called when the session is extended to the conference session.
+         *
+         * @param session the session object that carries out the IMS session
+         * @param newSession the session object that is extended to the conference
+         *      from the active session
+         */
+        public void callSessionConferenceExtended(ImsCallSession session,
+                ImsCallSession newSession, ImsCallProfile profile) {
+        }
+
+        /**
+         * Called when the conference extension is failed.
+         *
+         * @param session the session object that carries out the IMS session
+         * @param reasonInfo detailed reason of the conference extension failure
+         */
+        public void callSessionConferenceExtendFailed(ImsCallSession session,
+                ImsReasonInfo reasonInfo) {
+        }
+
+        /**
+         * Called when the conference extension is received from the remote user.
+         *
+         * @param session the session object that carries out the IMS session
+         */
+        public void callSessionConferenceExtendReceived(ImsCallSession session,
+                ImsCallSession newSession, ImsCallProfile profile) {
+            // no-op
+        }
+
+        /**
+         * Called when the invitation request of the participants is delivered to the conference
+         * server.
+         *
+         * @param session the session object that carries out the IMS session
+         */
+        public void callSessionInviteParticipantsRequestDelivered(ImsCallSession session) {
+            // no-op
+        }
+
+        /**
+         * Called when the invitation request of the participants is failed.
+         *
+         * @param session the session object that carries out the IMS session
+         * @param reasonInfo detailed reason of the conference invitation failure
+         */
+        public void callSessionInviteParticipantsRequestFailed(ImsCallSession session,
+                ImsReasonInfo reasonInfo) {
+            // no-op
+        }
+
+        /**
+         * Called when the removal request of the participants is delivered to the conference
+         * server.
+         *
+         * @param session the session object that carries out the IMS session
+         */
+        public void callSessionRemoveParticipantsRequestDelivered(ImsCallSession session) {
+            // no-op
+        }
+
+        /**
+         * Called when the removal request of the participants is failed.
+         *
+         * @param session the session object that carries out the IMS session
+         * @param reasonInfo detailed reason of the conference removal failure
+         */
+        public void callSessionRemoveParticipantsRequestFailed(ImsCallSession session,
+                ImsReasonInfo reasonInfo) {
+            // no-op
+        }
+
+        /**
+         * Called when the conference state is updated.
+         *
+         * @param session the session object that carries out the IMS session
+         */
+        public void callSessionConferenceStateUpdated(ImsCallSession session,
+                ImsConferenceState state) {
+            // no-op
+        }
+
+        /**
+         * Called when the USSD message is received from the network.
+         *
+         * @param mode mode of the USSD message (REQUEST / NOTIFY)
+         * @param ussdMessage USSD message
+         */
+        public void callSessionUssdMessageReceived(ImsCallSession session,
+                int mode, String ussdMessage) {
+            // no-op
+        }
+
+        /**
+         * Called when session access technology changes
+         *
+         * @param session IMS session object
+         * @param srcAccessTech original access technology
+         * @param targetAccessTech new access technology
+         * @param reasonInfo
+         */
+        public void callSessionHandover(ImsCallSession session,
+                                 int srcAccessTech, int targetAccessTech,
+                                 ImsReasonInfo reasonInfo) {
+            // no-op
+        }
+
+        /**
+         * Called when session access technology change fails
+         *
+         * @param session IMS session object
+         * @param srcAccessTech original access technology
+         * @param targetAccessTech new access technology
+         * @param reasonInfo handover failure reason
+         */
+        public void callSessionHandoverFailed(ImsCallSession session,
+                                       int srcAccessTech, int targetAccessTech,
+                                       ImsReasonInfo reasonInfo) {
+            // no-op
+        }
+
+        /**
+         * Called when TTY mode of remote party changed
+         *
+         * @param session IMS session object
+         * @param mode TTY mode of remote party
+         */
+        public void callSessionTtyModeReceived(ImsCallSession session,
+                                       int mode) {
+            // no-op
+        }
+
+        /**
+         * Notifies of a change to the multiparty state for this {@code ImsCallSession}.
+         *
+         * @param session The call session.
+         * @param isMultiParty {@code true} if the session became multiparty, {@code false}
+         *      otherwise.
+         */
+        public void callSessionMultipartyStateChanged(ImsCallSession session,
+                boolean isMultiParty) {
+            // no-op
+        }
+
+        /**
+         * Called when the session supplementary service is received
+         *
+         * @param session the session object that carries out the IMS session
+         */
+        public void callSessionSuppServiceReceived(ImsCallSession session,
+                ImsSuppServiceNotification suppServiceInfo) {
+        }
+    }
+
+    private final IImsCallSession miSession;
+    private boolean mClosed = false;
+    private Listener mListener;
+
+    public ImsCallSession(IImsCallSession iSession) {
+        miSession = iSession;
+
+        if (iSession != null) {
+            try {
+                iSession.setListener(new IImsCallSessionListenerProxy());
+            } catch (RemoteException e) {
+            }
+        } else {
+            mClosed = true;
+        }
+    }
+
+    public ImsCallSession(IImsCallSession iSession, Listener listener) {
+        this(iSession);
+        setListener(listener);
+    }
+
+    /**
+     * Closes this object. This object is not usable after being closed.
+     */
+    public synchronized void close() {
+        if (mClosed) {
+            return;
+        }
+
+        try {
+            miSession.close();
+            mClosed = true;
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Gets the call ID of the session.
+     *
+     * @return the call ID
+     */
+    public String getCallId() {
+        if (mClosed) {
+            return null;
+        }
+
+        try {
+            return miSession.getCallId();
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Gets the call profile that this session is associated with
+     *
+     * @return the call profile that this session is associated with
+     */
+    public ImsCallProfile getCallProfile() {
+        if (mClosed) {
+            return null;
+        }
+
+        try {
+            return miSession.getCallProfile();
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Gets the local call profile that this session is associated with
+     *
+     * @return the local call profile that this session is associated with
+     */
+    public ImsCallProfile getLocalCallProfile() {
+        if (mClosed) {
+            return null;
+        }
+
+        try {
+            return miSession.getLocalCallProfile();
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Gets the remote call profile that this session is associated with
+     *
+     * @return the remote call profile that this session is associated with
+     */
+    public ImsCallProfile getRemoteCallProfile() {
+        if (mClosed) {
+            return null;
+        }
+
+        try {
+            return miSession.getRemoteCallProfile();
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Gets the video call provider for the session.
+     *
+     * @return The video call provider.
+     */
+    public IImsVideoCallProvider getVideoCallProvider() {
+        if (mClosed) {
+            return null;
+        }
+
+        try {
+            return miSession.getVideoCallProvider();
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Gets the value associated with the specified property of this session.
+     *
+     * @return the string value associated with the specified property
+     */
+    public String getProperty(String name) {
+        if (mClosed) {
+            return null;
+        }
+
+        try {
+            return miSession.getProperty(name);
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Gets the session state.
+     * The value returned must be one of the states in {@link State}.
+     *
+     * @return the session state
+     */
+    public int getState() {
+        if (mClosed) {
+            return State.INVALID;
+        }
+
+        try {
+            return miSession.getState();
+        } catch (RemoteException e) {
+            return State.INVALID;
+        }
+    }
+
+    /**
+     * Determines if the {@link ImsCallSession} is currently alive (e.g. not in a terminated or
+     * closed state).
+     *
+     * @return {@code True} if the session is alive.
+     */
+    public boolean isAlive() {
+        if (mClosed) {
+            return false;
+        }
+
+        int state = getState();
+        switch (state) {
+            case State.IDLE:
+            case State.INITIATED:
+            case State.NEGOTIATING:
+            case State.ESTABLISHING:
+            case State.ESTABLISHED:
+            case State.RENEGOTIATING:
+            case State.REESTABLISHING:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    /**
+     * Gets the native IMS call session.
+     * @hide
+     */
+    public IImsCallSession getSession() {
+        return miSession;
+    }
+
+    /**
+     * Checks if the session is in call.
+     *
+     * @return true if the session is in call
+     */
+    public boolean isInCall() {
+        if (mClosed) {
+            return false;
+        }
+
+        try {
+            return miSession.isInCall();
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /**
+     * Sets the listener to listen to the session events. A {@link ImsCallSession}
+     * can only hold one listener at a time. Subsequent calls to this method
+     * override the previous listener.
+     *
+     * @param listener to listen to the session events of this object
+     */
+    public void setListener(Listener listener) {
+        mListener = listener;
+    }
+
+    /**
+     * Mutes or unmutes the mic for the active call.
+     *
+     * @param muted true if the call is muted, false otherwise
+     */
+    public void setMute(boolean muted) {
+        if (mClosed) {
+            return;
+        }
+
+        try {
+            miSession.setMute(muted);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Initiates an IMS call with the specified target and call profile.
+     * The session listener is called back upon defined session events.
+     * The method is only valid to call when the session state is in
+     * {@link ImsCallSession.State#IDLE}.
+     *
+     * @param callee dialed string to make the call to
+     * @param profile call profile to make the call with the specified service type,
+     *      call type and media information
+     * @see Listener#callSessionStarted, Listener#callSessionStartFailed
+     */
+    public void start(String callee, ImsCallProfile profile) {
+        if (mClosed) {
+            return;
+        }
+
+        try {
+            miSession.start(callee, profile);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Initiates an IMS conference call with the specified target and call profile.
+     * The session listener is called back upon defined session events.
+     * The method is only valid to call when the session state is in
+     * {@link ImsCallSession.State#IDLE}.
+     *
+     * @param participants participant list to initiate an IMS conference call
+     * @param profile call profile to make the call with the specified service type,
+     *      call type and media information
+     * @see Listener#callSessionStarted, Listener#callSessionStartFailed
+     */
+    public void start(String[] participants, ImsCallProfile profile) {
+        if (mClosed) {
+            return;
+        }
+
+        try {
+            miSession.startConference(participants, profile);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Accepts an incoming call or session update.
+     *
+     * @param callType call type specified in {@link ImsCallProfile} to be answered
+     * @param profile stream media profile {@link ImsStreamMediaProfile} to be answered
+     * @see Listener#callSessionStarted
+     */
+    public void accept(int callType, ImsStreamMediaProfile profile) {
+        if (mClosed) {
+            return;
+        }
+
+        try {
+            miSession.accept(callType, profile);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Rejects an incoming call or session update.
+     *
+     * @param reason reason code to reject an incoming call
+     * @see Listener#callSessionStartFailed
+     */
+    public void reject(int reason) {
+        if (mClosed) {
+            return;
+        }
+
+        try {
+            miSession.reject(reason);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Terminates a call.
+     *
+     * @see Listener#callSessionTerminated
+     */
+    public void terminate(int reason) {
+        if (mClosed) {
+            return;
+        }
+
+        try {
+            miSession.terminate(reason);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Puts a call on hold. When it succeeds, {@link Listener#callSessionHeld} is called.
+     *
+     * @param profile stream media profile {@link ImsStreamMediaProfile} to hold the call
+     * @see Listener#callSessionHeld, Listener#callSessionHoldFailed
+     */
+    public void hold(ImsStreamMediaProfile profile) {
+        if (mClosed) {
+            return;
+        }
+
+        try {
+            miSession.hold(profile);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Continues a call that's on hold. When it succeeds,
+     * {@link Listener#callSessionResumed} is called.
+     *
+     * @param profile stream media profile {@link ImsStreamMediaProfile} to resume the call
+     * @see Listener#callSessionResumed, Listener#callSessionResumeFailed
+     */
+    public void resume(ImsStreamMediaProfile profile) {
+        if (mClosed) {
+            return;
+        }
+
+        try {
+            miSession.resume(profile);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Merges the active & hold call. When it succeeds,
+     * {@link Listener#callSessionMergeStarted} is called.
+     *
+     * @see Listener#callSessionMergeStarted , Listener#callSessionMergeFailed
+     */
+    public void merge() {
+        if (mClosed) {
+            return;
+        }
+
+        try {
+            miSession.merge();
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Updates the current call's properties (ex. call mode change: video upgrade / downgrade).
+     *
+     * @param callType call type specified in {@link ImsCallProfile} to be updated
+     * @param profile stream media profile {@link ImsStreamMediaProfile} to be updated
+     * @see Listener#callSessionUpdated, Listener#callSessionUpdateFailed
+     */
+    public void update(int callType, ImsStreamMediaProfile profile) {
+        if (mClosed) {
+            return;
+        }
+
+        try {
+            miSession.update(callType, profile);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Extends this call to the conference call with the specified recipients.
+     *
+     * @param participants list to be invited to the conference call after extending the call
+     * @see Listener#callSessionConferenceExtended
+     * @see Listener#callSessionConferenceExtendFailed
+     */
+    public void extendToConference(String[] participants) {
+        if (mClosed) {
+            return;
+        }
+
+        try {
+            miSession.extendToConference(participants);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Requests the conference server to invite an additional participants to the conference.
+     *
+     * @param participants list to be invited to the conference call
+     * @see Listener#callSessionInviteParticipantsRequestDelivered
+     * @see Listener#callSessionInviteParticipantsRequestFailed
+     */
+    public void inviteParticipants(String[] participants) {
+        if (mClosed) {
+            return;
+        }
+
+        try {
+            miSession.inviteParticipants(participants);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Requests the conference server to remove the specified participants from the conference.
+     *
+     * @param participants participant list to be removed from the conference call
+     * @see Listener#callSessionRemoveParticipantsRequestDelivered
+     * @see Listener#callSessionRemoveParticipantsRequestFailed
+     */
+    public void removeParticipants(String[] participants) {
+        if (mClosed) {
+            return;
+        }
+
+        try {
+            miSession.removeParticipants(participants);
+        } catch (RemoteException e) {
+        }
+    }
+
+
+    /**
+     * Sends a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>,
+     * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15,
+     * and event flash to 16. Currently, event flash is not supported.
+     *
+     * @param c the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs.
+     */
+    public void sendDtmf(char c, Message result) {
+        if (mClosed) {
+            return;
+        }
+
+        try {
+            miSession.sendDtmf(c, result);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Starts a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>,
+     * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15,
+     * and event flash to 16. Currently, event flash is not supported.
+     *
+     * @param c the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs.
+     */
+    public void startDtmf(char c) {
+        if (mClosed) {
+            return;
+        }
+
+        try {
+            miSession.startDtmf(c);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Stops a DTMF code.
+     */
+    public void stopDtmf() {
+        if (mClosed) {
+            return;
+        }
+
+        try {
+            miSession.stopDtmf();
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Sends an USSD message.
+     *
+     * @param ussdMessage USSD message to send
+     */
+    public void sendUssd(String ussdMessage) {
+        if (mClosed) {
+            return;
+        }
+
+        try {
+            miSession.sendUssd(ussdMessage);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Determines if the session is multiparty.
+     *
+     * @return {@code True} if the session is multiparty.
+     */
+    public boolean isMultiparty() {
+        if (mClosed) {
+            return false;
+        }
+
+        try {
+            return miSession.isMultiparty();
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /**
+     * A listener type for receiving notification on IMS call session events.
+     * When an event is generated for an {@link IImsCallSession},
+     * the application is notified by having one of the methods called on
+     * the {@link IImsCallSessionListener}.
+     */
+    private class IImsCallSessionListenerProxy extends ImsCallSessionListenerImplBase {
+        /**
+         * Notifies the result of the basic session operation (setup / terminate).
+         */
+        @Override
+        public void callSessionProgressing(IImsCallSession session,
+                ImsStreamMediaProfile profile) {
+            if (mListener != null) {
+                mListener.callSessionProgressing(ImsCallSession.this, profile);
+            }
+        }
+
+        @Override
+        public void callSessionStarted(IImsCallSession session,
+                ImsCallProfile profile) {
+            if (mListener != null) {
+                mListener.callSessionStarted(ImsCallSession.this, profile);
+            }
+        }
+
+        @Override
+        public void callSessionStartFailed(IImsCallSession session,
+                ImsReasonInfo reasonInfo) {
+            if (mListener != null) {
+                mListener.callSessionStartFailed(ImsCallSession.this, reasonInfo);
+            }
+        }
+
+        @Override
+        public void callSessionTerminated(IImsCallSession session,
+                ImsReasonInfo reasonInfo) {
+            if (mListener != null) {
+                mListener.callSessionTerminated(ImsCallSession.this, reasonInfo);
+            }
+        }
+
+        /**
+         * Notifies the result of the call hold/resume operation.
+         */
+        @Override
+        public void callSessionHeld(IImsCallSession session,
+                ImsCallProfile profile) {
+            if (mListener != null) {
+                mListener.callSessionHeld(ImsCallSession.this, profile);
+            }
+        }
+
+        @Override
+        public void callSessionHoldFailed(IImsCallSession session,
+                ImsReasonInfo reasonInfo) {
+            if (mListener != null) {
+                mListener.callSessionHoldFailed(ImsCallSession.this, reasonInfo);
+            }
+        }
+
+        @Override
+        public void callSessionHoldReceived(IImsCallSession session,
+                ImsCallProfile profile) {
+            if (mListener != null) {
+                mListener.callSessionHoldReceived(ImsCallSession.this, profile);
+            }
+        }
+
+        @Override
+        public void callSessionResumed(IImsCallSession session,
+                ImsCallProfile profile) {
+            if (mListener != null) {
+                mListener.callSessionResumed(ImsCallSession.this, profile);
+            }
+        }
+
+        @Override
+        public void callSessionResumeFailed(IImsCallSession session,
+                ImsReasonInfo reasonInfo) {
+            if (mListener != null) {
+                mListener.callSessionResumeFailed(ImsCallSession.this, reasonInfo);
+            }
+        }
+
+        @Override
+        public void callSessionResumeReceived(IImsCallSession session,
+                ImsCallProfile profile) {
+            if (mListener != null) {
+                mListener.callSessionResumeReceived(ImsCallSession.this, profile);
+            }
+        }
+
+        /**
+         * Notifies the start of a call merge operation.
+         *
+         * @param session The call session.
+         * @param newSession The merged call session.
+         * @param profile The call profile.
+         */
+        @Override
+        public void callSessionMergeStarted(IImsCallSession session,
+                IImsCallSession newSession, ImsCallProfile profile) {
+            // This callback can be used for future use to add additional
+            // functionality that may be needed between conference start and complete
+            Log.d(TAG, "callSessionMergeStarted");
+        }
+
+        /**
+         * Notifies the successful completion of a call merge operation.
+         *
+         * @param newSession The call session.
+         */
+        @Override
+        public void callSessionMergeComplete(IImsCallSession newSession) {
+            if (mListener != null) {
+                if (newSession != null) {
+                    // Check if the active session is the same session that was
+                    // active before the merge request was sent.
+                    ImsCallSession validActiveSession = ImsCallSession.this;
+                    try {
+                        if (!Objects.equals(miSession.getCallId(), newSession.getCallId())) {
+                            // New session created after conference
+                            validActiveSession = new ImsCallSession(newSession);
+                        }
+                    } catch (RemoteException rex) {
+                        Log.e(TAG, "callSessionMergeComplete: exception for getCallId!");
+                    }
+                    mListener.callSessionMergeComplete(validActiveSession);
+               } else {
+                   // Session already exists. Hence no need to pass
+                   mListener.callSessionMergeComplete(null);
+               }
+            }
+        }
+
+        /**
+         * Notifies of a failure to perform a call merge operation.
+         *
+         * @param session The call session.
+         * @param reasonInfo The merge failure reason.
+         */
+        @Override
+        public void callSessionMergeFailed(IImsCallSession session,
+                ImsReasonInfo reasonInfo) {
+            if (mListener != null) {
+                mListener.callSessionMergeFailed(ImsCallSession.this, reasonInfo);
+            }
+        }
+
+        /**
+         * Notifies the result of call upgrade / downgrade or any other call updates.
+         */
+        @Override
+        public void callSessionUpdated(IImsCallSession session,
+                ImsCallProfile profile) {
+            if (mListener != null) {
+                mListener.callSessionUpdated(ImsCallSession.this, profile);
+            }
+        }
+
+        @Override
+        public void callSessionUpdateFailed(IImsCallSession session,
+                ImsReasonInfo reasonInfo) {
+            if (mListener != null) {
+                mListener.callSessionUpdateFailed(ImsCallSession.this, reasonInfo);
+            }
+        }
+
+        @Override
+        public void callSessionUpdateReceived(IImsCallSession session,
+                ImsCallProfile profile) {
+            if (mListener != null) {
+                mListener.callSessionUpdateReceived(ImsCallSession.this, profile);
+            }
+        }
+
+        /**
+         * Notifies the result of conference extension.
+         */
+        @Override
+        public void callSessionConferenceExtended(IImsCallSession session,
+                IImsCallSession newSession, ImsCallProfile profile) {
+            if (mListener != null) {
+                mListener.callSessionConferenceExtended(ImsCallSession.this,
+                        new ImsCallSession(newSession), profile);
+            }
+        }
+
+        @Override
+        public void callSessionConferenceExtendFailed(IImsCallSession session,
+                ImsReasonInfo reasonInfo) {
+            if (mListener != null) {
+                mListener.callSessionConferenceExtendFailed(ImsCallSession.this, reasonInfo);
+            }
+        }
+
+        @Override
+        public void callSessionConferenceExtendReceived(IImsCallSession session,
+                IImsCallSession newSession, ImsCallProfile profile) {
+            if (mListener != null) {
+                mListener.callSessionConferenceExtendReceived(ImsCallSession.this,
+                        new ImsCallSession(newSession), profile);
+            }
+        }
+
+        /**
+         * Notifies the result of the participant invitation / removal to/from
+         * the conference session.
+         */
+        @Override
+        public void callSessionInviteParticipantsRequestDelivered(IImsCallSession session) {
+            if (mListener != null) {
+                mListener.callSessionInviteParticipantsRequestDelivered(ImsCallSession.this);
+            }
+        }
+
+        @Override
+        public void callSessionInviteParticipantsRequestFailed(IImsCallSession session,
+                ImsReasonInfo reasonInfo) {
+            if (mListener != null) {
+                mListener.callSessionInviteParticipantsRequestFailed(ImsCallSession.this,
+                        reasonInfo);
+            }
+        }
+
+        @Override
+        public void callSessionRemoveParticipantsRequestDelivered(IImsCallSession session) {
+            if (mListener != null) {
+                mListener.callSessionRemoveParticipantsRequestDelivered(ImsCallSession.this);
+            }
+        }
+
+        @Override
+        public void callSessionRemoveParticipantsRequestFailed(IImsCallSession session,
+                ImsReasonInfo reasonInfo) {
+            if (mListener != null) {
+                mListener.callSessionRemoveParticipantsRequestFailed(ImsCallSession.this,
+                        reasonInfo);
+            }
+        }
+
+        /**
+         * Notifies the changes of the conference info. in the conference session.
+         */
+        @Override
+        public void callSessionConferenceStateUpdated(IImsCallSession session,
+                ImsConferenceState state) {
+            if (mListener != null) {
+                mListener.callSessionConferenceStateUpdated(ImsCallSession.this, state);
+            }
+        }
+
+        /**
+         * Notifies the incoming USSD message.
+         */
+        @Override
+        public void callSessionUssdMessageReceived(IImsCallSession session,
+                int mode, String ussdMessage) {
+            if (mListener != null) {
+                mListener.callSessionUssdMessageReceived(ImsCallSession.this, mode, ussdMessage);
+            }
+        }
+
+        /**
+         * Notifies of handover information for this call
+         */
+        @Override
+        public void callSessionHandover(IImsCallSession session,
+                                 int srcAccessTech, int targetAccessTech,
+                                 ImsReasonInfo reasonInfo) {
+            if (mListener != null) {
+                mListener.callSessionHandover(ImsCallSession.this, srcAccessTech,
+                        targetAccessTech, reasonInfo);
+            }
+        }
+
+        /**
+         * Notifies of handover failure info for this call
+         */
+        @Override
+        public void callSessionHandoverFailed(IImsCallSession session,
+                                       int srcAccessTech, int targetAccessTech,
+                                       ImsReasonInfo reasonInfo) {
+            if (mListener != null) {
+                mListener.callSessionHandoverFailed(ImsCallSession.this, srcAccessTech,
+                        targetAccessTech, reasonInfo);
+            }
+        }
+
+        /**
+         * Notifies the TTY mode received from remote party.
+         */
+        @Override
+        public void callSessionTtyModeReceived(IImsCallSession session,
+                int mode) {
+            if (mListener != null) {
+                mListener.callSessionTtyModeReceived(ImsCallSession.this, mode);
+            }
+        }
+
+        /**
+         * Notifies of a change to the multiparty state for this {@code ImsCallSession}.
+         *
+         * @param session The call session.
+         * @param isMultiParty {@code true} if the session became multiparty, {@code false}
+         *      otherwise.
+         */
+        public void callSessionMultipartyStateChanged(IImsCallSession session,
+                boolean isMultiParty) {
+
+            if (mListener != null) {
+                mListener.callSessionMultipartyStateChanged(ImsCallSession.this, isMultiParty);
+            }
+        }
+
+        @Override
+        public void callSessionSuppServiceReceived(IImsCallSession session,
+                ImsSuppServiceNotification suppServiceInfo ) {
+            if (mListener != null) {
+                mListener.callSessionSuppServiceReceived(ImsCallSession.this, suppServiceInfo);
+            }
+        }
+
+    }
+
+    /**
+     * Provides a string representation of the {@link ImsCallSession}.  Primarily intended for
+     * use in log statements.
+     *
+     * @return String representation of session.
+     */
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("[ImsCallSession objId:");
+        sb.append(System.identityHashCode(this));
+        sb.append(" state:");
+        sb.append(State.toString(getState()));
+        sb.append(" callId:");
+        sb.append(getCallId());
+        sb.append("]");
+        return sb.toString();
+    }
+}
diff --git a/telephony/java/com/android/ims/internal/ImsVideoCallProvider.java b/telephony/java/com/android/ims/internal/ImsVideoCallProvider.java
new file mode 100644
index 0000000..432dc39
--- /dev/null
+++ b/telephony/java/com/android/ims/internal/ImsVideoCallProvider.java
@@ -0,0 +1,294 @@
+/*
+ * 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.ims.internal;
+
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.telecom.Connection;
+import android.telecom.VideoProfile;
+import android.telecom.VideoProfile.CameraCapabilities;
+import android.view.Surface;
+
+import com.android.internal.os.SomeArgs;
+
+/**
+ * @hide
+ */
+public abstract class ImsVideoCallProvider {
+    private static final int MSG_SET_CALLBACK = 1;
+    private static final int MSG_SET_CAMERA = 2;
+    private static final int MSG_SET_PREVIEW_SURFACE = 3;
+    private static final int MSG_SET_DISPLAY_SURFACE = 4;
+    private static final int MSG_SET_DEVICE_ORIENTATION = 5;
+    private static final int MSG_SET_ZOOM = 6;
+    private static final int MSG_SEND_SESSION_MODIFY_REQUEST = 7;
+    private static final int MSG_SEND_SESSION_MODIFY_RESPONSE = 8;
+    private static final int MSG_REQUEST_CAMERA_CAPABILITIES = 9;
+    private static final int MSG_REQUEST_CALL_DATA_USAGE = 10;
+    private static final int MSG_SET_PAUSE_IMAGE = 11;
+
+    private final ImsVideoCallProviderBinder mBinder;
+
+    private IImsVideoCallCallback mCallback;
+
+    /**
+     * Default handler used to consolidate binder method calls onto a single thread.
+     */
+    private final Handler mProviderHandler = new Handler(Looper.getMainLooper()) {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_SET_CALLBACK:
+                    mCallback = (IImsVideoCallCallback) msg.obj;
+                    break;
+                case MSG_SET_CAMERA:
+                {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    try {
+                        onSetCamera((String) args.arg1);
+                        onSetCamera((String) args.arg1, args.argi1);
+                    } finally {
+                        args.recycle();
+                    }
+                    break;
+                }
+                case MSG_SET_PREVIEW_SURFACE:
+                    onSetPreviewSurface((Surface) msg.obj);
+                    break;
+                case MSG_SET_DISPLAY_SURFACE:
+                    onSetDisplaySurface((Surface) msg.obj);
+                    break;
+                case MSG_SET_DEVICE_ORIENTATION:
+                    onSetDeviceOrientation(msg.arg1);
+                    break;
+                case MSG_SET_ZOOM:
+                    onSetZoom((Float) msg.obj);
+                    break;
+                case MSG_SEND_SESSION_MODIFY_REQUEST: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    try {
+                        VideoProfile fromProfile = (VideoProfile) args.arg1;
+                        VideoProfile toProfile = (VideoProfile) args.arg2;
+
+                        onSendSessionModifyRequest(fromProfile, toProfile);
+                    } finally {
+                        args.recycle();
+                    }
+                    break;
+                }
+                case MSG_SEND_SESSION_MODIFY_RESPONSE:
+                    onSendSessionModifyResponse((VideoProfile) msg.obj);
+                    break;
+                case MSG_REQUEST_CAMERA_CAPABILITIES:
+                    onRequestCameraCapabilities();
+                    break;
+                case MSG_REQUEST_CALL_DATA_USAGE:
+                    onRequestCallDataUsage();
+                    break;
+                case MSG_SET_PAUSE_IMAGE:
+                    onSetPauseImage((Uri) msg.obj);
+                    break;
+                default:
+                    break;
+            }
+        }
+    };
+
+    /**
+     * IImsVideoCallProvider stub implementation.
+     */
+    private final class ImsVideoCallProviderBinder extends IImsVideoCallProvider.Stub {
+        public void setCallback(IImsVideoCallCallback callback) {
+            mProviderHandler.obtainMessage(MSG_SET_CALLBACK, callback).sendToTarget();
+        }
+
+        public void setCamera(String cameraId, int uid) {
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = cameraId;
+            args.argi1 = uid;
+            mProviderHandler.obtainMessage(MSG_SET_CAMERA, args).sendToTarget();
+        }
+
+        public void setPreviewSurface(Surface surface) {
+            mProviderHandler.obtainMessage(MSG_SET_PREVIEW_SURFACE, surface).sendToTarget();
+        }
+
+        public void setDisplaySurface(Surface surface) {
+            mProviderHandler.obtainMessage(MSG_SET_DISPLAY_SURFACE, surface).sendToTarget();
+        }
+
+        public void setDeviceOrientation(int rotation) {
+            mProviderHandler.obtainMessage(MSG_SET_DEVICE_ORIENTATION, rotation, 0).sendToTarget();
+        }
+
+        public void setZoom(float value) {
+            mProviderHandler.obtainMessage(MSG_SET_ZOOM, value).sendToTarget();
+        }
+
+        public void sendSessionModifyRequest(VideoProfile fromProfile, VideoProfile toProfile) {
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = fromProfile;
+            args.arg2 = toProfile;
+            mProviderHandler.obtainMessage(MSG_SEND_SESSION_MODIFY_REQUEST, args).sendToTarget();
+        }
+
+        public void sendSessionModifyResponse(VideoProfile responseProfile) {
+            mProviderHandler.obtainMessage(
+                    MSG_SEND_SESSION_MODIFY_RESPONSE, responseProfile).sendToTarget();
+        }
+
+        public void requestCameraCapabilities() {
+            mProviderHandler.obtainMessage(MSG_REQUEST_CAMERA_CAPABILITIES).sendToTarget();
+        }
+
+        public void requestCallDataUsage() {
+            mProviderHandler.obtainMessage(MSG_REQUEST_CALL_DATA_USAGE).sendToTarget();
+        }
+
+        public void setPauseImage(Uri uri) {
+            mProviderHandler.obtainMessage(MSG_SET_PAUSE_IMAGE, uri).sendToTarget();
+        }
+    }
+
+    public ImsVideoCallProvider() {
+        mBinder = new ImsVideoCallProviderBinder();
+    }
+
+    /**
+     * Returns binder object which can be used across IPC methods.
+     */
+    public final IImsVideoCallProvider getInterface() {
+        return mBinder;
+    }
+
+    /** @see Connection.VideoProvider#onSetCamera */
+    public abstract void onSetCamera(String cameraId);
+
+    /**
+     * Similar to {@link #onSetCamera(String)}, except includes the UID of the calling process which
+     * the IMS service uses when opening the camera.  This ensures camera permissions are verified
+     * by the camera service.
+     *
+     * @param cameraId The id of the camera to be opened.
+     * @param uid The uid of the caller, used when opening the camera for permission verification.
+     * @see Connection.VideoProvider#onSetCamera
+     */
+    public void onSetCamera(String cameraId, int uid) {
+    }
+
+    /** @see Connection.VideoProvider#onSetPreviewSurface */
+    public abstract void onSetPreviewSurface(Surface surface);
+
+    /** @see Connection.VideoProvider#onSetDisplaySurface */
+    public abstract void onSetDisplaySurface(Surface surface);
+
+    /** @see Connection.VideoProvider#onSetDeviceOrientation */
+    public abstract void onSetDeviceOrientation(int rotation);
+
+    /** @see Connection.VideoProvider#onSetZoom */
+    public abstract void onSetZoom(float value);
+
+    /** @see Connection.VideoProvider#onSendSessionModifyRequest */
+    public abstract void onSendSessionModifyRequest(VideoProfile fromProfile,
+            VideoProfile toProfile);
+
+    /** @see Connection.VideoProvider#onSendSessionModifyResponse */
+    public abstract void onSendSessionModifyResponse(VideoProfile responseProfile);
+
+    /** @see Connection.VideoProvider#onRequestCameraCapabilities */
+    public abstract void onRequestCameraCapabilities();
+
+    /** @see Connection.VideoProvider#onRequestCallDataUsage */
+    public abstract void onRequestCallDataUsage();
+
+    /** @see Connection.VideoProvider#onSetPauseImage */
+    public abstract void onSetPauseImage(Uri uri);
+
+    /** @see Connection.VideoProvider#receiveSessionModifyRequest */
+    public void receiveSessionModifyRequest(VideoProfile VideoProfile) {
+        if (mCallback != null) {
+            try {
+                mCallback.receiveSessionModifyRequest(VideoProfile);
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
+    /** @see Connection.VideoProvider#receiveSessionModifyResponse */
+    public void receiveSessionModifyResponse(
+            int status, VideoProfile requestedProfile, VideoProfile responseProfile) {
+        if (mCallback != null) {
+            try {
+                mCallback.receiveSessionModifyResponse(status, requestedProfile, responseProfile);
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
+    /** @see Connection.VideoProvider#handleCallSessionEvent */
+    public void handleCallSessionEvent(int event) {
+        if (mCallback != null) {
+            try {
+                mCallback.handleCallSessionEvent(event);
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
+    /** @see Connection.VideoProvider#changePeerDimensions */
+    public void changePeerDimensions(int width, int height) {
+        if (mCallback != null) {
+            try {
+                mCallback.changePeerDimensions(width, height);
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
+    /** @see Connection.VideoProvider#changeCallDataUsage */
+    public void changeCallDataUsage(long dataUsage) {
+        if (mCallback != null) {
+            try {
+                mCallback.changeCallDataUsage(dataUsage);
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
+    /** @see Connection.VideoProvider#changeCameraCapabilities */
+    public void changeCameraCapabilities(CameraCapabilities CameraCapabilities) {
+        if (mCallback != null) {
+            try {
+                mCallback.changeCameraCapabilities(CameraCapabilities);
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
+    /** @see Connection.VideoProvider#changeVideoQuality */
+    public void changeVideoQuality(int videoQuality) {
+        if (mCallback != null) {
+            try {
+                mCallback.changeVideoQuality(videoQuality);
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index e6a6178..220ea14 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -527,7 +527,7 @@
      * Send a visual voicemail SMS. Internal use only.
      * Requires caller to be the default dialer and have SEND_SMS permission
      */
-    oneway void sendVisualVoicemailSmsForSubscriber(in String callingPackage, in int subId,
+    void sendVisualVoicemailSmsForSubscriber(in String callingPackage, in int subId,
             in String number, in int port, in String text, in PendingIntent sentIntent);
 
     // Send the special dialer code. The IPC caller must be the current default dialer.
@@ -1278,7 +1278,6 @@
      */
     void setPolicyDataEnabled(boolean enabled, int subId);
 
-
     /**
      * Get Client request stats which will contain statistical information
      * on each request made by client.
@@ -1287,4 +1286,24 @@
      * @hide
      */
     List<ClientRequestStats> getClientRequestStats(String callingPackage, int subid);
+
+    /**
+     * Set SIM card power state. Request is equivalent to inserting or removing the card.
+     * @param slotId SIM slot id
+     * @param powerUp True if powering up the SIM, otherwise powering down
+     * @hide
+     * */
+    void setSimPowerStateForSlot(int slotId, boolean powerUp);
+
+    /**
+     * Returns a list of Forbidden PLMNs from the specified SIM App
+     * Returns null if the query fails.
+     *
+     *
+     * <p>Requires that the calling app has READ_PRIVILEGED_PHONE_STATE
+     *
+     * @param subId subscription ID used for authentication
+     * @param appType the icc application type, like {@link #APPTYPE_USIM}
+     */
+    String[] getForbiddenPlmns(int subId, int appType);
 }
diff --git a/telephony/java/com/android/internal/telephony/IccUtils.java b/telephony/java/com/android/internal/telephony/IccUtils.java
new file mode 100644
index 0000000..67de87f
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/IccUtils.java
@@ -0,0 +1,570 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.uicc;
+
+import android.content.res.Resources;
+import android.content.res.Resources.NotFoundException;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.telephony.Rlog;
+
+import com.android.internal.telephony.GsmAlphabet;
+
+import java.io.UnsupportedEncodingException;
+
+/**
+ * Various methods, useful for dealing with SIM data.
+ */
+public class IccUtils {
+    static final String LOG_TAG="IccUtils";
+
+    /**
+     * Many fields in GSM SIM's are stored as nibble-swizzled BCD
+     *
+     * Assumes left-justified field that may be padded right with 0xf
+     * values.
+     *
+     * Stops on invalid BCD value, returning string so far
+     */
+    public static String
+    bcdToString(byte[] data, int offset, int length) {
+        StringBuilder ret = new StringBuilder(length*2);
+
+        for (int i = offset ; i < offset + length ; i++) {
+            int v;
+
+            v = data[i] & 0xf;
+            if (v > 9)  break;
+            ret.append((char)('0' + v));
+
+            v = (data[i] >> 4) & 0xf;
+            // Some PLMNs have 'f' as high nibble, ignore it
+            if (v == 0xf) continue;
+            if (v > 9)  break;
+            ret.append((char)('0' + v));
+        }
+
+        return ret.toString();
+    }
+
+    /**
+     * PLMN (MCC/MNC) is encoded as per 24.008 10.5.1.3
+     * Returns a concatenated string of MCC+MNC, stripping
+     * a trailing character for a 2-digit MNC
+     */
+    public static String bcdPlmnToString(byte[] data, int offset) {
+        if (offset + 3 > data.length) {
+            return null;
+        }
+        byte[] trans = new byte[3];
+        trans[0] = (byte) ((data[0 + offset] << 4) | ((data[0 + offset] >> 4) & 0xF));
+        trans[1] = (byte) ((data[1 + offset] << 4) | (data[2 + offset] & 0xF));
+        trans[2] = (byte) ((data[2 + offset] & 0xF0) | ((data[1 + offset] >> 4) & 0xF));
+        String ret = bytesToHexString(trans);
+
+        // For a 2-digit MNC we trim the trailing 'f'
+        if (ret.endsWith("f")) {
+            ret = ret.substring(0, ret.length() - 1);
+        }
+        return ret;
+    }
+
+    /**
+     * Some fields (like ICC ID) in GSM SIMs are stored as nibble-swizzled BCH
+     */
+    public static String
+    bchToString(byte[] data, int offset, int length) {
+        StringBuilder ret = new StringBuilder(length*2);
+
+        for (int i = offset ; i < offset + length ; i++) {
+            int v;
+
+            v = data[i] & 0xf;
+            ret.append("0123456789abcdef".charAt(v));
+
+            v = (data[i] >> 4) & 0xf;
+            ret.append("0123456789abcdef".charAt(v));
+        }
+
+        return ret.toString();
+    }
+
+    /**
+     * Decode cdma byte into String.
+     */
+    public static String
+    cdmaBcdToString(byte[] data, int offset, int length) {
+        StringBuilder ret = new StringBuilder(length);
+
+        int count = 0;
+        for (int i = offset; count < length; i++) {
+            int v;
+            v = data[i] & 0xf;
+            if (v > 9)  v = 0;
+            ret.append((char)('0' + v));
+
+            if (++count == length) break;
+
+            v = (data[i] >> 4) & 0xf;
+            if (v > 9)  v = 0;
+            ret.append((char)('0' + v));
+            ++count;
+        }
+        return ret.toString();
+    }
+
+    /**
+     * Decodes a GSM-style BCD byte, returning an int ranging from 0-99.
+     *
+     * In GSM land, the least significant BCD digit is stored in the most
+     * significant nibble.
+     *
+     * Out-of-range digits are treated as 0 for the sake of the time stamp,
+     * because of this:
+     *
+     * TS 23.040 section 9.2.3.11
+     * "if the MS receives a non-integer value in the SCTS, it shall
+     * assume the digit is set to 0 but shall store the entire field
+     * exactly as received"
+     */
+    public static int
+    gsmBcdByteToInt(byte b) {
+        int ret = 0;
+
+        // treat out-of-range BCD values as 0
+        if ((b & 0xf0) <= 0x90) {
+            ret = (b >> 4) & 0xf;
+        }
+
+        if ((b & 0x0f) <= 0x09) {
+            ret +=  (b & 0xf) * 10;
+        }
+
+        return ret;
+    }
+
+    /**
+     * Decodes a CDMA style BCD byte like {@link #gsmBcdByteToInt}, but
+     * opposite nibble format. The least significant BCD digit
+     * is in the least significant nibble and the most significant
+     * is in the most significant nibble.
+     */
+    public static int
+    cdmaBcdByteToInt(byte b) {
+        int ret = 0;
+
+        // treat out-of-range BCD values as 0
+        if ((b & 0xf0) <= 0x90) {
+            ret = ((b >> 4) & 0xf) * 10;
+        }
+
+        if ((b & 0x0f) <= 0x09) {
+            ret +=  (b & 0xf);
+        }
+
+        return ret;
+    }
+
+    /**
+     * Decodes a string field that's formatted like the EF[ADN] alpha
+     * identifier
+     *
+     * From TS 51.011 10.5.1:
+     *   Coding:
+     *       this alpha tagging shall use either
+     *      -    the SMS default 7 bit coded alphabet as defined in
+     *          TS 23.038 [12] with bit 8 set to 0. The alpha identifier
+     *          shall be left justified. Unused bytes shall be set to 'FF'; or
+     *      -    one of the UCS2 coded options as defined in annex B.
+     *
+     * Annex B from TS 11.11 V8.13.0:
+     *      1)  If the first octet in the alpha string is '80', then the
+     *          remaining octets are 16 bit UCS2 characters ...
+     *      2)  if the first octet in the alpha string is '81', then the
+     *          second octet contains a value indicating the number of
+     *          characters in the string, and the third octet contains an
+     *          8 bit number which defines bits 15 to 8 of a 16 bit
+     *          base pointer, where bit 16 is set to zero and bits 7 to 1
+     *          are also set to zero.  These sixteen bits constitute a
+     *          base pointer to a "half page" in the UCS2 code space, to be
+     *          used with some or all of the remaining octets in the string.
+     *          The fourth and subsequent octets contain codings as follows:
+     *          If bit 8 of the octet is set to zero, the remaining 7 bits
+     *          of the octet contain a GSM Default Alphabet character,
+     *          whereas if bit 8 of the octet is set to one, then the
+     *          remaining seven bits are an offset value added to the
+     *          16 bit base pointer defined earlier...
+     *      3)  If the first octet of the alpha string is set to '82', then
+     *          the second octet contains a value indicating the number of
+     *          characters in the string, and the third and fourth octets
+     *          contain a 16 bit number which defines the complete 16 bit
+     *          base pointer to a "half page" in the UCS2 code space...
+     */
+    public static String
+    adnStringFieldToString(byte[] data, int offset, int length) {
+        if (length == 0) {
+            return "";
+        }
+        if (length >= 1) {
+            if (data[offset] == (byte) 0x80) {
+                int ucslen = (length - 1) / 2;
+                String ret = null;
+
+                try {
+                    ret = new String(data, offset + 1, ucslen * 2, "utf-16be");
+                } catch (UnsupportedEncodingException ex) {
+                    Rlog.e(LOG_TAG, "implausible UnsupportedEncodingException",
+                          ex);
+                }
+
+                if (ret != null) {
+                    // trim off trailing FFFF characters
+
+                    ucslen = ret.length();
+                    while (ucslen > 0 && ret.charAt(ucslen - 1) == '\uFFFF')
+                        ucslen--;
+
+                    return ret.substring(0, ucslen);
+                }
+            }
+        }
+
+        boolean isucs2 = false;
+        char base = '\0';
+        int len = 0;
+
+        if (length >= 3 && data[offset] == (byte) 0x81) {
+            len = data[offset + 1] & 0xFF;
+            if (len > length - 3)
+                len = length - 3;
+
+            base = (char) ((data[offset + 2] & 0xFF) << 7);
+            offset += 3;
+            isucs2 = true;
+        } else if (length >= 4 && data[offset] == (byte) 0x82) {
+            len = data[offset + 1] & 0xFF;
+            if (len > length - 4)
+                len = length - 4;
+
+            base = (char) (((data[offset + 2] & 0xFF) << 8) |
+                            (data[offset + 3] & 0xFF));
+            offset += 4;
+            isucs2 = true;
+        }
+
+        if (isucs2) {
+            StringBuilder ret = new StringBuilder();
+
+            while (len > 0) {
+                // UCS2 subset case
+
+                if (data[offset] < 0) {
+                    ret.append((char) (base + (data[offset] & 0x7F)));
+                    offset++;
+                    len--;
+                }
+
+                // GSM character set case
+
+                int count = 0;
+                while (count < len && data[offset + count] >= 0)
+                    count++;
+
+                ret.append(GsmAlphabet.gsm8BitUnpackedToString(data,
+                           offset, count));
+
+                offset += count;
+                len -= count;
+            }
+
+            return ret.toString();
+        }
+
+        Resources resource = Resources.getSystem();
+        String defaultCharset = "";
+        try {
+            defaultCharset =
+                    resource.getString(com.android.internal.R.string.gsm_alphabet_default_charset);
+        } catch (NotFoundException e) {
+            // Ignore Exception and defaultCharset is set to a empty string.
+        }
+        return GsmAlphabet.gsm8BitUnpackedToString(data, offset, length, defaultCharset.trim());
+    }
+
+    static int
+    hexCharToInt(char c) {
+        if (c >= '0' && c <= '9') return (c - '0');
+        if (c >= 'A' && c <= 'F') return (c - 'A' + 10);
+        if (c >= 'a' && c <= 'f') return (c - 'a' + 10);
+
+        throw new RuntimeException ("invalid hex char '" + c + "'");
+    }
+
+    /**
+     * Converts a hex String to a byte array.
+     *
+     * @param s A string of hexadecimal characters, must be an even number of
+     *          chars long
+     *
+     * @return byte array representation
+     *
+     * @throws RuntimeException on invalid format
+     */
+    public static byte[]
+    hexStringToBytes(String s) {
+        byte[] ret;
+
+        if (s == null) return null;
+
+        int sz = s.length();
+
+        ret = new byte[sz/2];
+
+        for (int i=0 ; i <sz ; i+=2) {
+            ret[i/2] = (byte) ((hexCharToInt(s.charAt(i)) << 4)
+                                | hexCharToInt(s.charAt(i+1)));
+        }
+
+        return ret;
+    }
+
+
+    /**
+     * Converts a byte array into a String of hexadecimal characters.
+     *
+     * @param bytes an array of bytes
+     *
+     * @return hex string representation of bytes array
+     */
+    public static String
+    bytesToHexString(byte[] bytes) {
+        if (bytes == null) return null;
+
+        StringBuilder ret = new StringBuilder(2*bytes.length);
+
+        for (int i = 0 ; i < bytes.length ; i++) {
+            int b;
+
+            b = 0x0f & (bytes[i] >> 4);
+
+            ret.append("0123456789abcdef".charAt(b));
+
+            b = 0x0f & bytes[i];
+
+            ret.append("0123456789abcdef".charAt(b));
+        }
+
+        return ret.toString();
+    }
+
+
+    /**
+     * Convert a TS 24.008 Section 10.5.3.5a Network Name field to a string
+     * "offset" points to "octet 3", the coding scheme byte
+     * empty string returned on decode error
+     */
+    public static String
+    networkNameToString(byte[] data, int offset, int length) {
+        String ret;
+
+        if ((data[offset] & 0x80) != 0x80 || length < 1) {
+            return "";
+        }
+
+        switch ((data[offset] >>> 4) & 0x7) {
+            case 0:
+                // SMS character set
+                int countSeptets;
+                int unusedBits = data[offset] & 7;
+                countSeptets = (((length - 1) * 8) - unusedBits) / 7 ;
+                ret =  GsmAlphabet.gsm7BitPackedToString(data, offset + 1, countSeptets);
+            break;
+            case 1:
+                // UCS2
+                try {
+                    ret = new String(data,
+                            offset + 1, length - 1, "utf-16");
+                } catch (UnsupportedEncodingException ex) {
+                    ret = "";
+                    Rlog.e(LOG_TAG,"implausible UnsupportedEncodingException", ex);
+                }
+            break;
+
+            // unsupported encoding
+            default:
+                ret = "";
+            break;
+        }
+
+        // "Add CI"
+        // "The MS should add the letters for the Country's Initials and
+        //  a separator (e.g. a space) to the text string"
+
+        if ((data[offset] & 0x40) != 0) {
+            // FIXME(mkf) add country initials here
+
+        }
+
+        return ret;
+    }
+
+    /**
+     * Convert a TS 131.102 image instance of code scheme '11' into Bitmap
+     * @param data The raw data
+     * @param length The length of image body
+     * @return The bitmap
+     */
+    public static Bitmap parseToBnW(byte[] data, int length){
+        int valueIndex = 0;
+        int width = data[valueIndex++] & 0xFF;
+        int height = data[valueIndex++] & 0xFF;
+        int numOfPixels = width*height;
+
+        int[] pixels = new int[numOfPixels];
+
+        int pixelIndex = 0;
+        int bitIndex = 7;
+        byte currentByte = 0x00;
+        while (pixelIndex < numOfPixels) {
+            // reassign data and index for every byte (8 bits).
+            if (pixelIndex % 8 == 0) {
+                currentByte = data[valueIndex++];
+                bitIndex = 7;
+            }
+            pixels[pixelIndex++] = bitToRGB((currentByte >> bitIndex-- ) & 0x01);
+        }
+
+        if (pixelIndex != numOfPixels) {
+            Rlog.e(LOG_TAG, "parse end and size error");
+        }
+        return Bitmap.createBitmap(pixels, width, height, Bitmap.Config.ARGB_8888);
+    }
+
+    private static int bitToRGB(int bit){
+        if(bit == 1){
+            return Color.WHITE;
+        } else {
+            return Color.BLACK;
+        }
+    }
+
+    /**
+     * a TS 131.102 image instance of code scheme '11' into color Bitmap
+     *
+     * @param data The raw data
+     * @param length the length of image body
+     * @param transparency with or without transparency
+     * @return The color bitmap
+     */
+    public static Bitmap parseToRGB(byte[] data, int length,
+            boolean transparency) {
+        int valueIndex = 0;
+        int width = data[valueIndex++] & 0xFF;
+        int height = data[valueIndex++] & 0xFF;
+        int bits = data[valueIndex++] & 0xFF;
+        int colorNumber = data[valueIndex++] & 0xFF;
+        int clutOffset = ((data[valueIndex++] & 0xFF) << 8)
+                | (data[valueIndex++] & 0xFF);
+
+        int[] colorIndexArray = getCLUT(data, clutOffset, colorNumber);
+        if (true == transparency) {
+            colorIndexArray[colorNumber - 1] = Color.TRANSPARENT;
+        }
+
+        int[] resultArray = null;
+        if (0 == (8 % bits)) {
+            resultArray = mapTo2OrderBitColor(data, valueIndex,
+                    (width * height), colorIndexArray, bits);
+        } else {
+            resultArray = mapToNon2OrderBitColor(data, valueIndex,
+                    (width * height), colorIndexArray, bits);
+        }
+
+        return Bitmap.createBitmap(resultArray, width, height,
+                Bitmap.Config.RGB_565);
+    }
+
+    private static int[] mapTo2OrderBitColor(byte[] data, int valueIndex,
+            int length, int[] colorArray, int bits) {
+        if (0 != (8 % bits)) {
+            Rlog.e(LOG_TAG, "not event number of color");
+            return mapToNon2OrderBitColor(data, valueIndex, length, colorArray,
+                    bits);
+        }
+
+        int mask = 0x01;
+        switch (bits) {
+        case 1:
+            mask = 0x01;
+            break;
+        case 2:
+            mask = 0x03;
+            break;
+        case 4:
+            mask = 0x0F;
+            break;
+        case 8:
+            mask = 0xFF;
+            break;
+        }
+
+        int[] resultArray = new int[length];
+        int resultIndex = 0;
+        int run = 8 / bits;
+        while (resultIndex < length) {
+            byte tempByte = data[valueIndex++];
+            for (int runIndex = 0; runIndex < run; ++runIndex) {
+                int offset = run - runIndex - 1;
+                resultArray[resultIndex++] = colorArray[(tempByte >> (offset * bits))
+                        & mask];
+            }
+        }
+        return resultArray;
+    }
+
+    private static int[] mapToNon2OrderBitColor(byte[] data, int valueIndex,
+            int length, int[] colorArray, int bits) {
+        if (0 == (8 % bits)) {
+            Rlog.e(LOG_TAG, "not odd number of color");
+            return mapTo2OrderBitColor(data, valueIndex, length, colorArray,
+                    bits);
+        }
+
+        int[] resultArray = new int[length];
+        // TODO fix me:
+        return resultArray;
+    }
+
+    private static int[] getCLUT(byte[] rawData, int offset, int number) {
+        if (null == rawData) {
+            return null;
+        }
+
+        int[] result = new int[number];
+        int endIndex = offset + (number * 3); // 1 color use 3 bytes
+        int valueIndex = offset;
+        int colorIndex = 0;
+        int alpha = 0xff << 24;
+        do {
+            result[colorIndex++] = alpha
+                    | ((rawData[valueIndex++] & 0xFF) << 16)
+                    | ((rawData[valueIndex++] & 0xFF) << 8)
+                    | ((rawData[valueIndex++] & 0xFF));
+        } while (valueIndex < endIndex);
+        return result;
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/PhoneConstantConversions.java b/telephony/java/com/android/internal/telephony/PhoneConstantConversions.java
new file mode 100644
index 0000000..f7f0f29
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/PhoneConstantConversions.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.telephony.ServiceState;
+import android.telephony.TelephonyManager;
+import android.telephony.PreciseCallState;
+
+import com.android.internal.telephony.PhoneConstants;
+
+import java.util.List;
+
+public class PhoneConstantConversions {
+    /**
+     * Convert the {@link PhoneConstants.State} enum into the TelephonyManager.CALL_STATE_*
+     * constants for the public API.
+     */
+    public static int convertCallState(PhoneConstants.State state) {
+        switch (state) {
+            case RINGING:
+                return TelephonyManager.CALL_STATE_RINGING;
+            case OFFHOOK:
+                return TelephonyManager.CALL_STATE_OFFHOOK;
+            default:
+                return TelephonyManager.CALL_STATE_IDLE;
+        }
+    }
+
+    /**
+     * Convert the TelephonyManager.CALL_STATE_* constants into the
+     * {@link PhoneConstants.State} enum for the public API.
+     */
+    public static PhoneConstants.State convertCallState(int state) {
+        switch (state) {
+            case TelephonyManager.CALL_STATE_RINGING:
+                return PhoneConstants.State.RINGING;
+            case TelephonyManager.CALL_STATE_OFFHOOK:
+                return PhoneConstants.State.OFFHOOK;
+            default:
+                return PhoneConstants.State.IDLE;
+        }
+    }
+
+    /**
+     * Convert the {@link PhoneConstants.DataState} enum into the TelephonyManager.DATA_* constants
+     * for the public API.
+     */
+    public static int convertDataState(PhoneConstants.DataState state) {
+        switch (state) {
+            case CONNECTING:
+                return TelephonyManager.DATA_CONNECTING;
+            case CONNECTED:
+                return TelephonyManager.DATA_CONNECTED;
+            case SUSPENDED:
+                return TelephonyManager.DATA_SUSPENDED;
+            default:
+                return TelephonyManager.DATA_DISCONNECTED;
+        }
+    }
+
+    /**
+     * Convert the TelephonyManager.DATA_* constants into {@link PhoneConstants.DataState} enum
+     * for the public API.
+     */
+    public static PhoneConstants.DataState convertDataState(int state) {
+        switch (state) {
+            case TelephonyManager.DATA_CONNECTING:
+                return PhoneConstants.DataState.CONNECTING;
+            case TelephonyManager.DATA_CONNECTED:
+                return PhoneConstants.DataState.CONNECTED;
+            case TelephonyManager.DATA_SUSPENDED:
+                return PhoneConstants.DataState.SUSPENDED;
+            default:
+                return PhoneConstants.DataState.DISCONNECTED;
+        }
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index c3b740e..eafa6b7 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -411,6 +411,8 @@
     int RIL_REQUEST_GET_ACTIVITY_INFO = 135;
     int RIL_REQUEST_SET_ALLOWED_CARRIERS = 136;
     int RIL_REQUEST_GET_ALLOWED_CARRIERS = 137;
+    int RIL_REQUEST_SEND_DEVICE_STATE = 138;
+    int RIL_REQUEST_SET_UNSOLICITED_RESPONSE_FILTER = 139;
     int RIL_REQUEST_SET_SIM_CARD_POWER = 140;
 
     int RIL_RESPONSE_ACKNOWLEDGEMENT = 800;
diff --git a/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java b/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java
new file mode 100644
index 0000000..439eaea
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.telephony.Rlog;
+import android.os.Build;
+import android.util.SparseIntArray;
+import android.content.res.Resources;
+import android.content.res.XmlResourceParser;
+import android.telephony.SmsManager;
+import android.telephony.TelephonyManager;
+
+import com.android.internal.util.XmlUtils;
+import com.android.internal.telephony.cdma.sms.UserData;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+public class Sms7BitEncodingTranslator {
+    private static final String TAG = "Sms7BitEncodingTranslator";
+    private static final boolean DBG = Build.IS_DEBUGGABLE ;
+    private static boolean mIs7BitTranslationTableLoaded = false;
+    private static SparseIntArray mTranslationTable = null;
+    private static SparseIntArray mTranslationTableCommon = null;
+    private static SparseIntArray mTranslationTableGSM = null;
+    private static SparseIntArray mTranslationTableCDMA = null;
+
+    // Parser variables
+    private static final String XML_START_TAG = "SmsEnforce7BitTranslationTable";
+    private static final String XML_TRANSLATION_TYPE_TAG = "TranslationType";
+    private static final String XML_CHARACTOR_TAG = "Character";
+    private static final String XML_FROM_TAG = "from";
+    private static final String XML_TO_TAG = "to";
+
+    /**
+     * Translates each message character that is not supported by GSM 7bit
+     * alphabet into a supported one
+     *
+     * @param message
+     *            message to be translated
+     * @param throwsException
+     *            if true and some error occurs during translation, an exception
+     *            is thrown; otherwise a null String is returned
+     * @return translated message or null if some error occur
+     */
+    public static String translate(CharSequence message) {
+        if (message == null) {
+            Rlog.w(TAG, "Null message can not be translated");
+            return null;
+        }
+
+        int size = message.length();
+        if (size <= 0) {
+            return "";
+        }
+
+        if (!mIs7BitTranslationTableLoaded) {
+            mTranslationTableCommon = new SparseIntArray();
+            mTranslationTableGSM = new SparseIntArray();
+            mTranslationTableCDMA = new SparseIntArray();
+            load7BitTranslationTableFromXml();
+            mIs7BitTranslationTableLoaded = true;
+        }
+
+        if ((mTranslationTableCommon != null && mTranslationTableCommon.size() > 0) ||
+                (mTranslationTableGSM != null && mTranslationTableGSM.size() > 0) ||
+                (mTranslationTableCDMA != null && mTranslationTableCDMA.size() > 0)) {
+            char[] output = new char[size];
+            boolean isCdmaFormat = useCdmaFormatForMoSms();
+            for (int i = 0; i < size; i++) {
+                output[i] = translateIfNeeded(message.charAt(i), isCdmaFormat);
+            }
+
+            return String.valueOf(output);
+        }
+
+        return null;
+    }
+
+    /**
+     * Translates a single character into its corresponding acceptable one, if
+     * needed, based on GSM 7-bit alphabet
+     *
+     * @param c
+     *            character to be translated
+     * @return original character, if it's present on GSM 7-bit alphabet; a
+     *         corresponding character, based on the translation table or white
+     *         space, if no mapping is found in the translation table for such
+     *         character
+     */
+    private static char translateIfNeeded(char c, boolean isCdmaFormat) {
+        if (noTranslationNeeded(c, isCdmaFormat)) {
+            if (DBG) {
+                Rlog.v(TAG, "No translation needed for " + Integer.toHexString(c));
+            }
+            return c;
+        }
+
+        /*
+         * Trying to translate unicode to Gsm 7-bit alphabet; If c is not
+         * present on translation table, c does not belong to Unicode Latin-1
+         * (Basic + Supplement), so we don't know how to translate it to a Gsm
+         * 7-bit character! We replace c for an empty space and advises the user
+         * about it.
+         */
+        int translation = -1;
+
+        if (mTranslationTableCommon != null) {
+            translation = mTranslationTableCommon.get(c, -1);
+        }
+
+        if (translation == -1) {
+            if (isCdmaFormat) {
+                if (mTranslationTableCDMA != null) {
+                    translation = mTranslationTableCDMA.get(c, -1);
+                }
+            } else {
+                if (mTranslationTableGSM != null) {
+                    translation = mTranslationTableGSM.get(c, -1);
+                }
+            }
+        }
+
+        if (translation != -1) {
+            if (DBG) {
+                Rlog.v(TAG, Integer.toHexString(c) + " (" + c + ")" + " translated to "
+                        + Integer.toHexString(translation) + " (" + (char) translation + ")");
+            }
+            return (char) translation;
+        } else {
+            if (DBG) {
+                Rlog.w(TAG, "No translation found for " + Integer.toHexString(c)
+                        + "! Replacing for empty space");
+            }
+            return ' ';
+        }
+    }
+
+    private static boolean noTranslationNeeded(char c, boolean isCdmaFormat) {
+        if (isCdmaFormat) {
+            return GsmAlphabet.isGsmSeptets(c) && UserData.charToAscii.get(c, -1) != -1;
+        }
+        else {
+            return GsmAlphabet.isGsmSeptets(c);
+        }
+    }
+
+    private static boolean useCdmaFormatForMoSms() {
+        if (!SmsManager.getDefault().isImsSmsSupported()) {
+            // use Voice technology to determine SMS format.
+            return TelephonyManager.getDefault().getCurrentPhoneType()
+                    == PhoneConstants.PHONE_TYPE_CDMA;
+        }
+        // IMS is registered with SMS support, check the SMS format supported
+        return (SmsConstants.FORMAT_3GPP2.equals(SmsManager.getDefault().getImsSmsFormat()));
+    }
+
+    /**
+     * Load the whole translation table file from the framework resource
+     * encoded in XML.
+     */
+    private static void load7BitTranslationTableFromXml() {
+        XmlResourceParser parser = null;
+        Resources r = Resources.getSystem();
+
+        if (parser == null) {
+            if (DBG) Rlog.d(TAG, "load7BitTranslationTableFromXml: open normal file");
+            parser = r.getXml(com.android.internal.R.xml.sms_7bit_translation_table);
+        }
+
+        try {
+            XmlUtils.beginDocument(parser, XML_START_TAG);
+            while (true)  {
+                XmlUtils.nextElement(parser);
+                String tag = parser.getName();
+                if (DBG) {
+                    Rlog.d(TAG, "tag: " + tag);
+                }
+                if (XML_TRANSLATION_TYPE_TAG.equals(tag)) {
+                    String type = parser.getAttributeValue(null, "Type");
+                    if (DBG) {
+                        Rlog.d(TAG, "type: " + type);
+                    }
+                    if (type.equals("common")) {
+                        mTranslationTable = mTranslationTableCommon;
+                    } else if (type.equals("gsm")) {
+                        mTranslationTable = mTranslationTableGSM;
+                    } else if (type.equals("cdma")) {
+                        mTranslationTable = mTranslationTableCDMA;
+                    } else {
+                        Rlog.e(TAG, "Error Parsing 7BitTranslationTable: found incorrect type" + type);
+                    }
+                } else if (XML_CHARACTOR_TAG.equals(tag) && mTranslationTable != null) {
+                    int from = parser.getAttributeUnsignedIntValue(null,
+                            XML_FROM_TAG, -1);
+                    int to = parser.getAttributeUnsignedIntValue(null,
+                            XML_TO_TAG, -1);
+                    if ((from != -1) && (to != -1)) {
+                        if (DBG) {
+                            Rlog.d(TAG, "Loading mapping " + Integer.toHexString(from)
+                                    .toUpperCase() + " -> " + Integer.toHexString(to)
+                                    .toUpperCase());
+                        }
+                        mTranslationTable.put (from, to);
+                    } else {
+                        Rlog.d(TAG, "Invalid translation table file format");
+                    }
+                } else {
+                    break;
+                }
+            }
+            if (DBG) Rlog.d(TAG, "load7BitTranslationTableFromXml: parsing successful, file loaded");
+        } catch (Exception e) {
+            Rlog.e(TAG, "Got exception while loading 7BitTranslationTable file.", e);
+        } finally {
+            if (parser instanceof XmlResourceParser) {
+                ((XmlResourceParser)parser).close();
+            }
+        }
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/SmsAddress.java b/telephony/java/com/android/internal/telephony/SmsAddress.java
new file mode 100644
index 0000000..b3892cb
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/SmsAddress.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+public abstract class SmsAddress {
+    // From TS 23.040 9.1.2.5 and TS 24.008 table 10.5.118
+    // and C.S0005-D table 2.7.1.3.2.4-2
+    public static final int TON_UNKNOWN = 0;
+    public static final int TON_INTERNATIONAL = 1;
+    public static final int TON_NATIONAL = 2;
+    public static final int TON_NETWORK = 3;
+    public static final int TON_SUBSCRIBER = 4;
+    public static final int TON_ALPHANUMERIC = 5;
+    public static final int TON_ABBREVIATED = 6;
+
+    public int ton;
+    public String address;
+    public byte[] origBytes;
+
+    /**
+     * Returns the address of the SMS message in String form or null if unavailable
+     */
+    public String getAddressString() {
+        return address;
+    }
+
+    /**
+     * Returns true if this is an alphanumeric address
+     */
+    public boolean isAlphanumeric() {
+        return ton == TON_ALPHANUMERIC;
+    }
+
+    /**
+     * Returns true if this is a network address
+     */
+    public boolean isNetworkSpecific() {
+        return ton == TON_NETWORK;
+    }
+
+    public boolean couldBeEmailGateway() {
+        // Some carriers seems to send email gateway messages in this form:
+        // from: an UNKNOWN TON, 3 or 4 digits long, beginning with a 5
+        // PID: 0x00, Data coding scheme 0x03
+        // So we just attempt to treat any message from an address length <= 4
+        // as an email gateway
+
+        return address.length() <= 4;
+    }
+
+}
diff --git a/telephony/java/com/android/internal/telephony/SmsApplication.java b/telephony/java/com/android/internal/telephony/SmsApplication.java
new file mode 100644
index 0000000..d8ef429
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/SmsApplication.java
@@ -0,0 +1,980 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.Manifest.permission;
+import android.app.AppOpsManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.content.res.Resources;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Debug;
+import android.os.Process;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.provider.Telephony;
+import android.provider.Telephony.Sms.Intents;
+import android.telephony.Rlog;
+import android.telephony.SmsManager;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+
+import com.android.internal.content.PackageMonitor;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * Class for managing the primary application that we will deliver SMS/MMS messages to
+ *
+ * {@hide}
+ */
+public final class SmsApplication {
+    static final String LOG_TAG = "SmsApplication";
+    private static final String PHONE_PACKAGE_NAME = "com.android.phone";
+    private static final String BLUETOOTH_PACKAGE_NAME = "com.android.bluetooth";
+    private static final String MMS_SERVICE_PACKAGE_NAME = "com.android.mms.service";
+    private static final String TELEPHONY_PROVIDER_PACKAGE_NAME = "com.android.providers.telephony";
+
+    private static final String SCHEME_SMS = "sms";
+    private static final String SCHEME_SMSTO = "smsto";
+    private static final String SCHEME_MMS = "mms";
+    private static final String SCHEME_MMSTO = "mmsto";
+    private static final boolean DEBUG_MULTIUSER = false;
+
+    private static SmsPackageMonitor sSmsPackageMonitor = null;
+
+    public static class SmsApplicationData {
+        /**
+         * Name of this SMS app for display.
+         */
+        private String mApplicationName;
+
+        /**
+         * Package name for this SMS app.
+         */
+        public String mPackageName;
+
+        /**
+         * The class name of the SMS_DELIVER_ACTION receiver in this app.
+         */
+        private String mSmsReceiverClass;
+
+        /**
+         * The class name of the WAP_PUSH_DELIVER_ACTION receiver in this app.
+         */
+        private String mMmsReceiverClass;
+
+        /**
+         * The class name of the ACTION_RESPOND_VIA_MESSAGE intent in this app.
+         */
+        private String mRespondViaMessageClass;
+
+        /**
+         * The class name of the ACTION_SENDTO intent in this app.
+         */
+        private String mSendToClass;
+
+        /**
+         * The class name of the ACTION_DEFAULT_SMS_PACKAGE_CHANGED receiver in this app.
+         */
+        private String mSmsAppChangedReceiverClass;
+
+        /**
+         * The class name of the ACTION_EXTERNAL_PROVIDER_CHANGE receiver in this app.
+         */
+        private String mProviderChangedReceiverClass;
+
+        /**
+         * The class name of the SIM_FULL_ACTION receiver in this app.
+         */
+        private String mSimFullReceiverClass;
+
+        /**
+         * The user-id for this application
+         */
+        private int mUid;
+
+        /**
+         * Returns true if this SmsApplicationData is complete (all intents handled).
+         * @return
+         */
+        public boolean isComplete() {
+            return (mSmsReceiverClass != null && mMmsReceiverClass != null
+                    && mRespondViaMessageClass != null && mSendToClass != null);
+        }
+
+        public SmsApplicationData(String packageName, int uid) {
+            mPackageName = packageName;
+            mUid = uid;
+        }
+
+        public String getApplicationName(Context context) {
+            if (mApplicationName == null) {
+                PackageManager pm = context.getPackageManager();
+                ApplicationInfo appInfo;
+                try {
+                    appInfo = pm.getApplicationInfoAsUser(mPackageName, 0,
+                            UserHandle.getUserId(mUid));
+                } catch (NameNotFoundException e) {
+                    return null;
+                }
+                if (appInfo != null) {
+                    CharSequence label  = pm.getApplicationLabel(appInfo);
+                    mApplicationName = (label == null) ? null : label.toString();
+                }
+            }
+            return mApplicationName;
+        }
+
+        @Override
+        public String toString() {
+            return " mPackageName: " + mPackageName
+                    + " mSmsReceiverClass: " + mSmsReceiverClass
+                    + " mMmsReceiverClass: " + mMmsReceiverClass
+                    + " mRespondViaMessageClass: " + mRespondViaMessageClass
+                    + " mSendToClass: " + mSendToClass
+                    + " mSmsAppChangedClass: " + mSmsAppChangedReceiverClass
+                    + " mProviderChangedReceiverClass: " + mProviderChangedReceiverClass
+                    + " mSimFullReceiverClass: " + mSimFullReceiverClass
+                    + " mUid: " + mUid;
+        }
+    }
+
+    /**
+     * Returns the userId of the Context object, if called from a system app,
+     * otherwise it returns the caller's userId
+     * @param context The context object passed in by the caller.
+     * @return
+     */
+    private static int getIncomingUserId(Context context) {
+        int contextUserId = context.getUserId();
+        final int callingUid = Binder.getCallingUid();
+        if (DEBUG_MULTIUSER) {
+            Log.i(LOG_TAG, "getIncomingUserHandle caller=" + callingUid + ", myuid="
+                    + android.os.Process.myUid() + "\n\t" + Debug.getCallers(4));
+        }
+        if (UserHandle.getAppId(callingUid)
+                < android.os.Process.FIRST_APPLICATION_UID) {
+            return contextUserId;
+        } else {
+            return UserHandle.getUserId(callingUid);
+        }
+    }
+
+    /**
+     * Returns the list of available SMS apps defined as apps that are registered for both the
+     * SMS_RECEIVED_ACTION (SMS) and WAP_PUSH_RECEIVED_ACTION (MMS) broadcasts (and their broadcast
+     * receivers are enabled)
+     *
+     * Requirements to be an SMS application:
+     * Implement SMS_DELIVER_ACTION broadcast receiver.
+     * Require BROADCAST_SMS permission.
+     *
+     * Implement WAP_PUSH_DELIVER_ACTION broadcast receiver.
+     * Require BROADCAST_WAP_PUSH permission.
+     *
+     * Implement RESPOND_VIA_MESSAGE intent.
+     * Support smsto Uri scheme.
+     * Require SEND_RESPOND_VIA_MESSAGE permission.
+     *
+     * Implement ACTION_SENDTO intent.
+     * Support smsto Uri scheme.
+     */
+    public static Collection<SmsApplicationData> getApplicationCollection(Context context) {
+        int userId = getIncomingUserId(context);
+        final long token = Binder.clearCallingIdentity();
+        try {
+            return getApplicationCollectionInternal(context, userId);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    private static Collection<SmsApplicationData> getApplicationCollectionInternal(
+            Context context, int userId) {
+        PackageManager packageManager = context.getPackageManager();
+
+        // Get the list of apps registered for SMS
+        Intent intent = new Intent(Intents.SMS_DELIVER_ACTION);
+        List<ResolveInfo> smsReceivers = packageManager.queryBroadcastReceiversAsUser(intent, 0,
+                userId);
+
+        HashMap<String, SmsApplicationData> receivers = new HashMap<String, SmsApplicationData>();
+
+        // Add one entry to the map for every sms receiver (ignoring duplicate sms receivers)
+        for (ResolveInfo resolveInfo : smsReceivers) {
+            final ActivityInfo activityInfo = resolveInfo.activityInfo;
+            if (activityInfo == null) {
+                continue;
+            }
+            if (!permission.BROADCAST_SMS.equals(activityInfo.permission)) {
+                continue;
+            }
+            final String packageName = activityInfo.packageName;
+            if (!receivers.containsKey(packageName)) {
+                final SmsApplicationData smsApplicationData = new SmsApplicationData(packageName,
+                        activityInfo.applicationInfo.uid);
+                smsApplicationData.mSmsReceiverClass = activityInfo.name;
+                receivers.put(packageName, smsApplicationData);
+            }
+        }
+
+        // Update any existing entries with mms receiver class
+        intent = new Intent(Intents.WAP_PUSH_DELIVER_ACTION);
+        intent.setDataAndType(null, "application/vnd.wap.mms-message");
+        List<ResolveInfo> mmsReceivers = packageManager.queryBroadcastReceiversAsUser(intent, 0,
+                userId);
+        for (ResolveInfo resolveInfo : mmsReceivers) {
+            final ActivityInfo activityInfo = resolveInfo.activityInfo;
+            if (activityInfo == null) {
+                continue;
+            }
+            if (!permission.BROADCAST_WAP_PUSH.equals(activityInfo.permission)) {
+                continue;
+            }
+            final String packageName = activityInfo.packageName;
+            final SmsApplicationData smsApplicationData = receivers.get(packageName);
+            if (smsApplicationData != null) {
+                smsApplicationData.mMmsReceiverClass = activityInfo.name;
+            }
+        }
+
+        // Update any existing entries with respond via message intent class.
+        intent = new Intent(TelephonyManager.ACTION_RESPOND_VIA_MESSAGE,
+                Uri.fromParts(SCHEME_SMSTO, "", null));
+        List<ResolveInfo> respondServices = packageManager.queryIntentServicesAsUser(intent, 0,
+                userId);
+        for (ResolveInfo resolveInfo : respondServices) {
+            final ServiceInfo serviceInfo = resolveInfo.serviceInfo;
+            if (serviceInfo == null) {
+                continue;
+            }
+            if (!permission.SEND_RESPOND_VIA_MESSAGE.equals(serviceInfo.permission)) {
+                continue;
+            }
+            final String packageName = serviceInfo.packageName;
+            final SmsApplicationData smsApplicationData = receivers.get(packageName);
+            if (smsApplicationData != null) {
+                smsApplicationData.mRespondViaMessageClass = serviceInfo.name;
+            }
+        }
+
+        // Update any existing entries with supports send to.
+        intent = new Intent(Intent.ACTION_SENDTO,
+                Uri.fromParts(SCHEME_SMSTO, "", null));
+        List<ResolveInfo> sendToActivities = packageManager.queryIntentActivitiesAsUser(intent, 0,
+                userId);
+        for (ResolveInfo resolveInfo : sendToActivities) {
+            final ActivityInfo activityInfo = resolveInfo.activityInfo;
+            if (activityInfo == null) {
+                continue;
+            }
+            final String packageName = activityInfo.packageName;
+            final SmsApplicationData smsApplicationData = receivers.get(packageName);
+            if (smsApplicationData != null) {
+                smsApplicationData.mSendToClass = activityInfo.name;
+            }
+        }
+
+        // Update any existing entries with the default sms changed handler.
+        intent = new Intent(Telephony.Sms.Intents.ACTION_DEFAULT_SMS_PACKAGE_CHANGED);
+        List<ResolveInfo> smsAppChangedReceivers =
+                packageManager.queryBroadcastReceiversAsUser(intent, 0, userId);
+        if (DEBUG_MULTIUSER) {
+            Log.i(LOG_TAG, "getApplicationCollectionInternal smsAppChangedActivities=" +
+                    smsAppChangedReceivers);
+        }
+        for (ResolveInfo resolveInfo : smsAppChangedReceivers) {
+            final ActivityInfo activityInfo = resolveInfo.activityInfo;
+            if (activityInfo == null) {
+                continue;
+            }
+            final String packageName = activityInfo.packageName;
+            final SmsApplicationData smsApplicationData = receivers.get(packageName);
+            if (DEBUG_MULTIUSER) {
+                Log.i(LOG_TAG, "getApplicationCollectionInternal packageName=" +
+                        packageName + " smsApplicationData: " + smsApplicationData +
+                        " activityInfo.name: " + activityInfo.name);
+            }
+            if (smsApplicationData != null) {
+                smsApplicationData.mSmsAppChangedReceiverClass = activityInfo.name;
+            }
+        }
+
+        // Update any existing entries with the external provider changed handler.
+        intent = new Intent(Telephony.Sms.Intents.ACTION_EXTERNAL_PROVIDER_CHANGE);
+        List<ResolveInfo> providerChangedReceivers =
+                packageManager.queryBroadcastReceiversAsUser(intent, 0, userId);
+        if (DEBUG_MULTIUSER) {
+            Log.i(LOG_TAG, "getApplicationCollectionInternal providerChangedActivities=" +
+                    providerChangedReceivers);
+        }
+        for (ResolveInfo resolveInfo : providerChangedReceivers) {
+            final ActivityInfo activityInfo = resolveInfo.activityInfo;
+            if (activityInfo == null) {
+                continue;
+            }
+            final String packageName = activityInfo.packageName;
+            final SmsApplicationData smsApplicationData = receivers.get(packageName);
+            if (DEBUG_MULTIUSER) {
+                Log.i(LOG_TAG, "getApplicationCollectionInternal packageName=" +
+                        packageName + " smsApplicationData: " + smsApplicationData +
+                        " activityInfo.name: " + activityInfo.name);
+            }
+            if (smsApplicationData != null) {
+                smsApplicationData.mProviderChangedReceiverClass = activityInfo.name;
+            }
+        }
+
+        // Update any existing entries with the sim full handler.
+        intent = new Intent(Intents.SIM_FULL_ACTION);
+        List<ResolveInfo> simFullReceivers =
+                packageManager.queryBroadcastReceiversAsUser(intent, 0, userId);
+        if (DEBUG_MULTIUSER) {
+            Log.i(LOG_TAG, "getApplicationCollectionInternal simFullReceivers="
+                    + simFullReceivers);
+        }
+        for (ResolveInfo resolveInfo : simFullReceivers) {
+            final ActivityInfo activityInfo = resolveInfo.activityInfo;
+            if (activityInfo == null) {
+                continue;
+            }
+            final String packageName = activityInfo.packageName;
+            final SmsApplicationData smsApplicationData = receivers.get(packageName);
+            if (DEBUG_MULTIUSER) {
+                Log.i(LOG_TAG, "getApplicationCollectionInternal packageName="
+                        + packageName + " smsApplicationData: " + smsApplicationData
+                        + " activityInfo.name: " + activityInfo.name);
+            }
+            if (smsApplicationData != null) {
+                smsApplicationData.mSimFullReceiverClass = activityInfo.name;
+            }
+        }
+
+        // Remove any entries for which we did not find all required intents.
+        for (ResolveInfo resolveInfo : smsReceivers) {
+            final ActivityInfo activityInfo = resolveInfo.activityInfo;
+            if (activityInfo == null) {
+                continue;
+            }
+            final String packageName = activityInfo.packageName;
+            final SmsApplicationData smsApplicationData = receivers.get(packageName);
+            if (smsApplicationData != null) {
+                if (!smsApplicationData.isComplete()) {
+                    receivers.remove(packageName);
+                }
+            }
+        }
+        return receivers.values();
+    }
+
+    /**
+     * Checks to see if we have a valid installed SMS application for the specified package name
+     * @return Data for the specified package name or null if there isn't one
+     */
+    private static SmsApplicationData getApplicationForPackage(
+            Collection<SmsApplicationData> applications, String packageName) {
+        if (packageName == null) {
+            return null;
+        }
+        // Is there an entry in the application list for the specified package?
+        for (SmsApplicationData application : applications) {
+            if (application.mPackageName.contentEquals(packageName)) {
+                return application;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Get the application we will use for delivering SMS/MMS messages.
+     *
+     * We return the preferred sms application with the following order of preference:
+     * (1) User selected SMS app (if selected, and if still valid)
+     * (2) Android Messaging (if installed)
+     * (3) The currently configured highest priority broadcast receiver
+     * (4) Null
+     */
+    private static SmsApplicationData getApplication(Context context, boolean updateIfNeeded,
+            int userId) {
+        TelephonyManager tm = (TelephonyManager)
+                context.getSystemService(Context.TELEPHONY_SERVICE);
+        if (!tm.isSmsCapable()) {
+            // No phone, no SMS
+            return null;
+        }
+
+        Collection<SmsApplicationData> applications = getApplicationCollectionInternal(context,
+                userId);
+        if (DEBUG_MULTIUSER) {
+            Log.i(LOG_TAG, "getApplication userId=" + userId);
+        }
+        // Determine which application receives the broadcast
+        String defaultApplication = Settings.Secure.getStringForUser(context.getContentResolver(),
+                Settings.Secure.SMS_DEFAULT_APPLICATION, userId);
+        if (DEBUG_MULTIUSER) {
+            Log.i(LOG_TAG, "getApplication defaultApp=" + defaultApplication);
+        }
+
+        SmsApplicationData applicationData = null;
+        if (defaultApplication != null) {
+            applicationData = getApplicationForPackage(applications, defaultApplication);
+        }
+        if (DEBUG_MULTIUSER) {
+            Log.i(LOG_TAG, "getApplication appData=" + applicationData);
+        }
+        // Picking a new SMS app requires AppOps and Settings.Secure permissions, so we only do
+        // this if the caller asked us to.
+        if (updateIfNeeded && applicationData == null) {
+            // Try to find the default SMS package for this device
+            Resources r = context.getResources();
+            String defaultPackage =
+                    r.getString(com.android.internal.R.string.default_sms_application);
+            applicationData = getApplicationForPackage(applications, defaultPackage);
+
+            if (applicationData == null) {
+                // Are there any applications?
+                if (applications.size() != 0) {
+                    applicationData = (SmsApplicationData)applications.toArray()[0];
+                }
+            }
+
+            // If we found a new default app, update the setting
+            if (applicationData != null) {
+                setDefaultApplicationInternal(applicationData.mPackageName, context, userId);
+            }
+        }
+
+        // If we found a package, make sure AppOps permissions are set up correctly
+        if (applicationData != null) {
+            AppOpsManager appOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
+
+            // We can only call checkOp if we are privileged (updateIfNeeded) or if the app we
+            // are checking is for our current uid. Doing this check from the unprivileged current
+            // SMS app allows us to tell the current SMS app that it is not in a good state and
+            // needs to ask to be the current SMS app again to work properly.
+            if (updateIfNeeded || applicationData.mUid == android.os.Process.myUid()) {
+                // Verify that the SMS app has permissions
+                int mode = appOps.checkOp(AppOpsManager.OP_WRITE_SMS, applicationData.mUid,
+                        applicationData.mPackageName);
+                if (mode != AppOpsManager.MODE_ALLOWED) {
+                    Rlog.e(LOG_TAG, applicationData.mPackageName + " lost OP_WRITE_SMS: " +
+                            (updateIfNeeded ? " (fixing)" : " (no permission to fix)"));
+                    if (updateIfNeeded) {
+                        appOps.setMode(AppOpsManager.OP_WRITE_SMS, applicationData.mUid,
+                                applicationData.mPackageName, AppOpsManager.MODE_ALLOWED);
+                    } else {
+                        // We can not return a package if permissions are not set up correctly
+                        applicationData = null;
+                    }
+                }
+            }
+
+            // We can only verify the phone and BT app's permissions from a privileged caller
+            if (updateIfNeeded) {
+                // Ensure this component is still configured as the preferred activity. Usually the
+                // current SMS app will already be the preferred activity - but checking whether or
+                // not this is true is just as expensive as reconfiguring the preferred activity so
+                // we just reconfigure every time.
+                PackageManager packageManager = context.getPackageManager();
+                configurePreferredActivity(packageManager, new ComponentName(
+                        applicationData.mPackageName, applicationData.mSendToClass),
+                        userId);
+                // Assign permission to special system apps
+                assignWriteSmsPermissionToSystemApp(context, packageManager, appOps,
+                        PHONE_PACKAGE_NAME);
+                assignWriteSmsPermissionToSystemApp(context, packageManager, appOps,
+                        BLUETOOTH_PACKAGE_NAME);
+                assignWriteSmsPermissionToSystemApp(context, packageManager, appOps,
+                        MMS_SERVICE_PACKAGE_NAME);
+                assignWriteSmsPermissionToSystemApp(context, packageManager, appOps,
+                        TELEPHONY_PROVIDER_PACKAGE_NAME);
+                // Give WRITE_SMS AppOps permission to UID 1001 which contains multiple
+                // apps, all of them should be able to write to telephony provider.
+                // This is to allow the proxy package permission check in telephony provider
+                // to pass.
+                assignWriteSmsPermissionToSystemUid(appOps, Process.PHONE_UID);
+            }
+        }
+        if (DEBUG_MULTIUSER) {
+            Log.i(LOG_TAG, "getApplication returning appData=" + applicationData);
+        }
+        return applicationData;
+    }
+
+    /**
+     * Sets the specified package as the default SMS/MMS application. The caller of this method
+     * needs to have permission to set AppOps and write to secure settings.
+     */
+    public static void setDefaultApplication(String packageName, Context context) {
+        TelephonyManager tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
+        if (!tm.isSmsCapable()) {
+            // No phone, no SMS
+            return;
+        }
+
+        final int userId = getIncomingUserId(context);
+        final long token = Binder.clearCallingIdentity();
+        try {
+            setDefaultApplicationInternal(packageName, context, userId);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    private static void setDefaultApplicationInternal(String packageName, Context context,
+            int userId) {
+        // Get old package name
+        String oldPackageName = Settings.Secure.getStringForUser(context.getContentResolver(),
+                Settings.Secure.SMS_DEFAULT_APPLICATION, userId);
+
+        if (DEBUG_MULTIUSER) {
+            Log.i(LOG_TAG, "setDefaultApplicationInternal old=" + oldPackageName +
+                    " new=" + packageName);
+        }
+
+        if (packageName != null && oldPackageName != null && packageName.equals(oldPackageName)) {
+            // No change
+            return;
+        }
+
+        // We only make the change if the new package is valid
+        PackageManager packageManager = context.getPackageManager();
+        Collection<SmsApplicationData> applications = getApplicationCollection(context);
+        SmsApplicationData oldAppData = oldPackageName != null ?
+                getApplicationForPackage(applications, oldPackageName) : null;
+        SmsApplicationData applicationData = getApplicationForPackage(applications, packageName);
+        if (applicationData != null) {
+            // Ignore OP_WRITE_SMS for the previously configured default SMS app.
+            AppOpsManager appOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
+            if (oldPackageName != null) {
+                try {
+                    PackageInfo info = packageManager.getPackageInfoAsUser(oldPackageName,
+                            0, userId);
+                    appOps.setMode(AppOpsManager.OP_WRITE_SMS, info.applicationInfo.uid,
+                            oldPackageName, AppOpsManager.MODE_IGNORED);
+                } catch (NameNotFoundException e) {
+                    Rlog.w(LOG_TAG, "Old SMS package not found: " + oldPackageName);
+                }
+            }
+
+            // Update the secure setting.
+            Settings.Secure.putStringForUser(context.getContentResolver(),
+                    Settings.Secure.SMS_DEFAULT_APPLICATION, applicationData.mPackageName,
+                    userId);
+
+            // Configure this as the preferred activity for SENDTO sms/mms intents
+            configurePreferredActivity(packageManager, new ComponentName(
+                    applicationData.mPackageName, applicationData.mSendToClass), userId);
+
+            // Allow OP_WRITE_SMS for the newly configured default SMS app.
+            appOps.setMode(AppOpsManager.OP_WRITE_SMS, applicationData.mUid,
+                    applicationData.mPackageName, AppOpsManager.MODE_ALLOWED);
+
+            // Assign permission to special system apps
+            assignWriteSmsPermissionToSystemApp(context, packageManager, appOps,
+                    PHONE_PACKAGE_NAME);
+            assignWriteSmsPermissionToSystemApp(context, packageManager, appOps,
+                    BLUETOOTH_PACKAGE_NAME);
+            assignWriteSmsPermissionToSystemApp(context, packageManager, appOps,
+                    MMS_SERVICE_PACKAGE_NAME);
+            assignWriteSmsPermissionToSystemApp(context, packageManager, appOps,
+                    TELEPHONY_PROVIDER_PACKAGE_NAME);
+            // Give WRITE_SMS AppOps permission to UID 1001 which contains multiple
+            // apps, all of them should be able to write to telephony provider.
+            // This is to allow the proxy package permission check in telephony provider
+            // to pass.
+            assignWriteSmsPermissionToSystemUid(appOps, Process.PHONE_UID);
+
+            if (DEBUG_MULTIUSER) {
+                Log.i(LOG_TAG, "setDefaultApplicationInternal oldAppData=" + oldAppData);
+            }
+            if (oldAppData != null && oldAppData.mSmsAppChangedReceiverClass != null) {
+                // Notify the old sms app that it's no longer the default
+                final Intent oldAppIntent =
+                        new Intent(Telephony.Sms.Intents.ACTION_DEFAULT_SMS_PACKAGE_CHANGED);
+                final ComponentName component = new ComponentName(oldAppData.mPackageName,
+                        oldAppData.mSmsAppChangedReceiverClass);
+                oldAppIntent.setComponent(component);
+                oldAppIntent.putExtra(Telephony.Sms.Intents.EXTRA_IS_DEFAULT_SMS_APP, false);
+                if (DEBUG_MULTIUSER) {
+                    Log.i(LOG_TAG, "setDefaultApplicationInternal old=" + oldAppData.mPackageName);
+                }
+                context.sendBroadcast(oldAppIntent);
+            }
+            // Notify the new sms app that it's now the default (if the new sms app has a receiver
+            // to handle the changed default sms intent).
+            if (DEBUG_MULTIUSER) {
+                Log.i(LOG_TAG, "setDefaultApplicationInternal new applicationData=" +
+                        applicationData);
+            }
+            if (applicationData.mSmsAppChangedReceiverClass != null) {
+                final Intent intent =
+                        new Intent(Telephony.Sms.Intents.ACTION_DEFAULT_SMS_PACKAGE_CHANGED);
+                final ComponentName component = new ComponentName(applicationData.mPackageName,
+                        applicationData.mSmsAppChangedReceiverClass);
+                intent.setComponent(component);
+                intent.putExtra(Telephony.Sms.Intents.EXTRA_IS_DEFAULT_SMS_APP, true);
+                if (DEBUG_MULTIUSER) {
+                    Log.i(LOG_TAG, "setDefaultApplicationInternal new=" + packageName);
+                }
+                context.sendBroadcast(intent);
+            }
+            MetricsLogger.action(context, MetricsEvent.ACTION_DEFAULT_SMS_APP_CHANGED,
+                    applicationData.mPackageName);
+        }
+    }
+
+    /**
+     * Assign WRITE_SMS AppOps permission to some special system apps.
+     *
+     * @param context The context
+     * @param packageManager The package manager instance
+     * @param appOps The AppOps manager instance
+     * @param packageName The package name of the system app
+     */
+    private static void assignWriteSmsPermissionToSystemApp(Context context,
+            PackageManager packageManager, AppOpsManager appOps, String packageName) {
+        // First check package signature matches the caller's package signature.
+        // Since this class is only used internally by the system, this check makes sure
+        // the package signature matches system signature.
+        final int result = packageManager.checkSignatures(context.getPackageName(), packageName);
+        if (result != PackageManager.SIGNATURE_MATCH) {
+            Rlog.e(LOG_TAG, packageName + " does not have system signature");
+            return;
+        }
+        try {
+            PackageInfo info = packageManager.getPackageInfo(packageName, 0);
+            int mode = appOps.checkOp(AppOpsManager.OP_WRITE_SMS, info.applicationInfo.uid,
+                    packageName);
+            if (mode != AppOpsManager.MODE_ALLOWED) {
+                Rlog.w(LOG_TAG, packageName + " does not have OP_WRITE_SMS:  (fixing)");
+                appOps.setMode(AppOpsManager.OP_WRITE_SMS, info.applicationInfo.uid,
+                        packageName, AppOpsManager.MODE_ALLOWED);
+            }
+        } catch (NameNotFoundException e) {
+            // No whitelisted system app on this device
+            Rlog.e(LOG_TAG, "Package not found: " + packageName);
+        }
+
+    }
+
+    private static void assignWriteSmsPermissionToSystemUid(AppOpsManager appOps, int uid) {
+        appOps.setUidMode(AppOpsManager.OP_WRITE_SMS, uid, AppOpsManager.MODE_ALLOWED);
+    }
+
+    /**
+     * Tracks package changes and ensures that the default SMS app is always configured to be the
+     * preferred activity for SENDTO sms/mms intents.
+     */
+    private static final class SmsPackageMonitor extends PackageMonitor {
+        final Context mContext;
+
+        public SmsPackageMonitor(Context context) {
+            super();
+            mContext = context;
+        }
+
+        @Override
+        public void onPackageDisappeared(String packageName, int reason) {
+            onPackageChanged();
+        }
+
+        @Override
+        public void onPackageAppeared(String packageName, int reason) {
+            onPackageChanged();
+        }
+
+        @Override
+        public void onPackageModified(String packageName) {
+            onPackageChanged();
+        }
+
+        private void onPackageChanged() {
+            PackageManager packageManager = mContext.getPackageManager();
+            Context userContext = mContext;
+            final int userId = getSendingUserId();
+            if (userId != UserHandle.USER_SYSTEM) {
+                try {
+                    userContext = mContext.createPackageContextAsUser(mContext.getPackageName(), 0,
+                            new UserHandle(userId));
+                } catch (NameNotFoundException nnfe) {
+                    if (DEBUG_MULTIUSER) {
+                        Log.w(LOG_TAG, "Unable to create package context for user " + userId);
+                    }
+                }
+            }
+            // Ensure this component is still configured as the preferred activity
+            ComponentName componentName = getDefaultSendToApplication(userContext, true);
+            if (componentName != null) {
+                configurePreferredActivity(packageManager, componentName, userId);
+            }
+        }
+    }
+
+    public static void initSmsPackageMonitor(Context context) {
+        sSmsPackageMonitor = new SmsPackageMonitor(context);
+        sSmsPackageMonitor.register(context, context.getMainLooper(), UserHandle.ALL, false);
+    }
+
+    private static void configurePreferredActivity(PackageManager packageManager,
+            ComponentName componentName, int userId) {
+        // Add the four activity preferences we want to direct to this app.
+        replacePreferredActivity(packageManager, componentName, userId, SCHEME_SMS);
+        replacePreferredActivity(packageManager, componentName, userId, SCHEME_SMSTO);
+        replacePreferredActivity(packageManager, componentName, userId, SCHEME_MMS);
+        replacePreferredActivity(packageManager, componentName, userId, SCHEME_MMSTO);
+    }
+
+    /**
+     * Updates the ACTION_SENDTO activity to the specified component for the specified scheme.
+     */
+    private static void replacePreferredActivity(PackageManager packageManager,
+            ComponentName componentName, int userId, String scheme) {
+        // Build the set of existing activities that handle this scheme
+        Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts(scheme, "", null));
+        List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivitiesAsUser(
+                intent, PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_RESOLVED_FILTER,
+                userId);
+
+        // Build the set of ComponentNames for these activities
+        final int n = resolveInfoList.size();
+        ComponentName[] set = new ComponentName[n];
+        for (int i = 0; i < n; i++) {
+            ResolveInfo info = resolveInfoList.get(i);
+            set[i] = new ComponentName(info.activityInfo.packageName, info.activityInfo.name);
+        }
+
+        // Update the preferred SENDTO activity for the specified scheme
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(Intent.ACTION_SENDTO);
+        intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
+        intentFilter.addDataScheme(scheme);
+        packageManager.replacePreferredActivityAsUser(intentFilter,
+                IntentFilter.MATCH_CATEGORY_SCHEME + IntentFilter.MATCH_ADJUSTMENT_NORMAL,
+                set, componentName, userId);
+    }
+
+    /**
+     * Returns SmsApplicationData for this package if this package is capable of being set as the
+     * default SMS application.
+     */
+    public static SmsApplicationData getSmsApplicationData(String packageName, Context context) {
+        Collection<SmsApplicationData> applications = getApplicationCollection(context);
+        return getApplicationForPackage(applications, packageName);
+    }
+
+    /**
+     * Gets the default SMS application
+     * @param context context from the calling app
+     * @param updateIfNeeded update the default app if there is no valid default app configured.
+     * @return component name of the app and class to deliver SMS messages to
+     */
+    public static ComponentName getDefaultSmsApplication(Context context, boolean updateIfNeeded) {
+        int userId = getIncomingUserId(context);
+        final long token = Binder.clearCallingIdentity();
+        try {
+            ComponentName component = null;
+            SmsApplicationData smsApplicationData = getApplication(context, updateIfNeeded,
+                    userId);
+            if (smsApplicationData != null) {
+                component = new ComponentName(smsApplicationData.mPackageName,
+                        smsApplicationData.mSmsReceiverClass);
+            }
+            return component;
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    /**
+     * Gets the default MMS application
+     * @param context context from the calling app
+     * @param updateIfNeeded update the default app if there is no valid default app configured.
+     * @return component name of the app and class to deliver MMS messages to
+     */
+    public static ComponentName getDefaultMmsApplication(Context context, boolean updateIfNeeded) {
+        int userId = getIncomingUserId(context);
+        final long token = Binder.clearCallingIdentity();
+        try {
+            ComponentName component = null;
+            SmsApplicationData smsApplicationData = getApplication(context, updateIfNeeded,
+                    userId);
+            if (smsApplicationData != null) {
+                component = new ComponentName(smsApplicationData.mPackageName,
+                        smsApplicationData.mMmsReceiverClass);
+            }
+            return component;
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    /**
+     * Gets the default Respond Via Message application
+     * @param context context from the calling app
+     * @param updateIfNeeded update the default app if there is no valid default app configured.
+     * @return component name of the app and class to direct Respond Via Message intent to
+     */
+    public static ComponentName getDefaultRespondViaMessageApplication(Context context,
+            boolean updateIfNeeded) {
+        int userId = getIncomingUserId(context);
+        final long token = Binder.clearCallingIdentity();
+        try {
+            ComponentName component = null;
+            SmsApplicationData smsApplicationData = getApplication(context, updateIfNeeded,
+                    userId);
+            if (smsApplicationData != null) {
+                component = new ComponentName(smsApplicationData.mPackageName,
+                        smsApplicationData.mRespondViaMessageClass);
+            }
+            return component;
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    /**
+     * Gets the default Send To (smsto) application.
+     * <p>
+     * Caller must pass in the correct user context if calling from a singleton service.
+     * @param context context from the calling app
+     * @param updateIfNeeded update the default app if there is no valid default app configured.
+     * @return component name of the app and class to direct SEND_TO (smsto) intent to
+     */
+    public static ComponentName getDefaultSendToApplication(Context context,
+            boolean updateIfNeeded) {
+        int userId = getIncomingUserId(context);
+        final long token = Binder.clearCallingIdentity();
+        try {
+            ComponentName component = null;
+            SmsApplicationData smsApplicationData = getApplication(context, updateIfNeeded,
+                    userId);
+            if (smsApplicationData != null) {
+                component = new ComponentName(smsApplicationData.mPackageName,
+                        smsApplicationData.mSendToClass);
+            }
+            return component;
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    /**
+     * Gets the default application that handles external changes to the SmsProvider and
+     * MmsProvider.
+     * @param context context from the calling app
+     * @param updateIfNeeded update the default app if there is no valid default app configured.
+     * @return component name of the app and class to deliver change intents to
+     */
+    public static ComponentName getDefaultExternalTelephonyProviderChangedApplication(
+            Context context, boolean updateIfNeeded) {
+        int userId = getIncomingUserId(context);
+        final long token = Binder.clearCallingIdentity();
+        try {
+            ComponentName component = null;
+            SmsApplicationData smsApplicationData = getApplication(context, updateIfNeeded,
+                    userId);
+            if (smsApplicationData != null
+                    && smsApplicationData.mProviderChangedReceiverClass != null) {
+                component = new ComponentName(smsApplicationData.mPackageName,
+                        smsApplicationData.mProviderChangedReceiverClass);
+            }
+            return component;
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    /**
+     * Gets the default application that handles sim full event.
+     * @param context context from the calling app
+     * @param updateIfNeeded update the default app if there is no valid default app configured.
+     * @return component name of the app and class to deliver change intents to
+     */
+    public static ComponentName getDefaultSimFullApplication(
+            Context context, boolean updateIfNeeded) {
+        int userId = getIncomingUserId(context);
+        final long token = Binder.clearCallingIdentity();
+        try {
+            ComponentName component = null;
+            SmsApplicationData smsApplicationData = getApplication(context, updateIfNeeded,
+                    userId);
+            if (smsApplicationData != null
+                    && smsApplicationData.mSimFullReceiverClass != null) {
+                component = new ComponentName(smsApplicationData.mPackageName,
+                        smsApplicationData.mSimFullReceiverClass);
+            }
+            return component;
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    /**
+     * Returns whether need to write the SMS message to SMS database for this package.
+     * <p>
+     * Caller must pass in the correct user context if calling from a singleton service.
+     */
+    public static boolean shouldWriteMessageForPackage(String packageName, Context context) {
+        if (SmsManager.getDefault().getAutoPersisting()) {
+            return true;
+        }
+        return !isDefaultSmsApplication(context, packageName);
+    }
+
+    /**
+     * Check if a package is default sms app (or equivalent, like bluetooth)
+     *
+     * @param context context from the calling app
+     * @param packageName the name of the package to be checked
+     * @return true if the package is default sms app or bluetooth
+     */
+    public static boolean isDefaultSmsApplication(Context context, String packageName) {
+        if (packageName == null) {
+            return false;
+        }
+        final String defaultSmsPackage = getDefaultSmsApplicationPackageName(context);
+        if ((defaultSmsPackage != null && defaultSmsPackage.equals(packageName))
+                || BLUETOOTH_PACKAGE_NAME.equals(packageName)) {
+            return true;
+        }
+        return false;
+    }
+
+    private static String getDefaultSmsApplicationPackageName(Context context) {
+        final ComponentName component = getDefaultSmsApplication(context, false);
+        if (component != null) {
+            return component.getPackageName();
+        }
+        return null;
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/SmsCbCmasInfo.java b/telephony/java/com/android/internal/telephony/SmsCbCmasInfo.java
new file mode 100644
index 0000000..c912924
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/SmsCbCmasInfo.java
@@ -0,0 +1,310 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Contains CMAS warning notification Type 1 elements for a {@link SmsCbMessage}.
+ * Supported values for each element are defined in TIA-1149-0-1 (CMAS over CDMA) and
+ * 3GPP TS 23.041 (for GSM/UMTS).
+ *
+ * {@hide}
+ */
+public class SmsCbCmasInfo implements Parcelable {
+
+    // CMAS message class (in GSM/UMTS message identifier or CDMA service category).
+
+    /** Presidential-level alert (Korean Public Alert System Class 0 message). */
+    public static final int CMAS_CLASS_PRESIDENTIAL_LEVEL_ALERT = 0x00;
+
+    /** Extreme threat to life and property (Korean Public Alert System Class 1 message). */
+    public static final int CMAS_CLASS_EXTREME_THREAT = 0x01;
+
+    /** Severe threat to life and property (Korean Public Alert System Class 1 message). */
+    public static final int CMAS_CLASS_SEVERE_THREAT = 0x02;
+
+    /** Child abduction emergency (AMBER Alert). */
+    public static final int CMAS_CLASS_CHILD_ABDUCTION_EMERGENCY = 0x03;
+
+    /** CMAS test message. */
+    public static final int CMAS_CLASS_REQUIRED_MONTHLY_TEST = 0x04;
+
+    /** CMAS exercise. */
+    public static final int CMAS_CLASS_CMAS_EXERCISE = 0x05;
+
+    /** CMAS category for operator defined use. */
+    public static final int CMAS_CLASS_OPERATOR_DEFINED_USE = 0x06;
+
+    /** CMAS category for warning types that are reserved for future extension. */
+    public static final int CMAS_CLASS_UNKNOWN = -1;
+
+    // CMAS alert category (in CDMA type 1 elements record).
+
+    /** CMAS alert category: Geophysical including landslide. */
+    public static final int CMAS_CATEGORY_GEO = 0x00;
+
+    /** CMAS alert category: Meteorological including flood. */
+    public static final int CMAS_CATEGORY_MET = 0x01;
+
+    /** CMAS alert category: General emergency and public safety. */
+    public static final int CMAS_CATEGORY_SAFETY = 0x02;
+
+    /** CMAS alert category: Law enforcement, military, homeland/local/private security. */
+    public static final int CMAS_CATEGORY_SECURITY = 0x03;
+
+    /** CMAS alert category: Rescue and recovery. */
+    public static final int CMAS_CATEGORY_RESCUE = 0x04;
+
+    /** CMAS alert category: Fire suppression and rescue. */
+    public static final int CMAS_CATEGORY_FIRE = 0x05;
+
+    /** CMAS alert category: Medical and public health. */
+    public static final int CMAS_CATEGORY_HEALTH = 0x06;
+
+    /** CMAS alert category: Pollution and other environmental. */
+    public static final int CMAS_CATEGORY_ENV = 0x07;
+
+    /** CMAS alert category: Public and private transportation. */
+    public static final int CMAS_CATEGORY_TRANSPORT = 0x08;
+
+    /** CMAS alert category: Utility, telecom, other non-transport infrastructure. */
+    public static final int CMAS_CATEGORY_INFRA = 0x09;
+
+    /** CMAS alert category: Chem, bio, radiological, nuclear, high explosive threat or attack. */
+    public static final int CMAS_CATEGORY_CBRNE = 0x0a;
+
+    /** CMAS alert category: Other events. */
+    public static final int CMAS_CATEGORY_OTHER = 0x0b;
+
+    /**
+     * CMAS alert category is unknown. The category is only available for CDMA broadcasts
+     * containing a type 1 elements record, so GSM and UMTS broadcasts always return unknown.
+     */
+    public static final int CMAS_CATEGORY_UNKNOWN = -1;
+
+    // CMAS response type (in CDMA type 1 elements record).
+
+    /** CMAS response type: Take shelter in place. */
+    public static final int CMAS_RESPONSE_TYPE_SHELTER = 0x00;
+
+    /** CMAS response type: Evacuate (Relocate). */
+    public static final int CMAS_RESPONSE_TYPE_EVACUATE = 0x01;
+
+    /** CMAS response type: Make preparations. */
+    public static final int CMAS_RESPONSE_TYPE_PREPARE = 0x02;
+
+    /** CMAS response type: Execute a pre-planned activity. */
+    public static final int CMAS_RESPONSE_TYPE_EXECUTE = 0x03;
+
+    /** CMAS response type: Attend to information sources. */
+    public static final int CMAS_RESPONSE_TYPE_MONITOR = 0x04;
+
+    /** CMAS response type: Avoid hazard. */
+    public static final int CMAS_RESPONSE_TYPE_AVOID = 0x05;
+
+    /** CMAS response type: Evaluate the information in this message (not for public warnings). */
+    public static final int CMAS_RESPONSE_TYPE_ASSESS = 0x06;
+
+    /** CMAS response type: No action recommended. */
+    public static final int CMAS_RESPONSE_TYPE_NONE = 0x07;
+
+    /**
+     * CMAS response type is unknown. The response type is only available for CDMA broadcasts
+     * containing a type 1 elements record, so GSM and UMTS broadcasts always return unknown.
+     */
+    public static final int CMAS_RESPONSE_TYPE_UNKNOWN = -1;
+
+    // 4-bit CMAS severity (in GSM/UMTS message identifier or CDMA type 1 elements record).
+
+    /** CMAS severity type: Extraordinary threat to life or property. */
+    public static final int CMAS_SEVERITY_EXTREME = 0x0;
+
+    /** CMAS severity type: Significant threat to life or property. */
+    public static final int CMAS_SEVERITY_SEVERE = 0x1;
+
+    /**
+     * CMAS alert severity is unknown. The severity is available for CDMA warning alerts
+     * containing a type 1 elements record and for all GSM and UMTS alerts except for the
+     * Presidential-level alert class (Korean Public Alert System Class 0).
+     */
+    public static final int CMAS_SEVERITY_UNKNOWN = -1;
+
+    // CMAS urgency (in GSM/UMTS message identifier or CDMA type 1 elements record).
+
+    /** CMAS urgency type: Responsive action should be taken immediately. */
+    public static final int CMAS_URGENCY_IMMEDIATE = 0x0;
+
+    /** CMAS urgency type: Responsive action should be taken within the next hour. */
+    public static final int CMAS_URGENCY_EXPECTED = 0x1;
+
+    /**
+     * CMAS alert urgency is unknown. The urgency is available for CDMA warning alerts
+     * containing a type 1 elements record and for all GSM and UMTS alerts except for the
+     * Presidential-level alert class (Korean Public Alert System Class 0).
+     */
+    public static final int CMAS_URGENCY_UNKNOWN = -1;
+
+    // CMAS certainty (in GSM/UMTS message identifier or CDMA type 1 elements record).
+
+    /** CMAS certainty type: Determined to have occurred or to be ongoing. */
+    public static final int CMAS_CERTAINTY_OBSERVED = 0x0;
+
+    /** CMAS certainty type: Likely (probability > ~50%). */
+    public static final int CMAS_CERTAINTY_LIKELY = 0x1;
+
+    /**
+     * CMAS alert certainty is unknown. The certainty is available for CDMA warning alerts
+     * containing a type 1 elements record and for all GSM and UMTS alerts except for the
+     * Presidential-level alert class (Korean Public Alert System Class 0).
+     */
+    public static final int CMAS_CERTAINTY_UNKNOWN = -1;
+
+    /** CMAS message class. */
+    private final int mMessageClass;
+
+    /** CMAS category. */
+    private final int mCategory;
+
+    /** CMAS response type. */
+    private final int mResponseType;
+
+    /** CMAS severity. */
+    private final int mSeverity;
+
+    /** CMAS urgency. */
+    private final int mUrgency;
+
+    /** CMAS certainty. */
+    private final int mCertainty;
+
+    /** Create a new SmsCbCmasInfo object with the specified values. */
+    public SmsCbCmasInfo(int messageClass, int category, int responseType, int severity,
+            int urgency, int certainty) {
+        mMessageClass = messageClass;
+        mCategory = category;
+        mResponseType = responseType;
+        mSeverity = severity;
+        mUrgency = urgency;
+        mCertainty = certainty;
+    }
+
+    /** Create a new SmsCbCmasInfo object from a Parcel. */
+    SmsCbCmasInfo(Parcel in) {
+        mMessageClass = in.readInt();
+        mCategory = in.readInt();
+        mResponseType = in.readInt();
+        mSeverity = in.readInt();
+        mUrgency = in.readInt();
+        mCertainty = in.readInt();
+    }
+
+    /**
+     * Flatten this object into a Parcel.
+     *
+     * @param dest  The Parcel in which the object should be written.
+     * @param flags Additional flags about how the object should be written (ignored).
+     */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mMessageClass);
+        dest.writeInt(mCategory);
+        dest.writeInt(mResponseType);
+        dest.writeInt(mSeverity);
+        dest.writeInt(mUrgency);
+        dest.writeInt(mCertainty);
+    }
+
+    /**
+     * Returns the CMAS message class, e.g. {@link #CMAS_CLASS_PRESIDENTIAL_LEVEL_ALERT}.
+     * @return one of the {@code CMAS_CLASS} values
+     */
+    public int getMessageClass() {
+        return mMessageClass;
+    }
+
+    /**
+     * Returns the CMAS category, e.g. {@link #CMAS_CATEGORY_GEO}.
+     * @return one of the {@code CMAS_CATEGORY} values
+     */
+    public int getCategory() {
+        return mCategory;
+    }
+
+    /**
+     * Returns the CMAS response type, e.g. {@link #CMAS_RESPONSE_TYPE_SHELTER}.
+     * @return one of the {@code CMAS_RESPONSE_TYPE} values
+     */
+    public int getResponseType() {
+        return mResponseType;
+    }
+
+    /**
+     * Returns the CMAS severity, e.g. {@link #CMAS_SEVERITY_EXTREME}.
+     * @return one of the {@code CMAS_SEVERITY} values
+     */
+    public int getSeverity() {
+        return mSeverity;
+    }
+
+    /**
+     * Returns the CMAS urgency, e.g. {@link #CMAS_URGENCY_IMMEDIATE}.
+     * @return one of the {@code CMAS_URGENCY} values
+     */
+    public int getUrgency() {
+        return mUrgency;
+    }
+
+    /**
+     * Returns the CMAS certainty, e.g. {@link #CMAS_CERTAINTY_OBSERVED}.
+     * @return one of the {@code CMAS_CERTAINTY} values
+     */
+    public int getCertainty() {
+        return mCertainty;
+    }
+
+    @Override
+    public String toString() {
+        return "SmsCbCmasInfo{messageClass=" + mMessageClass + ", category=" + mCategory
+                + ", responseType=" + mResponseType + ", severity=" + mSeverity
+                + ", urgency=" + mUrgency + ", certainty=" + mCertainty + '}';
+    }
+
+    /**
+     * Describe the kinds of special objects contained in the marshalled representation.
+     * @return a bitmask indicating this Parcelable contains no special objects
+     */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Creator for unparcelling objects. */
+    public static final Parcelable.Creator<SmsCbCmasInfo>
+            CREATOR = new Parcelable.Creator<SmsCbCmasInfo>() {
+        @Override
+        public SmsCbCmasInfo createFromParcel(Parcel in) {
+            return new SmsCbCmasInfo(in);
+        }
+
+        @Override
+        public SmsCbCmasInfo[] newArray(int size) {
+            return new SmsCbCmasInfo[size];
+        }
+    };
+}
diff --git a/telephony/java/com/android/internal/telephony/SmsCbEtwsInfo.java b/telephony/java/com/android/internal/telephony/SmsCbEtwsInfo.java
new file mode 100644
index 0000000..14e02de
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/SmsCbEtwsInfo.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.format.Time;
+
+import com.android.internal.telephony.uicc.IccUtils;
+
+import java.util.Arrays;
+
+/**
+ * Contains information elements for a GSM or UMTS ETWS warning notification.
+ * Supported values for each element are defined in 3GPP TS 23.041.
+ *
+ * {@hide}
+ */
+public class SmsCbEtwsInfo implements Parcelable {
+
+    /** ETWS warning type for earthquake. */
+    public static final int ETWS_WARNING_TYPE_EARTHQUAKE = 0x00;
+
+    /** ETWS warning type for tsunami. */
+    public static final int ETWS_WARNING_TYPE_TSUNAMI = 0x01;
+
+    /** ETWS warning type for earthquake and tsunami. */
+    public static final int ETWS_WARNING_TYPE_EARTHQUAKE_AND_TSUNAMI = 0x02;
+
+    /** ETWS warning type for test messages. */
+    public static final int ETWS_WARNING_TYPE_TEST_MESSAGE = 0x03;
+
+    /** ETWS warning type for other emergency types. */
+    public static final int ETWS_WARNING_TYPE_OTHER_EMERGENCY = 0x04;
+
+    /** Unknown ETWS warning type. */
+    public static final int ETWS_WARNING_TYPE_UNKNOWN = -1;
+
+    /** One of the ETWS warning type constants defined in this class. */
+    private final int mWarningType;
+
+    /** Whether or not to activate the emergency user alert tone and vibration. */
+    private final boolean mEmergencyUserAlert;
+
+    /** Whether or not to activate a popup alert. */
+    private final boolean mActivatePopup;
+
+    /** Whether ETWS primary message or not/ */
+    private final boolean mPrimary;
+
+    /**
+     * 50-byte security information (ETWS primary notification for GSM only). As of Release 10,
+     * 3GPP TS 23.041 states that the UE shall ignore the ETWS primary notification timestamp
+     * and digital signature if received. Therefore it is treated as a raw byte array and
+     * parceled with the broadcast intent if present, but the timestamp is only computed if an
+     * application asks for the individual components.
+     */
+    private final byte[] mWarningSecurityInformation;
+
+    /** Create a new SmsCbEtwsInfo object with the specified values. */
+    public SmsCbEtwsInfo(int warningType, boolean emergencyUserAlert, boolean activatePopup,
+                boolean primary, byte[] warningSecurityInformation) {
+        mWarningType = warningType;
+        mEmergencyUserAlert = emergencyUserAlert;
+        mActivatePopup = activatePopup;
+        mPrimary = primary;
+        mWarningSecurityInformation = warningSecurityInformation;
+    }
+
+    /** Create a new SmsCbEtwsInfo object from a Parcel. */
+    SmsCbEtwsInfo(Parcel in) {
+        mWarningType = in.readInt();
+        mEmergencyUserAlert = (in.readInt() != 0);
+        mActivatePopup = (in.readInt() != 0);
+        mPrimary = (in.readInt() != 0);
+        mWarningSecurityInformation = in.createByteArray();
+    }
+
+    /**
+     * Flatten this object into a Parcel.
+     *
+     * @param dest  The Parcel in which the object should be written.
+     * @param flags Additional flags about how the object should be written (ignored).
+     */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mWarningType);
+        dest.writeInt(mEmergencyUserAlert ? 1 : 0);
+        dest.writeInt(mActivatePopup ? 1 : 0);
+        dest.writeInt(mPrimary ? 1 : 0);
+        dest.writeByteArray(mWarningSecurityInformation);
+    }
+
+    /**
+     * Returns the ETWS warning type.
+     * @return a warning type such as {@link #ETWS_WARNING_TYPE_EARTHQUAKE}
+     */
+    public int getWarningType() {
+        return mWarningType;
+    }
+
+    /**
+     * Returns the ETWS emergency user alert flag.
+     * @return true to notify terminal to activate emergency user alert; false otherwise
+     */
+    public boolean isEmergencyUserAlert() {
+        return mEmergencyUserAlert;
+    }
+
+    /**
+     * Returns the ETWS activate popup flag.
+     * @return true to notify terminal to activate display popup; false otherwise
+     */
+    public boolean isPopupAlert() {
+        return mActivatePopup;
+    }
+
+    /**
+     * Returns the ETWS format flag.
+     * @return true if the message is primary message, otherwise secondary message
+     */
+    public boolean isPrimary() {
+        return mPrimary;
+    }
+
+    /**
+     * Returns the Warning-Security-Information timestamp (GSM primary notifications only).
+     * As of Release 10, 3GPP TS 23.041 states that the UE shall ignore this value if received.
+     * @return a UTC timestamp in System.currentTimeMillis() format, or 0 if not present
+     */
+    public long getPrimaryNotificationTimestamp() {
+        if (mWarningSecurityInformation == null || mWarningSecurityInformation.length < 7) {
+            return 0;
+        }
+
+        int year = IccUtils.gsmBcdByteToInt(mWarningSecurityInformation[0]);
+        int month = IccUtils.gsmBcdByteToInt(mWarningSecurityInformation[1]);
+        int day = IccUtils.gsmBcdByteToInt(mWarningSecurityInformation[2]);
+        int hour = IccUtils.gsmBcdByteToInt(mWarningSecurityInformation[3]);
+        int minute = IccUtils.gsmBcdByteToInt(mWarningSecurityInformation[4]);
+        int second = IccUtils.gsmBcdByteToInt(mWarningSecurityInformation[5]);
+
+        // For the timezone, the most significant bit of the
+        // least significant nibble is the sign byte
+        // (meaning the max range of this field is 79 quarter-hours,
+        // which is more than enough)
+
+        byte tzByte = mWarningSecurityInformation[6];
+
+        // Mask out sign bit.
+        int timezoneOffset = IccUtils.gsmBcdByteToInt((byte) (tzByte & (~0x08)));
+
+        timezoneOffset = ((tzByte & 0x08) == 0) ? timezoneOffset : -timezoneOffset;
+
+        Time time = new Time(Time.TIMEZONE_UTC);
+
+        // We only need to support years above 2000.
+        time.year = year + 2000;
+        time.month = month - 1;
+        time.monthDay = day;
+        time.hour = hour;
+        time.minute = minute;
+        time.second = second;
+
+        // Timezone offset is in quarter hours.
+        return time.toMillis(true) - timezoneOffset * 15 * 60 * 1000;
+    }
+
+    /**
+     * Returns the digital signature (GSM primary notifications only). As of Release 10,
+     * 3GPP TS 23.041 states that the UE shall ignore this value if received.
+     * @return a byte array containing a copy of the primary notification digital signature
+     */
+    public byte[] getPrimaryNotificationSignature() {
+        if (mWarningSecurityInformation == null || mWarningSecurityInformation.length < 50) {
+            return null;
+        }
+        return Arrays.copyOfRange(mWarningSecurityInformation, 7, 50);
+    }
+
+    @Override
+    public String toString() {
+        return "SmsCbEtwsInfo{warningType=" + mWarningType + ", emergencyUserAlert="
+                + mEmergencyUserAlert + ", activatePopup=" + mActivatePopup + '}';
+    }
+
+    /**
+     * Describe the kinds of special objects contained in the marshalled representation.
+     * @return a bitmask indicating this Parcelable contains no special objects
+     */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Creator for unparcelling objects. */
+    public static final Creator<SmsCbEtwsInfo> CREATOR = new Creator<SmsCbEtwsInfo>() {
+        @Override
+        public SmsCbEtwsInfo createFromParcel(Parcel in) {
+            return new SmsCbEtwsInfo(in);
+        }
+
+        @Override
+        public SmsCbEtwsInfo[] newArray(int size) {
+            return new SmsCbEtwsInfo[size];
+        }
+    };
+}
diff --git a/telephony/java/com/android/internal/telephony/SmsCbLocation.java b/telephony/java/com/android/internal/telephony/SmsCbLocation.java
new file mode 100644
index 0000000..6eb72a8
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/SmsCbLocation.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Represents the location and geographical scope of a cell broadcast message.
+ * For GSM/UMTS, the Location Area and Cell ID are set when the broadcast
+ * geographical scope is cell wide or Location Area wide. For CDMA, the
+ * broadcast geographical scope is always PLMN wide.
+ *
+ * @hide
+ */
+public class SmsCbLocation implements Parcelable {
+
+    /** The PLMN. Note that this field may be an empty string, but isn't allowed to be null. */
+    private final String mPlmn;
+
+    private final int mLac;
+    private final int mCid;
+
+    /**
+     * Construct an empty location object. This is used for some test cases, and for
+     * cell broadcasts saved in older versions of the database without location info.
+     */
+    public SmsCbLocation() {
+        mPlmn = "";
+        mLac = -1;
+        mCid = -1;
+    }
+
+    /**
+     * Construct a location object for the PLMN. This class is immutable, so
+     * the same object can be reused for multiple broadcasts.
+     */
+    public SmsCbLocation(String plmn) {
+        mPlmn = plmn;
+        mLac = -1;
+        mCid = -1;
+    }
+
+    /**
+     * Construct a location object for the PLMN, LAC, and Cell ID. This class is immutable, so
+     * the same object can be reused for multiple broadcasts.
+     */
+    public SmsCbLocation(String plmn, int lac, int cid) {
+        mPlmn = plmn;
+        mLac = lac;
+        mCid = cid;
+    }
+
+    /**
+     * Initialize the object from a Parcel.
+     */
+    public SmsCbLocation(Parcel in) {
+        mPlmn = in.readString();
+        mLac = in.readInt();
+        mCid = in.readInt();
+    }
+
+    /**
+     * Returns the MCC/MNC of the network as a String.
+     * @return the PLMN identifier (MCC+MNC) as a String
+     */
+    public String getPlmn() {
+        return mPlmn;
+    }
+
+    /**
+     * Returns the GSM location area code, or UMTS service area code.
+     * @return location area code, -1 if unknown, 0xffff max legal value
+     */
+    public int getLac() {
+        return mLac;
+    }
+
+    /**
+     * Returns the GSM or UMTS cell ID.
+     * @return gsm cell id, -1 if unknown, 0xffff max legal value
+     */
+    public int getCid() {
+        return mCid;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = mPlmn.hashCode();
+        hash = hash * 31 + mLac;
+        hash = hash * 31 + mCid;
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == this) {
+            return true;
+        }
+        if (o == null || !(o instanceof SmsCbLocation)) {
+            return false;
+        }
+        SmsCbLocation other = (SmsCbLocation) o;
+        return mPlmn.equals(other.mPlmn) && mLac == other.mLac && mCid == other.mCid;
+    }
+
+    @Override
+    public String toString() {
+        return '[' + mPlmn + ',' + mLac + ',' + mCid + ']';
+    }
+
+    /**
+     * Test whether this location is within the location area of the specified object.
+     *
+     * @param area the location area to compare with this location
+     * @return true if this location is contained within the specified location area
+     */
+    public boolean isInLocationArea(SmsCbLocation area) {
+        if (mCid != -1 && mCid != area.mCid) {
+            return false;
+        }
+        if (mLac != -1 && mLac != area.mLac) {
+            return false;
+        }
+        return mPlmn.equals(area.mPlmn);
+    }
+
+    /**
+     * Test whether this location is within the location area of the CellLocation.
+     *
+     * @param plmn the PLMN to use for comparison
+     * @param lac the Location Area (GSM) or Service Area (UMTS) to compare with
+     * @param cid the Cell ID to compare with
+     * @return true if this location is contained within the specified PLMN, LAC, and Cell ID
+     */
+    public boolean isInLocationArea(String plmn, int lac, int cid) {
+        if (!mPlmn.equals(plmn)) {
+            return false;
+        }
+
+        if (mLac != -1 && mLac != lac) {
+            return false;
+        }
+
+        if (mCid != -1 && mCid != cid) {
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Flatten this object into a Parcel.
+     *
+     * @param dest  The Parcel in which the object should be written.
+     * @param flags Additional flags about how the object should be written (ignored).
+     */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mPlmn);
+        dest.writeInt(mLac);
+        dest.writeInt(mCid);
+    }
+
+    public static final Parcelable.Creator<SmsCbLocation> CREATOR
+            = new Parcelable.Creator<SmsCbLocation>() {
+        @Override
+        public SmsCbLocation createFromParcel(Parcel in) {
+            return new SmsCbLocation(in);
+        }
+
+        @Override
+        public SmsCbLocation[] newArray(int size) {
+            return new SmsCbLocation[size];
+        }
+    };
+
+    /**
+     * Describe the kinds of special objects contained in the marshalled representation.
+     * @return a bitmask indicating this Parcelable contains no special objects
+     */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/SmsCbMessage.java b/telephony/java/com/android/internal/telephony/SmsCbMessage.java
new file mode 100644
index 0000000..046bf8c
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/SmsCbMessage.java
@@ -0,0 +1,382 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Parcelable object containing a received cell broadcast message. There are four different types
+ * of Cell Broadcast messages:
+ *
+ * <ul>
+ * <li>opt-in informational broadcasts, e.g. news, weather, stock quotes, sports scores</li>
+ * <li>cell information messages, broadcast on channel 50, indicating the current cell name for
+ *  roaming purposes (required to display on the idle screen in Brazil)</li>
+ * <li>emergency broadcasts for the Japanese Earthquake and Tsunami Warning System (ETWS)</li>
+ * <li>emergency broadcasts for the American Commercial Mobile Alert Service (CMAS)</li>
+ * </ul>
+ *
+ * <p>There are also four different CB message formats: GSM, ETWS Primary Notification (GSM only),
+ * UMTS, and CDMA. Some fields are only applicable for some message formats. Other fields were
+ * unified under a common name, avoiding some names, such as "Message Identifier", that refer to
+ * two completely different concepts in 3GPP and CDMA.
+ *
+ * <p>The GSM/UMTS Message Identifier field is available via {@link #getServiceCategory}, the name
+ * of the equivalent field in CDMA. In both cases the service category is a 16-bit value, but 3GPP
+ * and 3GPP2 have completely different meanings for the respective values. For ETWS and CMAS, the
+ * application should
+ *
+ * <p>The CDMA Message Identifier field is available via {@link #getSerialNumber}, which is used
+ * to detect the receipt of a duplicate message to be discarded. In CDMA, the message ID is
+ * unique to the current PLMN. In GSM/UMTS, there is a 16-bit serial number containing a 2-bit
+ * Geographical Scope field which indicates whether the 10-bit message code and 4-bit update number
+ * are considered unique to the PLMN, to the current cell, or to the current Location Area (or
+ * Service Area in UMTS). The relevant values are concatenated into a single String which will be
+ * unique if the messages are not duplicates.
+ *
+ * <p>The SMS dispatcher does not detect duplicate messages. However, it does concatenate the
+ * pages of a GSM multi-page cell broadcast into a single SmsCbMessage object.
+ *
+ * <p>Interested applications with {@code RECEIVE_SMS_PERMISSION} can register to receive
+ * {@code SMS_CB_RECEIVED_ACTION} broadcast intents for incoming non-emergency broadcasts.
+ * Only system applications such as the CellBroadcastReceiver may receive notifications for
+ * emergency broadcasts (ETWS and CMAS). This is intended to prevent any potential for delays or
+ * interference with the immediate display of the alert message and playing of the alert sound and
+ * vibration pattern, which could be caused by poorly written or malicious non-system code.
+ *
+ * @hide
+ */
+public class SmsCbMessage implements Parcelable {
+
+    protected static final String LOG_TAG = "SMSCB";
+
+    /** Cell wide geographical scope with immediate display (GSM/UMTS only). */
+    public static final int GEOGRAPHICAL_SCOPE_CELL_WIDE_IMMEDIATE = 0;
+
+    /** PLMN wide geographical scope (GSM/UMTS and all CDMA broadcasts). */
+    public static final int GEOGRAPHICAL_SCOPE_PLMN_WIDE = 1;
+
+    /** Location / service area wide geographical scope (GSM/UMTS only). */
+    public static final int GEOGRAPHICAL_SCOPE_LA_WIDE = 2;
+
+    /** Cell wide geographical scope (GSM/UMTS only). */
+    public static final int GEOGRAPHICAL_SCOPE_CELL_WIDE = 3;
+
+    /** GSM or UMTS format cell broadcast. */
+    public static final int MESSAGE_FORMAT_3GPP = 1;
+
+    /** CDMA format cell broadcast. */
+    public static final int MESSAGE_FORMAT_3GPP2 = 2;
+
+    /** Normal message priority. */
+    public static final int MESSAGE_PRIORITY_NORMAL = 0;
+
+    /** Interactive message priority. */
+    public static final int MESSAGE_PRIORITY_INTERACTIVE = 1;
+
+    /** Urgent message priority. */
+    public static final int MESSAGE_PRIORITY_URGENT = 2;
+
+    /** Emergency message priority. */
+    public static final int MESSAGE_PRIORITY_EMERGENCY = 3;
+
+    /** Format of this message (for interpretation of service category values). */
+    private final int mMessageFormat;
+
+    /** Geographical scope of broadcast. */
+    private final int mGeographicalScope;
+
+    /**
+     * Serial number of broadcast (message identifier for CDMA, geographical scope + message code +
+     * update number for GSM/UMTS). The serial number plus the location code uniquely identify
+     * a cell broadcast for duplicate detection.
+     */
+    private final int mSerialNumber;
+
+    /**
+     * Location identifier for this message. It consists of the current operator MCC/MNC as a
+     * 5 or 6-digit decimal string. In addition, for GSM/UMTS, if the Geographical Scope of the
+     * message is not binary 01, the Location Area is included for comparison. If the GS is
+     * 00 or 11, the Cell ID is also included. LAC and Cell ID are -1 if not specified.
+     */
+    private final SmsCbLocation mLocation;
+
+    /**
+     * 16-bit CDMA service category or GSM/UMTS message identifier. For ETWS and CMAS warnings,
+     * the information provided by the category is also available via {@link #getEtwsWarningInfo()}
+     * or {@link #getCmasWarningInfo()}.
+     */
+    private final int mServiceCategory;
+
+    /** Message language, as a two-character string, e.g. "en". */
+    private final String mLanguage;
+
+    /** Message body, as a String. */
+    private final String mBody;
+
+    /** Message priority (including emergency priority). */
+    private final int mPriority;
+
+    /** ETWS warning notification information (ETWS warnings only). */
+    private final SmsCbEtwsInfo mEtwsWarningInfo;
+
+    /** CMAS warning notification information (CMAS warnings only). */
+    private final SmsCbCmasInfo mCmasWarningInfo;
+
+    /**
+     * Create a new SmsCbMessage with the specified data.
+     */
+    public SmsCbMessage(int messageFormat, int geographicalScope, int serialNumber,
+            SmsCbLocation location, int serviceCategory, String language, String body,
+            int priority, SmsCbEtwsInfo etwsWarningInfo, SmsCbCmasInfo cmasWarningInfo) {
+        mMessageFormat = messageFormat;
+        mGeographicalScope = geographicalScope;
+        mSerialNumber = serialNumber;
+        mLocation = location;
+        mServiceCategory = serviceCategory;
+        mLanguage = language;
+        mBody = body;
+        mPriority = priority;
+        mEtwsWarningInfo = etwsWarningInfo;
+        mCmasWarningInfo = cmasWarningInfo;
+    }
+
+    /** Create a new SmsCbMessage object from a Parcel. */
+    public SmsCbMessage(Parcel in) {
+        mMessageFormat = in.readInt();
+        mGeographicalScope = in.readInt();
+        mSerialNumber = in.readInt();
+        mLocation = new SmsCbLocation(in);
+        mServiceCategory = in.readInt();
+        mLanguage = in.readString();
+        mBody = in.readString();
+        mPriority = in.readInt();
+        int type = in.readInt();
+        switch (type) {
+            case 'E':
+                // unparcel ETWS warning information
+                mEtwsWarningInfo = new SmsCbEtwsInfo(in);
+                mCmasWarningInfo = null;
+                break;
+
+            case 'C':
+                // unparcel CMAS warning information
+                mEtwsWarningInfo = null;
+                mCmasWarningInfo = new SmsCbCmasInfo(in);
+                break;
+
+            default:
+                mEtwsWarningInfo = null;
+                mCmasWarningInfo = null;
+        }
+    }
+
+    /**
+     * Flatten this object into a Parcel.
+     *
+     * @param dest  The Parcel in which the object should be written.
+     * @param flags Additional flags about how the object should be written (ignored).
+     */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mMessageFormat);
+        dest.writeInt(mGeographicalScope);
+        dest.writeInt(mSerialNumber);
+        mLocation.writeToParcel(dest, flags);
+        dest.writeInt(mServiceCategory);
+        dest.writeString(mLanguage);
+        dest.writeString(mBody);
+        dest.writeInt(mPriority);
+        if (mEtwsWarningInfo != null) {
+            // parcel ETWS warning information
+            dest.writeInt('E');
+            mEtwsWarningInfo.writeToParcel(dest, flags);
+        } else if (mCmasWarningInfo != null) {
+            // parcel CMAS warning information
+            dest.writeInt('C');
+            mCmasWarningInfo.writeToParcel(dest, flags);
+        } else {
+            // no ETWS or CMAS warning information
+            dest.writeInt('0');
+        }
+    }
+
+    public static final Parcelable.Creator<SmsCbMessage> CREATOR
+            = new Parcelable.Creator<SmsCbMessage>() {
+        @Override
+        public SmsCbMessage createFromParcel(Parcel in) {
+            return new SmsCbMessage(in);
+        }
+
+        @Override
+        public SmsCbMessage[] newArray(int size) {
+            return new SmsCbMessage[size];
+        }
+    };
+
+    /**
+     * Return the geographical scope of this message (GSM/UMTS only).
+     *
+     * @return Geographical scope
+     */
+    public int getGeographicalScope() {
+        return mGeographicalScope;
+    }
+
+    /**
+     * Return the broadcast serial number of broadcast (message identifier for CDMA, or
+     * geographical scope + message code + update number for GSM/UMTS). The serial number plus
+     * the location code uniquely identify a cell broadcast for duplicate detection.
+     *
+     * @return the 16-bit CDMA message identifier or GSM/UMTS serial number
+     */
+    public int getSerialNumber() {
+        return mSerialNumber;
+    }
+
+    /**
+     * Return the location identifier for this message, consisting of the MCC/MNC as a
+     * 5 or 6-digit decimal string. In addition, for GSM/UMTS, if the Geographical Scope of the
+     * message is not binary 01, the Location Area is included. If the GS is 00 or 11, the
+     * cell ID is also included. The {@link SmsCbLocation} object includes a method to test
+     * if the location is included within another location area or within a PLMN and CellLocation.
+     *
+     * @return the geographical location code for duplicate message detection
+     */
+    public SmsCbLocation getLocation() {
+        return mLocation;
+    }
+
+    /**
+     * Return the 16-bit CDMA service category or GSM/UMTS message identifier. The interpretation
+     * of the category is radio technology specific. For ETWS and CMAS warnings, the information
+     * provided by the category is available via {@link #getEtwsWarningInfo()} or
+     * {@link #getCmasWarningInfo()} in a radio technology independent format.
+     *
+     * @return the radio technology specific service category
+     */
+    public int getServiceCategory() {
+        return mServiceCategory;
+    }
+
+    /**
+     * Get the ISO-639-1 language code for this message, or null if unspecified
+     *
+     * @return Language code
+     */
+    public String getLanguageCode() {
+        return mLanguage;
+    }
+
+    /**
+     * Get the body of this message, or null if no body available
+     *
+     * @return Body, or null
+     */
+    public String getMessageBody() {
+        return mBody;
+    }
+
+    /**
+     * Get the message format ({@link #MESSAGE_FORMAT_3GPP} or {@link #MESSAGE_FORMAT_3GPP2}).
+     * @return an integer representing 3GPP or 3GPP2 message format
+     */
+    public int getMessageFormat() {
+        return mMessageFormat;
+    }
+
+    /**
+     * Get the message priority. Normal broadcasts return {@link #MESSAGE_PRIORITY_NORMAL}
+     * and emergency broadcasts return {@link #MESSAGE_PRIORITY_EMERGENCY}. CDMA also may return
+     * {@link #MESSAGE_PRIORITY_INTERACTIVE} or {@link #MESSAGE_PRIORITY_URGENT}.
+     * @return an integer representing the message priority
+     */
+    public int getMessagePriority() {
+        return mPriority;
+    }
+
+    /**
+     * If this is an ETWS warning notification then this method will return an object containing
+     * the ETWS warning type, the emergency user alert flag, and the popup flag. If this is an
+     * ETWS primary notification (GSM only), there will also be a 7-byte timestamp and 43-byte
+     * digital signature. As of Release 10, 3GPP TS 23.041 states that the UE shall ignore the
+     * ETWS primary notification timestamp and digital signature if received.
+     *
+     * @return an SmsCbEtwsInfo object, or null if this is not an ETWS warning notification
+     */
+    public SmsCbEtwsInfo getEtwsWarningInfo() {
+        return mEtwsWarningInfo;
+    }
+
+    /**
+     * If this is a CMAS warning notification then this method will return an object containing
+     * the CMAS message class, category, response type, severity, urgency and certainty.
+     * The message class is always present. Severity, urgency and certainty are present for CDMA
+     * warning notifications containing a type 1 elements record and for GSM and UMTS warnings
+     * except for the Presidential-level alert category. Category and response type are only
+     * available for CDMA notifications containing a type 1 elements record.
+     *
+     * @return an SmsCbCmasInfo object, or null if this is not a CMAS warning notification
+     */
+    public SmsCbCmasInfo getCmasWarningInfo() {
+        return mCmasWarningInfo;
+    }
+
+    /**
+     * Return whether this message is an emergency (PWS) message type.
+     * @return true if the message is a public warning notification; false otherwise
+     */
+    public boolean isEmergencyMessage() {
+        return mPriority == MESSAGE_PRIORITY_EMERGENCY;
+    }
+
+    /**
+     * Return whether this message is an ETWS warning alert.
+     * @return true if the message is an ETWS warning notification; false otherwise
+     */
+    public boolean isEtwsMessage() {
+        return mEtwsWarningInfo != null;
+    }
+
+    /**
+     * Return whether this message is a CMAS warning alert.
+     * @return true if the message is a CMAS warning notification; false otherwise
+     */
+    public boolean isCmasMessage() {
+        return mCmasWarningInfo != null;
+    }
+
+    @Override
+    public String toString() {
+        return "SmsCbMessage{geographicalScope=" + mGeographicalScope + ", serialNumber="
+                + mSerialNumber + ", location=" + mLocation + ", serviceCategory="
+                + mServiceCategory + ", language=" + mLanguage + ", body=" + mBody
+                + ", priority=" + mPriority
+                + (mEtwsWarningInfo != null ? (", " + mEtwsWarningInfo.toString()) : "")
+                + (mCmasWarningInfo != null ? (", " + mCmasWarningInfo.toString()) : "") + '}';
+    }
+
+    /**
+     * Describe the kinds of special objects contained in the marshalled representation.
+     * @return a bitmask indicating this Parcelable contains no special objects
+     */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/SmsHeader.java b/telephony/java/com/android/internal/telephony/SmsHeader.java
new file mode 100644
index 0000000..b519b70
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/SmsHeader.java
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import com.android.internal.telephony.SmsConstants;
+import com.android.internal.util.HexDump;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+
+import java.util.ArrayList;
+
+/**
+ * SMS user data header, as specified in TS 23.040 9.2.3.24.
+ */
+public class SmsHeader {
+
+    // TODO(cleanup): this data structure is generally referred to as
+    // the 'user data header' or UDH, and so the class name should
+    // change to reflect this...
+
+    /** SMS user data header information element identifiers.
+     * (see TS 23.040 9.2.3.24)
+     */
+    public static final int ELT_ID_CONCATENATED_8_BIT_REFERENCE       = 0x00;
+    public static final int ELT_ID_SPECIAL_SMS_MESSAGE_INDICATION     = 0x01;
+    public static final int ELT_ID_APPLICATION_PORT_ADDRESSING_8_BIT  = 0x04;
+    public static final int ELT_ID_APPLICATION_PORT_ADDRESSING_16_BIT = 0x05;
+    public static final int ELT_ID_SMSC_CONTROL_PARAMS                = 0x06;
+    public static final int ELT_ID_UDH_SOURCE_INDICATION              = 0x07;
+    public static final int ELT_ID_CONCATENATED_16_BIT_REFERENCE      = 0x08;
+    public static final int ELT_ID_WIRELESS_CTRL_MSG_PROTOCOL         = 0x09;
+    public static final int ELT_ID_TEXT_FORMATTING                    = 0x0A;
+    public static final int ELT_ID_PREDEFINED_SOUND                   = 0x0B;
+    public static final int ELT_ID_USER_DEFINED_SOUND                 = 0x0C;
+    public static final int ELT_ID_PREDEFINED_ANIMATION               = 0x0D;
+    public static final int ELT_ID_LARGE_ANIMATION                    = 0x0E;
+    public static final int ELT_ID_SMALL_ANIMATION                    = 0x0F;
+    public static final int ELT_ID_LARGE_PICTURE                      = 0x10;
+    public static final int ELT_ID_SMALL_PICTURE                      = 0x11;
+    public static final int ELT_ID_VARIABLE_PICTURE                   = 0x12;
+    public static final int ELT_ID_USER_PROMPT_INDICATOR              = 0x13;
+    public static final int ELT_ID_EXTENDED_OBJECT                    = 0x14;
+    public static final int ELT_ID_REUSED_EXTENDED_OBJECT             = 0x15;
+    public static final int ELT_ID_COMPRESSION_CONTROL                = 0x16;
+    public static final int ELT_ID_OBJECT_DISTR_INDICATOR             = 0x17;
+    public static final int ELT_ID_STANDARD_WVG_OBJECT                = 0x18;
+    public static final int ELT_ID_CHARACTER_SIZE_WVG_OBJECT          = 0x19;
+    public static final int ELT_ID_EXTENDED_OBJECT_DATA_REQUEST_CMD   = 0x1A;
+    public static final int ELT_ID_RFC_822_EMAIL_HEADER               = 0x20;
+    public static final int ELT_ID_HYPERLINK_FORMAT_ELEMENT           = 0x21;
+    public static final int ELT_ID_REPLY_ADDRESS_ELEMENT              = 0x22;
+    public static final int ELT_ID_ENHANCED_VOICE_MAIL_INFORMATION    = 0x23;
+    public static final int ELT_ID_NATIONAL_LANGUAGE_SINGLE_SHIFT     = 0x24;
+    public static final int ELT_ID_NATIONAL_LANGUAGE_LOCKING_SHIFT    = 0x25;
+
+    public static final int PORT_WAP_PUSH = 2948;
+    public static final int PORT_WAP_WSP  = 9200;
+
+    public static class PortAddrs {
+        public int destPort;
+        public int origPort;
+        public boolean areEightBits;
+    }
+
+    public static class ConcatRef {
+        public int refNumber;
+        public int seqNumber;
+        public int msgCount;
+        public boolean isEightBits;
+    }
+
+    public static class SpecialSmsMsg {
+        public int msgIndType;
+        public int msgCount;
+    }
+
+    /**
+     * A header element that is not explicitly parsed, meaning not
+     * PortAddrs or ConcatRef or SpecialSmsMsg.
+     */
+    public static class MiscElt {
+        public int id;
+        public byte[] data;
+    }
+
+    public PortAddrs portAddrs;
+    public ConcatRef concatRef;
+    public ArrayList<SpecialSmsMsg> specialSmsMsgList = new ArrayList<SpecialSmsMsg>();
+    public ArrayList<MiscElt> miscEltList = new ArrayList<MiscElt>();
+
+    /** 7 bit national language locking shift table, or 0 for GSM default 7 bit alphabet. */
+    public int languageTable;
+
+    /** 7 bit national language single shift table, or 0 for GSM default 7 bit extension table. */
+    public int languageShiftTable;
+
+    public SmsHeader() {}
+
+    /**
+     * Create structured SmsHeader object from serialized byte array representation.
+     * (see TS 23.040 9.2.3.24)
+     * @param data is user data header bytes
+     * @return SmsHeader object
+     */
+    public static SmsHeader fromByteArray(byte[] data) {
+        ByteArrayInputStream inStream = new ByteArrayInputStream(data);
+        SmsHeader smsHeader = new SmsHeader();
+        while (inStream.available() > 0) {
+            /**
+             * NOTE: as defined in the spec, ConcatRef and PortAddr
+             * fields should not reoccur, but if they do the last
+             * occurrence is to be used.  Also, for ConcatRef
+             * elements, if the count is zero, sequence is zero, or
+             * sequence is larger than count, the entire element is to
+             * be ignored.
+             */
+            int id = inStream.read();
+            int length = inStream.read();
+            ConcatRef concatRef;
+            PortAddrs portAddrs;
+            switch (id) {
+            case ELT_ID_CONCATENATED_8_BIT_REFERENCE:
+                concatRef = new ConcatRef();
+                concatRef.refNumber = inStream.read();
+                concatRef.msgCount = inStream.read();
+                concatRef.seqNumber = inStream.read();
+                concatRef.isEightBits = true;
+                if (concatRef.msgCount != 0 && concatRef.seqNumber != 0 &&
+                        concatRef.seqNumber <= concatRef.msgCount) {
+                    smsHeader.concatRef = concatRef;
+                }
+                break;
+            case ELT_ID_CONCATENATED_16_BIT_REFERENCE:
+                concatRef = new ConcatRef();
+                concatRef.refNumber = (inStream.read() << 8) | inStream.read();
+                concatRef.msgCount = inStream.read();
+                concatRef.seqNumber = inStream.read();
+                concatRef.isEightBits = false;
+                if (concatRef.msgCount != 0 && concatRef.seqNumber != 0 &&
+                        concatRef.seqNumber <= concatRef.msgCount) {
+                    smsHeader.concatRef = concatRef;
+                }
+                break;
+            case ELT_ID_APPLICATION_PORT_ADDRESSING_8_BIT:
+                portAddrs = new PortAddrs();
+                portAddrs.destPort = inStream.read();
+                portAddrs.origPort = inStream.read();
+                portAddrs.areEightBits = true;
+                smsHeader.portAddrs = portAddrs;
+                break;
+            case ELT_ID_APPLICATION_PORT_ADDRESSING_16_BIT:
+                portAddrs = new PortAddrs();
+                portAddrs.destPort = (inStream.read() << 8) | inStream.read();
+                portAddrs.origPort = (inStream.read() << 8) | inStream.read();
+                portAddrs.areEightBits = false;
+                smsHeader.portAddrs = portAddrs;
+                break;
+            case ELT_ID_NATIONAL_LANGUAGE_SINGLE_SHIFT:
+                smsHeader.languageShiftTable = inStream.read();
+                break;
+            case ELT_ID_NATIONAL_LANGUAGE_LOCKING_SHIFT:
+                smsHeader.languageTable = inStream.read();
+                break;
+            case ELT_ID_SPECIAL_SMS_MESSAGE_INDICATION:
+                SpecialSmsMsg specialSmsMsg = new SpecialSmsMsg();
+                specialSmsMsg.msgIndType = inStream.read();
+                specialSmsMsg.msgCount = inStream.read();
+                smsHeader.specialSmsMsgList.add(specialSmsMsg);
+                break;
+            default:
+                MiscElt miscElt = new MiscElt();
+                miscElt.id = id;
+                miscElt.data = new byte[length];
+                inStream.read(miscElt.data, 0, length);
+                smsHeader.miscEltList.add(miscElt);
+            }
+        }
+        return smsHeader;
+    }
+
+    /**
+     * Create serialized byte array representation from structured SmsHeader object.
+     * (see TS 23.040 9.2.3.24)
+     * @return Byte array representing the SmsHeader
+     */
+    public static byte[] toByteArray(SmsHeader smsHeader) {
+        if ((smsHeader.portAddrs == null) &&
+            (smsHeader.concatRef == null) &&
+            (smsHeader.specialSmsMsgList.isEmpty()) &&
+            (smsHeader.miscEltList.isEmpty()) &&
+            (smsHeader.languageShiftTable == 0) &&
+            (smsHeader.languageTable == 0)) {
+            return null;
+        }
+
+        ByteArrayOutputStream outStream =
+                new ByteArrayOutputStream(SmsConstants.MAX_USER_DATA_BYTES);
+        ConcatRef concatRef = smsHeader.concatRef;
+        if (concatRef != null) {
+            if (concatRef.isEightBits) {
+                outStream.write(ELT_ID_CONCATENATED_8_BIT_REFERENCE);
+                outStream.write(3);
+                outStream.write(concatRef.refNumber);
+            } else {
+                outStream.write(ELT_ID_CONCATENATED_16_BIT_REFERENCE);
+                outStream.write(4);
+                outStream.write(concatRef.refNumber >>> 8);
+                outStream.write(concatRef.refNumber & 0x00FF);
+            }
+            outStream.write(concatRef.msgCount);
+            outStream.write(concatRef.seqNumber);
+        }
+        PortAddrs portAddrs = smsHeader.portAddrs;
+        if (portAddrs != null) {
+            if (portAddrs.areEightBits) {
+                outStream.write(ELT_ID_APPLICATION_PORT_ADDRESSING_8_BIT);
+                outStream.write(2);
+                outStream.write(portAddrs.destPort);
+                outStream.write(portAddrs.origPort);
+            } else {
+                outStream.write(ELT_ID_APPLICATION_PORT_ADDRESSING_16_BIT);
+                outStream.write(4);
+                outStream.write(portAddrs.destPort >>> 8);
+                outStream.write(portAddrs.destPort & 0x00FF);
+                outStream.write(portAddrs.origPort >>> 8);
+                outStream.write(portAddrs.origPort & 0x00FF);
+            }
+        }
+        if (smsHeader.languageShiftTable != 0) {
+            outStream.write(ELT_ID_NATIONAL_LANGUAGE_SINGLE_SHIFT);
+            outStream.write(1);
+            outStream.write(smsHeader.languageShiftTable);
+        }
+        if (smsHeader.languageTable != 0) {
+            outStream.write(ELT_ID_NATIONAL_LANGUAGE_LOCKING_SHIFT);
+            outStream.write(1);
+            outStream.write(smsHeader.languageTable);
+        }
+        for (SpecialSmsMsg specialSmsMsg : smsHeader.specialSmsMsgList) {
+            outStream.write(ELT_ID_SPECIAL_SMS_MESSAGE_INDICATION);
+            outStream.write(2);
+            outStream.write(specialSmsMsg.msgIndType & 0xFF);
+            outStream.write(specialSmsMsg.msgCount & 0xFF);
+        }
+        for (MiscElt miscElt : smsHeader.miscEltList) {
+            outStream.write(miscElt.id);
+            outStream.write(miscElt.data.length);
+            outStream.write(miscElt.data, 0, miscElt.data.length);
+        }
+        return outStream.toByteArray();
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("UserDataHeader ");
+        builder.append("{ ConcatRef ");
+        if (concatRef == null) {
+            builder.append("unset");
+        } else {
+            builder.append("{ refNumber=" + concatRef.refNumber);
+            builder.append(", msgCount=" + concatRef.msgCount);
+            builder.append(", seqNumber=" + concatRef.seqNumber);
+            builder.append(", isEightBits=" + concatRef.isEightBits);
+            builder.append(" }");
+        }
+        builder.append(", PortAddrs ");
+        if (portAddrs == null) {
+            builder.append("unset");
+        } else {
+            builder.append("{ destPort=" + portAddrs.destPort);
+            builder.append(", origPort=" + portAddrs.origPort);
+            builder.append(", areEightBits=" + portAddrs.areEightBits);
+            builder.append(" }");
+        }
+        if (languageShiftTable != 0) {
+            builder.append(", languageShiftTable=" + languageShiftTable);
+        }
+        if (languageTable != 0) {
+            builder.append(", languageTable=" + languageTable);
+        }
+        for (SpecialSmsMsg specialSmsMsg : specialSmsMsgList) {
+            builder.append(", SpecialSmsMsg ");
+            builder.append("{ msgIndType=" + specialSmsMsg.msgIndType);
+            builder.append(", msgCount=" + specialSmsMsg.msgCount);
+            builder.append(" }");
+        }
+        for (MiscElt miscElt : miscEltList) {
+            builder.append(", MiscElt ");
+            builder.append("{ id=" + miscElt.id);
+            builder.append(", length=" + miscElt.data.length);
+            builder.append(", data=" + HexDump.toHexString(miscElt.data));
+            builder.append(" }");
+        }
+        builder.append(" }");
+        return builder.toString();
+    }
+
+}
diff --git a/telephony/java/com/android/internal/telephony/SmsMessageBase.java b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
new file mode 100644
index 0000000..e5821dc
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
@@ -0,0 +1,433 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
+import com.android.internal.telephony.SmsConstants;
+import com.android.internal.telephony.SmsHeader;
+import java.text.BreakIterator;
+import java.util.Arrays;
+
+import android.provider.Telephony;
+import android.telephony.SmsMessage;
+import android.text.Emoji;
+
+/**
+ * Base class declaring the specific methods and members for SmsMessage.
+ * {@hide}
+ */
+public abstract class SmsMessageBase {
+    /** {@hide} The address of the SMSC. May be null */
+    protected String mScAddress;
+
+    /** {@hide} The address of the sender */
+    protected SmsAddress mOriginatingAddress;
+
+    /** {@hide} The message body as a string. May be null if the message isn't text */
+    protected String mMessageBody;
+
+    /** {@hide} */
+    protected String mPseudoSubject;
+
+    /** {@hide} Non-null if this is an email gateway message */
+    protected String mEmailFrom;
+
+    /** {@hide} Non-null if this is an email gateway message */
+    protected String mEmailBody;
+
+    /** {@hide} */
+    protected boolean mIsEmail;
+
+    /** {@hide} Time when SC (service centre) received the message */
+    protected long mScTimeMillis;
+
+    /** {@hide} The raw PDU of the message */
+    protected byte[] mPdu;
+
+    /** {@hide} The raw bytes for the user data section of the message */
+    protected byte[] mUserData;
+
+    /** {@hide} */
+    protected SmsHeader mUserDataHeader;
+
+    // "Message Waiting Indication Group"
+    // 23.038 Section 4
+    /** {@hide} */
+    protected boolean mIsMwi;
+
+    /** {@hide} */
+    protected boolean mMwiSense;
+
+    /** {@hide} */
+    protected boolean mMwiDontStore;
+
+    /**
+     * Indicates status for messages stored on the ICC.
+     */
+    protected int mStatusOnIcc = -1;
+
+    /**
+     * Record index of message in the EF.
+     */
+    protected int mIndexOnIcc = -1;
+
+    /** TP-Message-Reference - Message Reference of sent message. @hide */
+    public int mMessageRef;
+
+    // TODO(): This class is duplicated in SmsMessage.java. Refactor accordingly.
+    public static abstract class SubmitPduBase  {
+        public byte[] encodedScAddress; // Null if not applicable.
+        public byte[] encodedMessage;
+
+        @Override
+        public String toString() {
+            return "SubmitPdu: encodedScAddress = "
+                    + Arrays.toString(encodedScAddress)
+                    + ", encodedMessage = "
+                    + Arrays.toString(encodedMessage);
+        }
+    }
+
+    /**
+     * Returns the address of the SMS service center that relayed this message
+     * or null if there is none.
+     */
+    public String getServiceCenterAddress() {
+        return mScAddress;
+    }
+
+    /**
+     * Returns the originating address (sender) of this SMS message in String
+     * form or null if unavailable
+     */
+    public String getOriginatingAddress() {
+        if (mOriginatingAddress == null) {
+            return null;
+        }
+
+        return mOriginatingAddress.getAddressString();
+    }
+
+    /**
+     * Returns the originating address, or email from address if this message
+     * was from an email gateway. Returns null if originating address
+     * unavailable.
+     */
+    public String getDisplayOriginatingAddress() {
+        if (mIsEmail) {
+            return mEmailFrom;
+        } else {
+            return getOriginatingAddress();
+        }
+    }
+
+    /**
+     * Returns the message body as a String, if it exists and is text based.
+     * @return message body is there is one, otherwise null
+     */
+    public String getMessageBody() {
+        return mMessageBody;
+    }
+
+    /**
+     * Returns the class of this message.
+     */
+    public abstract SmsConstants.MessageClass getMessageClass();
+
+    /**
+     * Returns the message body, or email message body if this message was from
+     * an email gateway. Returns null if message body unavailable.
+     */
+    public String getDisplayMessageBody() {
+        if (mIsEmail) {
+            return mEmailBody;
+        } else {
+            return getMessageBody();
+        }
+    }
+
+    /**
+     * Unofficial convention of a subject line enclosed in parens empty string
+     * if not present
+     */
+    public String getPseudoSubject() {
+        return mPseudoSubject == null ? "" : mPseudoSubject;
+    }
+
+    /**
+     * Returns the service centre timestamp in currentTimeMillis() format
+     */
+    public long getTimestampMillis() {
+        return mScTimeMillis;
+    }
+
+    /**
+     * Returns true if message is an email.
+     *
+     * @return true if this message came through an email gateway and email
+     *         sender / subject / parsed body are available
+     */
+    public boolean isEmail() {
+        return mIsEmail;
+    }
+
+    /**
+     * @return if isEmail() is true, body of the email sent through the gateway.
+     *         null otherwise
+     */
+    public String getEmailBody() {
+        return mEmailBody;
+    }
+
+    /**
+     * @return if isEmail() is true, email from address of email sent through
+     *         the gateway. null otherwise
+     */
+    public String getEmailFrom() {
+        return mEmailFrom;
+    }
+
+    /**
+     * Get protocol identifier.
+     */
+    public abstract int getProtocolIdentifier();
+
+    /**
+     * See TS 23.040 9.2.3.9 returns true if this is a "replace short message"
+     * SMS
+     */
+    public abstract boolean isReplace();
+
+    /**
+     * Returns true for CPHS MWI toggle message.
+     *
+     * @return true if this is a CPHS MWI toggle message See CPHS 4.2 section
+     *         B.4.2
+     */
+    public abstract boolean isCphsMwiMessage();
+
+    /**
+     * returns true if this message is a CPHS voicemail / message waiting
+     * indicator (MWI) clear message
+     */
+    public abstract boolean isMWIClearMessage();
+
+    /**
+     * returns true if this message is a CPHS voicemail / message waiting
+     * indicator (MWI) set message
+     */
+    public abstract boolean isMWISetMessage();
+
+    /**
+     * returns true if this message is a "Message Waiting Indication Group:
+     * Discard Message" notification and should not be stored.
+     */
+    public abstract boolean isMwiDontStore();
+
+    /**
+     * returns the user data section minus the user data header if one was
+     * present.
+     */
+    public byte[] getUserData() {
+        return mUserData;
+    }
+
+    /**
+     * Returns an object representing the user data header
+     *
+     * {@hide}
+     */
+    public SmsHeader getUserDataHeader() {
+        return mUserDataHeader;
+    }
+
+    /**
+     * TODO(cleanup): The term PDU is used in a seemingly non-unique
+     * manner -- for example, what is the difference between this byte
+     * array and the contents of SubmitPdu objects.  Maybe a more
+     * illustrative term would be appropriate.
+     */
+
+    /**
+     * Returns the raw PDU for the message.
+     */
+    public byte[] getPdu() {
+        return mPdu;
+    }
+
+    /**
+     * For an SMS-STATUS-REPORT message, this returns the status field from
+     * the status report.  This field indicates the status of a previously
+     * submitted SMS, if requested.  See TS 23.040, 9.2.3.15 TP-Status for a
+     * description of values.
+     *
+     * @return 0 indicates the previously sent message was received.
+     *         See TS 23.040, 9.9.2.3.15 for a description of other possible
+     *         values.
+     */
+    public abstract int getStatus();
+
+    /**
+     * Return true iff the message is a SMS-STATUS-REPORT message.
+     */
+    public abstract boolean isStatusReportMessage();
+
+    /**
+     * Returns true iff the <code>TP-Reply-Path</code> bit is set in
+     * this message.
+     */
+    public abstract boolean isReplyPathPresent();
+
+    /**
+     * Returns the status of the message on the ICC (read, unread, sent, unsent).
+     *
+     * @return the status of the message on the ICC.  These are:
+     *         SmsManager.STATUS_ON_ICC_FREE
+     *         SmsManager.STATUS_ON_ICC_READ
+     *         SmsManager.STATUS_ON_ICC_UNREAD
+     *         SmsManager.STATUS_ON_ICC_SEND
+     *         SmsManager.STATUS_ON_ICC_UNSENT
+     */
+    public int getStatusOnIcc() {
+        return mStatusOnIcc;
+    }
+
+    /**
+     * Returns the record index of the message on the ICC (1-based index).
+     * @return the record index of the message on the ICC, or -1 if this
+     *         SmsMessage was not created from a ICC SMS EF record.
+     */
+    public int getIndexOnIcc() {
+        return mIndexOnIcc;
+    }
+
+    protected void parseMessageBody() {
+        // originatingAddress could be null if this message is from a status
+        // report.
+        if (mOriginatingAddress != null && mOriginatingAddress.couldBeEmailGateway()) {
+            extractEmailAddressFromMessageBody();
+        }
+    }
+
+    /**
+     * Try to parse this message as an email gateway message
+     * There are two ways specified in TS 23.040 Section 3.8 :
+     *  - SMS message "may have its TP-PID set for Internet electronic mail - MT
+     * SMS format: [<from-address><space>]<message> - "Depending on the
+     * nature of the gateway, the destination/origination address is either
+     * derived from the content of the SMS TP-OA or TP-DA field, or the
+     * TP-OA/TP-DA field contains a generic gateway address and the to/from
+     * address is added at the beginning as shown above." (which is supported here)
+     * - Multiple addresses separated by commas, no spaces, Subject field delimited
+     * by '()' or '##' and '#' Section 9.2.3.24.11 (which are NOT supported here)
+     */
+    protected void extractEmailAddressFromMessageBody() {
+
+        /* Some carriers may use " /" delimiter as below
+         *
+         * 1. [x@y][ ]/[subject][ ]/[body]
+         * -or-
+         * 2. [x@y][ ]/[body]
+         */
+         String[] parts = mMessageBody.split("( /)|( )", 2);
+         if (parts.length < 2) return;
+         mEmailFrom = parts[0];
+         mEmailBody = parts[1];
+         mIsEmail = Telephony.Mms.isEmailAddress(mEmailFrom);
+    }
+
+    /**
+     * Find the next position to start a new fragment of a multipart SMS.
+     *
+     * @param currentPosition current start position of the fragment
+     * @param byteLimit maximum number of bytes in the fragment
+     * @param msgBody text of the SMS in UTF-16 encoding
+     * @return the position to start the next fragment
+     */
+    public static int findNextUnicodePosition(
+            int currentPosition, int byteLimit, CharSequence msgBody) {
+        int nextPos = Math.min(currentPosition + byteLimit / 2, msgBody.length());
+        // Check whether the fragment ends in a character boundary. Some characters take 4-bytes
+        // in UTF-16 encoding. Many carriers cannot handle
+        // a fragment correctly if it does not end at a character boundary.
+        if (nextPos < msgBody.length()) {
+            BreakIterator breakIterator = BreakIterator.getCharacterInstance();
+            breakIterator.setText(msgBody.toString());
+            if (!breakIterator.isBoundary(nextPos)) {
+                int breakPos = breakIterator.preceding(nextPos);
+                while (breakPos + 4 <= nextPos
+                        && Emoji.isRegionalIndicatorSymbol(
+                            Character.codePointAt(msgBody, breakPos))
+                        && Emoji.isRegionalIndicatorSymbol(
+                            Character.codePointAt(msgBody, breakPos + 2))) {
+                    // skip forward over flags (pairs of Regional Indicator Symbol)
+                    breakPos += 4;
+                }
+                if (breakPos > currentPosition) {
+                    nextPos = breakPos;
+                } else if (Character.isHighSurrogate(msgBody.charAt(nextPos - 1))) {
+                    // no character boundary in this fragment, try to at least land on a code point
+                    nextPos -= 1;
+                }
+            }
+        }
+        return nextPos;
+    }
+
+    /**
+     * Calculate the TextEncodingDetails of a message encoded in Unicode.
+     */
+    public static TextEncodingDetails calcUnicodeEncodingDetails(CharSequence msgBody) {
+        TextEncodingDetails ted = new TextEncodingDetails();
+        int octets = msgBody.length() * 2;
+        ted.codeUnitSize = SmsConstants.ENCODING_16BIT;
+        ted.codeUnitCount = msgBody.length();
+        if (octets > SmsConstants.MAX_USER_DATA_BYTES) {
+            // If EMS is not supported, break down EMS into single segment SMS
+            // and add page info " x/y".
+            // In the case of UCS2 encoding type, we need 8 bytes for this
+            // but we only have 6 bytes from UDH, so truncate the limit for
+            // each segment by 2 bytes (1 char).
+            int maxUserDataBytesWithHeader = SmsConstants.MAX_USER_DATA_BYTES_WITH_HEADER;
+            if (!SmsMessage.hasEmsSupport()) {
+                // make sure total number of segments is less than 10
+                if (octets <= 9 * (maxUserDataBytesWithHeader - 2)) {
+                    maxUserDataBytesWithHeader -= 2;
+                }
+            }
+
+            int pos = 0;  // Index in code units.
+            int msgCount = 0;
+            while (pos < msgBody.length()) {
+                int nextPos = findNextUnicodePosition(pos, maxUserDataBytesWithHeader,
+                        msgBody);
+                if (nextPos == msgBody.length()) {
+                    ted.codeUnitsRemaining = pos + maxUserDataBytesWithHeader / 2 -
+                            msgBody.length();
+                }
+                pos = nextPos;
+                msgCount++;
+            }
+            ted.msgCount = msgCount;
+        } else {
+            ted.msgCount = 1;
+            ted.codeUnitsRemaining = (SmsConstants.MAX_USER_DATA_BYTES - octets) / 2;
+        }
+
+        return ted;
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index 0168874..bcaac6e 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -16,6 +16,8 @@
 
 package com.android.internal.telephony;
 
+import android.content.Intent;
+
 /**
  * The intents that the telephony services broadcast.
  *
@@ -184,7 +186,6 @@
     public static final String ACTION_DATA_CONNECTION_FAILED
             = "android.intent.action.DATA_CONNECTION_FAILED";
 
-
     /**
      * Broadcast Action: The sim card state has changed.
      * The intent will have the following extra values:</p>
@@ -213,8 +214,7 @@
      * by the system.
      */
     public static final String ACTION_SIM_STATE_CHANGED
-            = "android.intent.action.SIM_STATE_CHANGED";
-
+            = Intent.ACTION_SIM_STATE_CHANGED;
 
     /**
      * Broadcast Action: The time was set by the carrier (typically by the NITZ string).
@@ -264,22 +264,13 @@
             = "android.intent.action.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS";
 
     /**
-     * Activity Action: Start this activity to invoke the carrier setup app.
-     * The carrier app must be signed using a certificate that matches the UICC access rules.
-     *
-     * <p class="note">Callers of this should hold the android.permission.INVOKE_CARRIER_SETUP
-     * permission.</p>
-     */
-    public static final String ACTION_CARRIER_SETUP = "android.intent.action.ACTION_CARRIER_SETUP";
-
-    /**
      * <p>Broadcast Action: Indicates that the action is forbidden by network.
      * <p class="note">
      * This is for the OEM applications to understand about possible provisioning issues.
      * Used in OMA-DM applications.
      */
     public static final String ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION
-            = "android.intent.action.ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION";
+            = "com.android.internal.intent.action.ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION";
 
     /**
      * Broadcast Action: A "secret code" has been entered in the dialer. Secret codes are
@@ -411,7 +402,7 @@
      * <p class="note">This is a protected intent that can only be sent by the system.</p>
      */
     public static final String ACTION_CARRIER_SIGNAL_REDIRECTED =
-            "android.intent.action.CARRIER_SIGNAL_REDIRECTED";
+            "com.android.internal.telephony.CARRIER_SIGNAL_REDIRECTED";
     /**
      * <p>Broadcast Action: when data connections setup fails.
      * intended for sim/account status checks and only sent to the specified carrier app
@@ -424,7 +415,7 @@
      * <p class="note">This is a protected intent that can only be sent by the system. </p>
      */
     public static final String ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED =
-            "android.intent.action.CARRIER_SIGNAL_REQUEST_NETWORK_FAILED";
+            "com.android.internal.telephony.CARRIER_SIGNAL_REQUEST_NETWORK_FAILED";
 
     /**
      * <p>Broadcast Action: when pco value is available.
@@ -441,7 +432,7 @@
      * <p class="note">This is a protected intent that can only be sent by the system. </p>
      */
     public static final String ACTION_CARRIER_SIGNAL_PCO_VALUE =
-            "android.intent.action.CARRIER_SIGNAL_PCO_VALUE";
+            "com.android.internal.telephony.CARRIER_SIGNAL_PCO_VALUE";
 
     // CARRIER_SIGNAL_ACTION extra keys
     public static final String EXTRA_REDIRECTION_URL_KEY = "redirectionUrl";
diff --git a/telephony/java/com/android/internal/telephony/cdma/BearerData.java b/telephony/java/com/android/internal/telephony/cdma/BearerData.java
new file mode 100644
index 0000000..a4cd56b
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/BearerData.java
@@ -0,0 +1,2025 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.cdma.sms;
+
+import android.content.res.Resources;
+import android.telephony.SmsCbCmasInfo;
+import android.telephony.cdma.CdmaSmsCbProgramData;
+import android.telephony.cdma.CdmaSmsCbProgramResults;
+import android.text.format.Time;
+import android.telephony.Rlog;
+
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
+import com.android.internal.telephony.SmsConstants;
+import com.android.internal.telephony.SmsHeader;
+import com.android.internal.telephony.SmsMessageBase;
+import com.android.internal.telephony.uicc.IccUtils;
+import com.android.internal.util.BitwiseInputStream;
+import com.android.internal.util.BitwiseOutputStream;
+
+import java.util.ArrayList;
+import java.util.TimeZone;
+
+/**
+ * An object to encode and decode CDMA SMS bearer data.
+ */
+public final class BearerData {
+    private final static String LOG_TAG = "BearerData";
+
+    /**
+     * Bearer Data Subparameter Identifiers
+     * (See 3GPP2 C.S0015-B, v2.0, table 4.5-1)
+     * NOTE: Commented subparameter types are not implemented.
+     */
+    private final static byte SUBPARAM_MESSAGE_IDENTIFIER               = 0x00;
+    private final static byte SUBPARAM_USER_DATA                        = 0x01;
+    private final static byte SUBPARAM_USER_RESPONSE_CODE               = 0x02;
+    private final static byte SUBPARAM_MESSAGE_CENTER_TIME_STAMP        = 0x03;
+    private final static byte SUBPARAM_VALIDITY_PERIOD_ABSOLUTE         = 0x04;
+    private final static byte SUBPARAM_VALIDITY_PERIOD_RELATIVE         = 0x05;
+    private final static byte SUBPARAM_DEFERRED_DELIVERY_TIME_ABSOLUTE  = 0x06;
+    private final static byte SUBPARAM_DEFERRED_DELIVERY_TIME_RELATIVE  = 0x07;
+    private final static byte SUBPARAM_PRIORITY_INDICATOR               = 0x08;
+    private final static byte SUBPARAM_PRIVACY_INDICATOR                = 0x09;
+    private final static byte SUBPARAM_REPLY_OPTION                     = 0x0A;
+    private final static byte SUBPARAM_NUMBER_OF_MESSAGES               = 0x0B;
+    private final static byte SUBPARAM_ALERT_ON_MESSAGE_DELIVERY        = 0x0C;
+    private final static byte SUBPARAM_LANGUAGE_INDICATOR               = 0x0D;
+    private final static byte SUBPARAM_CALLBACK_NUMBER                  = 0x0E;
+    private final static byte SUBPARAM_MESSAGE_DISPLAY_MODE             = 0x0F;
+    //private final static byte SUBPARAM_MULTIPLE_ENCODING_USER_DATA      = 0x10;
+    private final static byte SUBPARAM_MESSAGE_DEPOSIT_INDEX            = 0x11;
+    private final static byte SUBPARAM_SERVICE_CATEGORY_PROGRAM_DATA    = 0x12;
+    private final static byte SUBPARAM_SERVICE_CATEGORY_PROGRAM_RESULTS = 0x13;
+    private final static byte SUBPARAM_MESSAGE_STATUS                   = 0x14;
+    //private final static byte SUBPARAM_TP_FAILURE_CAUSE                 = 0x15;
+    //private final static byte SUBPARAM_ENHANCED_VMN                     = 0x16;
+    //private final static byte SUBPARAM_ENHANCED_VMN_ACK                 = 0x17;
+
+    // All other values after this are reserved.
+    private final static byte SUBPARAM_ID_LAST_DEFINED                    = 0x17;
+
+    /**
+     * Supported message types for CDMA SMS messages
+     * (See 3GPP2 C.S0015-B, v2.0, table 4.5.1-1)
+     */
+    public static final int MESSAGE_TYPE_DELIVER        = 0x01;
+    public static final int MESSAGE_TYPE_SUBMIT         = 0x02;
+    public static final int MESSAGE_TYPE_CANCELLATION   = 0x03;
+    public static final int MESSAGE_TYPE_DELIVERY_ACK   = 0x04;
+    public static final int MESSAGE_TYPE_USER_ACK       = 0x05;
+    public static final int MESSAGE_TYPE_READ_ACK       = 0x06;
+    public static final int MESSAGE_TYPE_DELIVER_REPORT = 0x07;
+    public static final int MESSAGE_TYPE_SUBMIT_REPORT  = 0x08;
+
+    public int messageType;
+
+    /**
+     * 16-bit value indicating the message ID, which increments modulo 65536.
+     * (Special rules apply for WAP-messages.)
+     * (See 3GPP2 C.S0015-B, v2, 4.5.1)
+     */
+    public int messageId;
+
+    /**
+     * Supported priority modes for CDMA SMS messages
+     * (See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1)
+     */
+    public static final int PRIORITY_NORMAL        = 0x0;
+    public static final int PRIORITY_INTERACTIVE   = 0x1;
+    public static final int PRIORITY_URGENT        = 0x2;
+    public static final int PRIORITY_EMERGENCY     = 0x3;
+
+    public boolean priorityIndicatorSet = false;
+    public int priority = PRIORITY_NORMAL;
+
+    /**
+     * Supported privacy modes for CDMA SMS messages
+     * (See 3GPP2 C.S0015-B, v2.0, table 4.5.10-1)
+     */
+    public static final int PRIVACY_NOT_RESTRICTED = 0x0;
+    public static final int PRIVACY_RESTRICTED     = 0x1;
+    public static final int PRIVACY_CONFIDENTIAL   = 0x2;
+    public static final int PRIVACY_SECRET         = 0x3;
+
+    public boolean privacyIndicatorSet = false;
+    public int privacy = PRIVACY_NOT_RESTRICTED;
+
+    /**
+     * Supported alert priority modes for CDMA SMS messages
+     * (See 3GPP2 C.S0015-B, v2.0, table 4.5.13-1)
+     */
+    public static final int ALERT_DEFAULT          = 0x0;
+    public static final int ALERT_LOW_PRIO         = 0x1;
+    public static final int ALERT_MEDIUM_PRIO      = 0x2;
+    public static final int ALERT_HIGH_PRIO        = 0x3;
+
+    public boolean alertIndicatorSet = false;
+    public int alert = ALERT_DEFAULT;
+
+    /**
+     * Supported display modes for CDMA SMS messages.  Display mode is
+     * a 2-bit value used to indicate to the mobile station when to
+     * display the received message.  (See 3GPP2 C.S0015-B, v2,
+     * 4.5.16)
+     */
+    public static final int DISPLAY_MODE_IMMEDIATE      = 0x0;
+    public static final int DISPLAY_MODE_DEFAULT        = 0x1;
+    public static final int DISPLAY_MODE_USER           = 0x2;
+
+    public boolean displayModeSet = false;
+    public int displayMode = DISPLAY_MODE_DEFAULT;
+
+    /**
+     * Language Indicator values.  NOTE: the spec (3GPP2 C.S0015-B,
+     * v2, 4.5.14) is ambiguous as to the meaning of this field, as it
+     * refers to C.R1001-D but that reference has been crossed out.
+     * It would seem reasonable to assume the values from C.R1001-F
+     * (table 9.2-1) are to be used instead.
+     */
+    public static final int LANGUAGE_UNKNOWN  = 0x00;
+    public static final int LANGUAGE_ENGLISH  = 0x01;
+    public static final int LANGUAGE_FRENCH   = 0x02;
+    public static final int LANGUAGE_SPANISH  = 0x03;
+    public static final int LANGUAGE_JAPANESE = 0x04;
+    public static final int LANGUAGE_KOREAN   = 0x05;
+    public static final int LANGUAGE_CHINESE  = 0x06;
+    public static final int LANGUAGE_HEBREW   = 0x07;
+
+    public boolean languageIndicatorSet = false;
+    public int language = LANGUAGE_UNKNOWN;
+
+    /**
+     * SMS Message Status Codes.  The first component of the Message
+     * status indicates if an error has occurred and whether the error
+     * is considered permanent or temporary.  The second component of
+     * the Message status indicates the cause of the error (if any).
+     * (See 3GPP2 C.S0015-B, v2.0, 4.5.21)
+     */
+    /* no-error codes */
+    public static final int ERROR_NONE                   = 0x00;
+    public static final int STATUS_ACCEPTED              = 0x00;
+    public static final int STATUS_DEPOSITED_TO_INTERNET = 0x01;
+    public static final int STATUS_DELIVERED             = 0x02;
+    public static final int STATUS_CANCELLED             = 0x03;
+    /* temporary-error and permanent-error codes */
+    public static final int ERROR_TEMPORARY              = 0x02;
+    public static final int STATUS_NETWORK_CONGESTION    = 0x04;
+    public static final int STATUS_NETWORK_ERROR         = 0x05;
+    public static final int STATUS_UNKNOWN_ERROR         = 0x1F;
+    /* permanent-error codes */
+    public static final int ERROR_PERMANENT              = 0x03;
+    public static final int STATUS_CANCEL_FAILED         = 0x06;
+    public static final int STATUS_BLOCKED_DESTINATION   = 0x07;
+    public static final int STATUS_TEXT_TOO_LONG         = 0x08;
+    public static final int STATUS_DUPLICATE_MESSAGE     = 0x09;
+    public static final int STATUS_INVALID_DESTINATION   = 0x0A;
+    public static final int STATUS_MESSAGE_EXPIRED       = 0x0D;
+    /* undefined-status codes */
+    public static final int ERROR_UNDEFINED              = 0xFF;
+    public static final int STATUS_UNDEFINED             = 0xFF;
+
+    public boolean messageStatusSet = false;
+    public int errorClass = ERROR_UNDEFINED;
+    public int messageStatus = STATUS_UNDEFINED;
+
+    /**
+     * 1-bit value that indicates whether a User Data Header (UDH) is present.
+     * (See 3GPP2 C.S0015-B, v2, 4.5.1)
+     *
+     * NOTE: during encoding, this value will be set based on the
+     * presence of a UDH in the structured data, any existing setting
+     * will be overwritten.
+     */
+    public boolean hasUserDataHeader;
+
+    /**
+     * provides the information for the user data
+     * (e.g. padding bits, user data, user data header, etc)
+     * (See 3GPP2 C.S.0015-B, v2, 4.5.2)
+     */
+    public UserData userData;
+
+    /**
+     * The User Response Code subparameter is used in the SMS User
+     * Acknowledgment Message to respond to previously received short
+     * messages. This message center-specific element carries the
+     * identifier of a predefined response. (See 3GPP2 C.S.0015-B, v2,
+     * 4.5.3)
+     */
+    public boolean userResponseCodeSet = false;
+    public int userResponseCode;
+
+    /**
+     * 6-byte-field, see 3GPP2 C.S0015-B, v2, 4.5.4
+     */
+    public static class TimeStamp extends Time {
+
+        public TimeStamp() {
+            super(TimeZone.getDefault().getID());   // 3GPP2 timestamps use the local timezone
+        }
+
+        public static TimeStamp fromByteArray(byte[] data) {
+            TimeStamp ts = new TimeStamp();
+            // C.S0015-B v2.0, 4.5.4: range is 1996-2095
+            int year = IccUtils.cdmaBcdByteToInt(data[0]);
+            if (year > 99 || year < 0) return null;
+            ts.year = year >= 96 ? year + 1900 : year + 2000;
+            int month = IccUtils.cdmaBcdByteToInt(data[1]);
+            if (month < 1 || month > 12) return null;
+            ts.month = month - 1;
+            int day = IccUtils.cdmaBcdByteToInt(data[2]);
+            if (day < 1 || day > 31) return null;
+            ts.monthDay = day;
+            int hour = IccUtils.cdmaBcdByteToInt(data[3]);
+            if (hour < 0 || hour > 23) return null;
+            ts.hour = hour;
+            int minute = IccUtils.cdmaBcdByteToInt(data[4]);
+            if (minute < 0 || minute > 59) return null;
+            ts.minute = minute;
+            int second = IccUtils.cdmaBcdByteToInt(data[5]);
+            if (second < 0 || second > 59) return null;
+            ts.second = second;
+            return ts;
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder builder = new StringBuilder();
+            builder.append("TimeStamp ");
+            builder.append("{ year=" + year);
+            builder.append(", month=" + month);
+            builder.append(", day=" + monthDay);
+            builder.append(", hour=" + hour);
+            builder.append(", minute=" + minute);
+            builder.append(", second=" + second);
+            builder.append(" }");
+            return builder.toString();
+        }
+    }
+
+    public TimeStamp msgCenterTimeStamp;
+    public TimeStamp validityPeriodAbsolute;
+    public TimeStamp deferredDeliveryTimeAbsolute;
+
+    /**
+     * Relative time is specified as one byte, the value of which
+     * falls into a series of ranges, as specified below.  The idea is
+     * that shorter time intervals allow greater precision -- the
+     * value means minutes from zero until the MINS_LIMIT (inclusive),
+     * upon which it means hours until the HOURS_LIMIT, and so
+     * forth. (See 3GPP2 C.S0015-B, v2, 4.5.6-1)
+     */
+    public static final int RELATIVE_TIME_MINS_LIMIT      = 143;
+    public static final int RELATIVE_TIME_HOURS_LIMIT     = 167;
+    public static final int RELATIVE_TIME_DAYS_LIMIT      = 196;
+    public static final int RELATIVE_TIME_WEEKS_LIMIT     = 244;
+    public static final int RELATIVE_TIME_INDEFINITE      = 245;
+    public static final int RELATIVE_TIME_NOW             = 246;
+    public static final int RELATIVE_TIME_MOBILE_INACTIVE = 247;
+    public static final int RELATIVE_TIME_RESERVED        = 248;
+
+    public boolean validityPeriodRelativeSet;
+    public int validityPeriodRelative;
+    public boolean deferredDeliveryTimeRelativeSet;
+    public int deferredDeliveryTimeRelative;
+
+    /**
+     * The Reply Option subparameter contains 1-bit values which
+     * indicate whether SMS acknowledgment is requested or not.  (See
+     * 3GPP2 C.S0015-B, v2, 4.5.11)
+     */
+    public boolean userAckReq;
+    public boolean deliveryAckReq;
+    public boolean readAckReq;
+    public boolean reportReq;
+
+    /**
+     * The Number of Messages subparameter (8-bit value) is a decimal
+     * number in the 0 to 99 range representing the number of messages
+     * stored at the Voice Mail System. This element is used by the
+     * Voice Mail Notification service.  (See 3GPP2 C.S0015-B, v2,
+     * 4.5.12)
+     */
+    public int numberOfMessages;
+
+    /**
+     * The Message Deposit Index subparameter is assigned by the
+     * message center as a unique index to the contents of the User
+     * Data subparameter in each message sent to a particular mobile
+     * station. The mobile station, when replying to a previously
+     * received short message which included a Message Deposit Index
+     * subparameter, may include the Message Deposit Index of the
+     * received message to indicate to the message center that the
+     * original contents of the message are to be included in the
+     * reply.  (See 3GPP2 C.S0015-B, v2, 4.5.18)
+     */
+    public int depositIndex;
+
+    /**
+     * 4-bit or 8-bit value that indicates the number to be dialed in reply to a
+     * received SMS message.
+     * (See 3GPP2 C.S0015-B, v2, 4.5.15)
+     */
+    public CdmaSmsAddress callbackNumber;
+
+    /**
+     * CMAS warning notification information.
+     * @see #decodeCmasUserData(BearerData, int)
+     */
+    public SmsCbCmasInfo cmasWarningInfo;
+
+    /**
+     * The Service Category Program Data subparameter is used to enable and disable
+     * SMS broadcast service categories to display. If this subparameter is present,
+     * this field will contain a list of one or more
+     * {@link android.telephony.cdma.CdmaSmsCbProgramData} objects containing the
+     * operation(s) to perform.
+     */
+    public ArrayList<CdmaSmsCbProgramData> serviceCategoryProgramData;
+
+    /**
+     * The Service Category Program Results subparameter informs the message center
+     * of the results of a Service Category Program Data request.
+     */
+    public ArrayList<CdmaSmsCbProgramResults> serviceCategoryProgramResults;
+
+
+    private static class CodingException extends Exception {
+        public CodingException(String s) {
+            super(s);
+        }
+    }
+
+    /**
+     * Returns the language indicator as a two-character ISO 639 string.
+     * @return a two character ISO 639 language code
+     */
+    public String getLanguage() {
+        return getLanguageCodeForValue(language);
+    }
+
+    /**
+     * Converts a CDMA language indicator value to an ISO 639 two character language code.
+     * @param languageValue the CDMA language value to convert
+     * @return the two character ISO 639 language code for the specified value, or null if unknown
+     */
+    private static String getLanguageCodeForValue(int languageValue) {
+        switch (languageValue) {
+            case LANGUAGE_ENGLISH:
+                return "en";
+
+            case LANGUAGE_FRENCH:
+                return "fr";
+
+            case LANGUAGE_SPANISH:
+                return "es";
+
+            case LANGUAGE_JAPANESE:
+                return "ja";
+
+            case LANGUAGE_KOREAN:
+                return "ko";
+
+            case LANGUAGE_CHINESE:
+                return "zh";
+
+            case LANGUAGE_HEBREW:
+                return "he";
+
+            default:
+                return null;
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("BearerData ");
+        builder.append("{ messageType=" + messageType);
+        builder.append(", messageId=" + messageId);
+        builder.append(", priority=" + (priorityIndicatorSet ? priority : "unset"));
+        builder.append(", privacy=" + (privacyIndicatorSet ? privacy : "unset"));
+        builder.append(", alert=" + (alertIndicatorSet ? alert : "unset"));
+        builder.append(", displayMode=" + (displayModeSet ? displayMode : "unset"));
+        builder.append(", language=" + (languageIndicatorSet ? language : "unset"));
+        builder.append(", errorClass=" + (messageStatusSet ? errorClass : "unset"));
+        builder.append(", msgStatus=" + (messageStatusSet ? messageStatus : "unset"));
+        builder.append(", msgCenterTimeStamp=" +
+                ((msgCenterTimeStamp != null) ? msgCenterTimeStamp : "unset"));
+        builder.append(", validityPeriodAbsolute=" +
+                ((validityPeriodAbsolute != null) ? validityPeriodAbsolute : "unset"));
+        builder.append(", validityPeriodRelative=" +
+                ((validityPeriodRelativeSet) ? validityPeriodRelative : "unset"));
+        builder.append(", deferredDeliveryTimeAbsolute=" +
+                ((deferredDeliveryTimeAbsolute != null) ? deferredDeliveryTimeAbsolute : "unset"));
+        builder.append(", deferredDeliveryTimeRelative=" +
+                ((deferredDeliveryTimeRelativeSet) ? deferredDeliveryTimeRelative : "unset"));
+        builder.append(", userAckReq=" + userAckReq);
+        builder.append(", deliveryAckReq=" + deliveryAckReq);
+        builder.append(", readAckReq=" + readAckReq);
+        builder.append(", reportReq=" + reportReq);
+        builder.append(", numberOfMessages=" + numberOfMessages);
+        builder.append(", callbackNumber=" + Rlog.pii(LOG_TAG, callbackNumber));
+        builder.append(", depositIndex=" + depositIndex);
+        builder.append(", hasUserDataHeader=" + hasUserDataHeader);
+        builder.append(", userData=" + userData);
+        builder.append(" }");
+        return builder.toString();
+    }
+
+    private static void encodeMessageId(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException
+    {
+        outStream.write(8, 3);
+        outStream.write(4, bData.messageType);
+        outStream.write(8, bData.messageId >> 8);
+        outStream.write(8, bData.messageId);
+        outStream.write(1, bData.hasUserDataHeader ? 1 : 0);
+        outStream.skip(3);
+    }
+
+    private static int countAsciiSeptets(CharSequence msg, boolean force) {
+        int msgLen = msg.length();
+        if (force) return msgLen;
+        for (int i = 0; i < msgLen; i++) {
+            if (UserData.charToAscii.get(msg.charAt(i), -1) == -1) {
+                return -1;
+            }
+        }
+        return msgLen;
+    }
+
+    /**
+     * Calculate the message text encoding length, fragmentation, and other details.
+     *
+     * @param msg message text
+     * @param force7BitEncoding ignore (but still count) illegal characters if true
+     * @param isEntireMsg indicates if this is entire msg or a segment in multipart msg
+     * @return septet count, or -1 on failure
+     */
+    public static TextEncodingDetails calcTextEncodingDetails(CharSequence msg,
+            boolean force7BitEncoding, boolean isEntireMsg) {
+        TextEncodingDetails ted;
+        int septets = countAsciiSeptets(msg, force7BitEncoding);
+        if (septets != -1 && septets <= SmsConstants.MAX_USER_DATA_SEPTETS) {
+            ted = new TextEncodingDetails();
+            ted.msgCount = 1;
+            ted.codeUnitCount = septets;
+            ted.codeUnitsRemaining = SmsConstants.MAX_USER_DATA_SEPTETS - septets;
+            ted.codeUnitSize = SmsConstants.ENCODING_7BIT;
+        } else {
+            ted = com.android.internal.telephony.gsm.SmsMessage.calculateLength(
+                    msg, force7BitEncoding);
+            if (ted.msgCount == 1 && ted.codeUnitSize == SmsConstants.ENCODING_7BIT &&
+                    isEntireMsg) {
+                // We don't support single-segment EMS, so calculate for 16-bit
+                // TODO: Consider supporting single-segment EMS
+                return SmsMessageBase.calcUnicodeEncodingDetails(msg);
+            }
+        }
+        return ted;
+    }
+
+    private static byte[] encode7bitAscii(String msg, boolean force)
+        throws CodingException
+    {
+        try {
+            BitwiseOutputStream outStream = new BitwiseOutputStream(msg.length());
+            int msgLen = msg.length();
+            for (int i = 0; i < msgLen; i++) {
+                int charCode = UserData.charToAscii.get(msg.charAt(i), -1);
+                if (charCode == -1) {
+                    if (force) {
+                        outStream.write(7, UserData.UNENCODABLE_7_BIT_CHAR);
+                    } else {
+                        throw new CodingException("cannot ASCII encode (" + msg.charAt(i) + ")");
+                    }
+                } else {
+                    outStream.write(7, charCode);
+                }
+            }
+            return outStream.toByteArray();
+        } catch (BitwiseOutputStream.AccessException ex) {
+            throw new CodingException("7bit ASCII encode failed: " + ex);
+        }
+    }
+
+    private static byte[] encodeUtf16(String msg)
+        throws CodingException
+    {
+        try {
+            return msg.getBytes("utf-16be");
+        } catch (java.io.UnsupportedEncodingException ex) {
+            throw new CodingException("UTF-16 encode failed: " + ex);
+        }
+    }
+
+    private static class Gsm7bitCodingResult {
+        int septets;
+        byte[] data;
+    }
+
+    private static Gsm7bitCodingResult encode7bitGsm(String msg, int septetOffset, boolean force)
+        throws CodingException
+    {
+        try {
+            /*
+             * TODO(cleanup): It would be nice if GsmAlphabet provided
+             * an option to produce just the data without prepending
+             * the septet count, as this function is really just a
+             * wrapper to strip that off.  Not to mention that the
+             * septet count is generally known prior to invocation of
+             * the encoder.  Note that it cannot be derived from the
+             * resulting array length, since that cannot distinguish
+             * if the last contains either 1 or 8 valid bits.
+             *
+             * TODO(cleanup): The BitwiseXStreams could also be
+             * extended with byte-wise reversed endianness read/write
+             * routines to allow a corresponding implementation of
+             * stringToGsm7BitPacked, and potentially directly support
+             * access to the main bitwise stream from encode/decode.
+             */
+            byte[] fullData = GsmAlphabet.stringToGsm7BitPacked(msg, septetOffset, !force, 0, 0);
+            Gsm7bitCodingResult result = new Gsm7bitCodingResult();
+            result.data = new byte[fullData.length - 1];
+            System.arraycopy(fullData, 1, result.data, 0, fullData.length - 1);
+            result.septets = fullData[0] & 0x00FF;
+            return result;
+        } catch (com.android.internal.telephony.EncodeException ex) {
+            throw new CodingException("7bit GSM encode failed: " + ex);
+        }
+    }
+
+    private static void encode7bitEms(UserData uData, byte[] udhData, boolean force)
+        throws CodingException
+    {
+        int udhBytes = udhData.length + 1;  // Add length octet.
+        int udhSeptets = ((udhBytes * 8) + 6) / 7;
+        Gsm7bitCodingResult gcr = encode7bitGsm(uData.payloadStr, udhSeptets, force);
+        uData.msgEncoding = UserData.ENCODING_GSM_7BIT_ALPHABET;
+        uData.msgEncodingSet = true;
+        uData.numFields = gcr.septets;
+        uData.payload = gcr.data;
+        uData.payload[0] = (byte)udhData.length;
+        System.arraycopy(udhData, 0, uData.payload, 1, udhData.length);
+    }
+
+    private static void encode16bitEms(UserData uData, byte[] udhData)
+        throws CodingException
+    {
+        byte[] payload = encodeUtf16(uData.payloadStr);
+        int udhBytes = udhData.length + 1;  // Add length octet.
+        int udhCodeUnits = (udhBytes + 1) / 2;
+        int payloadCodeUnits = payload.length / 2;
+        uData.msgEncoding = UserData.ENCODING_UNICODE_16;
+        uData.msgEncodingSet = true;
+        uData.numFields = udhCodeUnits + payloadCodeUnits;
+        uData.payload = new byte[uData.numFields * 2];
+        uData.payload[0] = (byte)udhData.length;
+        System.arraycopy(udhData, 0, uData.payload, 1, udhData.length);
+        System.arraycopy(payload, 0, uData.payload, udhBytes, payload.length);
+    }
+
+    private static void encodeEmsUserDataPayload(UserData uData)
+        throws CodingException
+    {
+        byte[] headerData = SmsHeader.toByteArray(uData.userDataHeader);
+        if (uData.msgEncodingSet) {
+            if (uData.msgEncoding == UserData.ENCODING_GSM_7BIT_ALPHABET) {
+                encode7bitEms(uData, headerData, true);
+            } else if (uData.msgEncoding == UserData.ENCODING_UNICODE_16) {
+                encode16bitEms(uData, headerData);
+            } else {
+                throw new CodingException("unsupported EMS user data encoding (" +
+                                          uData.msgEncoding + ")");
+            }
+        } else {
+            try {
+                encode7bitEms(uData, headerData, false);
+            } catch (CodingException ex) {
+                encode16bitEms(uData, headerData);
+            }
+        }
+    }
+
+    private static byte[] encodeShiftJis(String msg) throws CodingException {
+        try {
+            return msg.getBytes("Shift_JIS");
+        } catch (java.io.UnsupportedEncodingException ex) {
+            throw new CodingException("Shift-JIS encode failed: " + ex);
+        }
+    }
+
+    private static void encodeUserDataPayload(UserData uData)
+        throws CodingException
+    {
+        if ((uData.payloadStr == null) && (uData.msgEncoding != UserData.ENCODING_OCTET)) {
+            Rlog.e(LOG_TAG, "user data with null payloadStr");
+            uData.payloadStr = "";
+        }
+
+        if (uData.userDataHeader != null) {
+            encodeEmsUserDataPayload(uData);
+            return;
+        }
+
+        if (uData.msgEncodingSet) {
+            if (uData.msgEncoding == UserData.ENCODING_OCTET) {
+                if (uData.payload == null) {
+                    Rlog.e(LOG_TAG, "user data with octet encoding but null payload");
+                    uData.payload = new byte[0];
+                    uData.numFields = 0;
+                } else {
+                    uData.numFields = uData.payload.length;
+                }
+            } else {
+                if (uData.payloadStr == null) {
+                    Rlog.e(LOG_TAG, "non-octet user data with null payloadStr");
+                    uData.payloadStr = "";
+                }
+                if (uData.msgEncoding == UserData.ENCODING_GSM_7BIT_ALPHABET) {
+                    Gsm7bitCodingResult gcr = encode7bitGsm(uData.payloadStr, 0, true);
+                    uData.payload = gcr.data;
+                    uData.numFields = gcr.septets;
+                } else if (uData.msgEncoding == UserData.ENCODING_7BIT_ASCII) {
+                    uData.payload = encode7bitAscii(uData.payloadStr, true);
+                    uData.numFields = uData.payloadStr.length();
+                } else if (uData.msgEncoding == UserData.ENCODING_UNICODE_16) {
+                    uData.payload = encodeUtf16(uData.payloadStr);
+                    uData.numFields = uData.payloadStr.length();
+                } else if (uData.msgEncoding == UserData.ENCODING_SHIFT_JIS) {
+                    uData.payload = encodeShiftJis(uData.payloadStr);
+                    uData.numFields = uData.payload.length;
+                } else {
+                    throw new CodingException("unsupported user data encoding (" +
+                                              uData.msgEncoding + ")");
+                }
+            }
+        } else {
+            try {
+                uData.payload = encode7bitAscii(uData.payloadStr, false);
+                uData.msgEncoding = UserData.ENCODING_7BIT_ASCII;
+            } catch (CodingException ex) {
+                uData.payload = encodeUtf16(uData.payloadStr);
+                uData.msgEncoding = UserData.ENCODING_UNICODE_16;
+            }
+            uData.numFields = uData.payloadStr.length();
+            uData.msgEncodingSet = true;
+        }
+    }
+
+    private static void encodeUserData(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException, CodingException
+    {
+        /*
+         * TODO(cleanup): Do we really need to set userData.payload as
+         * a side effect of encoding?  If not, we could avoid data
+         * copies by passing outStream directly.
+         */
+        encodeUserDataPayload(bData.userData);
+        bData.hasUserDataHeader = bData.userData.userDataHeader != null;
+
+        if (bData.userData.payload.length > SmsConstants.MAX_USER_DATA_BYTES) {
+            throw new CodingException("encoded user data too large (" +
+                                      bData.userData.payload.length +
+                                      " > " + SmsConstants.MAX_USER_DATA_BYTES + " bytes)");
+        }
+
+        /*
+         * TODO(cleanup): figure out what the right answer is WRT paddingBits field
+         *
+         *   userData.paddingBits = (userData.payload.length * 8) - (userData.numFields * 7);
+         *   userData.paddingBits = 0; // XXX this seems better, but why?
+         *
+         */
+        int dataBits = (bData.userData.payload.length * 8) - bData.userData.paddingBits;
+        int paramBits = dataBits + 13;
+        if ((bData.userData.msgEncoding == UserData.ENCODING_IS91_EXTENDED_PROTOCOL) ||
+            (bData.userData.msgEncoding == UserData.ENCODING_GSM_DCS)) {
+            paramBits += 8;
+        }
+        int paramBytes = (paramBits / 8) + ((paramBits % 8) > 0 ? 1 : 0);
+        int paddingBits = (paramBytes * 8) - paramBits;
+        outStream.write(8, paramBytes);
+        outStream.write(5, bData.userData.msgEncoding);
+        if ((bData.userData.msgEncoding == UserData.ENCODING_IS91_EXTENDED_PROTOCOL) ||
+            (bData.userData.msgEncoding == UserData.ENCODING_GSM_DCS)) {
+            outStream.write(8, bData.userData.msgType);
+        }
+        outStream.write(8, bData.userData.numFields);
+        outStream.writeByteArray(dataBits, bData.userData.payload);
+        if (paddingBits > 0) outStream.write(paddingBits, 0);
+    }
+
+    private static void encodeReplyOption(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException
+    {
+        outStream.write(8, 1);
+        outStream.write(1, bData.userAckReq     ? 1 : 0);
+        outStream.write(1, bData.deliveryAckReq ? 1 : 0);
+        outStream.write(1, bData.readAckReq     ? 1 : 0);
+        outStream.write(1, bData.reportReq      ? 1 : 0);
+        outStream.write(4, 0);
+    }
+
+    private static byte[] encodeDtmfSmsAddress(String address) {
+        int digits = address.length();
+        int dataBits = digits * 4;
+        int dataBytes = (dataBits / 8);
+        dataBytes += (dataBits % 8) > 0 ? 1 : 0;
+        byte[] rawData = new byte[dataBytes];
+        for (int i = 0; i < digits; i++) {
+            char c = address.charAt(i);
+            int val = 0;
+            if ((c >= '1') && (c <= '9')) val = c - '0';
+            else if (c == '0') val = 10;
+            else if (c == '*') val = 11;
+            else if (c == '#') val = 12;
+            else return null;
+            rawData[i / 2] |= val << (4 - ((i % 2) * 4));
+        }
+        return rawData;
+    }
+
+    /*
+     * TODO(cleanup): CdmaSmsAddress encoding should make use of
+     * CdmaSmsAddress.parse provided that DTMF encoding is unified,
+     * and the difference in 4-bit vs. 8-bit is resolved.
+     */
+
+    private static void encodeCdmaSmsAddress(CdmaSmsAddress addr) throws CodingException {
+        if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
+            try {
+                addr.origBytes = addr.address.getBytes("US-ASCII");
+            } catch (java.io.UnsupportedEncodingException ex) {
+                throw new CodingException("invalid SMS address, cannot convert to ASCII");
+            }
+        } else {
+            addr.origBytes = encodeDtmfSmsAddress(addr.address);
+        }
+    }
+
+    private static void encodeCallbackNumber(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException, CodingException
+    {
+        CdmaSmsAddress addr = bData.callbackNumber;
+        encodeCdmaSmsAddress(addr);
+        int paramBits = 9;
+        int dataBits = 0;
+        if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
+            paramBits += 7;
+            dataBits = addr.numberOfDigits * 8;
+        } else {
+            dataBits = addr.numberOfDigits * 4;
+        }
+        paramBits += dataBits;
+        int paramBytes = (paramBits / 8) + ((paramBits % 8) > 0 ? 1 : 0);
+        int paddingBits = (paramBytes * 8) - paramBits;
+        outStream.write(8, paramBytes);
+        outStream.write(1, addr.digitMode);
+        if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
+            outStream.write(3, addr.ton);
+            outStream.write(4, addr.numberPlan);
+        }
+        outStream.write(8, addr.numberOfDigits);
+        outStream.writeByteArray(dataBits, addr.origBytes);
+        if (paddingBits > 0) outStream.write(paddingBits, 0);
+    }
+
+    private static void encodeMsgStatus(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException
+    {
+        outStream.write(8, 1);
+        outStream.write(2, bData.errorClass);
+        outStream.write(6, bData.messageStatus);
+    }
+
+    private static void encodeMsgCount(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException
+    {
+        outStream.write(8, 1);
+        outStream.write(8, bData.numberOfMessages);
+    }
+
+    private static void encodeValidityPeriodRel(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException
+    {
+        outStream.write(8, 1);
+        outStream.write(8, bData.validityPeriodRelative);
+    }
+
+    private static void encodePrivacyIndicator(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException
+    {
+        outStream.write(8, 1);
+        outStream.write(2, bData.privacy);
+        outStream.skip(6);
+    }
+
+    private static void encodeLanguageIndicator(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException
+    {
+        outStream.write(8, 1);
+        outStream.write(8, bData.language);
+    }
+
+    private static void encodeDisplayMode(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException
+    {
+        outStream.write(8, 1);
+        outStream.write(2, bData.displayMode);
+        outStream.skip(6);
+    }
+
+    private static void encodePriorityIndicator(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException
+    {
+        outStream.write(8, 1);
+        outStream.write(2, bData.priority);
+        outStream.skip(6);
+    }
+
+    private static void encodeMsgDeliveryAlert(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException
+    {
+        outStream.write(8, 1);
+        outStream.write(2, bData.alert);
+        outStream.skip(6);
+    }
+
+    private static void encodeScpResults(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException
+    {
+        ArrayList<CdmaSmsCbProgramResults> results = bData.serviceCategoryProgramResults;
+        outStream.write(8, (results.size() * 4));   // 4 octets per program result
+        for (CdmaSmsCbProgramResults result : results) {
+            int category = result.getCategory();
+            outStream.write(8, category >> 8);
+            outStream.write(8, category);
+            outStream.write(8, result.getLanguage());
+            outStream.write(4, result.getCategoryResult());
+            outStream.skip(4);
+        }
+    }
+
+    /**
+     * Create serialized representation for BearerData object.
+     * (See 3GPP2 C.R1001-F, v1.0, section 4.5 for layout details)
+     *
+     * @param bData an instance of BearerData.
+     *
+     * @return byte array of raw encoded SMS bearer data.
+     */
+    public static byte[] encode(BearerData bData) {
+        bData.hasUserDataHeader = ((bData.userData != null) &&
+                (bData.userData.userDataHeader != null));
+        try {
+            BitwiseOutputStream outStream = new BitwiseOutputStream(200);
+            outStream.write(8, SUBPARAM_MESSAGE_IDENTIFIER);
+            encodeMessageId(bData, outStream);
+            if (bData.userData != null) {
+                outStream.write(8, SUBPARAM_USER_DATA);
+                encodeUserData(bData, outStream);
+            }
+            if (bData.callbackNumber != null) {
+                outStream.write(8, SUBPARAM_CALLBACK_NUMBER);
+                encodeCallbackNumber(bData, outStream);
+            }
+            if (bData.userAckReq || bData.deliveryAckReq || bData.readAckReq || bData.reportReq) {
+                outStream.write(8, SUBPARAM_REPLY_OPTION);
+                encodeReplyOption(bData, outStream);
+            }
+            if (bData.numberOfMessages != 0) {
+                outStream.write(8, SUBPARAM_NUMBER_OF_MESSAGES);
+                encodeMsgCount(bData, outStream);
+            }
+            if (bData.validityPeriodRelativeSet) {
+                outStream.write(8, SUBPARAM_VALIDITY_PERIOD_RELATIVE);
+                encodeValidityPeriodRel(bData, outStream);
+            }
+            if (bData.privacyIndicatorSet) {
+                outStream.write(8, SUBPARAM_PRIVACY_INDICATOR);
+                encodePrivacyIndicator(bData, outStream);
+            }
+            if (bData.languageIndicatorSet) {
+                outStream.write(8, SUBPARAM_LANGUAGE_INDICATOR);
+                encodeLanguageIndicator(bData, outStream);
+            }
+            if (bData.displayModeSet) {
+                outStream.write(8, SUBPARAM_MESSAGE_DISPLAY_MODE);
+                encodeDisplayMode(bData, outStream);
+            }
+            if (bData.priorityIndicatorSet) {
+                outStream.write(8, SUBPARAM_PRIORITY_INDICATOR);
+                encodePriorityIndicator(bData, outStream);
+            }
+            if (bData.alertIndicatorSet) {
+                outStream.write(8, SUBPARAM_ALERT_ON_MESSAGE_DELIVERY);
+                encodeMsgDeliveryAlert(bData, outStream);
+            }
+            if (bData.messageStatusSet) {
+                outStream.write(8, SUBPARAM_MESSAGE_STATUS);
+                encodeMsgStatus(bData, outStream);
+            }
+            if (bData.serviceCategoryProgramResults != null) {
+                outStream.write(8, SUBPARAM_SERVICE_CATEGORY_PROGRAM_RESULTS);
+                encodeScpResults(bData, outStream);
+            }
+            return outStream.toByteArray();
+        } catch (BitwiseOutputStream.AccessException ex) {
+            Rlog.e(LOG_TAG, "BearerData encode failed: " + ex);
+        } catch (CodingException ex) {
+            Rlog.e(LOG_TAG, "BearerData encode failed: " + ex);
+        }
+        return null;
+   }
+
+    private static boolean decodeMessageId(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException {
+        final int EXPECTED_PARAM_SIZE = 3 * 8;
+        boolean decodeSuccess = false;
+        int paramBits = inStream.read(8) * 8;
+        if (paramBits >= EXPECTED_PARAM_SIZE) {
+            paramBits -= EXPECTED_PARAM_SIZE;
+            decodeSuccess = true;
+            bData.messageType = inStream.read(4);
+            bData.messageId = inStream.read(8) << 8;
+            bData.messageId |= inStream.read(8);
+            bData.hasUserDataHeader = (inStream.read(1) == 1);
+            inStream.skip(3);
+        }
+        if ((! decodeSuccess) || (paramBits > 0)) {
+            Rlog.d(LOG_TAG, "MESSAGE_IDENTIFIER decode " +
+                      (decodeSuccess ? "succeeded" : "failed") +
+                      " (extra bits = " + paramBits + ")");
+        }
+        inStream.skip(paramBits);
+        return decodeSuccess;
+    }
+
+    private static boolean decodeReserved(
+            BearerData bData, BitwiseInputStream inStream, int subparamId)
+        throws BitwiseInputStream.AccessException, CodingException
+    {
+        boolean decodeSuccess = false;
+        int subparamLen = inStream.read(8); // SUBPARAM_LEN
+        int paramBits = subparamLen * 8;
+        if (paramBits <= inStream.available()) {
+            decodeSuccess = true;
+            inStream.skip(paramBits);
+        }
+        Rlog.d(LOG_TAG, "RESERVED bearer data subparameter " + subparamId + " decode "
+                + (decodeSuccess ? "succeeded" : "failed") + " (param bits = " + paramBits + ")");
+        if (!decodeSuccess) {
+            throw new CodingException("RESERVED bearer data subparameter " + subparamId
+                    + " had invalid SUBPARAM_LEN " + subparamLen);
+        }
+
+        return decodeSuccess;
+    }
+
+    private static boolean decodeUserData(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException
+    {
+        int paramBits = inStream.read(8) * 8;
+        bData.userData = new UserData();
+        bData.userData.msgEncoding = inStream.read(5);
+        bData.userData.msgEncodingSet = true;
+        bData.userData.msgType = 0;
+        int consumedBits = 5;
+        if ((bData.userData.msgEncoding == UserData.ENCODING_IS91_EXTENDED_PROTOCOL) ||
+            (bData.userData.msgEncoding == UserData.ENCODING_GSM_DCS)) {
+            bData.userData.msgType = inStream.read(8);
+            consumedBits += 8;
+        }
+        bData.userData.numFields = inStream.read(8);
+        consumedBits += 8;
+        int dataBits = paramBits - consumedBits;
+        bData.userData.payload = inStream.readByteArray(dataBits);
+        return true;
+    }
+
+    private static String decodeUtf8(byte[] data, int offset, int numFields)
+        throws CodingException
+    {
+        return decodeCharset(data, offset, numFields, 1, "UTF-8");
+    }
+
+    private static String decodeUtf16(byte[] data, int offset, int numFields)
+        throws CodingException
+    {
+        // Subtract header and possible padding byte (at end) from num fields.
+        int padding = offset % 2;
+        numFields -= (offset + padding) / 2;
+        return decodeCharset(data, offset, numFields, 2, "utf-16be");
+    }
+
+    private static String decodeCharset(byte[] data, int offset, int numFields, int width,
+            String charset) throws CodingException
+    {
+        if (numFields < 0 || (numFields * width + offset) > data.length) {
+            // Try to decode the max number of characters in payload
+            int padding = offset % width;
+            int maxNumFields = (data.length - offset - padding) / width;
+            if (maxNumFields < 0) {
+                throw new CodingException(charset + " decode failed: offset out of range");
+            }
+            Rlog.e(LOG_TAG, charset + " decode error: offset = " + offset + " numFields = "
+                    + numFields + " data.length = " + data.length + " maxNumFields = "
+                    + maxNumFields);
+            numFields = maxNumFields;
+        }
+        try {
+            return new String(data, offset, numFields * width, charset);
+        } catch (java.io.UnsupportedEncodingException ex) {
+            throw new CodingException(charset + " decode failed: " + ex);
+        }
+    }
+
+    private static String decode7bitAscii(byte[] data, int offset, int numFields)
+        throws CodingException
+    {
+        try {
+            offset *= 8;
+            StringBuffer strBuf = new StringBuffer(numFields);
+            BitwiseInputStream inStream = new BitwiseInputStream(data);
+            int wantedBits = (offset * 8) + (numFields * 7);
+            if (inStream.available() < wantedBits) {
+                throw new CodingException("insufficient data (wanted " + wantedBits +
+                                          " bits, but only have " + inStream.available() + ")");
+            }
+            inStream.skip(offset);
+            for (int i = 0; i < numFields; i++) {
+                int charCode = inStream.read(7);
+                if ((charCode >= UserData.ASCII_MAP_BASE_INDEX) &&
+                        (charCode <= UserData.ASCII_MAP_MAX_INDEX)) {
+                    strBuf.append(UserData.ASCII_MAP[charCode - UserData.ASCII_MAP_BASE_INDEX]);
+                } else if (charCode == UserData.ASCII_NL_INDEX) {
+                    strBuf.append('\n');
+                } else if (charCode == UserData.ASCII_CR_INDEX) {
+                    strBuf.append('\r');
+                } else {
+                    /* For other charCodes, they are unprintable, and so simply use SPACE. */
+                    strBuf.append(' ');
+                }
+            }
+            return strBuf.toString();
+        } catch (BitwiseInputStream.AccessException ex) {
+            throw new CodingException("7bit ASCII decode failed: " + ex);
+        }
+    }
+
+    private static String decode7bitGsm(byte[] data, int offset, int numFields)
+        throws CodingException
+    {
+        // Start reading from the next 7-bit aligned boundary after offset.
+        int offsetBits = offset * 8;
+        int offsetSeptets = (offsetBits + 6) / 7;
+        numFields -= offsetSeptets;
+        int paddingBits = (offsetSeptets * 7) - offsetBits;
+        String result = GsmAlphabet.gsm7BitPackedToString(data, offset, numFields, paddingBits,
+                0, 0);
+        if (result == null) {
+            throw new CodingException("7bit GSM decoding failed");
+        }
+        return result;
+    }
+
+    private static String decodeLatin(byte[] data, int offset, int numFields)
+        throws CodingException
+    {
+        return decodeCharset(data, offset, numFields, 1, "ISO-8859-1");
+    }
+
+    private static String decodeShiftJis(byte[] data, int offset, int numFields)
+        throws CodingException
+    {
+        return decodeCharset(data, offset, numFields, 1, "Shift_JIS");
+    }
+
+    private static String decodeGsmDcs(byte[] data, int offset, int numFields, int msgType)
+            throws CodingException
+    {
+        if ((msgType & 0xC0) != 0) {
+            throw new CodingException("unsupported coding group ("
+                    + msgType + ")");
+        }
+
+        switch ((msgType >> 2) & 0x3) {
+        case UserData.ENCODING_GSM_DCS_7BIT:
+            return decode7bitGsm(data, offset, numFields);
+        case UserData.ENCODING_GSM_DCS_8BIT:
+            return decodeUtf8(data, offset, numFields);
+        case UserData.ENCODING_GSM_DCS_16BIT:
+            return decodeUtf16(data, offset, numFields);
+        default:
+            throw new CodingException("unsupported user msgType encoding ("
+                    + msgType + ")");
+        }
+    }
+
+    private static void decodeUserDataPayload(UserData userData, boolean hasUserDataHeader)
+        throws CodingException
+    {
+        int offset = 0;
+        if (hasUserDataHeader) {
+            int udhLen = userData.payload[0] & 0x00FF;
+            offset += udhLen + 1;
+            byte[] headerData = new byte[udhLen];
+            System.arraycopy(userData.payload, 1, headerData, 0, udhLen);
+            userData.userDataHeader = SmsHeader.fromByteArray(headerData);
+        }
+        switch (userData.msgEncoding) {
+        case UserData.ENCODING_OCTET:
+            /*
+            *  Octet decoding depends on the carrier service.
+            */
+            boolean decodingtypeUTF8 = Resources.getSystem()
+                    .getBoolean(com.android.internal.R.bool.config_sms_utf8_support);
+
+            // Strip off any padding bytes, meaning any differences between the length of the
+            // array and the target length specified by numFields.  This is to avoid any
+            // confusion by code elsewhere that only considers the payload array length.
+            byte[] payload = new byte[userData.numFields];
+            int copyLen = userData.numFields < userData.payload.length
+                    ? userData.numFields : userData.payload.length;
+
+            System.arraycopy(userData.payload, 0, payload, 0, copyLen);
+            userData.payload = payload;
+
+            if (!decodingtypeUTF8) {
+                // There are many devices in the market that send 8bit text sms (latin encoded) as
+                // octet encoded.
+                userData.payloadStr = decodeLatin(userData.payload, offset, userData.numFields);
+            } else {
+                userData.payloadStr = decodeUtf8(userData.payload, offset, userData.numFields);
+            }
+            break;
+
+        case UserData.ENCODING_IA5:
+        case UserData.ENCODING_7BIT_ASCII:
+            userData.payloadStr = decode7bitAscii(userData.payload, offset, userData.numFields);
+            break;
+        case UserData.ENCODING_UNICODE_16:
+            userData.payloadStr = decodeUtf16(userData.payload, offset, userData.numFields);
+            break;
+        case UserData.ENCODING_GSM_7BIT_ALPHABET:
+            userData.payloadStr = decode7bitGsm(userData.payload, offset, userData.numFields);
+            break;
+        case UserData.ENCODING_LATIN:
+            userData.payloadStr = decodeLatin(userData.payload, offset, userData.numFields);
+            break;
+        case UserData.ENCODING_SHIFT_JIS:
+            userData.payloadStr = decodeShiftJis(userData.payload, offset, userData.numFields);
+            break;
+        case UserData.ENCODING_GSM_DCS:
+            userData.payloadStr = decodeGsmDcs(userData.payload, offset,
+                    userData.numFields, userData.msgType);
+            break;
+        default:
+            throw new CodingException("unsupported user data encoding ("
+                                      + userData.msgEncoding + ")");
+        }
+    }
+
+    /**
+     * IS-91 Voice Mail message decoding
+     * (See 3GPP2 C.S0015-A, Table 4.3.1.4.1-1)
+     * (For character encodings, see TIA/EIA/IS-91, Annex B)
+     *
+     * Protocol Summary: The user data payload may contain 3-14
+     * characters.  The first two characters are parsed as a number
+     * and indicate the number of voicemails.  The third character is
+     * either a SPACE or '!' to indicate normal or urgent priority,
+     * respectively.  Any following characters are treated as normal
+     * text user data payload.
+     *
+     * Note that the characters encoding is 6-bit packed.
+     */
+    private static void decodeIs91VoicemailStatus(BearerData bData)
+        throws BitwiseInputStream.AccessException, CodingException
+    {
+        BitwiseInputStream inStream = new BitwiseInputStream(bData.userData.payload);
+        int dataLen = inStream.available() / 6;  // 6-bit packed character encoding.
+        int numFields = bData.userData.numFields;
+        if ((dataLen > 14) || (dataLen < 3) || (dataLen < numFields)) {
+            throw new CodingException("IS-91 voicemail status decoding failed");
+        }
+        try {
+            StringBuffer strbuf = new StringBuffer(dataLen);
+            while (inStream.available() >= 6) {
+                strbuf.append(UserData.ASCII_MAP[inStream.read(6)]);
+            }
+            String data = strbuf.toString();
+            bData.numberOfMessages = Integer.parseInt(data.substring(0, 2));
+            char prioCode = data.charAt(2);
+            if (prioCode == ' ') {
+                bData.priority = PRIORITY_NORMAL;
+            } else if (prioCode == '!') {
+                bData.priority = PRIORITY_URGENT;
+            } else {
+                throw new CodingException("IS-91 voicemail status decoding failed: " +
+                        "illegal priority setting (" + prioCode + ")");
+            }
+            bData.priorityIndicatorSet = true;
+            bData.userData.payloadStr = data.substring(3, numFields - 3);
+       } catch (java.lang.NumberFormatException ex) {
+            throw new CodingException("IS-91 voicemail status decoding failed: " + ex);
+        } catch (java.lang.IndexOutOfBoundsException ex) {
+            throw new CodingException("IS-91 voicemail status decoding failed: " + ex);
+        }
+    }
+
+    /**
+     * IS-91 Short Message decoding
+     * (See 3GPP2 C.S0015-A, Table 4.3.1.4.1-1)
+     * (For character encodings, see TIA/EIA/IS-91, Annex B)
+     *
+     * Protocol Summary: The user data payload may contain 1-14
+     * characters, which are treated as normal text user data payload.
+     * Note that the characters encoding is 6-bit packed.
+     */
+    private static void decodeIs91ShortMessage(BearerData bData)
+        throws BitwiseInputStream.AccessException, CodingException
+    {
+        BitwiseInputStream inStream = new BitwiseInputStream(bData.userData.payload);
+        int dataLen = inStream.available() / 6;  // 6-bit packed character encoding.
+        int numFields = bData.userData.numFields;
+        // dataLen may be > 14 characters due to octet padding
+        if ((numFields > 14) || (dataLen < numFields)) {
+            throw new CodingException("IS-91 short message decoding failed");
+        }
+        StringBuffer strbuf = new StringBuffer(dataLen);
+        for (int i = 0; i < numFields; i++) {
+            strbuf.append(UserData.ASCII_MAP[inStream.read(6)]);
+        }
+        bData.userData.payloadStr = strbuf.toString();
+    }
+
+    /**
+     * IS-91 CLI message (callback number) decoding
+     * (See 3GPP2 C.S0015-A, Table 4.3.1.4.1-1)
+     *
+     * Protocol Summary: The data payload may contain 1-32 digits,
+     * encoded using standard 4-bit DTMF, which are treated as a
+     * callback number.
+     */
+    private static void decodeIs91Cli(BearerData bData) throws CodingException {
+        BitwiseInputStream inStream = new BitwiseInputStream(bData.userData.payload);
+        int dataLen = inStream.available() / 4;  // 4-bit packed DTMF digit encoding.
+        int numFields = bData.userData.numFields;
+        if ((dataLen > 14) || (dataLen < 3) || (dataLen < numFields)) {
+            throw new CodingException("IS-91 voicemail status decoding failed");
+        }
+        CdmaSmsAddress addr = new CdmaSmsAddress();
+        addr.digitMode = CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF;
+        addr.origBytes = bData.userData.payload;
+        addr.numberOfDigits = (byte)numFields;
+        decodeSmsAddress(addr);
+        bData.callbackNumber = addr;
+    }
+
+    private static void decodeIs91(BearerData bData)
+        throws BitwiseInputStream.AccessException, CodingException
+    {
+        switch (bData.userData.msgType) {
+        case UserData.IS91_MSG_TYPE_VOICEMAIL_STATUS:
+            decodeIs91VoicemailStatus(bData);
+            break;
+        case UserData.IS91_MSG_TYPE_CLI:
+            decodeIs91Cli(bData);
+            break;
+        case UserData.IS91_MSG_TYPE_SHORT_MESSAGE_FULL:
+        case UserData.IS91_MSG_TYPE_SHORT_MESSAGE:
+            decodeIs91ShortMessage(bData);
+            break;
+        default:
+            throw new CodingException("unsupported IS-91 message type (" +
+                    bData.userData.msgType + ")");
+        }
+    }
+
+    private static boolean decodeReplyOption(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException {
+        final int EXPECTED_PARAM_SIZE = 1 * 8;
+        boolean decodeSuccess = false;
+        int paramBits = inStream.read(8) * 8;
+        if (paramBits >= EXPECTED_PARAM_SIZE) {
+            paramBits -= EXPECTED_PARAM_SIZE;
+            decodeSuccess = true;
+            bData.userAckReq     = (inStream.read(1) == 1);
+            bData.deliveryAckReq = (inStream.read(1) == 1);
+            bData.readAckReq     = (inStream.read(1) == 1);
+            bData.reportReq      = (inStream.read(1) == 1);
+            inStream.skip(4);
+        }
+        if ((! decodeSuccess) || (paramBits > 0)) {
+            Rlog.d(LOG_TAG, "REPLY_OPTION decode " +
+                      (decodeSuccess ? "succeeded" : "failed") +
+                      " (extra bits = " + paramBits + ")");
+        }
+        inStream.skip(paramBits);
+        return decodeSuccess;
+    }
+
+    private static boolean decodeMsgCount(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException {
+        final int EXPECTED_PARAM_SIZE = 1 * 8;
+        boolean decodeSuccess = false;
+        int paramBits = inStream.read(8) * 8;
+        if (paramBits >= EXPECTED_PARAM_SIZE) {
+            paramBits -= EXPECTED_PARAM_SIZE;
+            decodeSuccess = true;
+            bData.numberOfMessages = IccUtils.cdmaBcdByteToInt((byte)inStream.read(8));
+        }
+        if ((! decodeSuccess) || (paramBits > 0)) {
+            Rlog.d(LOG_TAG, "NUMBER_OF_MESSAGES decode " +
+                      (decodeSuccess ? "succeeded" : "failed") +
+                      " (extra bits = " + paramBits + ")");
+        }
+        inStream.skip(paramBits);
+        return decodeSuccess;
+    }
+
+    private static boolean decodeDepositIndex(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException {
+        final int EXPECTED_PARAM_SIZE = 2 * 8;
+        boolean decodeSuccess = false;
+        int paramBits = inStream.read(8) * 8;
+        if (paramBits >= EXPECTED_PARAM_SIZE) {
+            paramBits -= EXPECTED_PARAM_SIZE;
+            decodeSuccess = true;
+            bData.depositIndex = (inStream.read(8) << 8) | inStream.read(8);
+        }
+        if ((! decodeSuccess) || (paramBits > 0)) {
+            Rlog.d(LOG_TAG, "MESSAGE_DEPOSIT_INDEX decode " +
+                      (decodeSuccess ? "succeeded" : "failed") +
+                      " (extra bits = " + paramBits + ")");
+        }
+        inStream.skip(paramBits);
+        return decodeSuccess;
+    }
+
+    private static String decodeDtmfSmsAddress(byte[] rawData, int numFields)
+        throws CodingException
+    {
+        /* DTMF 4-bit digit encoding, defined in at
+         * 3GPP2 C.S005-D, v2.0, table 2.7.1.3.2.4-4 */
+        StringBuffer strBuf = new StringBuffer(numFields);
+        for (int i = 0; i < numFields; i++) {
+            int val = 0x0F & (rawData[i / 2] >>> (4 - ((i % 2) * 4)));
+            if ((val >= 1) && (val <= 9)) strBuf.append(Integer.toString(val, 10));
+            else if (val == 10) strBuf.append('0');
+            else if (val == 11) strBuf.append('*');
+            else if (val == 12) strBuf.append('#');
+            else throw new CodingException("invalid SMS address DTMF code (" + val + ")");
+        }
+        return strBuf.toString();
+    }
+
+    private static void decodeSmsAddress(CdmaSmsAddress addr) throws CodingException {
+        if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
+            try {
+                /* As specified in 3GPP2 C.S0015-B, v2, 4.5.15 -- actually
+                 * just 7-bit ASCII encoding, with the MSB being zero. */
+                addr.address = new String(addr.origBytes, 0, addr.origBytes.length, "US-ASCII");
+            } catch (java.io.UnsupportedEncodingException ex) {
+                throw new CodingException("invalid SMS address ASCII code");
+            }
+        } else {
+            addr.address = decodeDtmfSmsAddress(addr.origBytes, addr.numberOfDigits);
+        }
+    }
+
+    private static boolean decodeCallbackNumber(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException, CodingException
+    {
+        final int EXPECTED_PARAM_SIZE = 1 * 8; //at least
+        int paramBits = inStream.read(8) * 8;
+        if (paramBits < EXPECTED_PARAM_SIZE) {
+            inStream.skip(paramBits);
+            return false;
+        }
+        CdmaSmsAddress addr = new CdmaSmsAddress();
+        addr.digitMode = inStream.read(1);
+        byte fieldBits = 4;
+        byte consumedBits = 1;
+        if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
+            addr.ton = inStream.read(3);
+            addr.numberPlan = inStream.read(4);
+            fieldBits = 8;
+            consumedBits += 7;
+        }
+        addr.numberOfDigits = inStream.read(8);
+        consumedBits += 8;
+        int remainingBits = paramBits - consumedBits;
+        int dataBits = addr.numberOfDigits * fieldBits;
+        int paddingBits = remainingBits - dataBits;
+        if (remainingBits < dataBits) {
+            throw new CodingException("CALLBACK_NUMBER subparam encoding size error (" +
+                                      "remainingBits + " + remainingBits + ", dataBits + " +
+                                      dataBits + ", paddingBits + " + paddingBits + ")");
+        }
+        addr.origBytes = inStream.readByteArray(dataBits);
+        inStream.skip(paddingBits);
+        decodeSmsAddress(addr);
+        bData.callbackNumber = addr;
+        return true;
+    }
+
+    private static boolean decodeMsgStatus(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException {
+        final int EXPECTED_PARAM_SIZE = 1 * 8;
+        boolean decodeSuccess = false;
+        int paramBits = inStream.read(8) * 8;
+        if (paramBits >= EXPECTED_PARAM_SIZE) {
+            paramBits -= EXPECTED_PARAM_SIZE;
+            decodeSuccess = true;
+            bData.errorClass = inStream.read(2);
+            bData.messageStatus = inStream.read(6);
+        }
+        if ((! decodeSuccess) || (paramBits > 0)) {
+            Rlog.d(LOG_TAG, "MESSAGE_STATUS decode " +
+                      (decodeSuccess ? "succeeded" : "failed") +
+                      " (extra bits = " + paramBits + ")");
+        }
+        inStream.skip(paramBits);
+        bData.messageStatusSet = decodeSuccess;
+        return decodeSuccess;
+    }
+
+    private static boolean decodeMsgCenterTimeStamp(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException {
+        final int EXPECTED_PARAM_SIZE = 6 * 8;
+        boolean decodeSuccess = false;
+        int paramBits = inStream.read(8) * 8;
+        if (paramBits >= EXPECTED_PARAM_SIZE) {
+            paramBits -= EXPECTED_PARAM_SIZE;
+            decodeSuccess = true;
+            bData.msgCenterTimeStamp = TimeStamp.fromByteArray(inStream.readByteArray(6 * 8));
+        }
+        if ((! decodeSuccess) || (paramBits > 0)) {
+            Rlog.d(LOG_TAG, "MESSAGE_CENTER_TIME_STAMP decode " +
+                      (decodeSuccess ? "succeeded" : "failed") +
+                      " (extra bits = " + paramBits + ")");
+        }
+        inStream.skip(paramBits);
+        return decodeSuccess;
+    }
+
+    private static boolean decodeValidityAbs(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException {
+        final int EXPECTED_PARAM_SIZE = 6 * 8;
+        boolean decodeSuccess = false;
+        int paramBits = inStream.read(8) * 8;
+        if (paramBits >= EXPECTED_PARAM_SIZE) {
+            paramBits -= EXPECTED_PARAM_SIZE;
+            decodeSuccess = true;
+            bData.validityPeriodAbsolute = TimeStamp.fromByteArray(inStream.readByteArray(6 * 8));
+        }
+        if ((! decodeSuccess) || (paramBits > 0)) {
+            Rlog.d(LOG_TAG, "VALIDITY_PERIOD_ABSOLUTE decode " +
+                      (decodeSuccess ? "succeeded" : "failed") +
+                      " (extra bits = " + paramBits + ")");
+        }
+        inStream.skip(paramBits);
+        return decodeSuccess;
+    }
+
+    private static boolean decodeDeferredDeliveryAbs(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException {
+        final int EXPECTED_PARAM_SIZE = 6 * 8;
+        boolean decodeSuccess = false;
+        int paramBits = inStream.read(8) * 8;
+        if (paramBits >= EXPECTED_PARAM_SIZE) {
+            paramBits -= EXPECTED_PARAM_SIZE;
+            decodeSuccess = true;
+            bData.deferredDeliveryTimeAbsolute = TimeStamp.fromByteArray(
+                    inStream.readByteArray(6 * 8));
+        }
+        if ((! decodeSuccess) || (paramBits > 0)) {
+            Rlog.d(LOG_TAG, "DEFERRED_DELIVERY_TIME_ABSOLUTE decode " +
+                      (decodeSuccess ? "succeeded" : "failed") +
+                      " (extra bits = " + paramBits + ")");
+        }
+        inStream.skip(paramBits);
+        return decodeSuccess;
+    }
+
+    private static boolean decodeValidityRel(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException {
+        final int EXPECTED_PARAM_SIZE = 1 * 8;
+        boolean decodeSuccess = false;
+        int paramBits = inStream.read(8) * 8;
+        if (paramBits >= EXPECTED_PARAM_SIZE) {
+            paramBits -= EXPECTED_PARAM_SIZE;
+            decodeSuccess = true;
+            bData.deferredDeliveryTimeRelative = inStream.read(8);
+        }
+        if ((! decodeSuccess) || (paramBits > 0)) {
+            Rlog.d(LOG_TAG, "VALIDITY_PERIOD_RELATIVE decode " +
+                      (decodeSuccess ? "succeeded" : "failed") +
+                      " (extra bits = " + paramBits + ")");
+        }
+        inStream.skip(paramBits);
+        bData.deferredDeliveryTimeRelativeSet = decodeSuccess;
+        return decodeSuccess;
+    }
+
+    private static boolean decodeDeferredDeliveryRel(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException {
+        final int EXPECTED_PARAM_SIZE = 1 * 8;
+        boolean decodeSuccess = false;
+        int paramBits = inStream.read(8) * 8;
+        if (paramBits >= EXPECTED_PARAM_SIZE) {
+            paramBits -= EXPECTED_PARAM_SIZE;
+            decodeSuccess = true;
+            bData.validityPeriodRelative = inStream.read(8);
+        }
+        if ((! decodeSuccess) || (paramBits > 0)) {
+            Rlog.d(LOG_TAG, "DEFERRED_DELIVERY_TIME_RELATIVE decode " +
+                      (decodeSuccess ? "succeeded" : "failed") +
+                      " (extra bits = " + paramBits + ")");
+        }
+        inStream.skip(paramBits);
+        bData.validityPeriodRelativeSet = decodeSuccess;
+        return decodeSuccess;
+    }
+
+    private static boolean decodePrivacyIndicator(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException {
+        final int EXPECTED_PARAM_SIZE = 1 * 8;
+        boolean decodeSuccess = false;
+        int paramBits = inStream.read(8) * 8;
+        if (paramBits >= EXPECTED_PARAM_SIZE) {
+            paramBits -= EXPECTED_PARAM_SIZE;
+            decodeSuccess = true;
+            bData.privacy = inStream.read(2);
+            inStream.skip(6);
+        }
+        if ((! decodeSuccess) || (paramBits > 0)) {
+            Rlog.d(LOG_TAG, "PRIVACY_INDICATOR decode " +
+                      (decodeSuccess ? "succeeded" : "failed") +
+                      " (extra bits = " + paramBits + ")");
+        }
+        inStream.skip(paramBits);
+        bData.privacyIndicatorSet = decodeSuccess;
+        return decodeSuccess;
+    }
+
+    private static boolean decodeLanguageIndicator(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException {
+        final int EXPECTED_PARAM_SIZE = 1 * 8;
+        boolean decodeSuccess = false;
+        int paramBits = inStream.read(8) * 8;
+        if (paramBits >= EXPECTED_PARAM_SIZE) {
+            paramBits -= EXPECTED_PARAM_SIZE;
+            decodeSuccess = true;
+            bData.language = inStream.read(8);
+        }
+        if ((! decodeSuccess) || (paramBits > 0)) {
+            Rlog.d(LOG_TAG, "LANGUAGE_INDICATOR decode " +
+                      (decodeSuccess ? "succeeded" : "failed") +
+                      " (extra bits = " + paramBits + ")");
+        }
+        inStream.skip(paramBits);
+        bData.languageIndicatorSet = decodeSuccess;
+        return decodeSuccess;
+    }
+
+    private static boolean decodeDisplayMode(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException {
+        final int EXPECTED_PARAM_SIZE = 1 * 8;
+        boolean decodeSuccess = false;
+        int paramBits = inStream.read(8) * 8;
+        if (paramBits >= EXPECTED_PARAM_SIZE) {
+            paramBits -= EXPECTED_PARAM_SIZE;
+            decodeSuccess = true;
+            bData.displayMode = inStream.read(2);
+            inStream.skip(6);
+        }
+        if ((! decodeSuccess) || (paramBits > 0)) {
+            Rlog.d(LOG_TAG, "DISPLAY_MODE decode " +
+                      (decodeSuccess ? "succeeded" : "failed") +
+                      " (extra bits = " + paramBits + ")");
+        }
+        inStream.skip(paramBits);
+        bData.displayModeSet = decodeSuccess;
+        return decodeSuccess;
+    }
+
+    private static boolean decodePriorityIndicator(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException {
+        final int EXPECTED_PARAM_SIZE = 1 * 8;
+        boolean decodeSuccess = false;
+        int paramBits = inStream.read(8) * 8;
+        if (paramBits >= EXPECTED_PARAM_SIZE) {
+            paramBits -= EXPECTED_PARAM_SIZE;
+            decodeSuccess = true;
+            bData.priority = inStream.read(2);
+            inStream.skip(6);
+        }
+        if ((! decodeSuccess) || (paramBits > 0)) {
+            Rlog.d(LOG_TAG, "PRIORITY_INDICATOR decode " +
+                      (decodeSuccess ? "succeeded" : "failed") +
+                      " (extra bits = " + paramBits + ")");
+        }
+        inStream.skip(paramBits);
+        bData.priorityIndicatorSet = decodeSuccess;
+        return decodeSuccess;
+    }
+
+    private static boolean decodeMsgDeliveryAlert(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException {
+        final int EXPECTED_PARAM_SIZE = 1 * 8;
+        boolean decodeSuccess = false;
+        int paramBits = inStream.read(8) * 8;
+        if (paramBits >= EXPECTED_PARAM_SIZE) {
+            paramBits -= EXPECTED_PARAM_SIZE;
+            decodeSuccess = true;
+            bData.alert = inStream.read(2);
+            inStream.skip(6);
+        }
+        if ((! decodeSuccess) || (paramBits > 0)) {
+            Rlog.d(LOG_TAG, "ALERT_ON_MESSAGE_DELIVERY decode " +
+                      (decodeSuccess ? "succeeded" : "failed") +
+                      " (extra bits = " + paramBits + ")");
+        }
+        inStream.skip(paramBits);
+        bData.alertIndicatorSet = decodeSuccess;
+        return decodeSuccess;
+    }
+
+    private static boolean decodeUserResponseCode(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException {
+        final int EXPECTED_PARAM_SIZE = 1 * 8;
+        boolean decodeSuccess = false;
+        int paramBits = inStream.read(8) * 8;
+        if (paramBits >= EXPECTED_PARAM_SIZE) {
+            paramBits -= EXPECTED_PARAM_SIZE;
+            decodeSuccess = true;
+            bData.userResponseCode = inStream.read(8);
+        }
+        if ((! decodeSuccess) || (paramBits > 0)) {
+            Rlog.d(LOG_TAG, "USER_RESPONSE_CODE decode " +
+                      (decodeSuccess ? "succeeded" : "failed") +
+                      " (extra bits = " + paramBits + ")");
+        }
+        inStream.skip(paramBits);
+        bData.userResponseCodeSet = decodeSuccess;
+        return decodeSuccess;
+    }
+
+    private static boolean decodeServiceCategoryProgramData(BearerData bData,
+            BitwiseInputStream inStream) throws BitwiseInputStream.AccessException, CodingException
+    {
+        if (inStream.available() < 13) {
+            throw new CodingException("SERVICE_CATEGORY_PROGRAM_DATA decode failed: only "
+                    + inStream.available() + " bits available");
+        }
+
+        int paramBits = inStream.read(8) * 8;
+        int msgEncoding = inStream.read(5);
+        paramBits -= 5;
+
+        if (inStream.available() < paramBits) {
+            throw new CodingException("SERVICE_CATEGORY_PROGRAM_DATA decode failed: only "
+                    + inStream.available() + " bits available (" + paramBits + " bits expected)");
+        }
+
+        ArrayList<CdmaSmsCbProgramData> programDataList = new ArrayList<CdmaSmsCbProgramData>();
+
+        final int CATEGORY_FIELD_MIN_SIZE = 6 * 8;
+        boolean decodeSuccess = false;
+        while (paramBits >= CATEGORY_FIELD_MIN_SIZE) {
+            int operation = inStream.read(4);
+            int category = (inStream.read(8) << 8) | inStream.read(8);
+            int language = inStream.read(8);
+            int maxMessages = inStream.read(8);
+            int alertOption = inStream.read(4);
+            int numFields = inStream.read(8);
+            paramBits -= CATEGORY_FIELD_MIN_SIZE;
+
+            int textBits = getBitsForNumFields(msgEncoding, numFields);
+            if (paramBits < textBits) {
+                throw new CodingException("category name is " + textBits + " bits in length,"
+                        + " but there are only " + paramBits + " bits available");
+            }
+
+            UserData userData = new UserData();
+            userData.msgEncoding = msgEncoding;
+            userData.msgEncodingSet = true;
+            userData.numFields = numFields;
+            userData.payload = inStream.readByteArray(textBits);
+            paramBits -= textBits;
+
+            decodeUserDataPayload(userData, false);
+            String categoryName = userData.payloadStr;
+            CdmaSmsCbProgramData programData = new CdmaSmsCbProgramData(operation, category,
+                    language, maxMessages, alertOption, categoryName);
+            programDataList.add(programData);
+
+            decodeSuccess = true;
+        }
+
+        if ((! decodeSuccess) || (paramBits > 0)) {
+            Rlog.d(LOG_TAG, "SERVICE_CATEGORY_PROGRAM_DATA decode " +
+                      (decodeSuccess ? "succeeded" : "failed") +
+                      " (extra bits = " + paramBits + ')');
+        }
+
+        inStream.skip(paramBits);
+        bData.serviceCategoryProgramData = programDataList;
+        return decodeSuccess;
+    }
+
+    private static int serviceCategoryToCmasMessageClass(int serviceCategory) {
+        switch (serviceCategory) {
+            case SmsEnvelope.SERVICE_CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT:
+                return SmsCbCmasInfo.CMAS_CLASS_PRESIDENTIAL_LEVEL_ALERT;
+
+            case SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT:
+                return SmsCbCmasInfo.CMAS_CLASS_EXTREME_THREAT;
+
+            case SmsEnvelope.SERVICE_CATEGORY_CMAS_SEVERE_THREAT:
+                return SmsCbCmasInfo.CMAS_CLASS_SEVERE_THREAT;
+
+            case SmsEnvelope.SERVICE_CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY:
+                return SmsCbCmasInfo.CMAS_CLASS_CHILD_ABDUCTION_EMERGENCY;
+
+            case SmsEnvelope.SERVICE_CATEGORY_CMAS_TEST_MESSAGE:
+                return SmsCbCmasInfo.CMAS_CLASS_REQUIRED_MONTHLY_TEST;
+
+            default:
+                return SmsCbCmasInfo.CMAS_CLASS_UNKNOWN;
+        }
+    }
+
+    /**
+     * Calculates the number of bits to read for the specified number of encoded characters.
+     * @param msgEncoding the message encoding to use
+     * @param numFields the number of characters to read. For Shift-JIS and Korean encodings,
+     *  this is the number of bytes to read.
+     * @return the number of bits to read from the stream
+     * @throws CodingException if the specified encoding is not supported
+     */
+    private static int getBitsForNumFields(int msgEncoding, int numFields)
+            throws CodingException {
+        switch (msgEncoding) {
+            case UserData.ENCODING_OCTET:
+            case UserData.ENCODING_SHIFT_JIS:
+            case UserData.ENCODING_KOREAN:
+            case UserData.ENCODING_LATIN:
+            case UserData.ENCODING_LATIN_HEBREW:
+                return numFields * 8;
+
+            case UserData.ENCODING_IA5:
+            case UserData.ENCODING_7BIT_ASCII:
+            case UserData.ENCODING_GSM_7BIT_ALPHABET:
+                return numFields * 7;
+
+            case UserData.ENCODING_UNICODE_16:
+                return numFields * 16;
+
+            default:
+                throw new CodingException("unsupported message encoding (" + msgEncoding + ')');
+        }
+    }
+
+    /**
+     * CMAS message decoding.
+     * (See TIA-1149-0-1, CMAS over CDMA)
+     *
+     * @param serviceCategory is the service category from the SMS envelope
+     */
+    private static void decodeCmasUserData(BearerData bData, int serviceCategory)
+            throws BitwiseInputStream.AccessException, CodingException {
+        BitwiseInputStream inStream = new BitwiseInputStream(bData.userData.payload);
+        if (inStream.available() < 8) {
+            throw new CodingException("emergency CB with no CMAE_protocol_version");
+        }
+        int protocolVersion = inStream.read(8);
+        if (protocolVersion != 0) {
+            throw new CodingException("unsupported CMAE_protocol_version " + protocolVersion);
+        }
+
+        int messageClass = serviceCategoryToCmasMessageClass(serviceCategory);
+        int category = SmsCbCmasInfo.CMAS_CATEGORY_UNKNOWN;
+        int responseType = SmsCbCmasInfo.CMAS_RESPONSE_TYPE_UNKNOWN;
+        int severity = SmsCbCmasInfo.CMAS_SEVERITY_UNKNOWN;
+        int urgency = SmsCbCmasInfo.CMAS_URGENCY_UNKNOWN;
+        int certainty = SmsCbCmasInfo.CMAS_CERTAINTY_UNKNOWN;
+
+        while (inStream.available() >= 16) {
+            int recordType = inStream.read(8);
+            int recordLen = inStream.read(8);
+            switch (recordType) {
+                case 0:     // Type 0 elements (Alert text)
+                    UserData alertUserData = new UserData();
+                    alertUserData.msgEncoding = inStream.read(5);
+                    alertUserData.msgEncodingSet = true;
+                    alertUserData.msgType = 0;
+
+                    int numFields;                          // number of chars to decode
+                    switch (alertUserData.msgEncoding) {
+                        case UserData.ENCODING_OCTET:
+                        case UserData.ENCODING_LATIN:
+                            numFields = recordLen - 1;      // subtract 1 byte for encoding
+                            break;
+
+                        case UserData.ENCODING_IA5:
+                        case UserData.ENCODING_7BIT_ASCII:
+                        case UserData.ENCODING_GSM_7BIT_ALPHABET:
+                            numFields = ((recordLen * 8) - 5) / 7;  // subtract 5 bits for encoding
+                            break;
+
+                        case UserData.ENCODING_UNICODE_16:
+                            numFields = (recordLen - 1) / 2;
+                            break;
+
+                        default:
+                            numFields = 0;      // unsupported encoding
+                    }
+
+                    alertUserData.numFields = numFields;
+                    alertUserData.payload = inStream.readByteArray(recordLen * 8 - 5);
+                    decodeUserDataPayload(alertUserData, false);
+                    bData.userData = alertUserData;
+                    break;
+
+                case 1:     // Type 1 elements
+                    category = inStream.read(8);
+                    responseType = inStream.read(8);
+                    severity = inStream.read(4);
+                    urgency = inStream.read(4);
+                    certainty = inStream.read(4);
+                    inStream.skip(recordLen * 8 - 28);
+                    break;
+
+                default:
+                    Rlog.w(LOG_TAG, "skipping unsupported CMAS record type " + recordType);
+                    inStream.skip(recordLen * 8);
+                    break;
+            }
+        }
+
+        bData.cmasWarningInfo = new SmsCbCmasInfo(messageClass, category, responseType, severity,
+                urgency, certainty);
+    }
+
+    /**
+     * Create BearerData object from serialized representation.
+     * (See 3GPP2 C.R1001-F, v1.0, section 4.5 for layout details)
+     *
+     * @param smsData byte array of raw encoded SMS bearer data.
+     * @return an instance of BearerData.
+     */
+    public static BearerData decode(byte[] smsData) {
+        return decode(smsData, 0);
+    }
+
+    private static boolean isCmasAlertCategory(int category) {
+        return category >= SmsEnvelope.SERVICE_CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT
+                && category <= SmsEnvelope.SERVICE_CATEGORY_CMAS_LAST_RESERVED_VALUE;
+    }
+
+    /**
+     * Create BearerData object from serialized representation.
+     * (See 3GPP2 C.R1001-F, v1.0, section 4.5 for layout details)
+     *
+     * @param smsData byte array of raw encoded SMS bearer data.
+     * @param serviceCategory the envelope service category (for CMAS alert handling)
+     * @return an instance of BearerData.
+     */
+    public static BearerData decode(byte[] smsData, int serviceCategory) {
+        try {
+            BitwiseInputStream inStream = new BitwiseInputStream(smsData);
+            BearerData bData = new BearerData();
+            int foundSubparamMask = 0;
+            while (inStream.available() > 0) {
+                int subparamId = inStream.read(8);
+                int subparamIdBit = 1 << subparamId;
+                // int is 4 bytes. This duplicate check has a limit to Id number up to 32 (4*8)
+                // as 32th bit is the max bit in int.
+                // Per 3GPP2 C.S0015-B Table 4.5-1 Bearer Data Subparameter Identifiers:
+                // last defined subparam ID is 23 (00010111 = 0x17 = 23).
+                // Only do duplicate subparam ID check if subparam is within defined value as
+                // reserved subparams are just skipped.
+                if ((foundSubparamMask & subparamIdBit) != 0 &&
+                        (subparamId >= SUBPARAM_MESSAGE_IDENTIFIER &&
+                        subparamId <= SUBPARAM_ID_LAST_DEFINED)) {
+                    throw new CodingException("illegal duplicate subparameter (" +
+                                              subparamId + ")");
+                }
+                boolean decodeSuccess;
+                switch (subparamId) {
+                case SUBPARAM_MESSAGE_IDENTIFIER:
+                    decodeSuccess = decodeMessageId(bData, inStream);
+                    break;
+                case SUBPARAM_USER_DATA:
+                    decodeSuccess = decodeUserData(bData, inStream);
+                    break;
+                case SUBPARAM_USER_RESPONSE_CODE:
+                    decodeSuccess = decodeUserResponseCode(bData, inStream);
+                    break;
+                case SUBPARAM_REPLY_OPTION:
+                    decodeSuccess = decodeReplyOption(bData, inStream);
+                    break;
+                case SUBPARAM_NUMBER_OF_MESSAGES:
+                    decodeSuccess = decodeMsgCount(bData, inStream);
+                    break;
+                case SUBPARAM_CALLBACK_NUMBER:
+                    decodeSuccess = decodeCallbackNumber(bData, inStream);
+                    break;
+                case SUBPARAM_MESSAGE_STATUS:
+                    decodeSuccess = decodeMsgStatus(bData, inStream);
+                    break;
+                case SUBPARAM_MESSAGE_CENTER_TIME_STAMP:
+                    decodeSuccess = decodeMsgCenterTimeStamp(bData, inStream);
+                    break;
+                case SUBPARAM_VALIDITY_PERIOD_ABSOLUTE:
+                    decodeSuccess = decodeValidityAbs(bData, inStream);
+                    break;
+                case SUBPARAM_VALIDITY_PERIOD_RELATIVE:
+                    decodeSuccess = decodeValidityRel(bData, inStream);
+                    break;
+                case SUBPARAM_DEFERRED_DELIVERY_TIME_ABSOLUTE:
+                    decodeSuccess = decodeDeferredDeliveryAbs(bData, inStream);
+                    break;
+                case SUBPARAM_DEFERRED_DELIVERY_TIME_RELATIVE:
+                    decodeSuccess = decodeDeferredDeliveryRel(bData, inStream);
+                    break;
+                case SUBPARAM_PRIVACY_INDICATOR:
+                    decodeSuccess = decodePrivacyIndicator(bData, inStream);
+                    break;
+                case SUBPARAM_LANGUAGE_INDICATOR:
+                    decodeSuccess = decodeLanguageIndicator(bData, inStream);
+                    break;
+                case SUBPARAM_MESSAGE_DISPLAY_MODE:
+                    decodeSuccess = decodeDisplayMode(bData, inStream);
+                    break;
+                case SUBPARAM_PRIORITY_INDICATOR:
+                    decodeSuccess = decodePriorityIndicator(bData, inStream);
+                    break;
+                case SUBPARAM_ALERT_ON_MESSAGE_DELIVERY:
+                    decodeSuccess = decodeMsgDeliveryAlert(bData, inStream);
+                    break;
+                case SUBPARAM_MESSAGE_DEPOSIT_INDEX:
+                    decodeSuccess = decodeDepositIndex(bData, inStream);
+                    break;
+                case SUBPARAM_SERVICE_CATEGORY_PROGRAM_DATA:
+                    decodeSuccess = decodeServiceCategoryProgramData(bData, inStream);
+                    break;
+                default:
+                    decodeSuccess = decodeReserved(bData, inStream, subparamId);
+                }
+                if (decodeSuccess &&
+                        (subparamId >= SUBPARAM_MESSAGE_IDENTIFIER &&
+                        subparamId <= SUBPARAM_ID_LAST_DEFINED)) {
+                    foundSubparamMask |= subparamIdBit;
+                }
+            }
+            if ((foundSubparamMask & (1 << SUBPARAM_MESSAGE_IDENTIFIER)) == 0) {
+                throw new CodingException("missing MESSAGE_IDENTIFIER subparam");
+            }
+            if (bData.userData != null) {
+                if (isCmasAlertCategory(serviceCategory)) {
+                    decodeCmasUserData(bData, serviceCategory);
+                } else if (bData.userData.msgEncoding == UserData.ENCODING_IS91_EXTENDED_PROTOCOL) {
+                    if ((foundSubparamMask ^
+                             (1 << SUBPARAM_MESSAGE_IDENTIFIER) ^
+                             (1 << SUBPARAM_USER_DATA))
+                            != 0) {
+                        Rlog.e(LOG_TAG, "IS-91 must occur without extra subparams (" +
+                              foundSubparamMask + ")");
+                    }
+                    decodeIs91(bData);
+                } else {
+                    decodeUserDataPayload(bData.userData, bData.hasUserDataHeader);
+                }
+            }
+            return bData;
+        } catch (BitwiseInputStream.AccessException ex) {
+            Rlog.e(LOG_TAG, "BearerData decode failed: " + ex);
+        } catch (CodingException ex) {
+            Rlog.e(LOG_TAG, "BearerData decode failed: " + ex);
+        }
+        return null;
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaSmsAddress.java b/telephony/java/com/android/internal/telephony/cdma/CdmaSmsAddress.java
new file mode 100644
index 0000000..5f2e561
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaSmsAddress.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.cdma.sms;
+
+import android.util.SparseBooleanArray;
+
+import com.android.internal.telephony.SmsAddress;
+import com.android.internal.telephony.cdma.sms.UserData;
+import com.android.internal.util.HexDump;
+
+public class CdmaSmsAddress extends SmsAddress {
+
+    /**
+     * Digit Mode Indicator is a 1-bit value that indicates whether
+     * the address digits are 4-bit DTMF codes or 8-bit codes.  (See
+     * 3GPP2 C.S0015-B, v2, 3.4.3.3)
+     */
+    static public final int DIGIT_MODE_4BIT_DTMF              = 0x00;
+    static public final int DIGIT_MODE_8BIT_CHAR              = 0x01;
+
+    public int digitMode;
+
+    /**
+     * Number Mode Indicator is 1-bit value that indicates whether the
+     * address type is a data network address or not.  (See 3GPP2
+     * C.S0015-B, v2, 3.4.3.3)
+     */
+    static public final int NUMBER_MODE_NOT_DATA_NETWORK      = 0x00;
+    static public final int NUMBER_MODE_DATA_NETWORK          = 0x01;
+
+    public int numberMode;
+
+    /**
+     * Number Types for data networks.
+     * (See 3GPP2 C.S005-D, table2.7.1.3.2.4-2 for complete table)
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.3 for data network subset)
+     * NOTE: value is stored in the parent class ton field.
+     */
+    static public final int TON_UNKNOWN                   = 0x00;
+    static public final int TON_INTERNATIONAL_OR_IP       = 0x01;
+    static public final int TON_NATIONAL_OR_EMAIL         = 0x02;
+    static public final int TON_NETWORK                   = 0x03;
+    static public final int TON_SUBSCRIBER                = 0x04;
+    static public final int TON_ALPHANUMERIC              = 0x05;
+    static public final int TON_ABBREVIATED               = 0x06;
+    static public final int TON_RESERVED                  = 0x07;
+
+    /**
+     * Maximum lengths for fields as defined in ril_cdma_sms.h.
+     */
+    static public final int SMS_ADDRESS_MAX          =  36;
+    static public final int SMS_SUBADDRESS_MAX       =  36;
+
+    /**
+     * This field shall be set to the number of address digits
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.3)
+     */
+    public int numberOfDigits;
+
+    /**
+     * Numbering Plan identification is a 0 or 4-bit value that
+     * indicates which numbering plan identification is set.  (See
+     * 3GPP2, C.S0015-B, v2, 3.4.3.3 and C.S005-D, table2.7.1.3.2.4-3)
+     */
+    static public final int NUMBERING_PLAN_UNKNOWN           = 0x0;
+    static public final int NUMBERING_PLAN_ISDN_TELEPHONY    = 0x1;
+    //static protected final int NUMBERING_PLAN_DATA              = 0x3;
+    //static protected final int NUMBERING_PLAN_TELEX             = 0x4;
+    //static protected final int NUMBERING_PLAN_PRIVATE           = 0x9;
+
+    public int numberPlan;
+
+    /**
+     * NOTE: the parsed string address and the raw byte array values
+     * are stored in the parent class address and origBytes fields,
+     * respectively.
+     */
+
+    public CdmaSmsAddress(){
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("CdmaSmsAddress ");
+        builder.append("{ digitMode=" + digitMode);
+        builder.append(", numberMode=" + numberMode);
+        builder.append(", numberPlan=" + numberPlan);
+        builder.append(", numberOfDigits=" + numberOfDigits);
+        builder.append(", ton=" + ton);
+        builder.append(", address=\"" + address + "\"");
+        builder.append(", origBytes=" + HexDump.toHexString(origBytes));
+        builder.append(" }");
+        return builder.toString();
+    }
+
+    /*
+     * TODO(cleanup): Refactor the parsing for addresses to better
+     * share code and logic with GSM.  Also, gather all DTMF/BCD
+     * processing code in one place.
+     */
+
+    private static byte[] parseToDtmf(String address) {
+        int digits = address.length();
+        byte[] result = new byte[digits];
+        for (int i = 0; i < digits; i++) {
+            char c = address.charAt(i);
+            int val = 0;
+            if ((c >= '1') && (c <= '9')) val = c - '0';
+            else if (c == '0') val = 10;
+            else if (c == '*') val = 11;
+            else if (c == '#') val = 12;
+            else return null;
+            result[i] = (byte)val;
+        }
+        return result;
+    }
+
+    private static final char[] numericCharsDialable = {
+        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '*', '#'
+    };
+
+    private static final char[] numericCharsSugar = {
+        '(', ')', ' ', '-', '+', '.', '/', '\\'
+    };
+
+    private static final SparseBooleanArray numericCharDialableMap = new SparseBooleanArray (
+            numericCharsDialable.length + numericCharsSugar.length);
+    static {
+        for (int i = 0; i < numericCharsDialable.length; i++) {
+            numericCharDialableMap.put(numericCharsDialable[i], true);
+        }
+        for (int i = 0; i < numericCharsSugar.length; i++) {
+            numericCharDialableMap.put(numericCharsSugar[i], false);
+        }
+    }
+
+    /**
+     * Given a numeric address string, return the string without
+     * syntactic sugar, meaning parens, spaces, hyphens/minuses, or
+     * plus signs.  If the input string contains non-numeric
+     * non-punctuation characters, return null.
+     */
+    private static String filterNumericSugar(String address) {
+        StringBuilder builder = new StringBuilder();
+        int len = address.length();
+        for (int i = 0; i < len; i++) {
+            char c = address.charAt(i);
+            int mapIndex = numericCharDialableMap.indexOfKey(c);
+            if (mapIndex < 0) return null;
+            if (! numericCharDialableMap.valueAt(mapIndex)) continue;
+            builder.append(c);
+        }
+        return builder.toString();
+    }
+
+    /**
+     * Given a string, return the string without whitespace,
+     * including CR/LF.
+     */
+    private static String filterWhitespace(String address) {
+        StringBuilder builder = new StringBuilder();
+        int len = address.length();
+        for (int i = 0; i < len; i++) {
+            char c = address.charAt(i);
+            if ((c == ' ') || (c == '\r') || (c == '\n') || (c == '\t')) continue;
+            builder.append(c);
+        }
+        return builder.toString();
+    }
+
+    /**
+     * Given a string, create a corresponding CdmaSmsAddress object.
+     *
+     * The result will be null if the input string is not
+     * representable using printable ASCII.
+     *
+     * For numeric addresses, the string is cleaned up by removing
+     * common punctuation.  For alpha addresses, the string is cleaned
+     * up by removing whitespace.
+     */
+    public static CdmaSmsAddress parse(String address) {
+        CdmaSmsAddress addr = new CdmaSmsAddress();
+        addr.address = address;
+        addr.ton = CdmaSmsAddress.TON_UNKNOWN;
+        byte[] origBytes = null;
+        String filteredAddr = filterNumericSugar(address);
+        if (filteredAddr != null) {
+            origBytes = parseToDtmf(filteredAddr);
+        }
+        if (origBytes != null) {
+            addr.digitMode = DIGIT_MODE_4BIT_DTMF;
+            addr.numberMode = NUMBER_MODE_NOT_DATA_NETWORK;
+            if (address.indexOf('+') != -1) {
+                addr.ton = TON_INTERNATIONAL_OR_IP;
+            }
+        } else {
+            filteredAddr = filterWhitespace(address);
+            origBytes = UserData.stringToAscii(filteredAddr);
+            if (origBytes == null) {
+                return null;
+            }
+            addr.digitMode = DIGIT_MODE_8BIT_CHAR;
+            addr.numberMode = NUMBER_MODE_DATA_NETWORK;
+            if (address.indexOf('@') != -1) {
+                addr.ton = TON_NATIONAL_OR_EMAIL;
+            }
+        }
+        addr.origBytes = origBytes;
+        addr.numberOfDigits = origBytes.length;
+        return addr;
+    }
+
+}
diff --git a/core/java/com/android/internal/logging/legacy/Util.java b/telephony/java/com/android/internal/telephony/cdma/CdmaSmsSubaddress.java
similarity index 70%
copy from core/java/com/android/internal/logging/legacy/Util.java
copy to telephony/java/com/android/internal/telephony/cdma/CdmaSmsSubaddress.java
index 99f71ca..0d5b502 100644
--- a/core/java/com/android/internal/logging/legacy/Util.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaSmsSubaddress.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2010 The Android Open Source Project. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,13 +13,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.internal.logging.legacy;
 
-/**
- * Created by cwren on 11/21/16.
- */
-public class Util {
-    public static boolean debug() {
-        return false;
-    }
+package com.android.internal.telephony.cdma.sms;
+
+public class CdmaSmsSubaddress {
+    public int type;
+
+    public byte odd;
+
+    public byte[] origBytes;
 }
+
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsEnvelope.java b/telephony/java/com/android/internal/telephony/cdma/SmsEnvelope.java
new file mode 100644
index 0000000..f73df56
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsEnvelope.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.cdma.sms;
+
+
+import com.android.internal.telephony.cdma.sms.CdmaSmsSubaddress;
+
+public final class SmsEnvelope {
+    /**
+     * Message Types
+     * (See 3GPP2 C.S0015-B 3.4.1)
+     */
+    static public final int MESSAGE_TYPE_POINT_TO_POINT   = 0x00;
+    static public final int MESSAGE_TYPE_BROADCAST        = 0x01;
+    static public final int MESSAGE_TYPE_ACKNOWLEDGE      = 0x02;
+
+    /**
+     * Supported Teleservices
+     * (See 3GPP2 N.S0005 and TIA-41)
+     */
+    static public final int TELESERVICE_NOT_SET           = 0x0000;
+    static public final int TELESERVICE_WMT               = 0x1002;
+    static public final int TELESERVICE_VMN               = 0x1003;
+    static public final int TELESERVICE_WAP               = 0x1004;
+    static public final int TELESERVICE_WEMT              = 0x1005;
+    static public final int TELESERVICE_SCPT              = 0x1006;
+
+    /**
+     * The following are defined as extensions to the standard teleservices
+     */
+    // Voice mail notification through Message Waiting Indication in CDMA mode or Analog mode.
+    // Defined in 3GPP2 C.S-0005, 3.7.5.6, an Info Record containing an 8-bit number with the
+    // number of messages waiting, it's used by some CDMA carriers for a voice mail count.
+    static public final int TELESERVICE_MWI               = 0x40000;
+
+    // Service Categories for Cell Broadcast, see 3GPP2 C.R1001 table 9.3.1-1
+    // static final int SERVICE_CATEGORY_EMERGENCY      = 0x0001;
+    //...
+
+    // CMAS alert service category assignments, see 3GPP2 C.R1001 table 9.3.3-1
+    public static final int SERVICE_CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT  = 0x1000;
+    public static final int SERVICE_CATEGORY_CMAS_EXTREME_THREAT            = 0x1001;
+    public static final int SERVICE_CATEGORY_CMAS_SEVERE_THREAT             = 0x1002;
+    public static final int SERVICE_CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY = 0x1003;
+    public static final int SERVICE_CATEGORY_CMAS_TEST_MESSAGE              = 0x1004;
+    public static final int SERVICE_CATEGORY_CMAS_LAST_RESERVED_VALUE       = 0x10ff;
+
+    /**
+     * Provides the type of a SMS message like point to point, broadcast or acknowledge
+     */
+    public int messageType;
+
+    /**
+     * The 16-bit Teleservice parameter identifies which upper layer service access point is sending
+     * or receiving the message.
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.1)
+     */
+    public int teleService = TELESERVICE_NOT_SET;
+
+    /**
+     * The 16-bit service category parameter identifies the type of service provided
+     * by the SMS message.
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.2)
+     */
+    public int serviceCategory;
+
+    /**
+     * The origination address identifies the originator of the SMS message.
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.3)
+     */
+    public CdmaSmsAddress origAddress;
+
+    /**
+     * The destination address identifies the target of the SMS message.
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.3)
+     */
+    public CdmaSmsAddress destAddress;
+
+    /**
+     * The origination subaddress identifies the originator of the SMS message.
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.4)
+     */
+    public CdmaSmsSubaddress origSubaddress;
+
+    /**
+     * The 6-bit bearer reply parameter is used to request the return of a
+     * SMS Acknowledge Message.
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.5)
+     */
+    public int bearerReply;
+
+    /**
+     * Cause Code values:
+     * The cause code parameters are an indication whether an SMS error has occurred and if so,
+     * whether the condition is considered temporary or permanent.
+     * ReplySeqNo 6-bit value,
+     * ErrorClass 2-bit value,
+     * CauseCode 0-bit or 8-bit value
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.6)
+     */
+    public byte replySeqNo;
+    public byte errorClass;
+    public byte causeCode;
+
+    /**
+     * encoded bearer data
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.7)
+     */
+    public byte[] bearerData;
+
+    public SmsEnvelope() {
+        // nothing to see here
+    }
+
+}
+
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
new file mode 100644
index 0000000..629173d
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -0,0 +1,968 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.cdma;
+
+import android.os.Parcel;
+import android.os.SystemProperties;
+import android.telephony.PhoneNumberUtils;
+import android.telephony.SmsCbLocation;
+import android.telephony.SmsCbMessage;
+import android.telephony.TelephonyManager;
+import android.telephony.cdma.CdmaSmsCbProgramData;
+import android.telephony.Rlog;
+import android.util.Log;
+import android.text.TextUtils;
+import android.content.res.Resources;
+
+import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
+import com.android.internal.telephony.SmsAddress;
+import com.android.internal.telephony.SmsConstants;
+import com.android.internal.telephony.SmsHeader;
+import com.android.internal.telephony.SmsMessageBase;
+import com.android.internal.telephony.TelephonyProperties;
+import com.android.internal.telephony.cdma.sms.BearerData;
+import com.android.internal.telephony.cdma.sms.CdmaSmsAddress;
+import com.android.internal.telephony.cdma.sms.CdmaSmsSubaddress;
+import com.android.internal.telephony.cdma.sms.SmsEnvelope;
+import com.android.internal.telephony.cdma.sms.UserData;
+import com.android.internal.telephony.uicc.IccUtils;
+import com.android.internal.util.BitwiseInputStream;
+import com.android.internal.util.HexDump;
+import com.android.internal.telephony.Sms7BitEncodingTranslator;
+
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+
+/**
+ * TODO(cleanup): these constants are disturbing... are they not just
+ * different interpretations on one number?  And if we did not have
+ * terrible class name overlap, they would not need to be directly
+ * imported like this.  The class in this file could just as well be
+ * named CdmaSmsMessage, could it not?
+ */
+
+/**
+ * TODO(cleanup): internally returning null in many places makes
+ * debugging very hard (among many other reasons) and should be made
+ * more meaningful (replaced with exceptions for example).  Null
+ * returns should only occur at the very outside of the module/class
+ * scope.
+ */
+
+/**
+ * A Short Message Service message.
+ *
+ */
+public class SmsMessage extends SmsMessageBase {
+    static final String LOG_TAG = "SmsMessage";
+    static private final String LOGGABLE_TAG = "CDMA:SMS";
+    private static final boolean VDBG = false;
+
+    private final static byte TELESERVICE_IDENTIFIER                    = 0x00;
+    private final static byte SERVICE_CATEGORY                          = 0x01;
+    private final static byte ORIGINATING_ADDRESS                       = 0x02;
+    private final static byte ORIGINATING_SUB_ADDRESS                   = 0x03;
+    private final static byte DESTINATION_ADDRESS                       = 0x04;
+    private final static byte DESTINATION_SUB_ADDRESS                   = 0x05;
+    private final static byte BEARER_REPLY_OPTION                       = 0x06;
+    private final static byte CAUSE_CODES                               = 0x07;
+    private final static byte BEARER_DATA                               = 0x08;
+
+    /**
+     *  Status of a previously submitted SMS.
+     *  This field applies to SMS Delivery Acknowledge messages. 0 indicates success;
+     *  Here, the error class is defined by the bits from 9-8, the status code by the bits from 7-0.
+     *  See C.S0015-B, v2.0, 4.5.21 for a detailed description of possible values.
+     */
+    private int status;
+
+    /** Specifies if a return of an acknowledgment is requested for send SMS */
+    private static final int RETURN_NO_ACK  = 0;
+    private static final int RETURN_ACK     = 1;
+
+    private SmsEnvelope mEnvelope;
+    private BearerData mBearerData;
+
+    /** @hide */
+    public SmsMessage(SmsAddress addr, SmsEnvelope env) {
+        mOriginatingAddress = addr;
+        mEnvelope = env;
+        createPdu();
+    }
+
+    public SmsMessage() {}
+
+    public static class SubmitPdu extends SubmitPduBase {
+    }
+
+    /**
+     * Create an SmsMessage from a raw PDU.
+     * Note: In CDMA the PDU is just a byte representation of the received Sms.
+     */
+    public static SmsMessage createFromPdu(byte[] pdu) {
+        SmsMessage msg = new SmsMessage();
+
+        try {
+            msg.parsePdu(pdu);
+            return msg;
+        } catch (RuntimeException ex) {
+            Rlog.e(LOG_TAG, "SMS PDU parsing failed: ", ex);
+            return null;
+        } catch (OutOfMemoryError e) {
+            Log.e(LOG_TAG, "SMS PDU parsing failed with out of memory: ", e);
+            return null;
+        }
+    }
+
+    /**
+     * Create an SmsMessage from an SMS EF record.
+     *
+     * @param index Index of SMS record. This should be index in ArrayList
+     *              returned by RuimSmsInterfaceManager.getAllMessagesFromIcc + 1.
+     * @param data Record data.
+     * @return An SmsMessage representing the record.
+     *
+     * @hide
+     */
+    public static SmsMessage createFromEfRecord(int index, byte[] data) {
+        try {
+            SmsMessage msg = new SmsMessage();
+
+            msg.mIndexOnIcc = index;
+
+            // First byte is status: RECEIVED_READ, RECEIVED_UNREAD, STORED_SENT,
+            // or STORED_UNSENT
+            // See 3GPP2 C.S0023 3.4.27
+            if ((data[0] & 1) == 0) {
+                Rlog.w(LOG_TAG, "SMS parsing failed: Trying to parse a free record");
+                return null;
+            } else {
+                msg.mStatusOnIcc = data[0] & 0x07;
+            }
+
+            // Second byte is the MSG_LEN, length of the message
+            // See 3GPP2 C.S0023 3.4.27
+            int size = data[1];
+
+            // Note: Data may include trailing FF's.  That's OK; message
+            // should still parse correctly.
+            byte[] pdu = new byte[size];
+            System.arraycopy(data, 2, pdu, 0, size);
+            // the message has to be parsed before it can be displayed
+            // see gsm.SmsMessage
+            msg.parsePduFromEfRecord(pdu);
+            return msg;
+        } catch (RuntimeException ex) {
+            Rlog.e(LOG_TAG, "SMS PDU parsing failed: ", ex);
+            return null;
+        }
+
+    }
+
+    /**
+     * Note: This function is a GSM specific functionality which is not supported in CDMA mode.
+     */
+    public static int getTPLayerLengthForPDU(String pdu) {
+        Rlog.w(LOG_TAG, "getTPLayerLengthForPDU: is not supported in CDMA mode.");
+        return 0;
+    }
+
+    /**
+     * TODO(cleanup): why do getSubmitPdu methods take an scAddr input
+     * and do nothing with it?  GSM allows us to specify a SC (eg,
+     * when responding to an SMS that explicitly requests the response
+     * is sent to a specific SC), or pass null to use the default
+     * value.  Is there no similar notion in CDMA? Or do we just not
+     * have it hooked up?
+     */
+
+    /**
+     * Get an SMS-SUBMIT PDU for a destination address and a message
+     *
+     * @param scAddr                Service Centre address.  Null means use default.
+     * @param destAddr              Address of the recipient.
+     * @param message               String representation of the message payload.
+     * @param statusReportRequested Indicates whether a report is requested for this message.
+     * @param smsHeader             Array containing the data for the User Data Header, preceded
+     *                              by the Element Identifiers.
+     * @return a <code>SubmitPdu</code> containing the encoded SC
+     *         address, if applicable, and the encoded message.
+     *         Returns null on encode error.
+     * @hide
+     */
+    public static SubmitPdu getSubmitPdu(String scAddr, String destAddr, String message,
+            boolean statusReportRequested, SmsHeader smsHeader) {
+
+        /**
+         * TODO(cleanup): Do we really want silent failure like this?
+         * Would it not be much more reasonable to make sure we don't
+         * call this function if we really want nothing done?
+         */
+        if (message == null || destAddr == null) {
+            return null;
+        }
+
+        UserData uData = new UserData();
+        uData.payloadStr = message;
+        uData.userDataHeader = smsHeader;
+        return privateGetSubmitPdu(destAddr, statusReportRequested, uData);
+    }
+
+    /**
+     * Get an SMS-SUBMIT PDU for a data message to a destination address and port.
+     *
+     * @param scAddr Service Centre address. null == use default
+     * @param destAddr the address of the destination for the message
+     * @param destPort the port to deliver the message to at the
+     *        destination
+     * @param data the data for the message
+     * @return a <code>SubmitPdu</code> containing the encoded SC
+     *         address, if applicable, and the encoded message.
+     *         Returns null on encode error.
+     */
+    public static SubmitPdu getSubmitPdu(String scAddr, String destAddr, int destPort,
+            byte[] data, boolean statusReportRequested) {
+
+        /**
+         * TODO(cleanup): this is not a general-purpose SMS creation
+         * method, but rather something specialized to messages
+         * containing OCTET encoded (meaning non-human-readable) user
+         * data.  The name should reflect that, and not just overload.
+         */
+
+        SmsHeader.PortAddrs portAddrs = new SmsHeader.PortAddrs();
+        portAddrs.destPort = destPort;
+        portAddrs.origPort = 0;
+        portAddrs.areEightBits = false;
+
+        SmsHeader smsHeader = new SmsHeader();
+        smsHeader.portAddrs = portAddrs;
+
+        UserData uData = new UserData();
+        uData.userDataHeader = smsHeader;
+        uData.msgEncoding = UserData.ENCODING_OCTET;
+        uData.msgEncodingSet = true;
+        uData.payload = data;
+
+        return privateGetSubmitPdu(destAddr, statusReportRequested, uData);
+    }
+
+    /**
+     * Get an SMS-SUBMIT PDU for a data message to a destination address &amp; port
+     *
+     * @param destAddr the address of the destination for the message
+     * @param userData the data for the message
+     * @param statusReportRequested Indicates whether a report is requested for this message.
+     * @return a <code>SubmitPdu</code> containing the encoded SC
+     *         address, if applicable, and the encoded message.
+     *         Returns null on encode error.
+     */
+    public static SubmitPdu getSubmitPdu(String destAddr, UserData userData,
+            boolean statusReportRequested) {
+        return privateGetSubmitPdu(destAddr, statusReportRequested, userData);
+    }
+
+    /**
+     * Note: This function is a GSM specific functionality which is not supported in CDMA mode.
+     */
+    @Override
+    public int getProtocolIdentifier() {
+        Rlog.w(LOG_TAG, "getProtocolIdentifier: is not supported in CDMA mode.");
+        // (3GPP TS 23.040): "no interworking, but SME to SME protocol":
+        return 0;
+    }
+
+    /**
+     * Note: This function is a GSM specific functionality which is not supported in CDMA mode.
+     */
+    @Override
+    public boolean isReplace() {
+        Rlog.w(LOG_TAG, "isReplace: is not supported in CDMA mode.");
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * Note: This function is a GSM specific functionality which is not supported in CDMA mode.
+     */
+    @Override
+    public boolean isCphsMwiMessage() {
+        Rlog.w(LOG_TAG, "isCphsMwiMessage: is not supported in CDMA mode.");
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean isMWIClearMessage() {
+        return ((mBearerData != null) && (mBearerData.numberOfMessages == 0));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean isMWISetMessage() {
+        return ((mBearerData != null) && (mBearerData.numberOfMessages > 0));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean isMwiDontStore() {
+        return ((mBearerData != null) &&
+                (mBearerData.numberOfMessages > 0) &&
+                (mBearerData.userData == null));
+    }
+
+    /**
+     * Returns the status for a previously submitted message.
+     * For not interfering with status codes from GSM, this status code is
+     * shifted to the bits 31-16.
+     */
+    @Override
+    public int getStatus() {
+        return (status << 16);
+    }
+
+    /** Return true iff the bearer data message type is DELIVERY_ACK. */
+    @Override
+    public boolean isStatusReportMessage() {
+        return (mBearerData.messageType == BearerData.MESSAGE_TYPE_DELIVERY_ACK);
+    }
+
+    /**
+     * Note: This function is a GSM specific functionality which is not supported in CDMA mode.
+     */
+    @Override
+    public boolean isReplyPathPresent() {
+        Rlog.w(LOG_TAG, "isReplyPathPresent: is not supported in CDMA mode.");
+        return false;
+    }
+
+    /**
+     * Calculate the number of septets needed to encode the message.
+     *
+     * @param messageBody the message to encode
+     * @param use7bitOnly ignore (but still count) illegal characters if true
+     * @param isEntireMsg indicates if this is entire msg or a segment in multipart msg
+     * @return TextEncodingDetails
+     */
+    public static TextEncodingDetails calculateLength(CharSequence messageBody,
+            boolean use7bitOnly, boolean isEntireMsg) {
+        CharSequence newMsgBody = null;
+        Resources r = Resources.getSystem();
+        if (r.getBoolean(com.android.internal.R.bool.config_sms_force_7bit_encoding)) {
+            newMsgBody  = Sms7BitEncodingTranslator.translate(messageBody);
+        }
+        if (TextUtils.isEmpty(newMsgBody)) {
+            newMsgBody = messageBody;
+        }
+        return BearerData.calcTextEncodingDetails(newMsgBody, use7bitOnly, isEntireMsg);
+    }
+
+    /**
+     * Returns the teleservice type of the message.
+     * @return the teleservice:
+     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#TELESERVICE_NOT_SET},
+     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#TELESERVICE_WMT},
+     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#TELESERVICE_WEMT},
+     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#TELESERVICE_VMN},
+     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#TELESERVICE_WAP}
+    */
+    public int getTeleService() {
+        return mEnvelope.teleService;
+    }
+
+    /**
+     * Returns the message type of the message.
+     * @return the message type:
+     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#MESSAGE_TYPE_POINT_TO_POINT},
+     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#MESSAGE_TYPE_BROADCAST},
+     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#MESSAGE_TYPE_ACKNOWLEDGE},
+    */
+    public int getMessageType() {
+        // NOTE: mEnvelope.messageType is not set correctly for cell broadcasts with some RILs.
+        // Use the service category parameter to detect CMAS and other cell broadcast messages.
+        if (mEnvelope.serviceCategory != 0) {
+            return SmsEnvelope.MESSAGE_TYPE_BROADCAST;
+        } else {
+            return SmsEnvelope.MESSAGE_TYPE_POINT_TO_POINT;
+        }
+    }
+
+    /**
+     * Decodes pdu to an empty SMS object.
+     * In the CDMA case the pdu is just an internal byte stream representation
+     * of the SMS Java-object.
+     * @see #createPdu()
+     */
+    private void parsePdu(byte[] pdu) {
+        ByteArrayInputStream bais = new ByteArrayInputStream(pdu);
+        DataInputStream dis = new DataInputStream(bais);
+        int length;
+        int bearerDataLength;
+        SmsEnvelope env = new SmsEnvelope();
+        CdmaSmsAddress addr = new CdmaSmsAddress();
+
+        try {
+            env.messageType = dis.readInt();
+            env.teleService = dis.readInt();
+            env.serviceCategory = dis.readInt();
+
+            addr.digitMode = dis.readByte();
+            addr.numberMode = dis.readByte();
+            addr.ton = dis.readByte();
+            addr.numberPlan = dis.readByte();
+
+            length = dis.readUnsignedByte();
+            addr.numberOfDigits = length;
+
+            // sanity check on the length
+            if (length > pdu.length) {
+                throw new RuntimeException(
+                        "createFromPdu: Invalid pdu, addr.numberOfDigits " + length
+                        + " > pdu len " + pdu.length);
+            }
+            addr.origBytes = new byte[length];
+            dis.read(addr.origBytes, 0, length); // digits
+
+            env.bearerReply = dis.readInt();
+            // CauseCode values:
+            env.replySeqNo = dis.readByte();
+            env.errorClass = dis.readByte();
+            env.causeCode = dis.readByte();
+
+            //encoded BearerData:
+            bearerDataLength = dis.readInt();
+            // sanity check on the length
+            if (bearerDataLength > pdu.length) {
+                throw new RuntimeException(
+                        "createFromPdu: Invalid pdu, bearerDataLength " + bearerDataLength
+                        + " > pdu len " + pdu.length);
+            }
+            env.bearerData = new byte[bearerDataLength];
+            dis.read(env.bearerData, 0, bearerDataLength);
+            dis.close();
+        } catch (IOException ex) {
+            throw new RuntimeException(
+                    "createFromPdu: conversion from byte array to object failed: " + ex, ex);
+        } catch (Exception ex) {
+            Rlog.e(LOG_TAG, "createFromPdu: conversion from byte array to object failed: " + ex);
+        }
+
+        // link the filled objects to this SMS
+        mOriginatingAddress = addr;
+        env.origAddress = addr;
+        mEnvelope = env;
+        mPdu = pdu;
+
+        parseSms();
+    }
+
+    /**
+     * Decodes 3GPP2 sms stored in CSIM/RUIM cards As per 3GPP2 C.S0015-0
+     */
+    private void parsePduFromEfRecord(byte[] pdu) {
+        ByteArrayInputStream bais = new ByteArrayInputStream(pdu);
+        DataInputStream dis = new DataInputStream(bais);
+        SmsEnvelope env = new SmsEnvelope();
+        CdmaSmsAddress addr = new CdmaSmsAddress();
+        CdmaSmsSubaddress subAddr = new CdmaSmsSubaddress();
+
+        try {
+            env.messageType = dis.readByte();
+
+            while (dis.available() > 0) {
+                int parameterId = dis.readByte();
+                int parameterLen = dis.readUnsignedByte();
+                byte[] parameterData = new byte[parameterLen];
+
+                switch (parameterId) {
+                    case TELESERVICE_IDENTIFIER:
+                        /*
+                         * 16 bit parameter that identifies which upper layer
+                         * service access point is sending or should receive
+                         * this message
+                         */
+                        env.teleService = dis.readUnsignedShort();
+                        Rlog.i(LOG_TAG, "teleservice = " + env.teleService);
+                        break;
+                    case SERVICE_CATEGORY:
+                        /*
+                         * 16 bit parameter that identifies type of service as
+                         * in 3GPP2 C.S0015-0 Table 3.4.3.2-1
+                         */
+                        env.serviceCategory = dis.readUnsignedShort();
+                        break;
+                    case ORIGINATING_ADDRESS:
+                    case DESTINATION_ADDRESS:
+                        dis.read(parameterData, 0, parameterLen);
+                        BitwiseInputStream addrBis = new BitwiseInputStream(parameterData);
+                        addr.digitMode = addrBis.read(1);
+                        addr.numberMode = addrBis.read(1);
+                        int numberType = 0;
+                        if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
+                            numberType = addrBis.read(3);
+                            addr.ton = numberType;
+
+                            if (addr.numberMode == CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK)
+                                addr.numberPlan = addrBis.read(4);
+                        }
+
+                        addr.numberOfDigits = addrBis.read(8);
+
+                        byte[] data = new byte[addr.numberOfDigits];
+                        byte b = 0x00;
+
+                        if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF) {
+                            /* As per 3GPP2 C.S0005-0 Table 2.7.1.3.2.4-4 */
+                            for (int index = 0; index < addr.numberOfDigits; index++) {
+                                b = (byte) (0xF & addrBis.read(4));
+                                // convert the value if it is 4-bit DTMF to 8
+                                // bit
+                                data[index] = convertDtmfToAscii(b);
+                            }
+                        } else if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
+                            if (addr.numberMode == CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK) {
+                                for (int index = 0; index < addr.numberOfDigits; index++) {
+                                    b = (byte) (0xFF & addrBis.read(8));
+                                    data[index] = b;
+                                }
+
+                            } else if (addr.numberMode == CdmaSmsAddress.NUMBER_MODE_DATA_NETWORK) {
+                                if (numberType == 2)
+                                    Rlog.e(LOG_TAG, "TODO: Originating Addr is email id");
+                                else
+                                    Rlog.e(LOG_TAG,
+                                          "TODO: Originating Addr is data network address");
+                            } else {
+                                Rlog.e(LOG_TAG, "Originating Addr is of incorrect type");
+                            }
+                        } else {
+                            Rlog.e(LOG_TAG, "Incorrect Digit mode");
+                        }
+                        addr.origBytes = data;
+                        Rlog.i(LOG_TAG, "Originating Addr=" + addr.toString());
+                        break;
+                    case ORIGINATING_SUB_ADDRESS:
+                    case DESTINATION_SUB_ADDRESS:
+                        dis.read(parameterData, 0, parameterLen);
+                        BitwiseInputStream subAddrBis = new BitwiseInputStream(parameterData);
+                        subAddr.type = subAddrBis.read(3);
+                        subAddr.odd = subAddrBis.readByteArray(1)[0];
+                        int subAddrLen = subAddrBis.read(8);
+                        byte[] subdata = new byte[subAddrLen];
+                        for (int index = 0; index < subAddrLen; index++) {
+                            b = (byte) (0xFF & subAddrBis.read(4));
+                            // convert the value if it is 4-bit DTMF to 8 bit
+                            subdata[index] = convertDtmfToAscii(b);
+                        }
+                        subAddr.origBytes = subdata;
+                        break;
+                    case BEARER_REPLY_OPTION:
+                        dis.read(parameterData, 0, parameterLen);
+                        BitwiseInputStream replyOptBis = new BitwiseInputStream(parameterData);
+                        env.bearerReply = replyOptBis.read(6);
+                        break;
+                    case CAUSE_CODES:
+                        dis.read(parameterData, 0, parameterLen);
+                        BitwiseInputStream ccBis = new BitwiseInputStream(parameterData);
+                        env.replySeqNo = ccBis.readByteArray(6)[0];
+                        env.errorClass = ccBis.readByteArray(2)[0];
+                        if (env.errorClass != 0x00)
+                            env.causeCode = ccBis.readByteArray(8)[0];
+                        break;
+                    case BEARER_DATA:
+                        dis.read(parameterData, 0, parameterLen);
+                        env.bearerData = parameterData;
+                        break;
+                    default:
+                        throw new Exception("unsupported parameterId (" + parameterId + ")");
+                }
+            }
+            bais.close();
+            dis.close();
+        } catch (Exception ex) {
+            Rlog.e(LOG_TAG, "parsePduFromEfRecord: conversion from pdu to SmsMessage failed" + ex);
+        }
+
+        // link the filled objects to this SMS
+        mOriginatingAddress = addr;
+        env.origAddress = addr;
+        env.origSubaddress = subAddr;
+        mEnvelope = env;
+        mPdu = pdu;
+
+        parseSms();
+    }
+
+    /**
+     * Parses a SMS message from its BearerData stream. (mobile-terminated only)
+     */
+    public void parseSms() {
+        // Message Waiting Info Record defined in 3GPP2 C.S-0005, 3.7.5.6
+        // It contains only an 8-bit number with the number of messages waiting
+        if (mEnvelope.teleService == SmsEnvelope.TELESERVICE_MWI) {
+            mBearerData = new BearerData();
+            if (mEnvelope.bearerData != null) {
+                mBearerData.numberOfMessages = 0x000000FF & mEnvelope.bearerData[0];
+            }
+            if (VDBG) {
+                Rlog.d(LOG_TAG, "parseSms: get MWI " +
+                      Integer.toString(mBearerData.numberOfMessages));
+            }
+            return;
+        }
+        mBearerData = BearerData.decode(mEnvelope.bearerData);
+        if (Rlog.isLoggable(LOGGABLE_TAG, Log.VERBOSE)) {
+            Rlog.d(LOG_TAG, "MT raw BearerData = '" +
+                      HexDump.toHexString(mEnvelope.bearerData) + "'");
+            Rlog.d(LOG_TAG, "MT (decoded) BearerData = " + mBearerData);
+        }
+        mMessageRef = mBearerData.messageId;
+        if (mBearerData.userData != null) {
+            mUserData = mBearerData.userData.payload;
+            mUserDataHeader = mBearerData.userData.userDataHeader;
+            mMessageBody = mBearerData.userData.payloadStr;
+        }
+
+        if (mOriginatingAddress != null) {
+            mOriginatingAddress.address = new String(mOriginatingAddress.origBytes);
+            if (mOriginatingAddress.ton == CdmaSmsAddress.TON_INTERNATIONAL_OR_IP) {
+                if (mOriginatingAddress.address.charAt(0) != '+') {
+                    mOriginatingAddress.address = "+" + mOriginatingAddress.address;
+                }
+            }
+            if (VDBG) Rlog.v(LOG_TAG, "SMS originating address: "
+                    + mOriginatingAddress.address);
+        }
+
+        if (mBearerData.msgCenterTimeStamp != null) {
+            mScTimeMillis = mBearerData.msgCenterTimeStamp.toMillis(true);
+        }
+
+        if (VDBG) Rlog.d(LOG_TAG, "SMS SC timestamp: " + mScTimeMillis);
+
+        // Message Type (See 3GPP2 C.S0015-B, v2, 4.5.1)
+        if (mBearerData.messageType == BearerData.MESSAGE_TYPE_DELIVERY_ACK) {
+            // The BearerData MsgStatus subparameter should only be
+            // included for DELIVERY_ACK messages.  If it occurred for
+            // other messages, it would be unclear what the status
+            // being reported refers to.  The MsgStatus subparameter
+            // is primarily useful to indicate error conditions -- a
+            // message without this subparameter is assumed to
+            // indicate successful delivery (status == 0).
+            if (! mBearerData.messageStatusSet) {
+                Rlog.d(LOG_TAG, "DELIVERY_ACK message without msgStatus (" +
+                        (mUserData == null ? "also missing" : "does have") +
+                        " userData).");
+                status = 0;
+            } else {
+                status = mBearerData.errorClass << 8;
+                status |= mBearerData.messageStatus;
+            }
+        } else if (mBearerData.messageType != BearerData.MESSAGE_TYPE_DELIVER) {
+            throw new RuntimeException("Unsupported message type: " + mBearerData.messageType);
+        }
+
+        if (mMessageBody != null) {
+            if (VDBG) Rlog.v(LOG_TAG, "SMS message body: '" + mMessageBody + "'");
+            parseMessageBody();
+        } else if ((mUserData != null) && VDBG) {
+            Rlog.v(LOG_TAG, "SMS payload: '" + IccUtils.bytesToHexString(mUserData) + "'");
+        }
+    }
+
+    /**
+     * Parses a broadcast SMS, possibly containing a CMAS alert.
+     */
+    public SmsCbMessage parseBroadcastSms() {
+        BearerData bData = BearerData.decode(mEnvelope.bearerData, mEnvelope.serviceCategory);
+        if (bData == null) {
+            Rlog.w(LOG_TAG, "BearerData.decode() returned null");
+            return null;
+        }
+
+        if (Rlog.isLoggable(LOGGABLE_TAG, Log.VERBOSE)) {
+            Rlog.d(LOG_TAG, "MT raw BearerData = " + HexDump.toHexString(mEnvelope.bearerData));
+        }
+
+        String plmn = TelephonyManager.getDefault().getNetworkOperator();
+        SmsCbLocation location = new SmsCbLocation(plmn);
+
+        return new SmsCbMessage(SmsCbMessage.MESSAGE_FORMAT_3GPP2,
+                SmsCbMessage.GEOGRAPHICAL_SCOPE_PLMN_WIDE, bData.messageId, location,
+                mEnvelope.serviceCategory, bData.getLanguage(), bData.userData.payloadStr,
+                bData.priority, null, bData.cmasWarningInfo);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public SmsConstants.MessageClass getMessageClass() {
+        if (BearerData.DISPLAY_MODE_IMMEDIATE == mBearerData.displayMode ) {
+            return SmsConstants.MessageClass.CLASS_0;
+        } else {
+            return SmsConstants.MessageClass.UNKNOWN;
+        }
+    }
+
+    /**
+     * Calculate the next message id, starting at 1 and iteratively
+     * incrementing within the range 1..65535 remembering the state
+     * via a persistent system property.  (See C.S0015-B, v2.0,
+     * 4.3.1.5) Since this routine is expected to be accessed via via
+     * binder-call, and hence should be thread-safe, it has been
+     * synchronized.
+     */
+    public synchronized static int getNextMessageId() {
+        // Testing and dialog with partners has indicated that
+        // msgId==0 is (sometimes?) treated specially by lower levels.
+        // Specifically, the ID is not preserved for delivery ACKs.
+        // Hence, avoid 0 -- constraining the range to 1..65535.
+        int msgId = SystemProperties.getInt(TelephonyProperties.PROPERTY_CDMA_MSG_ID, 1);
+        String nextMsgId = Integer.toString((msgId % 0xFFFF) + 1);
+        try{
+            SystemProperties.set(TelephonyProperties.PROPERTY_CDMA_MSG_ID, nextMsgId);
+            if (Rlog.isLoggable(LOGGABLE_TAG, Log.VERBOSE)) {
+                Rlog.d(LOG_TAG, "next " + TelephonyProperties.PROPERTY_CDMA_MSG_ID + " = " + nextMsgId);
+                Rlog.d(LOG_TAG, "readback gets " +
+                        SystemProperties.get(TelephonyProperties.PROPERTY_CDMA_MSG_ID));
+            }
+        } catch(RuntimeException ex) {
+            Rlog.e(LOG_TAG, "set nextMessage ID failed: " + ex);
+        }
+        return msgId;
+    }
+
+    /**
+     * Creates BearerData and Envelope from parameters for a Submit SMS.
+     * @return byte stream for SubmitPdu.
+     */
+    private static SubmitPdu privateGetSubmitPdu(String destAddrStr, boolean statusReportRequested,
+            UserData userData) {
+
+        /**
+         * TODO(cleanup): give this function a more meaningful name.
+         */
+
+        /**
+         * TODO(cleanup): Make returning null from the getSubmitPdu
+         * variations meaningful -- clean up the error feedback
+         * mechanism, and avoid null pointer exceptions.
+         */
+
+        /**
+         * North America Plus Code :
+         * Convert + code to 011 and dial out for international SMS
+         */
+        CdmaSmsAddress destAddr = CdmaSmsAddress.parse(
+                PhoneNumberUtils.cdmaCheckAndProcessPlusCodeForSms(destAddrStr));
+        if (destAddr == null) return null;
+
+        BearerData bearerData = new BearerData();
+        bearerData.messageType = BearerData.MESSAGE_TYPE_SUBMIT;
+
+        bearerData.messageId = getNextMessageId();
+
+        bearerData.deliveryAckReq = statusReportRequested;
+        bearerData.userAckReq = false;
+        bearerData.readAckReq = false;
+        bearerData.reportReq = false;
+
+        bearerData.userData = userData;
+
+        byte[] encodedBearerData = BearerData.encode(bearerData);
+        if (Rlog.isLoggable(LOGGABLE_TAG, Log.VERBOSE)) {
+            Rlog.d(LOG_TAG, "MO (encoded) BearerData = " + bearerData);
+            Rlog.d(LOG_TAG, "MO raw BearerData = '" + HexDump.toHexString(encodedBearerData) + "'");
+        }
+        if (encodedBearerData == null) return null;
+
+        int teleservice = bearerData.hasUserDataHeader ?
+                SmsEnvelope.TELESERVICE_WEMT : SmsEnvelope.TELESERVICE_WMT;
+
+        SmsEnvelope envelope = new SmsEnvelope();
+        envelope.messageType = SmsEnvelope.MESSAGE_TYPE_POINT_TO_POINT;
+        envelope.teleService = teleservice;
+        envelope.destAddress = destAddr;
+        envelope.bearerReply = RETURN_ACK;
+        envelope.bearerData = encodedBearerData;
+
+        /**
+         * TODO(cleanup): envelope looks to be a pointless class, get
+         * rid of it.  Also -- most of the envelope fields set here
+         * are ignored, why?
+         */
+
+        try {
+            /**
+             * TODO(cleanup): reference a spec and get rid of the ugly comments
+             */
+            ByteArrayOutputStream baos = new ByteArrayOutputStream(100);
+            DataOutputStream dos = new DataOutputStream(baos);
+            dos.writeInt(envelope.teleService);
+            dos.writeInt(0); //servicePresent
+            dos.writeInt(0); //serviceCategory
+            dos.write(destAddr.digitMode);
+            dos.write(destAddr.numberMode);
+            dos.write(destAddr.ton); // number_type
+            dos.write(destAddr.numberPlan);
+            dos.write(destAddr.numberOfDigits);
+            dos.write(destAddr.origBytes, 0, destAddr.origBytes.length); // digits
+            // Subaddress is not supported.
+            dos.write(0); //subaddressType
+            dos.write(0); //subaddr_odd
+            dos.write(0); //subaddr_nbr_of_digits
+            dos.write(encodedBearerData.length);
+            dos.write(encodedBearerData, 0, encodedBearerData.length);
+            dos.close();
+
+            SubmitPdu pdu = new SubmitPdu();
+            pdu.encodedMessage = baos.toByteArray();
+            pdu.encodedScAddress = null;
+            return pdu;
+        } catch(IOException ex) {
+            Rlog.e(LOG_TAG, "creating SubmitPdu failed: " + ex);
+        }
+        return null;
+    }
+
+    /**
+     * Creates byte array (pseudo pdu) from SMS object.
+     * Note: Do not call this method more than once per object!
+     * @hide
+     */
+    public void createPdu() {
+        SmsEnvelope env = mEnvelope;
+        CdmaSmsAddress addr = env.origAddress;
+        ByteArrayOutputStream baos = new ByteArrayOutputStream(100);
+        DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(baos));
+
+        try {
+            dos.writeInt(env.messageType);
+            dos.writeInt(env.teleService);
+            dos.writeInt(env.serviceCategory);
+
+            dos.writeByte(addr.digitMode);
+            dos.writeByte(addr.numberMode);
+            dos.writeByte(addr.ton);
+            dos.writeByte(addr.numberPlan);
+            dos.writeByte(addr.numberOfDigits);
+            dos.write(addr.origBytes, 0, addr.origBytes.length); // digits
+
+            dos.writeInt(env.bearerReply);
+            // CauseCode values:
+            dos.writeByte(env.replySeqNo);
+            dos.writeByte(env.errorClass);
+            dos.writeByte(env.causeCode);
+            //encoded BearerData:
+            dos.writeInt(env.bearerData.length);
+            dos.write(env.bearerData, 0, env.bearerData.length);
+            dos.close();
+
+            /**
+             * TODO(cleanup) -- The mPdu field is managed in
+             * a fragile manner, and it would be much nicer if
+             * accessing the serialized representation used a less
+             * fragile mechanism.  Maybe the getPdu method could
+             * generate a representation if there was not yet one?
+             */
+
+            mPdu = baos.toByteArray();
+        } catch (IOException ex) {
+            Rlog.e(LOG_TAG, "createPdu: conversion from object to byte array failed: " + ex);
+        }
+    }
+
+    /**
+     * Converts a 4-Bit DTMF encoded symbol from the calling address number to ASCII character
+     * @hide
+     */
+    public static byte convertDtmfToAscii(byte dtmfDigit) {
+        byte asciiDigit;
+
+        switch (dtmfDigit) {
+        case  0: asciiDigit = 68; break; // 'D'
+        case  1: asciiDigit = 49; break; // '1'
+        case  2: asciiDigit = 50; break; // '2'
+        case  3: asciiDigit = 51; break; // '3'
+        case  4: asciiDigit = 52; break; // '4'
+        case  5: asciiDigit = 53; break; // '5'
+        case  6: asciiDigit = 54; break; // '6'
+        case  7: asciiDigit = 55; break; // '7'
+        case  8: asciiDigit = 56; break; // '8'
+        case  9: asciiDigit = 57; break; // '9'
+        case 10: asciiDigit = 48; break; // '0'
+        case 11: asciiDigit = 42; break; // '*'
+        case 12: asciiDigit = 35; break; // '#'
+        case 13: asciiDigit = 65; break; // 'A'
+        case 14: asciiDigit = 66; break; // 'B'
+        case 15: asciiDigit = 67; break; // 'C'
+        default:
+            asciiDigit = 32; // Invalid DTMF code
+            break;
+        }
+
+        return asciiDigit;
+    }
+
+    /** This function  shall be called to get the number of voicemails.
+     * @hide
+     */
+    public int getNumOfVoicemails() {
+        return mBearerData.numberOfMessages;
+    }
+
+    /**
+     * Returns a byte array that can be use to uniquely identify a received SMS message.
+     * C.S0015-B  4.3.1.6 Unique Message Identification.
+     *
+     * @return byte array uniquely identifying the message.
+     * @hide
+     */
+    public byte[] getIncomingSmsFingerprint() {
+        ByteArrayOutputStream output = new ByteArrayOutputStream();
+
+        output.write(mEnvelope.serviceCategory);
+        output.write(mEnvelope.teleService);
+        output.write(mEnvelope.origAddress.origBytes, 0, mEnvelope.origAddress.origBytes.length);
+        output.write(mEnvelope.bearerData, 0, mEnvelope.bearerData.length);
+        output.write(mEnvelope.origSubaddress.origBytes, 0,
+                mEnvelope.origSubaddress.origBytes.length);
+
+        return output.toByteArray();
+    }
+
+    /**
+     * Returns the list of service category program data, if present.
+     * @return a list of CdmaSmsCbProgramData objects, or null if not present
+     * @hide
+     */
+    public ArrayList<CdmaSmsCbProgramData> getSmsCbProgramData() {
+        return mBearerData.serviceCategoryProgramData;
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/UserData.java b/telephony/java/com/android/internal/telephony/cdma/UserData.java
new file mode 100644
index 0000000..f879560
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/UserData.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.cdma.sms;
+
+import android.util.SparseIntArray;
+
+import com.android.internal.telephony.SmsHeader;
+import com.android.internal.util.HexDump;
+
+public class UserData {
+
+    /**
+     * User data encoding types.
+     * (See 3GPP2 C.R1001-F, v1.0, table 9.1-1)
+     */
+    public static final int ENCODING_OCTET                      = 0x00;
+    public static final int ENCODING_IS91_EXTENDED_PROTOCOL     = 0x01;
+    public static final int ENCODING_7BIT_ASCII                 = 0x02;
+    public static final int ENCODING_IA5                        = 0x03;
+    public static final int ENCODING_UNICODE_16                 = 0x04;
+    public static final int ENCODING_SHIFT_JIS                  = 0x05;
+    public static final int ENCODING_KOREAN                     = 0x06;
+    public static final int ENCODING_LATIN_HEBREW               = 0x07;
+    public static final int ENCODING_LATIN                      = 0x08;
+    public static final int ENCODING_GSM_7BIT_ALPHABET          = 0x09;
+    public static final int ENCODING_GSM_DCS                    = 0x0A;
+
+    /**
+     * User data message type encoding types.
+     * (See 3GPP2 C.S0015-B, 4.5.2 and 3GPP 23.038, Section 4)
+     */
+    public static final int ENCODING_GSM_DCS_7BIT               = 0x00;
+    public static final int ENCODING_GSM_DCS_8BIT               = 0x01;
+    public static final int ENCODING_GSM_DCS_16BIT              = 0x02;
+
+    /**
+     * IS-91 message types.
+     * (See TIA/EIS/IS-91-A-ENGL 1999, table 3.7.1.1-3)
+     */
+    public static final int IS91_MSG_TYPE_VOICEMAIL_STATUS   = 0x82;
+    public static final int IS91_MSG_TYPE_SHORT_MESSAGE_FULL = 0x83;
+    public static final int IS91_MSG_TYPE_CLI                = 0x84;
+    public static final int IS91_MSG_TYPE_SHORT_MESSAGE      = 0x85;
+
+    /**
+     * US ASCII character mapping table.
+     *
+     * This table contains only the printable ASCII characters, with a
+     * 0x20 offset, meaning that the ASCII SPACE character is at index
+     * 0, with the resulting code of 0x20.
+     *
+     * Note this mapping is also equivalent to that used by both the
+     * IA5 and the IS-91 encodings.  For the former this is defined
+     * using CCITT Rec. T.50 Tables 1 and 3.  For the latter IS 637 B,
+     * Table 4.3.1.4.1-1 -- and note the encoding uses only 6 bits,
+     * and hence only maps entries up to the '_' character.
+     *
+     */
+    public static final char[] ASCII_MAP = {
+        ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/',
+        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
+        '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+        'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
+        '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+        'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~'};
+
+    /**
+     * Character to use when forced to encode otherwise unencodable
+     * characters, meaning those not in the respective ASCII or GSM
+     * 7-bit encoding tables.  Current choice is SPACE, which is 0x20
+     * in both the GSM-7bit and ASCII-7bit encodings.
+     */
+    static final byte UNENCODABLE_7_BIT_CHAR = 0x20;
+
+    /**
+     * Only elements between these indices in the ASCII table are printable.
+     */
+    public static final int PRINTABLE_ASCII_MIN_INDEX = 0x20;
+    public static final int ASCII_NL_INDEX = 0x0A;
+    public static final int ASCII_CR_INDEX = 0x0D;
+    public static final SparseIntArray charToAscii = new SparseIntArray();
+    static {
+        for (int i = 0; i < ASCII_MAP.length; i++) {
+            charToAscii.put(ASCII_MAP[i], PRINTABLE_ASCII_MIN_INDEX + i);
+        }
+        charToAscii.put('\n', ASCII_NL_INDEX);
+        charToAscii.put('\r', ASCII_CR_INDEX);
+    }
+
+    /*
+     * TODO(cleanup): Move this very generic functionality somewhere
+     * more general.
+     */
+    /**
+     * Given a string generate a corresponding ASCII-encoded byte
+     * array, but limited to printable characters.  If the input
+     * contains unprintable characters, return null.
+     */
+    public static byte[] stringToAscii(String str) {
+        int len = str.length();
+        byte[] result = new byte[len];
+        for (int i = 0; i < len; i++) {
+            int charCode = charToAscii.get(str.charAt(i), -1);
+            if (charCode == -1) return null;
+            result[i] = (byte)charCode;
+        }
+        return result;
+    }
+
+    /**
+     * Mapping for ASCII values less than 32 are flow control signals
+     * and not used here.
+     */
+    public static final int ASCII_MAP_BASE_INDEX = 0x20;
+    public static final int ASCII_MAP_MAX_INDEX = ASCII_MAP_BASE_INDEX + ASCII_MAP.length - 1;
+
+    /**
+     * Contains the data header of the user data
+     */
+    public SmsHeader userDataHeader;
+
+    /**
+     * Contains the data encoding type for the SMS message
+     */
+    public int msgEncoding;
+    public boolean msgEncodingSet = false;
+
+    public int msgType;
+
+    /**
+     * Number of invalid bits in the last byte of data.
+     */
+    public int paddingBits;
+
+    public int numFields;
+
+    /**
+     * Contains the user data of a SMS message
+     * (See 3GPP2 C.S0015-B, v2, 4.5.2)
+     */
+    public byte[] payload;
+    public String payloadStr;
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("UserData ");
+        builder.append("{ msgEncoding=" + (msgEncodingSet ? msgEncoding : "unset"));
+        builder.append(", msgType=" + msgType);
+        builder.append(", paddingBits=" + paddingBits);
+        builder.append(", numFields=" + numFields);
+        builder.append(", userDataHeader=" + userDataHeader);
+        builder.append(", payload='" + HexDump.toHexString(payload) + "'");
+        builder.append(", payloadStr='" + payloadStr + "'");
+        builder.append(" }");
+        return builder.toString();
+    }
+
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/package.html b/telephony/java/com/android/internal/telephony/cdma/package.html
new file mode 100644
index 0000000..b2bc736
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/package.html
@@ -0,0 +1,6 @@
+<HTML>
+<BODY>
+Provides CDMA-specific features for text/data/PDU SMS messages
+@hide
+</BODY>
+</HTML>
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSmsAddress.java b/telephony/java/com/android/internal/telephony/gsm/GsmSmsAddress.java
new file mode 100644
index 0000000..2fbf7ed
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmSmsAddress.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.gsm;
+
+import android.telephony.PhoneNumberUtils;
+import java.text.ParseException;
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.SmsAddress;
+
+public class GsmSmsAddress extends SmsAddress {
+
+    static final int OFFSET_ADDRESS_LENGTH = 0;
+
+    static final int OFFSET_TOA = 1;
+
+    static final int OFFSET_ADDRESS_VALUE = 2;
+
+    /**
+     * New GsmSmsAddress from TS 23.040 9.1.2.5 Address Field
+     *
+     * @param offset the offset of the Address-Length byte
+     * @param length the length in bytes rounded up, e.g. "2 +
+     *        (addressLength + 1) / 2"
+     * @throws ParseException
+     */
+
+    public GsmSmsAddress(byte[] data, int offset, int length) throws ParseException {
+        origBytes = new byte[length];
+        System.arraycopy(data, offset, origBytes, 0, length);
+
+        // addressLength is the count of semi-octets, not bytes
+        int addressLength = origBytes[OFFSET_ADDRESS_LENGTH] & 0xff;
+
+        int toa = origBytes[OFFSET_TOA] & 0xff;
+        ton = 0x7 & (toa >> 4);
+
+        // TOA must have its high bit set
+        if ((toa & 0x80) != 0x80) {
+            throw new ParseException("Invalid TOA - high bit must be set. toa = " + toa,
+                    offset + OFFSET_TOA);
+        }
+
+        if (isAlphanumeric()) {
+            // An alphanumeric address
+            int countSeptets = addressLength * 4 / 7;
+
+            address = GsmAlphabet.gsm7BitPackedToString(origBytes,
+                    OFFSET_ADDRESS_VALUE, countSeptets);
+        } else {
+            // TS 23.040 9.1.2.5 says
+            // that "the MS shall interpret reserved values as 'Unknown'
+            // but shall store them exactly as received"
+
+            byte lastByte = origBytes[length - 1];
+
+            if ((addressLength & 1) == 1) {
+                // Make sure the final unused BCD digit is 0xf
+                origBytes[length - 1] |= 0xf0;
+            }
+            address = PhoneNumberUtils.calledPartyBCDToString(origBytes,
+                    OFFSET_TOA, length - OFFSET_TOA);
+
+            // And restore origBytes
+            origBytes[length - 1] = lastByte;
+        }
+    }
+
+    @Override
+    public String getAddressString() {
+        return address;
+    }
+
+    /**
+     * Returns true if this is an alphanumeric address
+     */
+    @Override
+    public boolean isAlphanumeric() {
+        return ton == TON_ALPHANUMERIC;
+    }
+
+    @Override
+    public boolean isNetworkSpecific() {
+        return ton == TON_NETWORK;
+    }
+
+    /**
+     * Returns true of this is a valid CPHS voice message waiting indicator
+     * address
+     */
+    public boolean isCphsVoiceMessageIndicatorAddress() {
+        // CPHS-style MWI message
+        // See CPHS 4.7 B.4.2.1
+        //
+        // Basically:
+        //
+        // - Originating address should be 4 bytes long and alphanumeric
+        // - Decode will result with two chars:
+        // - Char 1
+        // 76543210
+        // ^ set/clear indicator (0 = clear)
+        // ^^^ type of indicator (000 = voice)
+        // ^^^^ must be equal to 0001
+        // - Char 2:
+        // 76543210
+        // ^ line number (0 = line 1)
+        // ^^^^^^^ set to 0
+        //
+        // Remember, since the alpha address is stored in 7-bit compact form,
+        // the "line number" is really the top bit of the first address value
+        // byte
+
+        return (origBytes[OFFSET_ADDRESS_LENGTH] & 0xff) == 4
+                && isAlphanumeric() && (origBytes[OFFSET_TOA] & 0x0f) == 0;
+    }
+
+    /**
+     * Returns true if this is a valid CPHS voice message waiting indicator
+     * address indicating a "set" of "indicator 1" of type "voice message
+     * waiting"
+     */
+    public boolean isCphsVoiceMessageSet() {
+        // 0x11 means "set" "voice message waiting" "indicator 1"
+        return isCphsVoiceMessageIndicatorAddress()
+                && (origBytes[OFFSET_ADDRESS_VALUE] & 0xff) == 0x11;
+
+    }
+
+    /**
+     * Returns true if this is a valid CPHS voice message waiting indicator
+     * address indicating a "clear" of "indicator 1" of type "voice message
+     * waiting"
+     */
+    public boolean isCphsVoiceMessageClear() {
+        // 0x10 means "clear" "voice message waiting" "indicator 1"
+        return isCphsVoiceMessageIndicatorAddress()
+                && (origBytes[OFFSET_ADDRESS_VALUE] & 0xff) == 0x10;
+
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java b/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
new file mode 100644
index 0000000..15ed810
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
@@ -0,0 +1,292 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.gsm;
+
+import android.telephony.SmsCbLocation;
+import android.telephony.SmsCbMessage;
+import android.util.Pair;
+
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.SmsConstants;
+
+import java.io.UnsupportedEncodingException;
+
+/**
+ * Parses a GSM or UMTS format SMS-CB message into an {@link SmsCbMessage} object. The class is
+ * public because {@link #createSmsCbMessage(SmsCbLocation, byte[][])} is used by some test cases.
+ */
+public class GsmSmsCbMessage {
+
+    /**
+     * Languages in the 0000xxxx DCS group as defined in 3GPP TS 23.038, section 5.
+     */
+    private static final String[] LANGUAGE_CODES_GROUP_0 = {
+            "de", "en", "it", "fr", "es", "nl", "sv", "da", "pt", "fi", "no", "el", "tr", "hu",
+            "pl", null
+    };
+
+    /**
+     * Languages in the 0010xxxx DCS group as defined in 3GPP TS 23.038, section 5.
+     */
+    private static final String[] LANGUAGE_CODES_GROUP_2 = {
+            "cs", "he", "ar", "ru", "is", null, null, null, null, null, null, null, null, null,
+            null, null
+    };
+
+    private static final char CARRIAGE_RETURN = 0x0d;
+
+    private static final int PDU_BODY_PAGE_LENGTH = 82;
+
+    /** Utility class with only static methods. */
+    private GsmSmsCbMessage() { }
+
+    /**
+     * Create a new SmsCbMessage object from a header object plus one or more received PDUs.
+     *
+     * @param pdus PDU bytes
+     */
+    public static SmsCbMessage createSmsCbMessage(SmsCbHeader header, SmsCbLocation location,
+            byte[][] pdus) throws IllegalArgumentException {
+        if (header.isEtwsPrimaryNotification()) {
+            // ETSI TS 23.041 ETWS Primary Notification message
+            // ETWS primary message only contains 4 fields including serial number,
+            // message identifier, warning type, and warning security information.
+            // There is no field for the content/text. We hardcode "ETWS" in the
+            // text body so the user won't see an empty dialog without any text.
+            return new SmsCbMessage(SmsCbMessage.MESSAGE_FORMAT_3GPP,
+                    header.getGeographicalScope(), header.getSerialNumber(),
+                    location, header.getServiceCategory(),
+                    null, "ETWS", SmsCbMessage.MESSAGE_PRIORITY_EMERGENCY,
+                    header.getEtwsInfo(), header.getCmasInfo());
+        } else {
+            String language = null;
+            StringBuilder sb = new StringBuilder();
+            for (byte[] pdu : pdus) {
+                Pair<String, String> p = parseBody(header, pdu);
+                language = p.first;
+                sb.append(p.second);
+            }
+            int priority = header.isEmergencyMessage() ? SmsCbMessage.MESSAGE_PRIORITY_EMERGENCY
+                    : SmsCbMessage.MESSAGE_PRIORITY_NORMAL;
+
+            return new SmsCbMessage(SmsCbMessage.MESSAGE_FORMAT_3GPP,
+                    header.getGeographicalScope(), header.getSerialNumber(), location,
+                    header.getServiceCategory(), language, sb.toString(), priority,
+                    header.getEtwsInfo(), header.getCmasInfo());
+        }
+    }
+
+    /**
+     * Create a new SmsCbMessage object from one or more received PDUs. This is used by some
+     * CellBroadcastReceiver test cases, because SmsCbHeader is now package local.
+     *
+     * @param location the location (geographical scope) for the message
+     * @param pdus PDU bytes
+     */
+    public static SmsCbMessage createSmsCbMessage(SmsCbLocation location, byte[][] pdus)
+            throws IllegalArgumentException {
+        SmsCbHeader header = new SmsCbHeader(pdus[0]);
+        return createSmsCbMessage(header, location, pdus);
+    }
+
+    /**
+     * Parse and unpack the body text according to the encoding in the DCS.
+     * After completing successfully this method will have assigned the body
+     * text into mBody, and optionally the language code into mLanguage
+     *
+     * @param header the message header to use
+     * @param pdu the PDU to decode
+     * @return a Pair of Strings containing the language and body of the message
+     */
+    private static Pair<String, String> parseBody(SmsCbHeader header, byte[] pdu) {
+        int encoding;
+        String language = null;
+        boolean hasLanguageIndicator = false;
+        int dataCodingScheme = header.getDataCodingScheme();
+
+        // Extract encoding and language from DCS, as defined in 3gpp TS 23.038,
+        // section 5.
+        switch ((dataCodingScheme & 0xf0) >> 4) {
+            case 0x00:
+                encoding = SmsConstants.ENCODING_7BIT;
+                language = LANGUAGE_CODES_GROUP_0[dataCodingScheme & 0x0f];
+                break;
+
+            case 0x01:
+                hasLanguageIndicator = true;
+                if ((dataCodingScheme & 0x0f) == 0x01) {
+                    encoding = SmsConstants.ENCODING_16BIT;
+                } else {
+                    encoding = SmsConstants.ENCODING_7BIT;
+                }
+                break;
+
+            case 0x02:
+                encoding = SmsConstants.ENCODING_7BIT;
+                language = LANGUAGE_CODES_GROUP_2[dataCodingScheme & 0x0f];
+                break;
+
+            case 0x03:
+                encoding = SmsConstants.ENCODING_7BIT;
+                break;
+
+            case 0x04:
+            case 0x05:
+                switch ((dataCodingScheme & 0x0c) >> 2) {
+                    case 0x01:
+                        encoding = SmsConstants.ENCODING_8BIT;
+                        break;
+
+                    case 0x02:
+                        encoding = SmsConstants.ENCODING_16BIT;
+                        break;
+
+                    case 0x00:
+                    default:
+                        encoding = SmsConstants.ENCODING_7BIT;
+                        break;
+                }
+                break;
+
+            case 0x06:
+            case 0x07:
+                // Compression not supported
+            case 0x09:
+                // UDH structure not supported
+            case 0x0e:
+                // Defined by the WAP forum not supported
+                throw new IllegalArgumentException("Unsupported GSM dataCodingScheme "
+                        + dataCodingScheme);
+
+            case 0x0f:
+                if (((dataCodingScheme & 0x04) >> 2) == 0x01) {
+                    encoding = SmsConstants.ENCODING_8BIT;
+                } else {
+                    encoding = SmsConstants.ENCODING_7BIT;
+                }
+                break;
+
+            default:
+                // Reserved values are to be treated as 7-bit
+                encoding = SmsConstants.ENCODING_7BIT;
+                break;
+        }
+
+        if (header.isUmtsFormat()) {
+            // Payload may contain multiple pages
+            int nrPages = pdu[SmsCbHeader.PDU_HEADER_LENGTH];
+
+            if (pdu.length < SmsCbHeader.PDU_HEADER_LENGTH + 1 + (PDU_BODY_PAGE_LENGTH + 1)
+                    * nrPages) {
+                throw new IllegalArgumentException("Pdu length " + pdu.length + " does not match "
+                        + nrPages + " pages");
+            }
+
+            StringBuilder sb = new StringBuilder();
+
+            for (int i = 0; i < nrPages; i++) {
+                // Each page is 82 bytes followed by a length octet indicating
+                // the number of useful octets within those 82
+                int offset = SmsCbHeader.PDU_HEADER_LENGTH + 1 + (PDU_BODY_PAGE_LENGTH + 1) * i;
+                int length = pdu[offset + PDU_BODY_PAGE_LENGTH];
+
+                if (length > PDU_BODY_PAGE_LENGTH) {
+                    throw new IllegalArgumentException("Page length " + length
+                            + " exceeds maximum value " + PDU_BODY_PAGE_LENGTH);
+                }
+
+                Pair<String, String> p = unpackBody(pdu, encoding, offset, length,
+                        hasLanguageIndicator, language);
+                language = p.first;
+                sb.append(p.second);
+            }
+            return new Pair<String, String>(language, sb.toString());
+        } else {
+            // Payload is one single page
+            int offset = SmsCbHeader.PDU_HEADER_LENGTH;
+            int length = pdu.length - offset;
+
+            return unpackBody(pdu, encoding, offset, length, hasLanguageIndicator, language);
+        }
+    }
+
+    /**
+     * Unpack body text from the pdu using the given encoding, position and
+     * length within the pdu
+     *
+     * @param pdu The pdu
+     * @param encoding The encoding, as derived from the DCS
+     * @param offset Position of the first byte to unpack
+     * @param length Number of bytes to unpack
+     * @param hasLanguageIndicator true if the body text is preceded by a
+     *            language indicator. If so, this method will as a side-effect
+     *            assign the extracted language code into mLanguage
+     * @param language the language to return if hasLanguageIndicator is false
+     * @return a Pair of Strings containing the language and body of the message
+     */
+    private static Pair<String, String> unpackBody(byte[] pdu, int encoding, int offset, int length,
+            boolean hasLanguageIndicator, String language) {
+        String body = null;
+
+        switch (encoding) {
+            case SmsConstants.ENCODING_7BIT:
+                body = GsmAlphabet.gsm7BitPackedToString(pdu, offset, length * 8 / 7);
+
+                if (hasLanguageIndicator && body != null && body.length() > 2) {
+                    // Language is two GSM characters followed by a CR.
+                    // The actual body text is offset by 3 characters.
+                    language = body.substring(0, 2);
+                    body = body.substring(3);
+                }
+                break;
+
+            case SmsConstants.ENCODING_16BIT:
+                if (hasLanguageIndicator && pdu.length >= offset + 2) {
+                    // Language is two GSM characters.
+                    // The actual body text is offset by 2 bytes.
+                    language = GsmAlphabet.gsm7BitPackedToString(pdu, offset, 2);
+                    offset += 2;
+                    length -= 2;
+                }
+
+                try {
+                    body = new String(pdu, offset, (length & 0xfffe), "utf-16");
+                } catch (UnsupportedEncodingException e) {
+                    // Apparently it wasn't valid UTF-16.
+                    throw new IllegalArgumentException("Error decoding UTF-16 message", e);
+                }
+                break;
+
+            default:
+                break;
+        }
+
+        if (body != null) {
+            // Remove trailing carriage return
+            for (int i = body.length() - 1; i >= 0; i--) {
+                if (body.charAt(i) != CARRIAGE_RETURN) {
+                    body = body.substring(0, i + 1);
+                    break;
+                }
+            }
+        } else {
+            body = "";
+        }
+
+        return new Pair<String, String>(language, body);
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsBroadcastConfigInfo.java b/telephony/java/com/android/internal/telephony/gsm/SmsBroadcastConfigInfo.java
new file mode 100644
index 0000000..f4f4036
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/gsm/SmsBroadcastConfigInfo.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.gsm;
+
+/**
+ * SmsBroadcastConfigInfo defines one configuration of Cell Broadcast
+ * Message (CBM) to be received by the ME
+ *
+ * fromServiceId - toServiceId defines a range of CBM message identifiers
+ * whose value is 0x0000 - 0xFFFF as defined in TS 23.041 9.4.1.2.2 for GMS
+ * and 9.4.4.2.2 for UMTS. All other values can be treated as empty
+ * CBM message ID.
+ *
+ * fromCodeScheme - toCodeScheme defines a range of CBM data coding schemes
+ * whose value is 0x00 - 0xFF as defined in TS 23.041 9.4.1.2.3 for GMS
+ * and 9.4.4.2.3 for UMTS.
+ * All other values can be treated as empty CBM data coding scheme.
+ *
+ * selected false means message types specified in {@code <fromServiceId, toServiceId>}
+ * and {@code <fromCodeScheme, toCodeScheme>} are not accepted, while true means accepted.
+ *
+ */
+public final class SmsBroadcastConfigInfo {
+    private int mFromServiceId;
+    private int mToServiceId;
+    private int mFromCodeScheme;
+    private int mToCodeScheme;
+    private boolean mSelected;
+
+    /**
+     * Initialize the object from rssi and cid.
+     */
+    public SmsBroadcastConfigInfo(int fromId, int toId, int fromScheme,
+            int toScheme, boolean selected) {
+        mFromServiceId = fromId;
+        mToServiceId = toId;
+        mFromCodeScheme = fromScheme;
+        mToCodeScheme = toScheme;
+        mSelected = selected;
+    }
+
+    /**
+     * @param fromServiceId the fromServiceId to set
+     */
+    public void setFromServiceId(int fromServiceId) {
+        mFromServiceId = fromServiceId;
+    }
+
+    /**
+     * @return the fromServiceId
+     */
+    public int getFromServiceId() {
+        return mFromServiceId;
+    }
+
+    /**
+     * @param toServiceId the toServiceId to set
+     */
+    public void setToServiceId(int toServiceId) {
+        mToServiceId = toServiceId;
+    }
+
+    /**
+     * @return the toServiceId
+     */
+    public int getToServiceId() {
+        return mToServiceId;
+    }
+
+    /**
+     * @param fromCodeScheme the fromCodeScheme to set
+     */
+    public void setFromCodeScheme(int fromCodeScheme) {
+        mFromCodeScheme = fromCodeScheme;
+    }
+
+    /**
+     * @return the fromCodeScheme
+     */
+    public int getFromCodeScheme() {
+        return mFromCodeScheme;
+    }
+
+    /**
+     * @param toCodeScheme the toCodeScheme to set
+     */
+    public void setToCodeScheme(int toCodeScheme) {
+        mToCodeScheme = toCodeScheme;
+    }
+
+    /**
+     * @return the toCodeScheme
+     */
+    public int getToCodeScheme() {
+        return mToCodeScheme;
+    }
+
+    /**
+     * @param selected the selected to set
+     */
+    public void setSelected(boolean selected) {
+        mSelected = selected;
+    }
+
+    /**
+     * @return the selected
+     */
+    public boolean isSelected() {
+        return mSelected;
+    }
+
+    @Override
+    public String toString() {
+        return "SmsBroadcastConfigInfo: Id [" +
+                mFromServiceId + ',' + mToServiceId + "] Code [" +
+                mFromCodeScheme + ',' + mToCodeScheme + "] " +
+            (mSelected ? "ENABLED" : "DISABLED");
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsCbConstants.java b/telephony/java/com/android/internal/telephony/gsm/SmsCbConstants.java
new file mode 100644
index 0000000..bce5680
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/gsm/SmsCbConstants.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.gsm;
+
+/**
+ * Constants used in SMS Cell Broadcast messages (see 3GPP TS 23.041). This class is used by the
+ * boot-time broadcast channel enable and database upgrade code in CellBroadcastReceiver, so it
+ * is public, but should be avoided in favor of the radio technology independent constants in
+ * {@link android.telephony.SmsCbMessage}, {@link android.telephony.SmsCbEtwsInfo}, and
+ * {@link android.telephony.SmsCbCmasInfo} classes.
+ *
+ * {@hide}
+ */
+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;
+
+    /** Channel 911 required by Taiwan NCC. ID 0~999 is allocated by GSMA */
+    public static final int MESSAGE_ID_GSMA_ALLOCATED_CHANNEL_911
+            = 0x038F; // 911
+
+    /** Channel 919 required by Taiwan NCC and Israel. ID 0~999 is allocated by GSMA */
+    public static final int MESSAGE_ID_GSMA_ALLOCATED_CHANNEL_919
+            = 0x0397; // 919
+
+    /** Channel 928 required by Israel. ID 0~999 is allocated by GSMA */
+    public static final int MESSAGE_ID_GSMA_ALLOCATED_CHANNEL_928
+            = 0x03A0; // 928
+
+    /** Start of PWS Message Identifier range (includes ETWS and CMAS). */
+    public static final int MESSAGE_ID_PWS_FIRST_IDENTIFIER
+            = 0x1100; // 4352
+
+    /** Bitmask for messages of ETWS type (including future extensions). */
+    public static final int MESSAGE_ID_ETWS_TYPE_MASK
+            = 0xFFF8;
+
+    /** Value for messages of ETWS type after applying {@link #MESSAGE_ID_ETWS_TYPE_MASK}. */
+    public static final int MESSAGE_ID_ETWS_TYPE
+            = 0x1100; // 4352
+
+    /** ETWS Message Identifier for earthquake warning message. */
+    public static final int MESSAGE_ID_ETWS_EARTHQUAKE_WARNING
+            = 0x1100; // 4352
+
+    /** ETWS Message Identifier for tsunami warning message. */
+    public static final int MESSAGE_ID_ETWS_TSUNAMI_WARNING
+            = 0x1101; // 4353
+
+    /** ETWS Message Identifier for earthquake and tsunami combined warning message. */
+    public static final int MESSAGE_ID_ETWS_EARTHQUAKE_AND_TSUNAMI_WARNING
+            = 0x1102; // 4354
+
+    /** ETWS Message Identifier for test message. */
+    public static final int MESSAGE_ID_ETWS_TEST_MESSAGE
+            = 0x1103; // 4355
+
+    /** ETWS Message Identifier for messages related to other emergency types. */
+    public static final int MESSAGE_ID_ETWS_OTHER_EMERGENCY_TYPE
+            = 0x1104; // 4356
+
+    /** Start of CMAS Message Identifier range. */
+    public static final int MESSAGE_ID_CMAS_FIRST_IDENTIFIER
+            = 0x1112; // 4370
+
+    /** CMAS Message Identifier for Presidential Level alerts. */
+    public static final int MESSAGE_ID_CMAS_ALERT_PRESIDENTIAL_LEVEL
+            = 0x1112; // 4370
+
+    /** CMAS Message Identifier for Extreme alerts, Urgency=Immediate, Certainty=Observed. */
+    public static final int MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_OBSERVED
+            = 0x1113; // 4371
+
+    /** CMAS Message Identifier for Extreme alerts, Urgency=Immediate, Certainty=Likely. */
+    public static final int MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_LIKELY
+            = 0x1114; // 4372
+
+    /** CMAS Message Identifier for Extreme alerts, Urgency=Expected, Certainty=Observed. */
+    public static final int MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_OBSERVED
+            = 0x1115; // 4373
+
+    /** CMAS Message Identifier for Extreme alerts, Urgency=Expected, Certainty=Likely. */
+    public static final int MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_LIKELY
+            = 0x1116; // 4374
+
+    /** CMAS Message Identifier for Severe alerts, Urgency=Immediate, Certainty=Observed. */
+    public static final int MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_OBSERVED
+            = 0x1117; // 4375
+
+    /** CMAS Message Identifier for Severe alerts, Urgency=Immediate, Certainty=Likely. */
+    public static final int MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_LIKELY
+            = 0x1118; // 4376
+
+    /** CMAS Message Identifier for Severe alerts, Urgency=Expected, Certainty=Observed. */
+    public static final int MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_OBSERVED
+            = 0x1119; // 4377
+
+    /** CMAS Message Identifier for Severe alerts, Urgency=Expected, Certainty=Likely. */
+    public static final int MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_LIKELY
+            = 0x111A; // 4378
+
+    /** CMAS Message Identifier for Child Abduction Emergency (Amber Alert). */
+    public static final int MESSAGE_ID_CMAS_ALERT_CHILD_ABDUCTION_EMERGENCY
+            = 0x111B; // 4379
+
+    /** CMAS Message Identifier for the Required Monthly Test. */
+    public static final int MESSAGE_ID_CMAS_ALERT_REQUIRED_MONTHLY_TEST
+            = 0x111C; // 4380
+
+    /** CMAS Message Identifier for CMAS Exercise. */
+    public static final int MESSAGE_ID_CMAS_ALERT_EXERCISE
+            = 0x111D; // 4381
+
+    /** CMAS Message Identifier for operator defined use. */
+    public static final int MESSAGE_ID_CMAS_ALERT_OPERATOR_DEFINED_USE
+            = 0x111E; // 4382
+
+    /** CMAS Message Identifier for Presidential Level alerts for additional languages
+     *  for additional languages. */
+    public static final int MESSAGE_ID_CMAS_ALERT_PRESIDENTIAL_LEVEL_LANGUAGE
+            = 0x111F; // 4383
+
+    /** CMAS Message Identifier for Extreme alerts, Urgency=Immediate, Certainty=Observed
+     *  for additional languages. */
+    public static final int MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_OBSERVED_LANGUAGE
+            = 0x1120; // 4384
+
+    /** CMAS Message Identifier for Extreme alerts, Urgency=Immediate, Certainty=Likely
+     *  for additional languages. */
+    public static final int MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_LIKELY_LANGUAGE
+            = 0x1121; // 4385
+
+    /** CMAS Message Identifier for Extreme alerts, Urgency=Expected, Certainty=Observed
+     *  for additional languages. */
+    public static final int MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_OBSERVED_LANGUAGE
+            = 0x1122; // 4386
+
+    /** CMAS Message Identifier for Extreme alerts, Urgency=Expected, Certainty=Likely
+     *  for additional languages. */
+    public static final int MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_LIKELY_LANGUAGE
+            = 0x1123; // 4387
+
+    /** CMAS Message Identifier for Severe alerts, Urgency=Immediate, Certainty=Observed
+     *  for additional languages. */
+    public static final int MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_OBSERVED_LANGUAGE
+            = 0x1124; // 4388
+
+    /** CMAS Message Identifier for Severe alerts, Urgency=Immediate, Certainty=Likely
+     *  for additional languages.*/
+    public static final int MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_LIKELY_LANGUAGE
+            = 0x1125; // 4389
+
+    /** CMAS Message Identifier for Severe alerts, Urgency=Expected, Certainty=Observed
+     *  for additional languages. */
+    public static final int MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_OBSERVED_LANGUAGE
+            = 0x1126; // 4390
+
+    /** CMAS Message Identifier for Severe alerts, Urgency=Expected, Certainty=Likely
+     *  for additional languages.*/
+    public static final int MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_LIKELY_LANGUAGE
+            = 0x1127; // 4391
+
+    /** CMAS Message Identifier for Child Abduction Emergency (Amber Alert)
+     *  for additional languages. */
+    public static final int MESSAGE_ID_CMAS_ALERT_CHILD_ABDUCTION_EMERGENCY_LANGUAGE
+            = 0x1128; // 4392
+
+    /** CMAS Message Identifier for the Required Monthly Test
+     *  for additional languages. */
+    public static final int MESSAGE_ID_CMAS_ALERT_REQUIRED_MONTHLY_TEST_LANGUAGE
+            = 0x1129; // 4393
+
+    /** CMAS Message Identifier for CMAS Exercise
+     *  for additional languages. */
+    public static final int MESSAGE_ID_CMAS_ALERT_EXERCISE_LANGUAGE
+            = 0x112A; // 4394
+
+    /** CMAS Message Identifier for operator defined use
+     *  for additional languages. */
+    public static final int MESSAGE_ID_CMAS_ALERT_OPERATOR_DEFINED_USE_LANGUAGE
+            = 0x112B; // 4395
+
+    /** End of CMAS Message Identifier range (including future extensions). */
+    public static final int MESSAGE_ID_CMAS_LAST_IDENTIFIER
+            = 0x112F; // 4399
+
+    /** End of PWS Message Identifier range (includes ETWS, CMAS, and future extensions). */
+    public static final int MESSAGE_ID_PWS_LAST_IDENTIFIER
+            = 0x18FF; // 6399
+
+    /** ETWS serial number flag to activate the popup display. */
+    public static final int SERIAL_NUMBER_ETWS_ACTIVATE_POPUP
+            = 0x1000; // 4096
+
+    /** ETWS serial number flag to activate the emergency user alert. */
+    public static final int SERIAL_NUMBER_ETWS_EMERGENCY_USER_ALERT
+            = 0x2000; // 8192
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsCbHeader.java b/telephony/java/com/android/internal/telephony/gsm/SmsCbHeader.java
new file mode 100644
index 0000000..d267ad2
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/gsm/SmsCbHeader.java
@@ -0,0 +1,450 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.gsm;
+
+import android.telephony.SmsCbCmasInfo;
+import android.telephony.SmsCbEtwsInfo;
+
+import java.util.Arrays;
+
+/**
+ * Parses a 3GPP TS 23.041 cell broadcast message header. This class is public for use by
+ * CellBroadcastReceiver test cases, but should not be used by applications.
+ *
+ * All relevant header information is now sent as a Parcelable
+ * {@link android.telephony.SmsCbMessage} object in the "message" extra of the
+ * {@link android.provider.Telephony.Sms.Intents#SMS_CB_RECEIVED_ACTION} or
+ * {@link android.provider.Telephony.Sms.Intents#SMS_EMERGENCY_CB_RECEIVED_ACTION} intent.
+ * The raw PDU is no longer sent to SMS CB applications.
+ */
+public class SmsCbHeader {
+
+    /**
+     * Length of SMS-CB header
+     */
+    static final int PDU_HEADER_LENGTH = 6;
+
+    /**
+     * GSM pdu format, as defined in 3gpp TS 23.041, section 9.4.1
+     */
+    static final int FORMAT_GSM = 1;
+
+    /**
+     * UMTS pdu format, as defined in 3gpp TS 23.041, section 9.4.2
+     */
+    static final int FORMAT_UMTS = 2;
+
+    /**
+     * GSM pdu format, as defined in 3gpp TS 23.041, section 9.4.1.3
+     */
+    static final int FORMAT_ETWS_PRIMARY = 3;
+
+    /**
+     * Message type value as defined in 3gpp TS 25.324, section 11.1.
+     */
+    private static final int MESSAGE_TYPE_CBS_MESSAGE = 1;
+
+    /**
+     * Length of GSM pdus
+     */
+    private static final int PDU_LENGTH_GSM = 88;
+
+    /**
+     * Maximum length of ETWS primary message GSM pdus
+     */
+    private static final int PDU_LENGTH_ETWS = 56;
+
+    private final int mGeographicalScope;
+
+    /** The serial number combines geographical scope, message code, and update number. */
+    private final int mSerialNumber;
+
+    /** The Message Identifier in 3GPP is the same as the Service Category in CDMA. */
+    private final int mMessageIdentifier;
+
+    private final int mDataCodingScheme;
+
+    private final int mPageIndex;
+
+    private final int mNrOfPages;
+
+    private final int mFormat;
+
+    /** ETWS warning notification info. */
+    private final SmsCbEtwsInfo mEtwsInfo;
+
+    /** CMAS warning notification info. */
+    private final SmsCbCmasInfo mCmasInfo;
+
+    public SmsCbHeader(byte[] pdu) throws IllegalArgumentException {
+        if (pdu == null || pdu.length < PDU_HEADER_LENGTH) {
+            throw new IllegalArgumentException("Illegal PDU");
+        }
+
+        if (pdu.length <= PDU_LENGTH_GSM) {
+            // can be ETWS or GSM format.
+            // Per TS23.041 9.4.1.2 and 9.4.1.3.2, GSM and ETWS format both
+            // contain serial number which contains GS, Message Code, and Update Number
+            // per 9.4.1.2.1, and message identifier in same octets
+            mGeographicalScope = (pdu[0] & 0xc0) >>> 6;
+            mSerialNumber = ((pdu[0] & 0xff) << 8) | (pdu[1] & 0xff);
+            mMessageIdentifier = ((pdu[2] & 0xff) << 8) | (pdu[3] & 0xff);
+            if (isEtwsMessage() && pdu.length <= PDU_LENGTH_ETWS) {
+                mFormat = FORMAT_ETWS_PRIMARY;
+                mDataCodingScheme = -1;
+                mPageIndex = -1;
+                mNrOfPages = -1;
+                boolean emergencyUserAlert = (pdu[4] & 0x1) != 0;
+                boolean activatePopup = (pdu[5] & 0x80) != 0;
+                int warningType = (pdu[4] & 0xfe) >>> 1;
+                byte[] warningSecurityInfo;
+                // copy the Warning-Security-Information, if present
+                if (pdu.length > PDU_HEADER_LENGTH) {
+                    warningSecurityInfo = Arrays.copyOfRange(pdu, 6, pdu.length);
+                } else {
+                    warningSecurityInfo = null;
+                }
+                mEtwsInfo = new SmsCbEtwsInfo(warningType, emergencyUserAlert, activatePopup,
+                        true, warningSecurityInfo);
+                mCmasInfo = null;
+                return;     // skip the ETWS/CMAS initialization code for regular notifications
+            } else {
+                // GSM pdus are no more than 88 bytes
+                mFormat = FORMAT_GSM;
+                mDataCodingScheme = pdu[4] & 0xff;
+
+                // Check for invalid page parameter
+                int pageIndex = (pdu[5] & 0xf0) >>> 4;
+                int nrOfPages = pdu[5] & 0x0f;
+
+                if (pageIndex == 0 || nrOfPages == 0 || pageIndex > nrOfPages) {
+                    pageIndex = 1;
+                    nrOfPages = 1;
+                }
+
+                mPageIndex = pageIndex;
+                mNrOfPages = nrOfPages;
+            }
+        } else {
+            // UMTS pdus are always at least 90 bytes since the payload includes
+            // a number-of-pages octet and also one length octet per page
+            mFormat = FORMAT_UMTS;
+
+            int messageType = pdu[0];
+
+            if (messageType != MESSAGE_TYPE_CBS_MESSAGE) {
+                throw new IllegalArgumentException("Unsupported message type " + messageType);
+            }
+
+            mMessageIdentifier = ((pdu[1] & 0xff) << 8) | pdu[2] & 0xff;
+            mGeographicalScope = (pdu[3] & 0xc0) >>> 6;
+            mSerialNumber = ((pdu[3] & 0xff) << 8) | (pdu[4] & 0xff);
+            mDataCodingScheme = pdu[5] & 0xff;
+
+            // We will always consider a UMTS message as having one single page
+            // since there's only one instance of the header, even though the
+            // actual payload may contain several pages.
+            mPageIndex = 1;
+            mNrOfPages = 1;
+        }
+
+        if (isEtwsMessage()) {
+            boolean emergencyUserAlert = isEtwsEmergencyUserAlert();
+            boolean activatePopup = isEtwsPopupAlert();
+            int warningType = getEtwsWarningType();
+            mEtwsInfo = new SmsCbEtwsInfo(warningType, emergencyUserAlert, activatePopup,
+                    false, null);
+            mCmasInfo = null;
+        } else if (isCmasMessage()) {
+            int messageClass = getCmasMessageClass();
+            int severity = getCmasSeverity();
+            int urgency = getCmasUrgency();
+            int certainty = getCmasCertainty();
+            mEtwsInfo = null;
+            mCmasInfo = new SmsCbCmasInfo(messageClass, SmsCbCmasInfo.CMAS_CATEGORY_UNKNOWN,
+                    SmsCbCmasInfo.CMAS_RESPONSE_TYPE_UNKNOWN, severity, urgency, certainty);
+        } else {
+            mEtwsInfo = null;
+            mCmasInfo = null;
+        }
+    }
+
+    int getGeographicalScope() {
+        return mGeographicalScope;
+    }
+
+    int getSerialNumber() {
+        return mSerialNumber;
+    }
+
+    int getServiceCategory() {
+        return mMessageIdentifier;
+    }
+
+    int getDataCodingScheme() {
+        return mDataCodingScheme;
+    }
+
+    int getPageIndex() {
+        return mPageIndex;
+    }
+
+    int getNumberOfPages() {
+        return mNrOfPages;
+    }
+
+    SmsCbEtwsInfo getEtwsInfo() {
+        return mEtwsInfo;
+    }
+
+    SmsCbCmasInfo getCmasInfo() {
+        return mCmasInfo;
+    }
+
+    /**
+     * Return whether this broadcast is an emergency (PWS) message type.
+     * @return true if this message is emergency type; false otherwise
+     */
+    boolean isEmergencyMessage() {
+        return mMessageIdentifier >= SmsCbConstants.MESSAGE_ID_PWS_FIRST_IDENTIFIER
+                && mMessageIdentifier <= SmsCbConstants.MESSAGE_ID_PWS_LAST_IDENTIFIER;
+    }
+
+    /**
+     * Return whether this broadcast is an ETWS emergency message type.
+     * @return true if this message is ETWS emergency type; false otherwise
+     */
+    private boolean isEtwsMessage() {
+        return (mMessageIdentifier & SmsCbConstants.MESSAGE_ID_ETWS_TYPE_MASK)
+                == SmsCbConstants.MESSAGE_ID_ETWS_TYPE;
+    }
+
+    /**
+     * Return whether this broadcast is an ETWS primary notification.
+     * @return true if this message is an ETWS primary notification; false otherwise
+     */
+    boolean isEtwsPrimaryNotification() {
+        return mFormat == FORMAT_ETWS_PRIMARY;
+    }
+
+    /**
+     * Return whether this broadcast is in UMTS format.
+     * @return true if this message is in UMTS format; false otherwise
+     */
+    boolean isUmtsFormat() {
+        return mFormat == FORMAT_UMTS;
+    }
+
+    /**
+     * Return whether this message is a CMAS emergency message type.
+     * @return true if this message is CMAS emergency type; false otherwise
+     */
+    private boolean isCmasMessage() {
+        return mMessageIdentifier >= SmsCbConstants.MESSAGE_ID_CMAS_FIRST_IDENTIFIER
+                && mMessageIdentifier <= SmsCbConstants.MESSAGE_ID_CMAS_LAST_IDENTIFIER;
+    }
+
+    /**
+     * Return whether the popup alert flag is set for an ETWS warning notification.
+     * This method assumes that the message ID has already been checked for ETWS type.
+     *
+     * @return true if the message code indicates a popup alert should be displayed
+     */
+    private boolean isEtwsPopupAlert() {
+        return (mSerialNumber & SmsCbConstants.SERIAL_NUMBER_ETWS_ACTIVATE_POPUP) != 0;
+    }
+
+    /**
+     * Return whether the emergency user alert flag is set for an ETWS warning notification.
+     * This method assumes that the message ID has already been checked for ETWS type.
+     *
+     * @return true if the message code indicates an emergency user alert
+     */
+    private boolean isEtwsEmergencyUserAlert() {
+        return (mSerialNumber & SmsCbConstants.SERIAL_NUMBER_ETWS_EMERGENCY_USER_ALERT) != 0;
+    }
+
+    /**
+     * Returns the warning type for an ETWS warning notification.
+     * This method assumes that the message ID has already been checked for ETWS type.
+     *
+     * @return the ETWS warning type defined in 3GPP TS 23.041 section 9.3.24
+     */
+    private int getEtwsWarningType() {
+        return mMessageIdentifier - SmsCbConstants.MESSAGE_ID_ETWS_EARTHQUAKE_WARNING;
+    }
+
+    /**
+     * Returns the message class for a CMAS warning notification.
+     * This method assumes that the message ID has already been checked for CMAS type.
+     * @return the CMAS message class as defined in {@link SmsCbCmasInfo}
+     */
+    private int getCmasMessageClass() {
+        switch (mMessageIdentifier) {
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_PRESIDENTIAL_LEVEL:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_PRESIDENTIAL_LEVEL_LANGUAGE:
+                return SmsCbCmasInfo.CMAS_CLASS_PRESIDENTIAL_LEVEL_ALERT;
+
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_OBSERVED:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_OBSERVED_LANGUAGE:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_LIKELY:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_LIKELY_LANGUAGE:
+                return SmsCbCmasInfo.CMAS_CLASS_EXTREME_THREAT;
+
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_OBSERVED:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_OBSERVED_LANGUAGE:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_LIKELY:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_LIKELY_LANGUAGE:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_OBSERVED:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_OBSERVED_LANGUAGE:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_LIKELY:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_LIKELY_LANGUAGE:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_OBSERVED:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_OBSERVED_LANGUAGE:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_LIKELY:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_LIKELY_LANGUAGE:
+                return SmsCbCmasInfo.CMAS_CLASS_SEVERE_THREAT;
+
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_CHILD_ABDUCTION_EMERGENCY:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_CHILD_ABDUCTION_EMERGENCY_LANGUAGE:
+                return SmsCbCmasInfo.CMAS_CLASS_CHILD_ABDUCTION_EMERGENCY;
+
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_REQUIRED_MONTHLY_TEST:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_REQUIRED_MONTHLY_TEST_LANGUAGE:
+                return SmsCbCmasInfo.CMAS_CLASS_REQUIRED_MONTHLY_TEST;
+
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXERCISE:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXERCISE_LANGUAGE:
+                return SmsCbCmasInfo.CMAS_CLASS_CMAS_EXERCISE;
+
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_OPERATOR_DEFINED_USE:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_OPERATOR_DEFINED_USE_LANGUAGE:
+                return SmsCbCmasInfo.CMAS_CLASS_OPERATOR_DEFINED_USE;
+
+            default:
+                return SmsCbCmasInfo.CMAS_CLASS_UNKNOWN;
+        }
+    }
+
+    /**
+     * Returns the severity for a CMAS warning notification. This is only available for extreme
+     * and severe alerts, not for other types such as Presidential Level and AMBER alerts.
+     * This method assumes that the message ID has already been checked for CMAS type.
+     * @return the CMAS severity as defined in {@link SmsCbCmasInfo}
+     */
+    private int getCmasSeverity() {
+        switch (mMessageIdentifier) {
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_OBSERVED:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_OBSERVED_LANGUAGE:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_LIKELY:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_LIKELY_LANGUAGE:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_OBSERVED:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_OBSERVED_LANGUAGE:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_LIKELY:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_LIKELY_LANGUAGE:
+                return SmsCbCmasInfo.CMAS_SEVERITY_EXTREME;
+
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_OBSERVED:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_OBSERVED_LANGUAGE:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_LIKELY:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_LIKELY_LANGUAGE:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_OBSERVED:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_OBSERVED_LANGUAGE:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_LIKELY:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_LIKELY_LANGUAGE:
+                return SmsCbCmasInfo.CMAS_SEVERITY_SEVERE;
+
+            default:
+                return SmsCbCmasInfo.CMAS_SEVERITY_UNKNOWN;
+        }
+    }
+
+    /**
+     * Returns the urgency for a CMAS warning notification. This is only available for extreme
+     * and severe alerts, not for other types such as Presidential Level and AMBER alerts.
+     * This method assumes that the message ID has already been checked for CMAS type.
+     * @return the CMAS urgency as defined in {@link SmsCbCmasInfo}
+     */
+    private int getCmasUrgency() {
+        switch (mMessageIdentifier) {
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_OBSERVED:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_OBSERVED_LANGUAGE:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_LIKELY:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_LIKELY_LANGUAGE:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_OBSERVED:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_OBSERVED_LANGUAGE:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_LIKELY:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_LIKELY_LANGUAGE:
+                return SmsCbCmasInfo.CMAS_URGENCY_IMMEDIATE;
+
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_OBSERVED:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_OBSERVED_LANGUAGE:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_LIKELY:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_LIKELY_LANGUAGE:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_OBSERVED:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_OBSERVED_LANGUAGE:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_LIKELY:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_LIKELY_LANGUAGE:
+                return SmsCbCmasInfo.CMAS_URGENCY_EXPECTED;
+
+            default:
+                return SmsCbCmasInfo.CMAS_URGENCY_UNKNOWN;
+        }
+    }
+
+    /**
+     * Returns the certainty for a CMAS warning notification. This is only available for extreme
+     * and severe alerts, not for other types such as Presidential Level and AMBER alerts.
+     * This method assumes that the message ID has already been checked for CMAS type.
+     * @return the CMAS certainty as defined in {@link SmsCbCmasInfo}
+     */
+    private int getCmasCertainty() {
+        switch (mMessageIdentifier) {
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_OBSERVED:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_OBSERVED_LANGUAGE:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_OBSERVED:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_OBSERVED_LANGUAGE:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_OBSERVED:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_OBSERVED_LANGUAGE:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_OBSERVED:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_OBSERVED_LANGUAGE:
+                return SmsCbCmasInfo.CMAS_CERTAINTY_OBSERVED;
+
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_LIKELY:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_LIKELY_LANGUAGE:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_LIKELY:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_LIKELY_LANGUAGE:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_LIKELY:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_LIKELY_LANGUAGE:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_LIKELY:
+            case SmsCbConstants.MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_LIKELY_LANGUAGE:
+                return SmsCbCmasInfo.CMAS_CERTAINTY_LIKELY;
+
+            default:
+                return SmsCbCmasInfo.CMAS_CERTAINTY_UNKNOWN;
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "SmsCbHeader{GS=" + mGeographicalScope + ", serialNumber=0x" +
+                Integer.toHexString(mSerialNumber) +
+                ", messageIdentifier=0x" + Integer.toHexString(mMessageIdentifier) +
+                ", DCS=0x" + Integer.toHexString(mDataCodingScheme) +
+                ", page " + mPageIndex + " of " + mNrOfPages + '}';
+    }
+}
\ No newline at end of file
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
new file mode 100644
index 0000000..582506a
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
@@ -0,0 +1,1369 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.gsm;
+
+import android.telephony.PhoneNumberUtils;
+import android.text.format.Time;
+import android.telephony.Rlog;
+import android.content.res.Resources;
+import android.text.TextUtils;
+
+import com.android.internal.telephony.EncodeException;
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
+import com.android.internal.telephony.uicc.IccUtils;
+import com.android.internal.telephony.SmsHeader;
+import com.android.internal.telephony.SmsMessageBase;
+import com.android.internal.telephony.Sms7BitEncodingTranslator;
+
+import java.io.ByteArrayOutputStream;
+import java.io.UnsupportedEncodingException;
+import java.text.ParseException;
+
+import static com.android.internal.telephony.SmsConstants.MessageClass;
+import static com.android.internal.telephony.SmsConstants.ENCODING_UNKNOWN;
+import static com.android.internal.telephony.SmsConstants.ENCODING_7BIT;
+import static com.android.internal.telephony.SmsConstants.ENCODING_8BIT;
+import static com.android.internal.telephony.SmsConstants.ENCODING_16BIT;
+import static com.android.internal.telephony.SmsConstants.ENCODING_KSC5601;
+import static com.android.internal.telephony.SmsConstants.MAX_USER_DATA_SEPTETS;
+import static com.android.internal.telephony.SmsConstants.MAX_USER_DATA_BYTES;
+import static com.android.internal.telephony.SmsConstants.MAX_USER_DATA_BYTES_WITH_HEADER;
+
+/**
+ * A Short Message Service message.
+ *
+ */
+public class SmsMessage extends SmsMessageBase {
+    static final String LOG_TAG = "SmsMessage";
+    private static final boolean VDBG = false;
+
+    private MessageClass messageClass;
+
+    /**
+     * TP-Message-Type-Indicator
+     * 9.2.3
+     */
+    private int mMti;
+
+    /** TP-Protocol-Identifier (TP-PID) */
+    private int mProtocolIdentifier;
+
+    // TP-Data-Coding-Scheme
+    // see TS 23.038
+    private int mDataCodingScheme;
+
+    // TP-Reply-Path
+    // e.g. 23.040 9.2.2.1
+    private boolean mReplyPathPresent = false;
+
+    /** The address of the receiver. */
+    private GsmSmsAddress mRecipientAddress;
+
+    /**
+     *  TP-Status - status of a previously submitted SMS.
+     *  This field applies to SMS-STATUS-REPORT messages.  0 indicates success;
+     *  see TS 23.040, 9.2.3.15 for description of other possible values.
+     */
+    private int mStatus;
+
+    /**
+     *  TP-Status - status of a previously submitted SMS.
+     *  This field is true iff the message is a SMS-STATUS-REPORT message.
+     */
+    private boolean mIsStatusReportMessage = false;
+
+    private int mVoiceMailCount = 0;
+
+    public static class SubmitPdu extends SubmitPduBase {
+    }
+
+    /**
+     * Create an SmsMessage from a raw PDU.
+     */
+    public static SmsMessage createFromPdu(byte[] pdu) {
+        try {
+            SmsMessage msg = new SmsMessage();
+            msg.parsePdu(pdu);
+            return msg;
+        } catch (RuntimeException ex) {
+            Rlog.e(LOG_TAG, "SMS PDU parsing failed: ", ex);
+            return null;
+        } catch (OutOfMemoryError e) {
+            Rlog.e(LOG_TAG, "SMS PDU parsing failed with out of memory: ", e);
+            return null;
+        }
+    }
+
+    /**
+     * 3GPP TS 23.040 9.2.3.9 specifies that Type Zero messages are indicated
+     * by TP_PID field set to value 0x40
+     */
+    public boolean isTypeZero() {
+        return (mProtocolIdentifier == 0x40);
+    }
+
+    /**
+     * TS 27.005 3.4.1 lines[0] and lines[1] are the two lines read from the
+     * +CMT unsolicited response (PDU mode, of course)
+     *  +CMT: [&lt;alpha>],<length><CR><LF><pdu>
+     *
+     * Only public for debugging
+     *
+     * {@hide}
+     */
+    public static SmsMessage newFromCMT(byte[] pdu) {
+        try {
+            SmsMessage msg = new SmsMessage();
+            msg.parsePdu(pdu);
+            return msg;
+        } catch (RuntimeException ex) {
+            Rlog.e(LOG_TAG, "SMS PDU parsing failed: ", ex);
+            return null;
+        }
+    }
+
+    /** @hide */
+    public static SmsMessage newFromCDS(byte[] pdu) {
+        try {
+            SmsMessage msg = new SmsMessage();
+            msg.parsePdu(pdu);
+            return msg;
+        } catch (RuntimeException ex) {
+            Rlog.e(LOG_TAG, "CDS SMS PDU parsing failed: ", ex);
+            return null;
+        }
+    }
+
+    /**
+     * Create an SmsMessage from an SMS EF record.
+     *
+     * @param index Index of SMS record. This should be index in ArrayList
+     *              returned by SmsManager.getAllMessagesFromSim + 1.
+     * @param data Record data.
+     * @return An SmsMessage representing the record.
+     *
+     * @hide
+     */
+    public static SmsMessage createFromEfRecord(int index, byte[] data) {
+        try {
+            SmsMessage msg = new SmsMessage();
+
+            msg.mIndexOnIcc = index;
+
+            // First byte is status: RECEIVED_READ, RECEIVED_UNREAD, STORED_SENT,
+            // or STORED_UNSENT
+            // See TS 51.011 10.5.3
+            if ((data[0] & 1) == 0) {
+                Rlog.w(LOG_TAG,
+                        "SMS parsing failed: Trying to parse a free record");
+                return null;
+            } else {
+                msg.mStatusOnIcc = data[0] & 0x07;
+            }
+
+            int size = data.length - 1;
+
+            // Note: Data may include trailing FF's.  That's OK; message
+            // should still parse correctly.
+            byte[] pdu = new byte[size];
+            System.arraycopy(data, 1, pdu, 0, size);
+            msg.parsePdu(pdu);
+            return msg;
+        } catch (RuntimeException ex) {
+            Rlog.e(LOG_TAG, "SMS PDU parsing failed: ", ex);
+            return null;
+        }
+    }
+
+    /**
+     * Get the TP-Layer-Length for the given SMS-SUBMIT PDU Basically, the
+     * length in bytes (not hex chars) less the SMSC header
+     */
+    public static int getTPLayerLengthForPDU(String pdu) {
+        int len = pdu.length() / 2;
+        int smscLen = Integer.parseInt(pdu.substring(0, 2), 16);
+
+        return len - smscLen - 1;
+    }
+
+    /**
+     * Get an SMS-SUBMIT PDU for a destination address and a message
+     *
+     * @param scAddress Service Centre address.  Null means use default.
+     * @return a <code>SubmitPdu</code> containing the encoded SC
+     *         address, if applicable, and the encoded message.
+     *         Returns null on encode error.
+     * @hide
+     */
+    public static SubmitPdu getSubmitPdu(String scAddress,
+            String destinationAddress, String message,
+            boolean statusReportRequested, byte[] header) {
+        return getSubmitPdu(scAddress, destinationAddress, message, statusReportRequested, header,
+                ENCODING_UNKNOWN, 0, 0);
+    }
+
+
+    /**
+     * Get an SMS-SUBMIT PDU for a destination address and a message using the
+     * specified encoding.
+     *
+     * @param scAddress Service Centre address.  Null means use default.
+     * @param encoding Encoding defined by constants in
+     *        com.android.internal.telephony.SmsConstants.ENCODING_*
+     * @param languageTable
+     * @param languageShiftTable
+     * @return a <code>SubmitPdu</code> containing the encoded SC
+     *         address, if applicable, and the encoded message.
+     *         Returns null on encode error.
+     * @hide
+     */
+    public static SubmitPdu getSubmitPdu(String scAddress,
+            String destinationAddress, String message,
+            boolean statusReportRequested, byte[] header, int encoding,
+            int languageTable, int languageShiftTable) {
+
+        // Perform null parameter checks.
+        if (message == null || destinationAddress == null) {
+            return null;
+        }
+
+        if (encoding == ENCODING_UNKNOWN) {
+            // Find the best encoding to use
+            TextEncodingDetails ted = calculateLength(message, false);
+            encoding = ted.codeUnitSize;
+            languageTable = ted.languageTable;
+            languageShiftTable = ted.languageShiftTable;
+
+            if (encoding == ENCODING_7BIT &&
+                    (languageTable != 0 || languageShiftTable != 0)) {
+                if (header != null) {
+                    SmsHeader smsHeader = SmsHeader.fromByteArray(header);
+                    if (smsHeader.languageTable != languageTable
+                            || smsHeader.languageShiftTable != languageShiftTable) {
+                        Rlog.w(LOG_TAG, "Updating language table in SMS header: "
+                                + smsHeader.languageTable + " -> " + languageTable + ", "
+                                + smsHeader.languageShiftTable + " -> " + languageShiftTable);
+                        smsHeader.languageTable = languageTable;
+                        smsHeader.languageShiftTable = languageShiftTable;
+                        header = SmsHeader.toByteArray(smsHeader);
+                    }
+                } else {
+                    SmsHeader smsHeader = new SmsHeader();
+                    smsHeader.languageTable = languageTable;
+                    smsHeader.languageShiftTable = languageShiftTable;
+                    header = SmsHeader.toByteArray(smsHeader);
+                }
+            }
+        }
+
+        SubmitPdu ret = new SubmitPdu();
+        // MTI = SMS-SUBMIT, UDHI = header != null
+        byte mtiByte = (byte)(0x01 | (header != null ? 0x40 : 0x00));
+        ByteArrayOutputStream bo = getSubmitPduHead(
+                scAddress, destinationAddress, mtiByte,
+                statusReportRequested, ret);
+
+        // User Data (and length)
+        byte[] userData;
+        try {
+            if (encoding == ENCODING_7BIT) {
+                userData = GsmAlphabet.stringToGsm7BitPackedWithHeader(message, header,
+                        languageTable, languageShiftTable);
+            } else { //assume UCS-2
+                try {
+                    userData = encodeUCS2(message, header);
+                } catch(UnsupportedEncodingException uex) {
+                    Rlog.e(LOG_TAG,
+                            "Implausible UnsupportedEncodingException ",
+                            uex);
+                    return null;
+                }
+            }
+        } catch (EncodeException ex) {
+            // Encoding to the 7-bit alphabet failed. Let's see if we can
+            // send it as a UCS-2 encoded message
+            try {
+                userData = encodeUCS2(message, header);
+                encoding = ENCODING_16BIT;
+            } catch(UnsupportedEncodingException uex) {
+                Rlog.e(LOG_TAG,
+                        "Implausible UnsupportedEncodingException ",
+                        uex);
+                return null;
+            }
+        }
+
+        if (encoding == ENCODING_7BIT) {
+            if ((0xff & userData[0]) > MAX_USER_DATA_SEPTETS) {
+                // Message too long
+                Rlog.e(LOG_TAG, "Message too long (" + (0xff & userData[0]) + " septets)");
+                return null;
+            }
+            // TP-Data-Coding-Scheme
+            // Default encoding, uncompressed
+            // To test writing messages to the SIM card, change this value 0x00
+            // to 0x12, which means "bits 1 and 0 contain message class, and the
+            // class is 2". Note that this takes effect for the sender. In other
+            // words, messages sent by the phone with this change will end up on
+            // the receiver's SIM card. You can then send messages to yourself
+            // (on a phone with this change) and they'll end up on the SIM card.
+            bo.write(0x00);
+        } else { // assume UCS-2
+            if ((0xff & userData[0]) > MAX_USER_DATA_BYTES) {
+                // Message too long
+                Rlog.e(LOG_TAG, "Message too long (" + (0xff & userData[0]) + " bytes)");
+                return null;
+            }
+            // TP-Data-Coding-Scheme
+            // UCS-2 encoding, uncompressed
+            bo.write(0x08);
+        }
+
+        // (no TP-Validity-Period)
+        bo.write(userData, 0, userData.length);
+        ret.encodedMessage = bo.toByteArray();
+        return ret;
+    }
+
+    /**
+     * Packs header and UCS-2 encoded message. Includes TP-UDL & TP-UDHL if necessary
+     *
+     * @return encoded message as UCS2
+     * @throws UnsupportedEncodingException
+     */
+    private static byte[] encodeUCS2(String message, byte[] header)
+        throws UnsupportedEncodingException {
+        byte[] userData, textPart;
+        textPart = message.getBytes("utf-16be");
+
+        if (header != null) {
+            // Need 1 byte for UDHL
+            userData = new byte[header.length + textPart.length + 1];
+
+            userData[0] = (byte)header.length;
+            System.arraycopy(header, 0, userData, 1, header.length);
+            System.arraycopy(textPart, 0, userData, header.length + 1, textPart.length);
+        }
+        else {
+            userData = textPart;
+        }
+        byte[] ret = new byte[userData.length+1];
+        ret[0] = (byte) (userData.length & 0xff );
+        System.arraycopy(userData, 0, ret, 1, userData.length);
+        return ret;
+    }
+
+    /**
+     * Get an SMS-SUBMIT PDU for a destination address and a message
+     *
+     * @param scAddress Service Centre address.  Null means use default.
+     * @return a <code>SubmitPdu</code> containing the encoded SC
+     *         address, if applicable, and the encoded message.
+     *         Returns null on encode error.
+     */
+    public static SubmitPdu getSubmitPdu(String scAddress,
+            String destinationAddress, String message,
+            boolean statusReportRequested) {
+
+        return getSubmitPdu(scAddress, destinationAddress, message, statusReportRequested, null);
+    }
+
+    /**
+     * Get an SMS-SUBMIT PDU for a data message to a destination address &amp; port
+     *
+     * @param scAddress Service Centre address. null == use default
+     * @param destinationAddress the address of the destination for the message
+     * @param destinationPort the port to deliver the message to at the
+     *        destination
+     * @param data the data for the message
+     * @return a <code>SubmitPdu</code> containing the encoded SC
+     *         address, if applicable, and the encoded message.
+     *         Returns null on encode error.
+     */
+    public static SubmitPdu getSubmitPdu(String scAddress,
+            String destinationAddress, int destinationPort, byte[] data,
+            boolean statusReportRequested) {
+
+        SmsHeader.PortAddrs portAddrs = new SmsHeader.PortAddrs();
+        portAddrs.destPort = destinationPort;
+        portAddrs.origPort = 0;
+        portAddrs.areEightBits = false;
+
+        SmsHeader smsHeader = new SmsHeader();
+        smsHeader.portAddrs = portAddrs;
+
+        byte[] smsHeaderData = SmsHeader.toByteArray(smsHeader);
+
+        if ((data.length + smsHeaderData.length + 1) > MAX_USER_DATA_BYTES) {
+            Rlog.e(LOG_TAG, "SMS data message may only contain "
+                    + (MAX_USER_DATA_BYTES - smsHeaderData.length - 1) + " bytes");
+            return null;
+        }
+
+        SubmitPdu ret = new SubmitPdu();
+        ByteArrayOutputStream bo = getSubmitPduHead(
+                scAddress, destinationAddress, (byte) 0x41, // MTI = SMS-SUBMIT,
+                                                            // TP-UDHI = true
+                statusReportRequested, ret);
+
+        // TP-Data-Coding-Scheme
+        // No class, 8 bit data
+        bo.write(0x04);
+
+        // (no TP-Validity-Period)
+
+        // Total size
+        bo.write(data.length + smsHeaderData.length + 1);
+
+        // User data header
+        bo.write(smsHeaderData.length);
+        bo.write(smsHeaderData, 0, smsHeaderData.length);
+
+        // User data
+        bo.write(data, 0, data.length);
+
+        ret.encodedMessage = bo.toByteArray();
+        return ret;
+    }
+
+    /**
+     * Create the beginning of a SUBMIT PDU.  This is the part of the
+     * SUBMIT PDU that is common to the two versions of {@link #getSubmitPdu},
+     * one of which takes a byte array and the other of which takes a
+     * <code>String</code>.
+     *
+     * @param scAddress Service Centre address. null == use default
+     * @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
+     */
+    private static ByteArrayOutputStream getSubmitPduHead(
+            String scAddress, String destinationAddress, byte mtiByte,
+            boolean statusReportRequested, SubmitPdu ret) {
+        ByteArrayOutputStream bo = new ByteArrayOutputStream(
+                MAX_USER_DATA_BYTES + 40);
+
+        // SMSC address with length octet, or 0
+        if (scAddress == null) {
+            ret.encodedScAddress = null;
+        } else {
+            ret.encodedScAddress = PhoneNumberUtils.networkPortionToCalledPartyBCDWithLength(
+                    scAddress);
+        }
+
+        // TP-Message-Type-Indicator (and friends)
+        if (statusReportRequested) {
+            // Set TP-Status-Report-Request bit.
+            mtiByte |= 0x20;
+            if (VDBG) Rlog.d(LOG_TAG, "SMS status report requested");
+        }
+        bo.write(mtiByte);
+
+        // space for TP-Message-Reference
+        bo.write(0);
+
+        byte[] daBytes;
+
+        daBytes = PhoneNumberUtils.networkPortionToCalledPartyBCD(destinationAddress);
+
+        // destination address length in BCD digits, ignoring TON byte and pad
+        // TODO Should be better.
+        bo.write((daBytes.length - 1) * 2
+                - ((daBytes[daBytes.length - 1] & 0xf0) == 0xf0 ? 1 : 0));
+
+        // destination address
+        bo.write(daBytes, 0, daBytes.length);
+
+        // TP-Protocol-Identifier
+        bo.write(0);
+        return bo;
+    }
+
+    private static class PduParser {
+        byte mPdu[];
+        int mCur;
+        SmsHeader mUserDataHeader;
+        byte[] mUserData;
+        int mUserDataSeptetPadding;
+
+        PduParser(byte[] pdu) {
+            mPdu = pdu;
+            mCur = 0;
+            mUserDataSeptetPadding = 0;
+        }
+
+        /**
+         * Parse and return the SC address prepended to SMS messages coming via
+         * the TS 27.005 / AT interface.  Returns null on invalid address
+         */
+        String getSCAddress() {
+            int len;
+            String ret;
+
+            // length of SC Address
+            len = getByte();
+
+            if (len == 0) {
+                // no SC address
+                ret = null;
+            } else {
+                // SC address
+                try {
+                    ret = PhoneNumberUtils
+                            .calledPartyBCDToString(mPdu, mCur, len);
+                } catch (RuntimeException tr) {
+                    Rlog.d(LOG_TAG, "invalid SC address: ", tr);
+                    ret = null;
+                }
+            }
+
+            mCur += len;
+
+            return ret;
+        }
+
+        /**
+         * returns non-sign-extended byte value
+         */
+        int getByte() {
+            return mPdu[mCur++] & 0xff;
+        }
+
+        /**
+         * Any address except the SC address (eg, originating address) See TS
+         * 23.040 9.1.2.5
+         */
+        GsmSmsAddress getAddress() {
+            GsmSmsAddress ret;
+
+            // "The Address-Length field is an integer representation of
+            // the number field, i.e. excludes any semi-octet containing only
+            // fill bits."
+            // The TOA field is not included as part of this
+            int addressLength = mPdu[mCur] & 0xff;
+            int lengthBytes = 2 + (addressLength + 1) / 2;
+
+            try {
+                ret = new GsmSmsAddress(mPdu, mCur, lengthBytes);
+            } catch (ParseException e) {
+                ret = null;
+                //This is caught by createFromPdu(byte[] pdu)
+                throw new RuntimeException(e.getMessage());
+            }
+
+            mCur += lengthBytes;
+
+            return ret;
+        }
+
+        /**
+         * Parses an SC timestamp and returns a currentTimeMillis()-style
+         * timestamp
+         */
+
+        long getSCTimestampMillis() {
+            // TP-Service-Centre-Time-Stamp
+            int year = IccUtils.gsmBcdByteToInt(mPdu[mCur++]);
+            int month = IccUtils.gsmBcdByteToInt(mPdu[mCur++]);
+            int day = IccUtils.gsmBcdByteToInt(mPdu[mCur++]);
+            int hour = IccUtils.gsmBcdByteToInt(mPdu[mCur++]);
+            int minute = IccUtils.gsmBcdByteToInt(mPdu[mCur++]);
+            int second = IccUtils.gsmBcdByteToInt(mPdu[mCur++]);
+
+            // For the timezone, the most significant bit of the
+            // least significant nibble is the sign byte
+            // (meaning the max range of this field is 79 quarter-hours,
+            // which is more than enough)
+
+            byte tzByte = mPdu[mCur++];
+
+            // Mask out sign bit.
+            int timezoneOffset = IccUtils.gsmBcdByteToInt((byte) (tzByte & (~0x08)));
+
+            timezoneOffset = ((tzByte & 0x08) == 0) ? timezoneOffset : -timezoneOffset;
+
+            Time time = new Time(Time.TIMEZONE_UTC);
+
+            // It's 2006.  Should I really support years < 2000?
+            time.year = year >= 90 ? year + 1900 : year + 2000;
+            time.month = month - 1;
+            time.monthDay = day;
+            time.hour = hour;
+            time.minute = minute;
+            time.second = second;
+
+            // Timezone offset is in quarter hours.
+            return time.toMillis(true) - (timezoneOffset * 15 * 60 * 1000);
+        }
+
+        /**
+         * Pulls the user data out of the PDU, and separates the payload from
+         * the header if there is one.
+         *
+         * @param hasUserDataHeader true if there is a user data header
+         * @param dataInSeptets true if the data payload is in septets instead
+         *  of octets
+         * @return the number of septets or octets in the user data payload
+         */
+        int constructUserData(boolean hasUserDataHeader, boolean dataInSeptets) {
+            int offset = mCur;
+            int userDataLength = mPdu[offset++] & 0xff;
+            int headerSeptets = 0;
+            int userDataHeaderLength = 0;
+
+            if (hasUserDataHeader) {
+                userDataHeaderLength = mPdu[offset++] & 0xff;
+
+                byte[] udh = new byte[userDataHeaderLength];
+                System.arraycopy(mPdu, offset, udh, 0, userDataHeaderLength);
+                mUserDataHeader = SmsHeader.fromByteArray(udh);
+                offset += userDataHeaderLength;
+
+                int headerBits = (userDataHeaderLength + 1) * 8;
+                headerSeptets = headerBits / 7;
+                headerSeptets += (headerBits % 7) > 0 ? 1 : 0;
+                mUserDataSeptetPadding = (headerSeptets * 7) - headerBits;
+            }
+
+            int bufferLen;
+            if (dataInSeptets) {
+                /*
+                 * Here we just create the user data length to be the remainder of
+                 * the pdu minus the user data header, since userDataLength means
+                 * the number of uncompressed septets.
+                 */
+                bufferLen = mPdu.length - offset;
+            } else {
+                /*
+                 * userDataLength is the count of octets, so just subtract the
+                 * user data header.
+                 */
+                bufferLen = userDataLength - (hasUserDataHeader ? (userDataHeaderLength + 1) : 0);
+                if (bufferLen < 0) {
+                    bufferLen = 0;
+                }
+            }
+
+            mUserData = new byte[bufferLen];
+            System.arraycopy(mPdu, offset, mUserData, 0, mUserData.length);
+            mCur = offset;
+
+            if (dataInSeptets) {
+                // Return the number of septets
+                int count = userDataLength - headerSeptets;
+                // If count < 0, return 0 (means UDL was probably incorrect)
+                return count < 0 ? 0 : count;
+            } else {
+                // Return the number of octets
+                return mUserData.length;
+            }
+        }
+
+        /**
+         * Returns the user data payload, not including the headers
+         *
+         * @return the user data payload, not including the headers
+         */
+        byte[] getUserData() {
+            return mUserData;
+        }
+
+        /**
+         * Returns an object representing the user data headers
+         *
+         * {@hide}
+         */
+        SmsHeader getUserDataHeader() {
+            return mUserDataHeader;
+        }
+
+        /**
+         * Interprets the user data payload as packed GSM 7bit characters, and
+         * decodes them into a String.
+         *
+         * @param septetCount the number of septets in the user data payload
+         * @return a String with the decoded characters
+         */
+        String getUserDataGSM7Bit(int septetCount, int languageTable,
+                int languageShiftTable) {
+            String ret;
+
+            ret = GsmAlphabet.gsm7BitPackedToString(mPdu, mCur, septetCount,
+                    mUserDataSeptetPadding, languageTable, languageShiftTable);
+
+            mCur += (septetCount * 7) / 8;
+
+            return ret;
+        }
+
+        /**
+         * Interprets the user data payload as pack GSM 8-bit (a GSM alphabet string that's
+         * stored in 8-bit unpacked format) characters, and decodes them into a String.
+         *
+         * @param byteCount the number of byest in the user data payload
+         * @return a String with the decoded characters
+         */
+        String getUserDataGSM8bit(int byteCount) {
+            String ret;
+
+            ret = GsmAlphabet.gsm8BitUnpackedToString(mPdu, mCur, byteCount);
+
+            mCur += byteCount;
+
+            return ret;
+        }
+
+        /**
+         * Interprets the user data payload as UCS2 characters, and
+         * decodes them into a String.
+         *
+         * @param byteCount the number of bytes in the user data payload
+         * @return a String with the decoded characters
+         */
+        String getUserDataUCS2(int byteCount) {
+            String ret;
+
+            try {
+                ret = new String(mPdu, mCur, byteCount, "utf-16");
+            } catch (UnsupportedEncodingException ex) {
+                ret = "";
+                Rlog.e(LOG_TAG, "implausible UnsupportedEncodingException", ex);
+            }
+
+            mCur += byteCount;
+            return ret;
+        }
+
+        /**
+         * Interprets the user data payload as KSC-5601 characters, and
+         * decodes them into a String.
+         *
+         * @param byteCount the number of bytes in the user data payload
+         * @return a String with the decoded characters
+         */
+        String getUserDataKSC5601(int byteCount) {
+            String ret;
+
+            try {
+                ret = new String(mPdu, mCur, byteCount, "KSC5601");
+            } catch (UnsupportedEncodingException ex) {
+                ret = "";
+                Rlog.e(LOG_TAG, "implausible UnsupportedEncodingException", ex);
+            }
+
+            mCur += byteCount;
+            return ret;
+        }
+
+        boolean moreDataPresent() {
+            return (mPdu.length > mCur);
+        }
+    }
+
+    /**
+     * Calculates the number of SMS's required to encode the message body and
+     * the number of characters remaining until the next message.
+     *
+     * @param msgBody the message to encode
+     * @param use7bitOnly ignore (but still count) illegal characters if true
+     * @return TextEncodingDetails
+     */
+    public static TextEncodingDetails calculateLength(CharSequence msgBody,
+            boolean use7bitOnly) {
+        CharSequence newMsgBody = null;
+        Resources r = Resources.getSystem();
+        if (r.getBoolean(com.android.internal.R.bool.config_sms_force_7bit_encoding)) {
+            newMsgBody  = Sms7BitEncodingTranslator.translate(msgBody);
+        }
+        if (TextUtils.isEmpty(newMsgBody)) {
+            newMsgBody = msgBody;
+        }
+        TextEncodingDetails ted = GsmAlphabet.countGsmSeptets(newMsgBody, use7bitOnly);
+        if (ted == null) {
+            return SmsMessageBase.calcUnicodeEncodingDetails(newMsgBody);
+        }
+        return ted;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public int getProtocolIdentifier() {
+        return mProtocolIdentifier;
+    }
+
+    /**
+     * Returns the TP-Data-Coding-Scheme byte, for acknowledgement of SMS-PP download messages.
+     * @return the TP-DCS field of the SMS header
+     */
+    int getDataCodingScheme() {
+        return mDataCodingScheme;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean isReplace() {
+        return (mProtocolIdentifier & 0xc0) == 0x40
+                && (mProtocolIdentifier & 0x3f) > 0
+                && (mProtocolIdentifier & 0x3f) < 8;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean isCphsMwiMessage() {
+        return ((GsmSmsAddress) mOriginatingAddress).isCphsVoiceMessageClear()
+                || ((GsmSmsAddress) mOriginatingAddress).isCphsVoiceMessageSet();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean isMWIClearMessage() {
+        if (mIsMwi && !mMwiSense) {
+            return true;
+        }
+
+        return mOriginatingAddress != null
+                && ((GsmSmsAddress) mOriginatingAddress).isCphsVoiceMessageClear();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean isMWISetMessage() {
+        if (mIsMwi && mMwiSense) {
+            return true;
+        }
+
+        return mOriginatingAddress != null
+                && ((GsmSmsAddress) mOriginatingAddress).isCphsVoiceMessageSet();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean isMwiDontStore() {
+        if (mIsMwi && mMwiDontStore) {
+            return true;
+        }
+
+        if (isCphsMwiMessage()) {
+            // See CPHS 4.2 Section B.4.2.1
+            // If the user data is a single space char, do not store
+            // the message. Otherwise, store and display as usual
+            if (" ".equals(getMessageBody())) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public int getStatus() {
+        return mStatus;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean isStatusReportMessage() {
+        return mIsStatusReportMessage;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean isReplyPathPresent() {
+        return mReplyPathPresent;
+    }
+
+    /**
+     * TS 27.005 3.1, &lt;pdu&gt; definition "In the case of SMS: 3GPP TS 24.011 [6]
+     * SC address followed by 3GPP TS 23.040 [3] TPDU in hexadecimal format:
+     * ME/TA converts each octet of TP data unit into two IRA character long
+     * hex number (e.g. octet with integer value 42 is presented to TE as two
+     * characters 2A (IRA 50 and 65))" ...in the case of cell broadcast,
+     * something else...
+     */
+    private void parsePdu(byte[] pdu) {
+        mPdu = pdu;
+        // Rlog.d(LOG_TAG, "raw sms message:");
+        // Rlog.d(LOG_TAG, s);
+
+        PduParser p = new PduParser(pdu);
+
+        mScAddress = p.getSCAddress();
+
+        if (mScAddress != null) {
+            if (VDBG) Rlog.d(LOG_TAG, "SMS SC address: " + mScAddress);
+        }
+
+        // TODO(mkf) support reply path, user data header indicator
+
+        // TP-Message-Type-Indicator
+        // 9.2.3
+        int firstByte = p.getByte();
+
+        mMti = firstByte & 0x3;
+        switch (mMti) {
+        // TP-Message-Type-Indicator
+        // 9.2.3
+        case 0:
+        case 3: //GSM 03.40 9.2.3.1: MTI == 3 is Reserved.
+                //This should be processed in the same way as MTI == 0 (Deliver)
+            parseSmsDeliver(p, firstByte);
+            break;
+        case 1:
+            parseSmsSubmit(p, firstByte);
+            break;
+        case 2:
+            parseSmsStatusReport(p, firstByte);
+            break;
+        default:
+            // TODO(mkf) the rest of these
+            throw new RuntimeException("Unsupported message type");
+        }
+    }
+
+    /**
+     * Parses a SMS-STATUS-REPORT message.
+     *
+     * @param p A PduParser, cued past the first byte.
+     * @param firstByte The first byte of the PDU, which contains MTI, etc.
+     */
+    private void parseSmsStatusReport(PduParser p, int firstByte) {
+        mIsStatusReportMessage = true;
+
+        // TP-Message-Reference
+        mMessageRef = p.getByte();
+        // TP-Recipient-Address
+        mRecipientAddress = p.getAddress();
+        // TP-Service-Centre-Time-Stamp
+        mScTimeMillis = p.getSCTimestampMillis();
+        p.getSCTimestampMillis();
+        // TP-Status
+        mStatus = p.getByte();
+
+        // The following are optional fields that may or may not be present.
+        if (p.moreDataPresent()) {
+            // TP-Parameter-Indicator
+            int extraParams = p.getByte();
+            int moreExtraParams = extraParams;
+            while ((moreExtraParams & 0x80) != 0) {
+                // We only know how to parse a few extra parameters, all
+                // indicated in the first TP-PI octet, so skip over any
+                // additional TP-PI octets.
+                moreExtraParams = p.getByte();
+            }
+            // As per 3GPP 23.040 section 9.2.3.27 TP-Parameter-Indicator,
+            // only process the byte if the reserved bits (bits3 to 6) are zero.
+            if ((extraParams & 0x78) == 0) {
+                // TP-Protocol-Identifier
+                if ((extraParams & 0x01) != 0) {
+                    mProtocolIdentifier = p.getByte();
+                }
+                // TP-Data-Coding-Scheme
+                if ((extraParams & 0x02) != 0) {
+                    mDataCodingScheme = p.getByte();
+                }
+                // TP-User-Data-Length (implies existence of TP-User-Data)
+                if ((extraParams & 0x04) != 0) {
+                    boolean hasUserDataHeader = (firstByte & 0x40) == 0x40;
+                    parseUserData(p, hasUserDataHeader);
+                }
+            }
+        }
+    }
+
+    private void parseSmsDeliver(PduParser p, int firstByte) {
+        mReplyPathPresent = (firstByte & 0x80) == 0x80;
+
+        mOriginatingAddress = p.getAddress();
+
+        if (mOriginatingAddress != null) {
+            if (VDBG) Rlog.v(LOG_TAG, "SMS originating address: "
+                    + mOriginatingAddress.address);
+        }
+
+        // TP-Protocol-Identifier (TP-PID)
+        // TS 23.040 9.2.3.9
+        mProtocolIdentifier = p.getByte();
+
+        // TP-Data-Coding-Scheme
+        // see TS 23.038
+        mDataCodingScheme = p.getByte();
+
+        if (VDBG) {
+            Rlog.v(LOG_TAG, "SMS TP-PID:" + mProtocolIdentifier
+                    + " data coding scheme: " + mDataCodingScheme);
+        }
+
+        mScTimeMillis = p.getSCTimestampMillis();
+
+        if (VDBG) Rlog.d(LOG_TAG, "SMS SC timestamp: " + mScTimeMillis);
+
+        boolean hasUserDataHeader = (firstByte & 0x40) == 0x40;
+
+        parseUserData(p, hasUserDataHeader);
+    }
+
+    /**
+     * Parses a SMS-SUBMIT message.
+     *
+     * @param p A PduParser, cued past the first byte.
+     * @param firstByte The first byte of the PDU, which contains MTI, etc.
+     */
+    private void parseSmsSubmit(PduParser p, int firstByte) {
+        mReplyPathPresent = (firstByte & 0x80) == 0x80;
+
+        // TP-MR (TP-Message Reference)
+        mMessageRef = p.getByte();
+
+        mRecipientAddress = p.getAddress();
+
+        if (mRecipientAddress != null) {
+            if (VDBG) Rlog.v(LOG_TAG, "SMS recipient address: " + mRecipientAddress.address);
+        }
+
+        // TP-Protocol-Identifier (TP-PID)
+        // TS 23.040 9.2.3.9
+        mProtocolIdentifier = p.getByte();
+
+        // TP-Data-Coding-Scheme
+        // see TS 23.038
+        mDataCodingScheme = p.getByte();
+
+        if (VDBG) {
+            Rlog.v(LOG_TAG, "SMS TP-PID:" + mProtocolIdentifier
+                    + " data coding scheme: " + mDataCodingScheme);
+        }
+
+        // TP-Validity-Period-Format
+        int validityPeriodLength = 0;
+        int validityPeriodFormat = ((firstByte>>3) & 0x3);
+        if (0x0 == validityPeriodFormat) /* 00, TP-VP field not present*/
+        {
+            validityPeriodLength = 0;
+        }
+        else if (0x2 == validityPeriodFormat) /* 10, TP-VP: relative format*/
+        {
+            validityPeriodLength = 1;
+        }
+        else /* other case, 11 or 01, TP-VP: absolute or enhanced format*/
+        {
+            validityPeriodLength = 7;
+        }
+
+        // TP-Validity-Period is not used on phone, so just ignore it for now.
+        while (validityPeriodLength-- > 0)
+        {
+            p.getByte();
+        }
+
+        boolean hasUserDataHeader = (firstByte & 0x40) == 0x40;
+
+        parseUserData(p, hasUserDataHeader);
+    }
+
+    /**
+     * Parses the User Data of an SMS.
+     *
+     * @param p The current PduParser.
+     * @param hasUserDataHeader Indicates whether a header is present in the
+     *                          User Data.
+     */
+    private void parseUserData(PduParser p, boolean hasUserDataHeader) {
+        boolean hasMessageClass = false;
+        boolean userDataCompressed = false;
+
+        int encodingType = ENCODING_UNKNOWN;
+
+        // Look up the data encoding scheme
+        if ((mDataCodingScheme & 0x80) == 0) {
+            userDataCompressed = (0 != (mDataCodingScheme & 0x20));
+            hasMessageClass = (0 != (mDataCodingScheme & 0x10));
+
+            if (userDataCompressed) {
+                Rlog.w(LOG_TAG, "4 - Unsupported SMS data coding scheme "
+                        + "(compression) " + (mDataCodingScheme & 0xff));
+            } else {
+                switch ((mDataCodingScheme >> 2) & 0x3) {
+                case 0: // GSM 7 bit default alphabet
+                    encodingType = ENCODING_7BIT;
+                    break;
+
+                case 2: // UCS 2 (16bit)
+                    encodingType = ENCODING_16BIT;
+                    break;
+
+                case 1: // 8 bit data
+                    //Support decoding the user data payload as pack GSM 8-bit (a GSM alphabet string
+                    //that's stored in 8-bit unpacked format) characters.
+                    Resources r = Resources.getSystem();
+                    if (r.getBoolean(com.android.internal.
+                            R.bool.config_sms_decode_gsm_8bit_data)) {
+                        encodingType = ENCODING_8BIT;
+                        break;
+                    }
+
+                case 3: // reserved
+                    Rlog.w(LOG_TAG, "1 - Unsupported SMS data coding scheme "
+                            + (mDataCodingScheme & 0xff));
+                    encodingType = ENCODING_8BIT;
+                    break;
+                }
+            }
+        } else if ((mDataCodingScheme & 0xf0) == 0xf0) {
+            hasMessageClass = true;
+            userDataCompressed = false;
+
+            if (0 == (mDataCodingScheme & 0x04)) {
+                // GSM 7 bit default alphabet
+                encodingType = ENCODING_7BIT;
+            } else {
+                // 8 bit data
+                encodingType = ENCODING_8BIT;
+            }
+        } else if ((mDataCodingScheme & 0xF0) == 0xC0
+                || (mDataCodingScheme & 0xF0) == 0xD0
+                || (mDataCodingScheme & 0xF0) == 0xE0) {
+            // 3GPP TS 23.038 V7.0.0 (2006-03) section 4
+
+            // 0xC0 == 7 bit, don't store
+            // 0xD0 == 7 bit, store
+            // 0xE0 == UCS-2, store
+
+            if ((mDataCodingScheme & 0xF0) == 0xE0) {
+                encodingType = ENCODING_16BIT;
+            } else {
+                encodingType = ENCODING_7BIT;
+            }
+
+            userDataCompressed = false;
+            boolean active = ((mDataCodingScheme & 0x08) == 0x08);
+            // bit 0x04 reserved
+
+            // VM - If TP-UDH is present, these values will be overwritten
+            if ((mDataCodingScheme & 0x03) == 0x00) {
+                mIsMwi = true; /* Indicates vmail */
+                mMwiSense = active;/* Indicates vmail notification set/clear */
+                mMwiDontStore = ((mDataCodingScheme & 0xF0) == 0xC0);
+
+                /* Set voice mail count based on notification bit */
+                if (active == true) {
+                    mVoiceMailCount = -1; // unknown number of messages waiting
+                } else {
+                    mVoiceMailCount = 0; // no unread messages
+                }
+
+                Rlog.w(LOG_TAG, "MWI in DCS for Vmail. DCS = "
+                        + (mDataCodingScheme & 0xff) + " Dont store = "
+                        + mMwiDontStore + " vmail count = " + mVoiceMailCount);
+
+            } else {
+                mIsMwi = false;
+                Rlog.w(LOG_TAG, "MWI in DCS for fax/email/other: "
+                        + (mDataCodingScheme & 0xff));
+            }
+        } else if ((mDataCodingScheme & 0xC0) == 0x80) {
+            // 3GPP TS 23.038 V7.0.0 (2006-03) section 4
+            // 0x80..0xBF == Reserved coding groups
+            if (mDataCodingScheme == 0x84) {
+                // This value used for KSC5601 by carriers in Korea.
+                encodingType = ENCODING_KSC5601;
+            } else {
+                Rlog.w(LOG_TAG, "5 - Unsupported SMS data coding scheme "
+                        + (mDataCodingScheme & 0xff));
+            }
+        } else {
+            Rlog.w(LOG_TAG, "3 - Unsupported SMS data coding scheme "
+                    + (mDataCodingScheme & 0xff));
+        }
+
+        // set both the user data and the user data header.
+        int count = p.constructUserData(hasUserDataHeader,
+                encodingType == ENCODING_7BIT);
+        this.mUserData = p.getUserData();
+        this.mUserDataHeader = p.getUserDataHeader();
+
+        /*
+         * Look for voice mail indication in TP_UDH TS23.040 9.2.3.24
+         * ieid = 1 (0x1) (SPECIAL_SMS_MSG_IND)
+         * ieidl =2 octets
+         * ieda msg_ind_type = 0x00 (voice mail; discard sms )or
+         *                   = 0x80 (voice mail; store sms)
+         * msg_count = 0x00 ..0xFF
+         */
+        if (hasUserDataHeader && (mUserDataHeader.specialSmsMsgList.size() != 0)) {
+            for (SmsHeader.SpecialSmsMsg msg : mUserDataHeader.specialSmsMsgList) {
+                int msgInd = msg.msgIndType & 0xff;
+                /*
+                 * TS 23.040 V6.8.1 Sec 9.2.3.24.2
+                 * bits 1 0 : basic message indication type
+                 * bits 4 3 2 : extended message indication type
+                 * bits 6 5 : Profile id bit 7 storage type
+                 */
+                if ((msgInd == 0) || (msgInd == 0x80)) {
+                    mIsMwi = true;
+                    if (msgInd == 0x80) {
+                        /* Store message because TP_UDH indicates so*/
+                        mMwiDontStore = false;
+                    } else if (mMwiDontStore == false) {
+                        /* Storage bit is not set by TP_UDH
+                         * Check for conflict
+                         * between message storage bit in TP_UDH
+                         * & DCS. The message shall be stored if either of
+                         * the one indicates so.
+                         * TS 23.040 V6.8.1 Sec 9.2.3.24.2
+                         */
+                        if (!((((mDataCodingScheme & 0xF0) == 0xD0)
+                               || ((mDataCodingScheme & 0xF0) == 0xE0))
+                               && ((mDataCodingScheme & 0x03) == 0x00))) {
+                            /* Even DCS did not have voice mail with Storage bit
+                             * 3GPP TS 23.038 V7.0.0 section 4
+                             * So clear this flag*/
+                            mMwiDontStore = true;
+                        }
+                    }
+
+                    mVoiceMailCount = msg.msgCount & 0xff;
+
+                    /*
+                     * In the event of a conflict between message count setting
+                     * and DCS then the Message Count in the TP-UDH shall
+                     * override the indication in the TP-DCS. Set voice mail
+                     * notification based on count in TP-UDH
+                     */
+                    if (mVoiceMailCount > 0)
+                        mMwiSense = true;
+                    else
+                        mMwiSense = false;
+
+                    Rlog.w(LOG_TAG, "MWI in TP-UDH for Vmail. Msg Ind = " + msgInd
+                            + " Dont store = " + mMwiDontStore + " Vmail count = "
+                            + mVoiceMailCount);
+
+                    /*
+                     * There can be only one IE for each type of message
+                     * indication in TP_UDH. In the event they are duplicated
+                     * last occurence will be used. Hence the for loop
+                     */
+                } else {
+                    Rlog.w(LOG_TAG, "TP_UDH fax/email/"
+                            + "extended msg/multisubscriber profile. Msg Ind = " + msgInd);
+                }
+            } // end of for
+        } // end of if UDH
+
+        switch (encodingType) {
+        case ENCODING_UNKNOWN:
+            mMessageBody = null;
+            break;
+
+        case ENCODING_8BIT:
+            //Support decoding the user data payload as pack GSM 8-bit (a GSM alphabet string
+            //that's stored in 8-bit unpacked format) characters.
+            Resources r = Resources.getSystem();
+            if (r.getBoolean(com.android.internal.
+                    R.bool.config_sms_decode_gsm_8bit_data)) {
+                mMessageBody = p.getUserDataGSM8bit(count);
+            } else {
+                mMessageBody = null;
+            }
+            break;
+
+        case ENCODING_7BIT:
+            mMessageBody = p.getUserDataGSM7Bit(count,
+                    hasUserDataHeader ? mUserDataHeader.languageTable : 0,
+                    hasUserDataHeader ? mUserDataHeader.languageShiftTable : 0);
+            break;
+
+        case ENCODING_16BIT:
+            mMessageBody = p.getUserDataUCS2(count);
+            break;
+
+        case ENCODING_KSC5601:
+            mMessageBody = p.getUserDataKSC5601(count);
+            break;
+        }
+
+        if (VDBG) Rlog.v(LOG_TAG, "SMS message body (raw): '" + mMessageBody + "'");
+
+        if (mMessageBody != null) {
+            parseMessageBody();
+        }
+
+        if (!hasMessageClass) {
+            messageClass = MessageClass.UNKNOWN;
+        } else {
+            switch (mDataCodingScheme & 0x3) {
+            case 0:
+                messageClass = MessageClass.CLASS_0;
+                break;
+            case 1:
+                messageClass = MessageClass.CLASS_1;
+                break;
+            case 2:
+                messageClass = MessageClass.CLASS_2;
+                break;
+            case 3:
+                messageClass = MessageClass.CLASS_3;
+                break;
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public MessageClass getMessageClass() {
+        return messageClass;
+    }
+
+    /**
+     * Returns true if this is a (U)SIM data download type SM.
+     * See 3GPP TS 31.111 section 9.1 and TS 23.040 section 9.2.3.9.
+     *
+     * @return true if this is a USIM data download message; false otherwise
+     */
+    boolean isUsimDataDownload() {
+        return messageClass == MessageClass.CLASS_2 &&
+                (mProtocolIdentifier == 0x7f || mProtocolIdentifier == 0x7c);
+    }
+
+    public int getNumOfVoicemails() {
+        /*
+         * Order of priority if multiple indications are present is 1.UDH,
+         *      2.DCS, 3.CPHS.
+         * Voice mail count if voice mail present indication is
+         * received
+         *  1. UDH (or both UDH & DCS): mVoiceMailCount = 0 to 0xff. Ref[TS 23. 040]
+         *  2. DCS only: count is unknown mVoiceMailCount= -1
+         *  3. CPHS only: count is unknown mVoiceMailCount = 0xff. Ref[GSM-BTR-1-4700]
+         * Voice mail clear, mVoiceMailCount = 0.
+         */
+        if ((!mIsMwi) && isCphsMwiMessage()) {
+            if (mOriginatingAddress != null
+                    && ((GsmSmsAddress) mOriginatingAddress).isCphsVoiceMessageSet()) {
+                mVoiceMailCount = 0xff;
+            } else {
+                mVoiceMailCount = 0;
+            }
+            Rlog.v(LOG_TAG, "CPHS voice mail message");
+        }
+        return mVoiceMailCount;
+    }
+}
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index d51d75e..29ba776 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -365,6 +365,12 @@
 
     /** @hide */
     @Override
+    public boolean isInstantApp(String packageName) {
+        throw new UnsupportedOperationException();
+    }
+
+    /** @hide */
+    @Override
     public int getInstantAppCookieMaxSize() {
         throw new UnsupportedOperationException();
     }
diff --git a/test-runner/src/android/test/suitebuilder/TestMethod.java b/test-runner/src/android/test/suitebuilder/TestMethod.java
index 08568d5..ae1db5e 100644
--- a/test-runner/src/android/test/suitebuilder/TestMethod.java
+++ b/test-runner/src/android/test/suitebuilder/TestMethod.java
@@ -26,7 +26,11 @@
 /**
  * Represents a test to be run. Can be constructed without instantiating the TestCase or even
  * loading the class.
+ *
+ * @deprecated New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
  */
+@Deprecated
 public class TestMethod {
 
     private final String enclosingClassname;
diff --git a/test-runner/src/android/test/suitebuilder/TestSuiteBuilder.java b/test-runner/src/android/test/suitebuilder/TestSuiteBuilder.java
index 8c89489..3b920cf 100644
--- a/test-runner/src/android/test/suitebuilder/TestSuiteBuilder.java
+++ b/test-runner/src/android/test/suitebuilder/TestSuiteBuilder.java
@@ -38,7 +38,11 @@
 /**
  * Build suites based on a combination of included packages, excluded packages,
  * and predicates that must be satisfied.
+ *
+ * @deprecated New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
  */
+@Deprecated
 public class TestSuiteBuilder {
 
     private Context context;
@@ -223,7 +227,11 @@
     /**
      * A special {@link junit.framework.TestCase} used to indicate a failure during the build()
      * step.
+     *
+     * @deprecated New tests should be written using the
+     * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
      */
+    @Deprecated
     public static class FailedToCreateTests extends TestCase {
         private final Exception exception;
 
diff --git a/test-runner/src/junit/runner/package-info.java b/test-runner/src/junit/runner/package-info.java
index b746185..364e362 100644
--- a/test-runner/src/junit/runner/package-info.java
+++ b/test-runner/src/junit/runner/package-info.java
@@ -1,4 +1,4 @@
 /**
- * Provides JUnit v3.x test runners.
+ * Utility classes supporting the junit test framework.
  */
 package junit.runner;
\ No newline at end of file
diff --git a/test-runner/src/junit/runner/package.html b/test-runner/src/junit/runner/package.html
deleted file mode 100644
index f08fa70..0000000
--- a/test-runner/src/junit/runner/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<HTML>
-<BODY>
-Utility classes supporting the junit test framework.
-</BODY>
-</HTML>
diff --git a/test-runner/src/junit/textui/package-info.java b/test-runner/src/junit/textui/package-info.java
index 2dcc10c..28b2ef4 100644
--- a/test-runner/src/junit/textui/package-info.java
+++ b/test-runner/src/junit/textui/package-info.java
@@ -1,5 +1,5 @@
 /**
- * Provides JUnit v3.x command line based tool to run tests.
+ * Utility classes supporting the junit test framework.
  * {@hide}
  */
 package junit.textui;
\ No newline at end of file
diff --git a/test-runner/src/junit/textui/package.html b/test-runner/src/junit/textui/package.html
deleted file mode 100644
index 723f2ae..0000000
--- a/test-runner/src/junit/textui/package.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<HTML>
-<BODY>
-Utility classes supporting the junit test framework.
-{@hide} - Not needed for 1.0 SDK
-</BODY>
-</HTML>
diff --git a/tests/FeatureSplit/base/Android.mk b/tests/FeatureSplit/base/Android.mk
index 7c0fc04..93f6d7a 100644
--- a/tests/FeatureSplit/base/Android.mk
+++ b/tests/FeatureSplit/base/Android.mk
@@ -19,6 +19,7 @@
 
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 LOCAL_PACKAGE_NAME := FeatureSplitBase
+LOCAL_EXPORT_PACKAGE_RESOURCES := true
 
 LOCAL_MODULE_TAGS := tests
 
diff --git a/tests/FeatureSplit/feature1/Android.mk b/tests/FeatureSplit/feature1/Android.mk
index aa222dd..e6ba5c2 100644
--- a/tests/FeatureSplit/feature1/Android.mk
+++ b/tests/FeatureSplit/feature1/Android.mk
@@ -17,17 +17,15 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
+LOCAL_USE_AAPT2 := true
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 LOCAL_PACKAGE_NAME := FeatureSplit1
 LOCAL_MODULE_TAGS := tests
 
-featureOf := FeatureSplitBase
+LOCAL_APK_LIBRARIES := FeatureSplitBase
+LOCAL_RES_LIBRARIES := FeatureSplitBase
 
-LOCAL_APK_LIBRARIES := $(featureOf)
-featureOfApk := $(call intermediates-dir-for,APPS,$(featureOf))/package.apk
-localRStamp := $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),,COMMON)/src/R.stamp
-$(localRStamp): $(featureOfApk)
-
-LOCAL_AAPT_FLAGS := --feature-of $(featureOfApk) --custom-package com.android.test.split.feature.one
+LOCAL_AAPT_FLAGS += --package-id 0x80
+LOCAL_AAPT_FLAGS += --custom-package com.android.test.split.feature.one
 
 include $(BUILD_PACKAGE)
diff --git a/tests/FeatureSplit/feature2/Android.mk b/tests/FeatureSplit/feature2/Android.mk
index 1a0322b..c8e8609 100644
--- a/tests/FeatureSplit/feature2/Android.mk
+++ b/tests/FeatureSplit/feature2/Android.mk
@@ -17,22 +17,15 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
+LOCAL_USE_AAPT2 := true
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 LOCAL_PACKAGE_NAME := FeatureSplit2
 LOCAL_MODULE_TAGS := tests
 
-featureOf := FeatureSplitBase
-featureAfter := FeatureSplit1
+LOCAL_APK_LIBRARIES := FeatureSplitBase
+LOCAL_RES_LIBRARIES := FeatureSplitBase
 
-LOCAL_APK_LIBRARIES := $(featureOf)
-
-featureOfApk := $(call intermediates-dir-for,APPS,$(featureOf))/package.apk
-featureAfterApk := $(call intermediates-dir-for,APPS,$(featureAfter))/package.apk
-localRStamp := $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),,COMMON)/src/R.stamp
-$(localRStamp): $(featureOfApk) $(featureAfterApk)
-
-LOCAL_AAPT_FLAGS := --feature-of $(featureOfApk)
-LOCAL_AAPT_FLAGS += --feature-after $(featureAfterApk)
+LOCAL_AAPT_FLAGS += --package-id 0x81
 LOCAL_AAPT_FLAGS += --custom-package com.android.test.split.feature.two
 
 include $(BUILD_PACKAGE)
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java
index db6421e..0defe92 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java
@@ -42,7 +42,7 @@
             "Burkina Faso", "Burundi", "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
             "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
             "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
-            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
+            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czechia",
             "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
             "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
             "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PathDestructionActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/PathDestructionActivity.java
index 4177725..5cede65 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/PathDestructionActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/PathDestructionActivity.java
@@ -25,6 +25,8 @@
 import android.util.MathUtils;
 import android.view.View;
 
+import java.util.Random;
+
 /**
  * The point of this test is to ensure that we can cause many paths to be created, drawn,
  * and destroyed without causing hangs or crashes. This tests the native reference counting
@@ -57,10 +59,11 @@
 
         private Path getRandomPath() {
             float left, top, right, bottom;
-            left = MathUtils.random(getWidth() - MIN_SIZE);
-            top = MathUtils.random(getHeight() - MIN_SIZE);
-            right = left + MathUtils.random(getWidth() - left);
-            bottom = top + MathUtils.random(getHeight() - top);
+            Random r = new Random();
+            left = r.nextFloat() * (getWidth() - MIN_SIZE);
+            top = r.nextFloat() * (getHeight() - MIN_SIZE);
+            right = left + r.nextFloat() * (getWidth() - left);
+            bottom = top + r.nextFloat() * (getHeight() - top);
             Path path = new Path();
             path.moveTo(left, top);
             path.lineTo(right, top);
@@ -71,9 +74,10 @@
         }
 
         private int getRandomColor() {
-            int red = MathUtils.random(255);
-            int green = MathUtils.random(255);
-            int blue = MathUtils.random(255);
+            Random r = new Random();
+            int red = r.nextInt(255);
+            int green = r.nextInt(255);
+            int blue = r.nextInt(255);
             return 0xff000000 | red << 16 | green << 8 | blue;
         }
 
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TransparentListActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TransparentListActivity.java
index 535f865..ffb8689 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/TransparentListActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TransparentListActivity.java
@@ -42,7 +42,7 @@
             "Burkina Faso", "Burundi", "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
             "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
             "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
-            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
+            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czechia",
             "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
             "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
             "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity.java
index 0ddd7fd..7168478 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity.java
@@ -126,7 +126,7 @@
             "Burkina Faso", "Burundi", "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
             "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
             "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
-            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
+            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czechia",
             "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
             "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
             "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity2.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity2.java
index e795f02..a037d70 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity2.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity2.java
@@ -76,7 +76,7 @@
             "Burkina Faso", "Burundi", "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
             "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
             "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
-            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
+            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czechia",
             "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
             "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
             "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity3.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity3.java
index c8ae75b..e65dd63 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity3.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity3.java
@@ -73,7 +73,7 @@
             "Burkina Faso", "Burundi", "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
             "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
             "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
-            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
+            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czechia",
             "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
             "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
             "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity4.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity4.java
index 6072c6e..17f78af 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity4.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity4.java
@@ -80,7 +80,7 @@
             "Burkina Faso", "Burundi", "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
             "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
             "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
-            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
+            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czechia",
             "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
             "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
             "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java
index cbbb7ef..2dd7b6a 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java
@@ -145,7 +145,7 @@
             "Burkina Faso", "Burundi", "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
             "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
             "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
-            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
+            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czechia",
             "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
             "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
             "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
diff --git a/tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityLandscape.java b/tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityLandscape.java
index 7a4fddf..292bbd2 100644
--- a/tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityLandscape.java
+++ b/tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityLandscape.java
@@ -65,7 +65,7 @@
    "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
    "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
    "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
-   "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
+   "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czechia",
    "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
    "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
    "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
diff --git a/tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityPortrait.java b/tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityPortrait.java
index 5bfe456..570cb6b 100644
--- a/tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityPortrait.java
+++ b/tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityPortrait.java
@@ -60,7 +60,7 @@
    "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
    "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
    "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
-   "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
+   "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czechia",
    "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
    "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
    "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
diff --git a/tests/SharedLibrary/client/Android.mk b/tests/SharedLibrary/client/Android.mk
index 1d66bb9..a04fb05 100644
--- a/tests/SharedLibrary/client/Android.mk
+++ b/tests/SharedLibrary/client/Android.mk
@@ -1,6 +1,7 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
+LOCAL_USE_AAPT2 := true
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_RES_LIBRARIES := SharedLibrary
diff --git a/tests/SharedLibrary/client/res/layout/main.xml b/tests/SharedLibrary/client/res/layout/main.xml
index 067ef9f..7dfe965 100644
--- a/tests/SharedLibrary/client/res/layout/main.xml
+++ b/tests/SharedLibrary/client/res/layout/main.xml
@@ -15,7 +15,7 @@
         xmlns:custom="http://schemas.android.com/apk/res/com.google.android.test.shared_library"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        custom:name="Professor Android"
+        custom:name="@string/name"
         custom:streetNumber="44"
         custom:streetName="KitKat Lane"
         custom:city="AndroidVille"
diff --git a/tests/SharedLibrary/client/res/values/strings.xml b/tests/SharedLibrary/client/res/values/strings.xml
index d9efdc7..63043ed 100644
--- a/tests/SharedLibrary/client/res/values/strings.xml
+++ b/tests/SharedLibrary/client/res/values/strings.xml
@@ -16,5 +16,6 @@
 
 <resources>
     <string name="app_title">SharedLibrary client</string>
+    <string name="name">Professor Android</string>
     <string name="changes">@com.google.android.test.shared_library:string/shared_string</string>
 </resources>
diff --git a/tests/SharedLibrary/lib/Android.mk b/tests/SharedLibrary/lib/Android.mk
index b2fc369..78fcb8b 100644
--- a/tests/SharedLibrary/lib/Android.mk
+++ b/tests/SharedLibrary/lib/Android.mk
@@ -1,5 +1,6 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
+LOCAL_USE_AAPT2 := true
 
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
diff --git a/tests/SharedLibrary/lib/res/values/public.xml b/tests/SharedLibrary/lib/res/values/public.xml
index 23d307e..8d7a7ad 100644
--- a/tests/SharedLibrary/lib/res/values/public.xml
+++ b/tests/SharedLibrary/lib/res/values/public.xml
@@ -15,5 +15,5 @@
 
     <public type="drawable" name="size_48x48" id="0x00030000" />
 
-    <public type="array" name="animals"     id="0x02050000" />
+    <public type="array" name="animals"     id="0x00050000" />
 </resources>
diff --git a/tests/SoundTriggerTestApp/res/layout/main.xml b/tests/SoundTriggerTestApp/res/layout/main.xml
index 0fd8b12..2c6c8d7 100644
--- a/tests/SoundTriggerTestApp/res/layout/main.xml
+++ b/tests/SoundTriggerTestApp/res/layout/main.xml
@@ -87,6 +87,7 @@
             android:text="@string/capture"
             android:id="@+id/caputre_check_box"
             android:layout_gravity="center_horizontal"
+            android:onClick="onCaptureAudioCheckboxClicked"
             android:padding="20dp" />
 
         <Button
@@ -94,6 +95,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:text="@string/play_capture"
+            android:onClick="onPlayCapturedAudioButtonClicked"
             android:padding="20dp"
             android:enabled="false" />
     </LinearLayout>
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
index 56aad23..c49be88 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
@@ -16,7 +16,13 @@
 
 package com.android.statusbartest;
 
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
+import static android.app.NotificationManager.IMPORTANCE_MIN;
+
 import android.app.Notification;
+import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.Context;
@@ -24,7 +30,9 @@
 import android.content.Intent;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
+import android.graphics.Color;
 import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Icon;
 import android.media.AudioAttributes;
 import android.os.Bundle;
 import android.os.Vibrator;
@@ -72,6 +80,13 @@
         super.onCreate(icicle);
         mVibrator = (Vibrator)getSystemService(VIBRATOR_SERVICE);
         mActivityCreateTime = System.currentTimeMillis();
+        mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
+
+        mNM.createNotificationChannel(new NotificationChannel("min", "Min", IMPORTANCE_MIN));
+        mNM.createNotificationChannel(new NotificationChannel("low", "Low", IMPORTANCE_LOW));
+        mNM.createNotificationChannel(
+                new NotificationChannel("default", "Default", IMPORTANCE_DEFAULT));
+        mNM.createNotificationChannel(new NotificationChannel("high", "High", IMPORTANCE_HIGH));
     }
 
     @Override
@@ -81,8 +96,6 @@
 
     @Override
     protected Test[] tests() {
-        mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
-        
         return mTests;
     }
 
@@ -95,20 +108,23 @@
             new Test("Phone call") {
                 public void run()
                 {
-                    Notification n = new Notification.Builder(NotificationTestList.this)
-                            .setSmallIcon(R.drawable.icon2)
-                            .setContentTitle("phone call")
-                            .setLights(0xff0000ff, 1, 0)
-                            .setDefaults(Notification.DEFAULT_LIGHTS|Notification.DEFAULT_VIBRATE)
-                            .setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
+                    NotificationChannel phoneCall =
+                            new NotificationChannel("phone call", "Phone Call", IMPORTANCE_HIGH);
+                    phoneCall.setVibrationPattern(new long[] {
+                            300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400,
+                            300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400,
+                            300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400 });
+                    phoneCall.enableVibration(true);
+                    phoneCall.setLightColor(0xff0000ff);
+                    phoneCall.enableLights(true);
+                    phoneCall.setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
                                     getPackageName() + "/raw/ringer"),
-                                    new AudioAttributes.Builder().setUsage(
-                                            AudioAttributes.USAGE_NOTIFICATION_RINGTONE).build())
-                            .setPriority(Notification.PRIORITY_MAX)
-                            .setVibrate(new long[] {
-                                    300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400,
-                                    300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400,
-                                    300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400 })
+                            new AudioAttributes.Builder().setUsage(
+                                    AudioAttributes.USAGE_NOTIFICATION_RINGTONE).build());
+                    Notification n = new Notification.Builder(NotificationTestList.this,
+                            "phone call")
+                            .setSmallIcon(R.drawable.icon2)
+                            .setChannel(phoneCall.getId())
                             .setFullScreenIntent(makeIntent2(), true)
                             .build();
                     mNM.notify(7001, n);
@@ -117,35 +133,29 @@
             new Test("Post a group") {
                 public void run()
                 {
-                    Notification n = new Notification.Builder(NotificationTestList.this)
+                    Notification n = new Notification.Builder(NotificationTestList.this, "min")
                             .setSmallIcon(R.drawable.icon2)
                             .setContentTitle("Min priority group 1")
-                            .setLights(0xff0000ff, 1, 0)
-                            .setPriority(Notification.PRIORITY_MIN)
                             .setGroup("group1")
                             .build();
                     mNM.notify(6000, n);
-                    n = new Notification.Builder(NotificationTestList.this)
+                    n = new Notification.Builder(NotificationTestList.this, "low")
                             .setSmallIcon(R.drawable.icon2)
                             .setContentTitle("low priority group 1")
-                            .setLights(0xff0000ff, 1, 0)
-                            .setPriority(Notification.PRIORITY_LOW)
                             .setGroup("group1")
                             .build();
                     mNM.notify(6001, n);
-                    n = new Notification.Builder(NotificationTestList.this)
+                    n = new Notification.Builder(NotificationTestList.this, "default")
                             .setSmallIcon(R.drawable.icon2)
                             .setContentTitle("default priority group 1")
-                            .setLights(0xff0000ff, 1, 0)
-                            .setPriority(Notification.PRIORITY_DEFAULT)
                             .setGroup("group1")
+                            .setOngoing(true)
+                            .setColorized(true)
                             .build();
                     mNM.notify(6002, n);
-                    n = new Notification.Builder(NotificationTestList.this)
+                    n = new Notification.Builder(NotificationTestList.this, "low")
                             .setSmallIcon(R.drawable.icon2)
                             .setContentTitle("summary group 1")
-                            .setLights(0xff0000ff, 1, 0)
-                            .setPriority(Notification.PRIORITY_MIN)
                             .setGroup("group1")
                             .setGroupSummary(true)
                             .build();
@@ -155,27 +165,21 @@
             new Test("Post a group (2) w/o summary") {
                 public void run()
                 {
-                    Notification n = new Notification.Builder(NotificationTestList.this)
+                    Notification n = new Notification.Builder(NotificationTestList.this, "min")
                             .setSmallIcon(R.drawable.icon2)
                             .setContentTitle("Min priority group 2")
-                            .setLights(0xff0000ff, 1, 0)
-                            .setPriority(Notification.PRIORITY_MIN)
                             .setGroup("group2")
                             .build();
                     mNM.notify(6100, n);
-                    n = new Notification.Builder(NotificationTestList.this)
+                    n = new Notification.Builder(NotificationTestList.this, "low")
                             .setSmallIcon(R.drawable.icon2)
                             .setContentTitle("low priority group 2")
-                            .setLights(0xff0000ff, 1, 0)
-                            .setPriority(Notification.PRIORITY_LOW)
                             .setGroup("group2")
                             .build();
                     mNM.notify(6101, n);
-                    n = new Notification.Builder(NotificationTestList.this)
+                    n = new Notification.Builder(NotificationTestList.this, "default")
                             .setSmallIcon(R.drawable.icon2)
                             .setContentTitle("default priority group 2")
-                            .setLights(0xff0000ff, 1, 0)
-                            .setPriority(Notification.PRIORITY_DEFAULT)
                             .setGroup("group2")
                             .build();
                     mNM.notify(6102, n);
@@ -184,11 +188,9 @@
             new Test("Summary for group 2") {
                 public void run()
                 {
-                    Notification n = new Notification.Builder(NotificationTestList.this)
+                    Notification n = new Notification.Builder(NotificationTestList.this, "min")
                             .setSmallIcon(R.drawable.icon2)
                             .setContentTitle("summary group 2")
-                            .setLights(0xff0000ff, 1, 0)
-                            .setPriority(Notification.PRIORITY_MIN)
                             .setGroup("group2")
                             .setGroupSummary(true)
                             .build();
@@ -198,54 +200,44 @@
             new Test("Group up public-secret") {
                 public void run()
                 {
-                    Notification n = new Notification.Builder(NotificationTestList.this)
+                    Notification n = new Notification.Builder(NotificationTestList.this, "default")
                             .setSmallIcon(R.drawable.icon2)
                             .setContentTitle("public notification")
-                            .setDefaults(Notification.DEFAULT_LIGHTS|Notification.DEFAULT_VIBRATE)
-                            .setPriority(Notification.PRIORITY_DEFAULT)
                             .setVisibility(Notification.VISIBILITY_PUBLIC)
                             .setGroup("public-secret")
                             .build();
                     mNM.notify("public", 7009, n);
-                    n = new Notification.Builder(NotificationTestList.this)
+                    n = new Notification.Builder(NotificationTestList.this, "default")
                             .setSmallIcon(R.drawable.icon2)
                             .setContentTitle("private only notification")
-                            .setDefaults(Notification.DEFAULT_LIGHTS|Notification.DEFAULT_VIBRATE)
-                            .setPriority(Notification.PRIORITY_DEFAULT)
                             .setVisibility(Notification.VISIBILITY_PRIVATE)
                             .setGroup("public-secret")
                             .build();
                     mNM.notify("no public", 7010, n);
-                    n = new Notification.Builder(NotificationTestList.this)
+                    n = new Notification.Builder(NotificationTestList.this, "default")
                             .setSmallIcon(R.drawable.icon2)
                             .setContentTitle("private version of notification")
-                            .setDefaults(Notification.DEFAULT_LIGHTS|Notification.DEFAULT_VIBRATE)
-                            .setPriority(Notification.PRIORITY_DEFAULT)
                             .setVisibility(Notification.VISIBILITY_PRIVATE)
                             .setGroup("public-secret")
-                            .setPublicVersion(new Notification.Builder(NotificationTestList.this)
+                            .setPublicVersion(new Notification.Builder(
+                                    NotificationTestList.this, "default")
                                     .setSmallIcon(R.drawable.icon2)
                                     .setContentTitle("public notification of private notification")
-                                    .setPriority(Notification.PRIORITY_DEFAULT)
                                     .setVisibility(Notification.VISIBILITY_PUBLIC)
                                     .build())
                             .build();
                     mNM.notify("priv with pub", 7011, n);
-                    n = new Notification.Builder(NotificationTestList.this)
+                    n = new Notification.Builder(NotificationTestList.this, "default")
                             .setSmallIcon(R.drawable.icon2)
                             .setContentTitle("secret notification")
-                            .setDefaults(Notification.DEFAULT_LIGHTS|Notification.DEFAULT_VIBRATE)
-                            .setPriority(Notification.PRIORITY_DEFAULT)
                             .setVisibility(Notification.VISIBILITY_SECRET)
                             .setGroup("public-secret")
                             .build();
                     mNM.notify("secret", 7012, n);
 
-                    Notification s = new Notification.Builder(NotificationTestList.this)
+                    Notification s = new Notification.Builder(NotificationTestList.this, "default")
                             .setSmallIcon(R.drawable.icon2)
                             .setContentTitle("summary group public-secret")
-                            .setLights(0xff0000ff, 1, 0)
-                            .setPriority(Notification.PRIORITY_MIN)
                             .setGroup("public-secret")
                             .setGroupSummary(true)
                             .build();
@@ -266,39 +258,19 @@
             new Test("Min priority") {
                 public void run()
                 {
-                    Notification n = new Notification.Builder(NotificationTestList.this)
+                    Notification n = new Notification.Builder(NotificationTestList.this, "min")
                             .setSmallIcon(R.drawable.icon2)
                             .setContentTitle("Min priority")
-                            .setLights(0xff0000ff, 1, 0)
-                            .setPriority(Notification.PRIORITY_MIN)
                             .build();
                     mNM.notify("min", 7000, n);
                 }
             },
-            new Test("Min priority, high pri flag") {
-                public void run()
-                {
-                    Notification n = new Notification.Builder(NotificationTestList.this)
-                            .setSmallIcon(R.drawable.icon2)
-                            .setContentTitle("Min priority, high pri flag")
-                            .setLights(0xff0000ff, 1, 0)
-                            .setDefaults(Notification.DEFAULT_LIGHTS|Notification.DEFAULT_VIBRATE)
-                            .setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
-                                    getPackageName() + "/raw/ringer"))
-                            .setPriority(Notification.PRIORITY_MIN)
-                            .setFullScreenIntent(makeIntent2(), true)
-                            .build();
-                    mNM.notify(7001, n);
-                }
-            },
             new Test("Low priority") {
                 public void run()
                 {
-                    Notification n = new Notification.Builder(NotificationTestList.this)
+                    Notification n = new Notification.Builder(NotificationTestList.this, "low")
                             .setSmallIcon(R.drawable.icon2)
                             .setContentTitle("Low priority")
-                            .setLights(0xff0000ff, 1, 0)
-                            .setPriority(Notification.PRIORITY_LOW)
                             .build();
                     mNM.notify("low", 7002, n);
                 }
@@ -306,11 +278,9 @@
             new Test("Default priority") {
                 public void run()
                 {
-                    Notification n = new Notification.Builder(NotificationTestList.this)
+                    Notification n = new Notification.Builder(NotificationTestList.this, "default")
                             .setSmallIcon(R.drawable.icon2)
                             .setContentTitle("Default priority")
-                            .setLights(0xff0000ff, 1, 0)
-                            .setPriority(Notification.PRIORITY_DEFAULT)
                             .build();
                     mNM.notify("default", 7004, n);
                 }
@@ -318,49 +288,23 @@
             new Test("High priority") {
                 public void run()
                 {
-                    Notification n = new Notification.Builder(NotificationTestList.this)
+                    Notification n = new Notification.Builder(NotificationTestList.this, "high")
                             .setSmallIcon(R.drawable.icon2)
                             .setContentTitle("High priority")
-                            .setLights(0xff0000ff, 1, 0)
-                            .setDefaults(Notification.DEFAULT_LIGHTS|Notification.DEFAULT_VIBRATE)
-                            .setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
-                                    getPackageName() + "/raw/ringer"))
-                            .setPriority(Notification.PRIORITY_HIGH)
                             .build();
                     mNM.notify("high", 7006, n);
                 }
             },
-            new Test("Max priority") {
-                public void run()
-                {
-                    Notification n = new Notification.Builder(NotificationTestList.this)
-                            .setSmallIcon(R.drawable.icon2)
-                            .setContentTitle("Max priority")
-                            .setLights(0xff0000ff, 1, 0)
-                            .setDefaults(Notification.DEFAULT_LIGHTS|Notification.DEFAULT_VIBRATE)
-                            .setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
-                                    getPackageName() + "/raw/ringer"))
-                            .setPriority(Notification.PRIORITY_MAX)
-                            .setFullScreenIntent(makeIntent2(), false)
-                            .build();
-                    mNM.notify("max", 7007, n);
-                }
-            },
-            new Test("Max priority with delay") {
+            new Test("high priority with delay") {
                 public void run()
                 {
                     try {
                         Thread.sleep(5000);
                     } catch (InterruptedException e) {
                     }
-                    Notification n = new Notification.Builder(NotificationTestList.this)
+                    Notification n = new Notification.Builder(NotificationTestList.this, "high")
                             .setSmallIcon(R.drawable.icon2)
-                            .setContentTitle("Max priority")
-                            .setLights(0xff0000ff, 1, 0)
-                            .setDefaults(Notification.DEFAULT_LIGHTS|Notification.DEFAULT_VIBRATE)
-                            .setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
-                                    getPackageName() + "/raw/ringer"))
-                            .setPriority(Notification.PRIORITY_MAX)
+                            .setContentTitle("High priority")
                             .setFullScreenIntent(makeIntent2(), false)
                             .build();
                     mNM.notify(7008, n);
@@ -369,11 +313,9 @@
             new Test("public notification") {
                 public void run()
                 {
-                    Notification n = new Notification.Builder(NotificationTestList.this)
+                    Notification n = new Notification.Builder(NotificationTestList.this, "default")
                             .setSmallIcon(R.drawable.icon2)
                             .setContentTitle("public notification")
-                            .setDefaults(Notification.DEFAULT_LIGHTS|Notification.DEFAULT_VIBRATE)
-                            .setPriority(Notification.PRIORITY_DEFAULT)
                             .setVisibility(Notification.VISIBILITY_PUBLIC)
                             .build();
                     mNM.notify("public", 7009, n);
@@ -382,11 +324,9 @@
             new Test("private notification, no public") {
                 public void run()
                 {
-                    Notification n = new Notification.Builder(NotificationTestList.this)
+                    Notification n = new Notification.Builder(NotificationTestList.this, "default")
                             .setSmallIcon(R.drawable.icon2)
                             .setContentTitle("private only notification")
-                            .setDefaults(Notification.DEFAULT_LIGHTS|Notification.DEFAULT_VIBRATE)
-                            .setPriority(Notification.PRIORITY_DEFAULT)
                             .setVisibility(Notification.VISIBILITY_PRIVATE)
                             .build();
                     mNM.notify("no public", 7010, n);
@@ -395,16 +335,14 @@
             new Test("private notification, has public") {
                 public void run()
                 {
-                    Notification n = new Notification.Builder(NotificationTestList.this)
+                    Notification n = new Notification.Builder(NotificationTestList.this, "default")
                             .setSmallIcon(R.drawable.icon2)
                             .setContentTitle("private version of notification")
-                            .setDefaults(Notification.DEFAULT_LIGHTS|Notification.DEFAULT_VIBRATE)
-                            .setPriority(Notification.PRIORITY_DEFAULT)
                             .setVisibility(Notification.VISIBILITY_PRIVATE)
-                            .setPublicVersion(new Notification.Builder(NotificationTestList.this)
+                            .setPublicVersion(new Notification.Builder(
+                                    NotificationTestList.this, "low")
                                     .setSmallIcon(R.drawable.icon2)
                                     .setContentTitle("public notification of private notification")
-                                    .setPriority(Notification.PRIORITY_DEFAULT)
                                     .setVisibility(Notification.VISIBILITY_PUBLIC)
                                     .build())
                             .build();
@@ -414,11 +352,9 @@
             new Test("secret notification") {
                 public void run()
                 {
-                    Notification n = new Notification.Builder(NotificationTestList.this)
+                    Notification n = new Notification.Builder(NotificationTestList.this, "default")
                             .setSmallIcon(R.drawable.icon2)
                             .setContentTitle("secret notification")
-                            .setDefaults(Notification.DEFAULT_LIGHTS|Notification.DEFAULT_VIBRATE)
-                            .setPriority(Notification.PRIORITY_DEFAULT)
                             .setVisibility(Notification.VISIBILITY_SECRET)
                             .build();
                     mNM.notify("secret", 7012, n);
@@ -427,7 +363,7 @@
             new Test("1 minute timeout") {
                 public void run()
                 {
-                    Notification n = new Notification.Builder(NotificationTestList.this)
+                    Notification n = new Notification.Builder(NotificationTestList.this, "default")
                             .setSmallIcon(R.drawable.icon2)
                             .setContentTitle("timeout in a minute")
                             .setTimeout(System.currentTimeMillis() + (1000 * 60))
@@ -435,20 +371,34 @@
                     mNM.notify("timeout_min", 7013, n);
                 }
             },
+            new Test("Colorized") {
+                public void run()
+                {
+                    Notification n = new Notification.Builder(NotificationTestList.this, "default")
+                            .setSmallIcon(R.drawable.icon2)
+                            .setContentTitle("RED IS BEST")
+                            .setContentText("or is blue?")
+                            .setTimeout(System.currentTimeMillis() + (1000 * 60))
+                            .setColor(Color.RED)
+                            .setFlag(Notification.FLAG_ONGOING_EVENT, true)
+                            .setColorized(true)
+                            .build();
+                    mNM.notify("timeout_min", 7013, n);
+                }
+            },
         new Test("Off") {
             public void run() {
-                PowerManager pm = (PowerManager)NotificationTestList.this.getSystemService(Context.POWER_SERVICE);
+                PowerManager pm = (PowerManager) NotificationTestList.this.getSystemService(
+                        Context.POWER_SERVICE);
                 PowerManager.WakeLock wl = 
                             pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "sound");
                 wl.acquire();
 
                 pm.goToSleep(SystemClock.uptimeMillis());
 
-                Notification n = new Notification.Builder(NotificationTestList.this)
+                Notification n = new Notification.Builder(NotificationTestList.this, "default")
                         .setSmallIcon(R.drawable.stat_sys_phone)
                         .setContentTitle(name)
-                        .setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
-                                        getPackageName() + "/raw/ringer"))
                         .build();
                 Log.d(TAG, "n.sound=" + n.sound);
 
@@ -469,14 +419,15 @@
 
         new Test("Custom Button") {
             public void run() {
-                Notification n = new Notification.Builder(NotificationTestList.this)
+                RemoteViews view = new RemoteViews(getPackageName(), R.layout.button_notification);
+                view.setOnClickPendingIntent(R.id.button, makeIntent2());
+                Notification n = new Notification.Builder(NotificationTestList.this, "default")
                         .setSmallIcon(R.drawable.icon1)
                         .setWhen(mActivityCreateTime)
                         .setContentTitle(name)
                         .setOngoing(true)
+                        .setCustomContentView(view)
                         .build();
-                n.contentView = new RemoteViews(getPackageName(), R.layout.button_notification);
-                n.contentView.setOnClickPendingIntent(R.id.button, makeIntent2());
 
                 mNM.notify(1, n);
             }
@@ -484,12 +435,16 @@
 
         new Test("Action Button") {
             public void run() {
-                Notification n = new Notification.Builder(NotificationTestList.this)
+                Notification n = new Notification.Builder(NotificationTestList.this, "default")
                         .setSmallIcon(R.drawable.icon1)
                         .setWhen(mActivityCreateTime)
                         .setContentTitle(name)
                         .setOngoing(true)
-                        .addAction(R.drawable.ic_statusbar_chat, "Button", makeIntent2())
+                        .addAction(new Notification.Action.Builder(
+                                Icon.createWithResource(NotificationTestList.this,
+                                        R.drawable.ic_statusbar_chat),
+                                "Button", makeIntent2())
+                                .build())
                         .build();
 
                 mNM.notify(1, n);
@@ -498,7 +453,7 @@
 
         new Test("with intent") {
             public void run() {
-                Notification n = new Notification.Builder(NotificationTestList.this)
+                Notification n = new Notification.Builder(NotificationTestList.this, "default")
                         .setSmallIcon(R.drawable.icon1)
                         .setWhen(mActivityCreateTime)
                         .setContentTitle("Persistent #1")
@@ -530,7 +485,8 @@
         new Test("Whens") {
             public void run()
             {
-                Notification.Builder n = new Notification.Builder(NotificationTestList.this)
+                Notification.Builder n = new Notification.Builder(
+                        NotificationTestList.this, "default")
                         .setSmallIcon(R.drawable.icon1)
                         .setContentTitle(name)
                         .setOngoing(true);
@@ -551,7 +507,7 @@
 
         new Test("Bad Icon #1 (when=create)") {
             public void run() {
-                Notification n = new Notification.Builder(NotificationTestList.this)
+                Notification n = new Notification.Builder(NotificationTestList.this, "low")
                         .setSmallIcon(R.layout.chrono_notification /* not an icon */)
                         .setWhen(mActivityCreateTime)
                         .setContentTitle("Persistent #1")
@@ -564,7 +520,7 @@
 
         new Test("Bad Icon #1 (when=now)") {
             public void run() {
-                Notification n = new Notification.Builder(NotificationTestList.this)
+                Notification n = new Notification.Builder(NotificationTestList.this, "low")
                         .setSmallIcon(R.layout.chrono_notification /* not an icon */)
                         .setWhen(System.currentTimeMillis())
                         .setContentTitle("Persistent #1")
@@ -577,7 +533,7 @@
 
         new Test("Null Icon #1 (when=now)") {
             public void run() {
-                Notification n = new Notification.Builder(NotificationTestList.this)
+                Notification n = new Notification.Builder(NotificationTestList.this, "low")
                         .setSmallIcon(0)
                         .setWhen(System.currentTimeMillis())
                         .setContentTitle("Persistent #1")
@@ -590,7 +546,7 @@
 
         new Test("Bad resource #1 (when=create)") {
             public void run() {
-                Notification n = new Notification.Builder(NotificationTestList.this)
+                Notification n = new Notification.Builder(NotificationTestList.this, "low")
                         .setSmallIcon(R.drawable.icon2)
                         .setWhen(mActivityCreateTime)
                         .setContentTitle("Persistent #1")
@@ -604,7 +560,7 @@
 
         new Test("Bad resource #1 (when=now)") {
             public void run() {
-                Notification n = new Notification.Builder(NotificationTestList.this)
+                Notification n = new Notification.Builder(NotificationTestList.this, "low")
                         .setSmallIcon(R.drawable.icon2)
                         .setWhen(System.currentTimeMillis())
                         .setContentTitle("Persistent #1")
@@ -634,7 +590,7 @@
                 new Runnable() {
                     public void run() {
                         Log.d(TAG, "Stress - Ongoing/Latest 0");
-                        Notification n = new Notification.Builder(NotificationTestList.this)
+                        Notification n = new Notification.Builder(NotificationTestList.this, "low")
                                 .setSmallIcon(R.drawable.icon3)
                                 .setWhen(System.currentTimeMillis())
                                 .setContentTitle("Stress - Ongoing")
@@ -647,7 +603,7 @@
                 new Runnable() {
                     public void run() {
                         Log.d(TAG, "Stress - Ongoing/Latest 1");
-                        Notification n = new Notification.Builder(NotificationTestList.this)
+                        Notification n = new Notification.Builder(NotificationTestList.this, "low")
                                 .setSmallIcon(R.drawable.icon4)
                                 .setWhen(System.currentTimeMillis())
                                 .setContentTitle("Stress - Latest")
@@ -661,14 +617,18 @@
         new Test("Long") {
             public void run()
             {
-                Notification n = new Notification.Builder(NotificationTestList.this)
+                NotificationChannel channel = new NotificationChannel("v. noisy",
+                        "channel for sound and a custom vibration", IMPORTANCE_DEFAULT);
+                channel.enableVibration(true);
+                channel.setVibrationPattern(new long[] {
+                        300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400,
+                        300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400,
+                        300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400 });
+                mNM.createNotificationChannel(channel);
+
+                Notification n = new Notification.Builder(NotificationTestList.this, "v. noisy")
                         .setSmallIcon(R.drawable.icon1)
                         .setContentTitle(name)
-                        .setDefaults(Notification.DEFAULT_SOUND)
-                        .setVibrate(new long[] {
-                                300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400,
-                                300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400,
-                                300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400 })
                         .build();
                 mNM.notify(1, n);
             }
@@ -682,7 +642,8 @@
                 Thread t = new Thread() {
                     public void run() {
                         int x = 0;
-                        final Notification.Builder n = new Notification.Builder(NotificationTestList.this)
+                        final Notification.Builder n = new Notification.Builder(
+                                NotificationTestList.this, "low")
                                 .setSmallIcon(R.drawable.icon1)
                                 .setContentTitle(name)
                                 .setOngoing(true);
@@ -719,11 +680,15 @@
         new Test("Blue Lights") {
             public void run()
             {
-                Notification n = new Notification.Builder(NotificationTestList.this)
+                NotificationChannel channel = new NotificationChannel("blue",
+                        "blue", IMPORTANCE_DEFAULT);
+                channel.enableLights(true);
+                channel.setLightColor(0xff0000ff);
+                mNM.createNotificationChannel(channel);
+
+                Notification n = new Notification.Builder(NotificationTestList.this, "blue")
                         .setSmallIcon(R.drawable.icon2)
                         .setContentTitle(name)
-                        .setLights(0xff0000ff, 1, 0)
-                        .setDefaults(Notification.DEFAULT_LIGHTS)
                         .build();
                 mNM.notify(1, n);
             }
@@ -732,24 +697,15 @@
         new Test("Red Lights") {
             public void run()
             {
-                Notification n = new Notification.Builder(NotificationTestList.this)
-                        .setSmallIcon(R.drawable.icon2)
-                        .setContentTitle(name)
-                        .setLights(0xffff0000, 1, 0)
-                        .setDefaults(Notification.DEFAULT_LIGHTS)
-                        .build();
-                mNM.notify(1, n);
-            }
-        },
+                NotificationChannel channel = new NotificationChannel("red",
+                        "red", IMPORTANCE_DEFAULT);
+                channel.enableLights(true);
+                channel.setLightColor(0xffff0000);
+                mNM.createNotificationChannel(channel);
 
-        new Test("Yellow Lights") {
-            public void run()
-            {
-                Notification n = new Notification.Builder(NotificationTestList.this)
+                Notification n = new Notification.Builder(NotificationTestList.this, "red")
                         .setSmallIcon(R.drawable.icon2)
                         .setContentTitle(name)
-                        .setLights(0xffffff00, 1, 0)
-                        .setDefaults(Notification.DEFAULT_LIGHTS)
                         .build();
                 mNM.notify(1, n);
             }
@@ -758,62 +714,21 @@
         new Test("Lights off") {
             public void run()
             {
-                Notification n = new Notification.Builder(NotificationTestList.this)
+                Notification n = new Notification.Builder(NotificationTestList.this, "default")
                         .setSmallIcon(R.drawable.icon2)
                         .setContentTitle(name)
-                        .setLights(0x00000000, 0, 0)
-                        .setDefaults(Notification.DEFAULT_LIGHTS)
                         .build();
                 mNM.notify(1, n);
             }
         },
 
-        new Test("Blue Blinking Slow") {
+        new Test("Alert once") {
             public void run()
             {
-                Notification n = new Notification.Builder(NotificationTestList.this)
-                        .setSmallIcon(R.drawable.icon2)
-                        .setContentTitle(name)
-                        .setLights(0xff0000ff, 1300, 1300)
-                        .setDefaults(Notification.DEFAULT_LIGHTS)
-                        .build();
-                mNM.notify(1, n);
-            }
-        },
-
-        new Test("Blue Blinking Fast") {
-            public void run()
-            {
-                Notification n = new Notification.Builder(NotificationTestList.this)
-                        .setSmallIcon(R.drawable.icon2)
-                        .setContentTitle(name)
-                        .setLights(0xff0000ff, 300, 300)
-                        .setDefaults(Notification.DEFAULT_LIGHTS)
-                        .build();
-                mNM.notify(1, n);
-            }
-        },
-
-        new Test("Default All") {
-            public void run()
-            {
-                Notification n = new Notification.Builder(NotificationTestList.this)
-                        .setSmallIcon(R.drawable.icon2)
-                        .setContentTitle(name)
-                        .setDefaults(Notification.DEFAULT_ALL)
-                        .build();
-                mNM.notify(1, n);
-            }
-        },
-
-        new Test("Default All, once") {
-            public void run()
-            {
-                Notification n = new Notification.Builder(NotificationTestList.this)
+                Notification n = new Notification.Builder(NotificationTestList.this, "high")
                         .setSmallIcon(R.drawable.icon2)
                         .setContentTitle(name)
                         .setOnlyAlertOnce(true)
-                        .setDefaults(Notification.DEFAULT_ALL)
                         .build();
                 mNM.notify(1, n);
             }
@@ -822,11 +737,15 @@
         new Test("Resource Sound") {
             public void run()
             {
-                Notification n = new Notification.Builder(NotificationTestList.this)
+                NotificationChannel channel = new NotificationChannel("res_sound",
+                        "resource sound", IMPORTANCE_DEFAULT);
+                channel.setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
+                        getPackageName() + "/raw/ringer"), Notification.AUDIO_ATTRIBUTES_DEFAULT);
+                mNM.createNotificationChannel(channel);
+
+                Notification n = new Notification.Builder(NotificationTestList.this, "res_sound")
                         .setSmallIcon(R.drawable.stat_sys_phone)
                         .setContentTitle(name)
-                        .setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
-                                getPackageName() + "/raw/ringer"))
                         .build();
                 Log.d(TAG, "n.sound=" + n.sound);
 
@@ -837,40 +756,37 @@
         new Test("Sound and Cancel") {
             public void run()
             {
-                Notification n = new Notification.Builder(NotificationTestList.this)
+                NotificationChannel channel = new NotificationChannel("res_sound",
+                        "resource sound", IMPORTANCE_DEFAULT);
+                channel.setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
+                        getPackageName() + "/raw/ringer"), Notification.AUDIO_ATTRIBUTES_DEFAULT);
+                mNM.createNotificationChannel(channel);
+
+                Notification n = new Notification.Builder(NotificationTestList.this, "res_sound")
                         .setSmallIcon(R.drawable.stat_sys_phone)
                         .setContentTitle(name)
-                        .setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
-                                getPackageName() + "/raw/ringer"))
                         .build();
-                Log.d(TAG, "n.sound=" + n.sound);
 
                 mNM.notify(1, n);
-                SystemClock.sleep(200);
+                SystemClock.sleep(600);
                 mNM.cancel(1);
             }
         },
 
-        new Test("Vibrate") {
-            public void run()
-            {
-                Notification n = new Notification.Builder(NotificationTestList.this)
-                        .setSmallIcon(R.drawable.stat_sys_phone)
-                        .setContentTitle(name)
-                        .setVibrate(new long[]{0, 700, 500, 1000})
-                        .build();
-
-                mNM.notify(1, n);
-            }
-        },
-
         new Test("Vibrate and cancel") {
             public void run()
             {
-                Notification n = new Notification.Builder(NotificationTestList.this)
+                NotificationChannel channel = new NotificationChannel("vibrate",
+                        "vibrate", IMPORTANCE_DEFAULT);
+                channel.enableVibration(true);
+                channel.setVibrationPattern(new long[] {0, 700, 500, 1000, 0, 700, 500, 1000,
+                        0, 700, 500, 1000, 0, 700, 500, 1000, 0, 700, 500, 1000, 0, 700, 500, 1000,
+                        0, 700, 500, 1000, 0, 700, 500, 1000});
+                mNM.createNotificationChannel(channel);
+
+                Notification n = new Notification.Builder(NotificationTestList.this, "vibrate")
                         .setSmallIcon(R.drawable.stat_sys_phone)
                         .setContentTitle(name)
-                        .setVibrate(new long[]{0, 700, 500, 1000})
                         .build();
 
                 mNM.notify(1, n);
@@ -960,7 +876,8 @@
                                         + "Sometimes."
                                         + "Ohandwhathappensifwehaveonereallylongstringarewesure"
                                         + "thatwesegmentitcorrectly?\n";
-                                Notification n = new Notification.Builder(NotificationTestList.this)
+                                Notification n = new Notification.Builder(
+                                        NotificationTestList.this, "low")
                                         .setSmallIcon(R.drawable.icon1)
                                         .setContentTitle(name)
                                         .setContentText("This is still a notification!!!")
@@ -975,7 +892,7 @@
 
         new Test("Persistent #2") {
             public void run() {
-                Notification n = new Notification.Builder(NotificationTestList.this)
+                Notification n = new Notification.Builder(NotificationTestList.this, "low")
                         .setSmallIcon(R.drawable.icon1)
                         .setWhen(mActivityCreateTime)
                         .setContentTitle(name)
@@ -988,7 +905,7 @@
 
         new Test("Persistent #3") {
             public void run() {
-                Notification n = new Notification.Builder(NotificationTestList.this)
+                Notification n = new Notification.Builder(NotificationTestList.this, "low")
                         .setSmallIcon(R.drawable.icon1)
                         .setWhen(mActivityCreateTime)
                         .setContentTitle(name)
@@ -1001,7 +918,7 @@
 
         new Test("Persistent #2 Vibrate") {
             public void run() {
-                Notification n = new Notification.Builder(NotificationTestList.this)
+                Notification n = new Notification.Builder(NotificationTestList.this, "low")
                         .setSmallIcon(R.drawable.icon1)
                         .setWhen(mActivityCreateTime)
                         .setContentTitle(name)
@@ -1015,7 +932,7 @@
 
         new Test("Persistent #1 - different icon") {
             public void run() {
-                Notification n = new Notification.Builder(NotificationTestList.this)
+                Notification n = new Notification.Builder(NotificationTestList.this, "low")
                         .setSmallIcon(R.drawable.icon2)
                         .setWhen(mActivityCreateTime)
                         .setContentTitle(name)
@@ -1028,7 +945,7 @@
 
         new Test("Chronometer Start") {
             public void run() {
-                Notification n = new Notification.Builder(NotificationTestList.this)
+                Notification n = new Notification.Builder(NotificationTestList.this, "low")
                         .setSmallIcon(R.drawable.icon1)
                         .setWhen(System.currentTimeMillis())
                         .setContentTitle(name)
@@ -1045,7 +962,8 @@
                 mHandler.postDelayed(new Runnable() {
                         public void run() {
                             Log.d(TAG, "Chronometer Stop");
-                            Notification n = new Notification.Builder(NotificationTestList.this)
+                            Notification n = new Notification.Builder(
+                                    NotificationTestList.this, "low")
                                     .setSmallIcon(R.drawable.icon1)
                                     .setWhen(System.currentTimeMillis())
                                     .setContentTitle(name)
@@ -1103,7 +1021,7 @@
         new Test("Ten Notifications") {
             public void run() {
                 for (int i = 0; i < 10; i++) {
-                    Notification n = new Notification.Builder(NotificationTestList.this)
+                    Notification n = new Notification.Builder(NotificationTestList.this, "low")
                             .setSmallIcon(kNumberedIconResIDs[i])
                             .setContentTitle("Persistent #" + i)
                             .setContentText("Notify me!!!" + i)
@@ -1154,90 +1072,12 @@
             }
         },
 
-        new Test("PRIORITY_HIGH") {
-            public void run() {
-                Notification n = new Notification.Builder(NotificationTestList.this)
-                    .setSmallIcon(R.drawable.notification5)
-                    .setContentTitle("High priority")
-                    .setContentText("This should appear before all others")
-                    .setPriority(Notification.PRIORITY_HIGH)
-                    .build();
-
-                int[] idOut = new int[1];
-                try {
-                    INotificationManager directLine = mNM.getService();
-                    directLine.enqueueNotificationWithTag(
-                            getPackageName(),
-                            getPackageName(),
-                            null, 
-                            100, 
-                            n,
-                            idOut,
-                            UserHandle.myUserId());
-                } catch (android.os.RemoteException ex) {
-                    // oh well
-                }
-            }
-        },
-
-        new Test("PRIORITY_MAX") {
-            public void run() {
-                Notification n = new Notification.Builder(NotificationTestList.this)
-                    .setSmallIcon(R.drawable.notification9)
-                    .setContentTitle("MAX priority")
-                    .setContentText("This might appear as an intruder alert")
-                    .setPriority(Notification.PRIORITY_MAX)
-                    .build();
-
-                int[] idOut = new int[1];
-                try {
-                    INotificationManager directLine = mNM.getService();
-                    directLine.enqueueNotificationWithTag(
-                            getPackageName(),
-                            getPackageName(),
-                            null,
-                            200, 
-                            n,
-                            idOut,
-                            UserHandle.myUserId());
-                } catch (android.os.RemoteException ex) {
-                    // oh well
-                }
-            }
-        },
-
-        new Test("PRIORITY_MIN") {
-            public void run() {
-                Notification n = new Notification.Builder(NotificationTestList.this)
-                    .setSmallIcon(R.drawable.notification0)
-                    .setContentTitle("MIN priority")
-                    .setContentText("You should not see this")
-                    .setPriority(Notification.PRIORITY_MIN)
-                    .build();
-
-                int[] idOut = new int[1];
-                try {
-                    INotificationManager directLine = mNM.getService();
-                    directLine.enqueueNotificationWithTag(
-                            getPackageName(),
-                            getPackageName(),
-                            null,
-                            1, 
-                            n,
-                            idOut,
-                            UserHandle.myUserId());
-                } catch (android.os.RemoteException ex) {
-                    // oh well
-                }
-            }
-        },
-
         new Test("Crash") {
             public void run()
             {
-                PowerManager.WakeLock wl
-                        = ((PowerManager)NotificationTestList.this.getSystemService(Context.POWER_SERVICE))
-                            .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "crasher");
+                PowerManager.WakeLock wl =
+                        ((PowerManager) NotificationTestList.this.getSystemService(Context.POWER_SERVICE))
+                                .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "crasher");
                 wl.acquire();
                 mHandler.postDelayed(new Runnable() {
                             public void run() {
@@ -1251,7 +1091,7 @@
     };
 
     private Notification notificationWithNumbers(String name, int num) {
-        Notification n = new Notification.Builder(NotificationTestList.this)
+        Notification n = new Notification.Builder(NotificationTestList.this, "low")
                 .setSmallIcon((num >= 0 && num < kNumberedIconResIDs.length)
                         ? kNumberedIconResIDs[num]
                         : kUnnumberedIconResID)
@@ -1306,7 +1146,7 @@
     }
 
     void timeNotification(int n, String label, long time) {
-        mNM.notify(n, new Notification.Builder(NotificationTestList.this)
+        mNM.notify(n, new Notification.Builder(NotificationTestList.this, "low")
                 .setSmallIcon(R.drawable.ic_statusbar_missedcall)
                 .setWhen(time)
                 .setContentTitle(label)
diff --git a/tests/TtsTests/Android.mk b/tests/TtsTests/Android.mk
index ed63e12..3c3cd77 100644
--- a/tests/TtsTests/Android.mk
+++ b/tests/TtsTests/Android.mk
@@ -20,7 +20,7 @@
 
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
-LOCAL_STATIC_JAVA_LIBRARIES := littlemock junit legacy-android-test
+LOCAL_STATIC_JAVA_LIBRARIES := mockito-target legacy-android-test
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
 LOCAL_PACKAGE_NAME := TtsTests
diff --git a/tests/TtsTests/src/com/android/speech/tts/TextToSpeechTests.java b/tests/TtsTests/src/com/android/speech/tts/TextToSpeechTests.java
index faf6827..918873b 100644
--- a/tests/TtsTests/src/com/android/speech/tts/TextToSpeechTests.java
+++ b/tests/TtsTests/src/com/android/speech/tts/TextToSpeechTests.java
@@ -22,9 +22,12 @@
 import android.test.InstrumentationTestCase;
 
 import com.android.speech.tts.MockableTextToSpeechService.IDelegate;
-import com.google.testing.littlemock.ArgumentCaptor;
-import com.google.testing.littlemock.Behaviour;
-import com.google.testing.littlemock.LittleMock;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+import org.mockito.internal.stubbing.StubberImpl;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.Stubber;
 import junit.framework.Assert;
 
 import java.util.Locale;
@@ -40,16 +43,16 @@
 
     @Override
     public void setUp() throws Exception {
-        IDelegate passThrough = LittleMock.mock(IDelegate.class);
+        IDelegate passThrough = Mockito.mock(IDelegate.class);
         MockableTextToSpeechService.setMocker(passThrough);
 
         // For the default voice selection
-        LittleMock.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).when(passThrough)
+        Mockito.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).when(passThrough)
             .onIsLanguageAvailable(
-                    LittleMock.anyString(), LittleMock.anyString(), LittleMock.anyString());
-        LittleMock.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).when(passThrough)
+                    Mockito.anyString(), Mockito.anyString(), Mockito.anyString());
+        Mockito.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).when(passThrough)
             .onLoadLanguage(
-                    LittleMock.anyString(), LittleMock.anyString(), LittleMock.anyString());
+                    Mockito.anyString(), Mockito.anyString(), Mockito.anyString());
 
         blockingInitAndVerify(MOCK_ENGINE, TextToSpeech.SUCCESS);
         assertEquals(MOCK_ENGINE, mTts.getCurrentEngine());
@@ -71,42 +74,42 @@
     }
 
     public void testSetLanguage_delegation() {
-        IDelegate delegate = LittleMock.mock(IDelegate.class);
+        IDelegate delegate = Mockito.mock(IDelegate.class);
         MockableTextToSpeechService.setMocker(delegate);
 
-        LittleMock.doReturn(TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE).when(delegate).onIsLanguageAvailable(
+        Mockito.doReturn(TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE).when(delegate).onIsLanguageAvailable(
                 "eng", "USA", "variant");
-        LittleMock.doReturn(TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE).when(delegate).onLoadLanguage(
+        Mockito.doReturn(TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE).when(delegate).onLoadLanguage(
                 "eng", "USA", "variant");
 
         // Test 1 :Tests that calls to onLoadLanguage( ) are delegated through to the
         // service without any caching or intermediate steps.
         assertEquals(TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE, mTts.setLanguage(new Locale("eng", "USA", "variant")));
-        LittleMock.verify(delegate, LittleMock.anyTimes()).onIsLanguageAvailable(
+        Mockito.verify(delegate, Mockito.atLeast(0)).onIsLanguageAvailable(
             "eng", "USA", "variant");
-        LittleMock.verify(delegate, LittleMock.anyTimes()).onLoadLanguage(
+        Mockito.verify(delegate, Mockito.atLeast(0)).onLoadLanguage(
             "eng", "USA", "variant");
     }
 
     public void testSetLanguage_availableLanguage() throws Exception {
-        IDelegate delegate = LittleMock.mock(IDelegate.class);
+        IDelegate delegate = Mockito.mock(IDelegate.class);
         MockableTextToSpeechService.setMocker(delegate);
 
         // ---------------------------------------------------------
         // Test 2 : Tests that when the language is successfully set
         // like above (returns LANG_COUNTRY_AVAILABLE). That the
         // request language changes from that point on.
-        LittleMock.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).when(delegate).onIsLanguageAvailable(
+        Mockito.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).when(delegate).onIsLanguageAvailable(
                 "eng", "USA", "variant");
-        LittleMock.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).when(delegate).onIsLanguageAvailable(
+        Mockito.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).when(delegate).onIsLanguageAvailable(
                 "eng", "USA", "");
-        LittleMock.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).when(delegate).onLoadLanguage(
+        Mockito.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).when(delegate).onLoadLanguage(
                 "eng", "USA", "");
         mTts.setLanguage(new Locale("eng", "USA", "variant"));
         blockingCallSpeak("foo bar", delegate);
-        ArgumentCaptor<SynthesisRequest> req = LittleMock.createCaptor();
-        LittleMock.verify(delegate, LittleMock.times(1)).onSynthesizeText(req.capture(),
-                LittleMock.<SynthesisCallback>anyObject());
+        ArgumentCaptor<SynthesisRequest> req = ArgumentCaptor.forClass(SynthesisRequest.class);
+        Mockito.verify(delegate, Mockito.times(1)).onSynthesizeText(req.capture(),
+                Mockito.<SynthesisCallback>anyObject());
 
         assertEquals("eng", req.getValue().getLanguage());
         assertEquals("USA", req.getValue().getCountry());
@@ -115,21 +118,21 @@
     }
 
     public void testSetLanguage_unavailableLanguage() throws Exception {
-        IDelegate delegate = LittleMock.mock(IDelegate.class);
+        IDelegate delegate = Mockito.mock(IDelegate.class);
         MockableTextToSpeechService.setMocker(delegate);
 
         // ---------------------------------------------------------
         // TEST 3 : Tests that the language that is set does not change when the
         // engine reports it could not load the specified language.
-        LittleMock.doReturn(TextToSpeech.LANG_NOT_SUPPORTED).when(
+        Mockito.doReturn(TextToSpeech.LANG_NOT_SUPPORTED).when(
                 delegate).onIsLanguageAvailable("fra", "FRA", "");
-        LittleMock.doReturn(TextToSpeech.LANG_NOT_SUPPORTED).when(
+        Mockito.doReturn(TextToSpeech.LANG_NOT_SUPPORTED).when(
                 delegate).onLoadLanguage("fra", "FRA", "");
         mTts.setLanguage(Locale.FRANCE);
         blockingCallSpeak("le fou barre", delegate);
-        ArgumentCaptor<SynthesisRequest> req2 = LittleMock.createCaptor();
-        LittleMock.verify(delegate, LittleMock.times(1)).onSynthesizeText(req2.capture(),
-                        LittleMock.<SynthesisCallback>anyObject());
+        ArgumentCaptor<SynthesisRequest> req2 = ArgumentCaptor.forClass(SynthesisRequest.class);
+        Mockito.verify(delegate, Mockito.times(1)).onSynthesizeText(req2.capture(),
+                        Mockito.<SynthesisCallback>anyObject());
 
         // The params are basically unchanged.
         assertEquals("eng", req2.getValue().getLanguage());
@@ -139,41 +142,41 @@
     }
 
     public void testIsLanguageAvailable() {
-        IDelegate delegate = LittleMock.mock(IDelegate.class);
+        IDelegate delegate = Mockito.mock(IDelegate.class);
         MockableTextToSpeechService.setMocker(delegate);
 
         // Test1: Simple end to end test.
-        LittleMock.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).when(
+        Mockito.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).when(
                 delegate).onIsLanguageAvailable("eng", "USA", "");
 
         assertEquals(TextToSpeech.LANG_COUNTRY_AVAILABLE, mTts.isLanguageAvailable(Locale.US));
-        LittleMock.verify(delegate, LittleMock.times(1)).onIsLanguageAvailable(
+        Mockito.verify(delegate, Mockito.times(1)).onIsLanguageAvailable(
                 "eng", "USA", "");
     }
 
     public void testDefaultLanguage_setsVoiceName() throws Exception {
-        IDelegate delegate = LittleMock.mock(IDelegate.class);
+        IDelegate delegate = Mockito.mock(IDelegate.class);
         MockableTextToSpeechService.setMocker(delegate);
         Locale defaultLocale = Locale.getDefault();
 
         // ---------------------------------------------------------
         // Test that default language also sets the default voice
         // name
-        LittleMock.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).
+        Mockito.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).
             when(delegate).onIsLanguageAvailable(
                 defaultLocale.getISO3Language(),
                 defaultLocale.getISO3Country().toUpperCase(),
                 defaultLocale.getVariant());
-        LittleMock.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).
+        Mockito.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).
             when(delegate).onLoadLanguage(
                 defaultLocale.getISO3Language(),
                 defaultLocale.getISO3Country(),
                 defaultLocale.getVariant());
 
         blockingCallSpeak("foo bar", delegate);
-        ArgumentCaptor<SynthesisRequest> req = LittleMock.createCaptor();
-        LittleMock.verify(delegate, LittleMock.times(1)).onSynthesizeText(req.capture(),
-                LittleMock.<SynthesisCallback>anyObject());
+        ArgumentCaptor<SynthesisRequest> req = ArgumentCaptor.forClass(SynthesisRequest.class);
+        Mockito.verify(delegate, Mockito.times(1)).onSynthesizeText(req.capture(),
+                Mockito.<SynthesisCallback>anyObject());
 
         assertEquals(defaultLocale.getISO3Language(), req.getValue().getLanguage());
         assertEquals(defaultLocale.getISO3Country(), req.getValue().getCountry());
@@ -185,8 +188,8 @@
     private void blockingCallSpeak(String speech, IDelegate mock) throws
             InterruptedException {
         final CountDownLatch latch = new CountDownLatch(1);
-        doCountDown(latch).when(mock).onSynthesizeText(LittleMock.<SynthesisRequest>anyObject(),
-                LittleMock.<SynthesisCallback>anyObject());
+        doCountDown(latch).when(mock).onSynthesizeText(Mockito.<SynthesisRequest>anyObject(),
+                Mockito.<SynthesisCallback>anyObject());
         mTts.speak(speech, TextToSpeech.QUEUE_ADD, null);
 
         awaitCountDown(latch, 5, TimeUnit.SECONDS);
@@ -194,7 +197,7 @@
 
     private void blockingInitAndVerify(final String engine, int errorCode) throws
             InterruptedException {
-        TextToSpeech.OnInitListener listener = LittleMock.mock(
+        TextToSpeech.OnInitListener listener = Mockito.mock(
                 TextToSpeech.OnInitListener.class);
 
         final CountDownLatch latch = new CountDownLatch(1);
@@ -206,18 +209,18 @@
         awaitCountDown(latch, 5, TimeUnit.SECONDS);
     }
 
-    public interface CountDownBehaviour extends Behaviour {
+    public static abstract class CountDownBehaviour extends StubberImpl {
         /** Used to mock methods that return a result. */
-        Behaviour andReturn(Object result);
+        public abstract Stubber andReturn(Object result);
     }
 
     public static CountDownBehaviour doCountDown(final CountDownLatch latch) {
         return new CountDownBehaviour() {
             @Override
             public <T> T when(T mock) {
-                return LittleMock.doAnswer(new Callable<Void>() {
+                return Mockito.doAnswer(new Answer<Void>() {
                     @Override
-                    public Void call() throws Exception {
+                    public Void answer(InvocationOnMock invocation) throws Exception {
                         latch.countDown();
                         return null;
                     }
@@ -225,13 +228,13 @@
             }
 
             @Override
-            public Behaviour andReturn(final Object result) {
-                return new Behaviour() {
+            public Stubber andReturn(final Object result) {
+                return new StubberImpl() {
                     @Override
                     public <T> T when(T mock) {
-                        return LittleMock.doAnswer(new Callable<Object>() {
+                        return Mockito.doAnswer(new Answer<Object>() {
                             @Override
-                            public Object call() throws Exception {
+                            public Object answer(InvocationOnMock invocation) throws Exception {
                                 latch.countDown();
                                 return result;
                             }
diff --git a/tests/net/Android.mk b/tests/net/Android.mk
index 8aa27a9..79f6e4d 100644
--- a/tests/net/Android.mk
+++ b/tests/net/Android.mk
@@ -40,7 +40,19 @@
     libnetdaidl \
     libui \
     libunwind \
-    libutils
+    libutils \
+    libcrypto \
+    libhidl-gen-utils \
+    libhidlbase \
+    libhidltransport \
+    libpackagelistparser \
+    libpcre2 \
+    libselinux \
+    libtinyxml2 \
+    libvintf \
+    libhwbinder \
+    android.hidl.base@1.0 \
+    android.hidl.token@1.0
 
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index eeaf26f..04443a5 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -369,6 +369,11 @@
             connect(false);
         }
 
+        public void suspend() {
+            mNetworkInfo.setDetailedState(DetailedState.SUSPENDED, null, null);
+            mNetworkAgent.sendNetworkInfo(mNetworkInfo);
+        }
+
         public void disconnect() {
             mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
@@ -1054,6 +1059,7 @@
         AVAILABLE,
         NETWORK_CAPABILITIES,
         LINK_PROPERTIES,
+        SUSPENDED,
         LOSING,
         LOST,
         UNAVAILABLE
@@ -1067,7 +1073,7 @@
             state = s; network = n; arg = o;
         }
         public String toString() {
-            return String.format("%s (%s)", state, network);
+            return String.format("%s (%s) (%s)", state, network, arg);
         }
         @Override
         public boolean equals(Object o) {
@@ -1105,11 +1111,26 @@
         }
 
         @Override
+        public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) {
+            setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap);
+        }
+
+        @Override
+        public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) {
+            setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp);
+        }
+
+        @Override
         public void onUnavailable() {
             setLastCallback(CallbackState.UNAVAILABLE, null, null);
         }
 
         @Override
+        public void onNetworkSuspended(Network network) {
+            setLastCallback(CallbackState.SUSPENDED, network, null);
+        }
+
+        @Override
         public void onLosing(Network network, int maxMsToLive) {
             setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
         }
@@ -1132,11 +1153,12 @@
             return cb;
         }
 
-        void expectCallback(CallbackState state, MockNetworkAgent mockAgent, int timeoutMs) {
-            CallbackInfo expected = new CallbackInfo(
-                    state, (mockAgent != null) ? mockAgent.getNetwork() : null, 0);
+        CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent, int timeoutMs) {
+            final Network expectedNetwork = (agent != null) ? agent.getNetwork() : null;
+            CallbackInfo expected = new CallbackInfo(state, expectedNetwork, 0);
             CallbackInfo actual = nextCallback(timeoutMs);
             assertEquals("Unexpected callback:", expected, actual);
+
             if (state == CallbackState.LOSING) {
                 String msg = String.format(
                         "Invalid linger time value %d, must be between %d and %d",
@@ -1144,10 +1166,46 @@
                 int maxMsToLive = (Integer) actual.arg;
                 assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= TEST_LINGER_DELAY_MS);
             }
+
+            return actual;
         }
 
-        void expectCallback(CallbackState state, MockNetworkAgent mockAgent) {
-            expectCallback(state, mockAgent, TIMEOUT_MS);
+        CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent) {
+            return expectCallback(state, agent, TIMEOUT_MS);
+        }
+
+        void expectAvailableCallbacks(MockNetworkAgent agent, boolean expectSuspended, int timeoutMs) {
+            expectCallback(CallbackState.AVAILABLE, agent, timeoutMs);
+            if (expectSuspended) {
+                expectCallback(CallbackState.SUSPENDED, agent, timeoutMs);
+            }
+            expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
+            expectCallback(CallbackState.LINK_PROPERTIES, agent, timeoutMs);
+        }
+
+        void expectAvailableCallbacks(MockNetworkAgent agent) {
+            expectAvailableCallbacks(agent, false, TIMEOUT_MS);
+        }
+
+        void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent) {
+            expectAvailableCallbacks(agent, true, TIMEOUT_MS);
+        }
+
+        void expectAvailableAndValidatedCallbacks(MockNetworkAgent agent) {
+            expectAvailableCallbacks(agent, false, TIMEOUT_MS);
+            expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
+        }
+
+        void expectCapabilitiesWith(int capability, MockNetworkAgent agent) {
+            CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent);
+            NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
+            assertTrue(nc.hasCapability(capability));
+        }
+
+        void expectCapabilitiesWithout(int capability, MockNetworkAgent agent) {
+            CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent);
+            NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
+            assertFalse(nc.hasCapability(capability));
         }
 
         void assertNoCallback() {
@@ -1184,8 +1242,8 @@
         ConditionVariable cv = waitForConnectivityBroadcasts(1);
         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
         mCellNetworkAgent.connect(false);
-        genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
-        cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+        genericNetworkCallback.expectAvailableCallbacks(mCellNetworkAgent);
+        cellNetworkCallback.expectAvailableCallbacks(mCellNetworkAgent);
         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
         waitFor(cv);
         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
@@ -1199,8 +1257,8 @@
         cv = waitForConnectivityBroadcasts(2);
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
         mWiFiNetworkAgent.connect(false);
-        genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
-        wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+        genericNetworkCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
+        wifiNetworkCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
         waitFor(cv);
         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
@@ -1223,8 +1281,8 @@
         // Test validated networks
         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
         mCellNetworkAgent.connect(true);
-        genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
-        cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+        genericNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
+        cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
 
@@ -1236,9 +1294,10 @@
 
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
         mWiFiNetworkAgent.connect(true);
-        genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+        genericNetworkCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
         genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
-        wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+        genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
+        wifiNetworkCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
         cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
         assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
@@ -1274,28 +1333,32 @@
         mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
 
         mCellNetworkAgent.connect(true);
-        callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
-        defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+        callback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
+        defaultCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
 
         mWiFiNetworkAgent.connect(true);
         // We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
         // We then get LOSING when wifi validates and cell is outscored.
-        callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+        callback.expectAvailableCallbacks(mWiFiNetworkAgent);
+        // TODO: Investigate sending validated before losing.
         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
-        defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+        callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
+        defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
 
         mEthernetNetworkAgent.connect(true);
-        callback.expectCallback(CallbackState.AVAILABLE, mEthernetNetworkAgent);
+        callback.expectAvailableCallbacks(mEthernetNetworkAgent);
+        // TODO: Investigate sending validated before losing.
         callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
-        defaultCallback.expectCallback(CallbackState.AVAILABLE, mEthernetNetworkAgent);
+        callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
+        defaultCallback.expectAvailableAndValidatedCallbacks(mEthernetNetworkAgent);
         assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
 
         mEthernetNetworkAgent.disconnect();
         callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
         defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
-        defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+        defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
 
         for (int i = 0; i < 4; i++) {
             MockNetworkAgent oldNetwork, newNetwork;
@@ -1312,7 +1375,7 @@
             callback.expectCallback(CallbackState.LOSING, oldNetwork);
             // TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
             // longer lingering?
-            defaultCallback.expectCallback(CallbackState.AVAILABLE, newNetwork);
+            defaultCallback.expectAvailableCallbacks(newNetwork);
             assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
         }
         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
@@ -1320,17 +1383,19 @@
         // Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
         // if the network is still up.
         mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
+        // We expect a notification about the capabilities change, and nothing else.
+        defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
+        defaultCallback.assertNoCallback();
         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
 
         // Wifi no longer satisfies our listen, which is for an unmetered network.
         // But because its score is 55, it's still up (and the default network).
-        defaultCallback.assertNoCallback();
         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
 
         // Disconnect our test networks.
         mWiFiNetworkAgent.disconnect();
         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
-        defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+        defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
         mCellNetworkAgent.disconnect();
         defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
 
@@ -1346,22 +1411,22 @@
 
         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
         mCellNetworkAgent.connect(false);   // Score: 10
-        callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
-        defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+        callback.expectAvailableCallbacks(mCellNetworkAgent);
+        defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
 
         // Bring up wifi with a score of 20.
         // Cell stays up because it would satisfy the default request if it validated.
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
         mWiFiNetworkAgent.connect(false);   // Score: 20
-        callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
-        defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+        callback.expectAvailableCallbacks(mWiFiNetworkAgent);
+        defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
 
         mWiFiNetworkAgent.disconnect();
         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
-        defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+        defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
 
         // Bring up wifi with a score of 70.
@@ -1369,31 +1434,33 @@
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
         mWiFiNetworkAgent.adjustScore(50);
         mWiFiNetworkAgent.connect(false);   // Score: 70
-        callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+        callback.expectAvailableCallbacks(mWiFiNetworkAgent);
         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
-        defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+        defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
 
         // Tear down wifi.
         mWiFiNetworkAgent.disconnect();
         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
-        defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+        defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
 
         // Bring up wifi, then validate it. Previous versions would immediately tear down cell, but
         // it's arguably correct to linger it, since it was the default network before it validated.
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
         mWiFiNetworkAgent.connect(true);
-        callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+        callback.expectAvailableCallbacks(mWiFiNetworkAgent);
+        // TODO: Investigate sending validated before losing.
         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
-        defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+        callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
+        defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
 
         mWiFiNetworkAgent.disconnect();
         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
-        defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+        defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
         mCellNetworkAgent.disconnect();
         callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
         defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
@@ -1401,13 +1468,15 @@
         // If a network is lingering, and we add and remove a request from it, resume lingering.
         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
         mCellNetworkAgent.connect(true);
-        callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
-        defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+        callback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
+        defaultCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
         mWiFiNetworkAgent.connect(true);
-        callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
-        defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+        defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
+        callback.expectAvailableCallbacks(mWiFiNetworkAgent);
+        // TODO: Investigate sending validated before losing.
         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+        callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
 
         NetworkRequest cellRequest = new NetworkRequest.Builder()
                 .addTransportType(TRANSPORT_CELLULAR).build();
@@ -1423,7 +1492,7 @@
         mWiFiNetworkAgent.disconnect();
         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
         defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
-        defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+        defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
 
         // Cell is now the default network. Pin it with a cell-specific request.
         noopCallback = new NetworkCallback();  // Can't reuse NetworkCallbacks. http://b/20701525
@@ -1432,8 +1501,8 @@
         // Now connect wifi, and expect it to become the default network.
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
         mWiFiNetworkAgent.connect(true);
-        callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
-        defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+        callback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
+        defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
         // The default request is lingering on cell, but nothing happens to cell, and we send no
         // callbacks for it, because it's kept up by cellRequest.
         callback.assertNoCallback();
@@ -1619,7 +1688,7 @@
         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
         mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
         mCellNetworkAgent.connectWithoutInternet();
-        networkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+        networkCallback.expectAvailableCallbacks(mCellNetworkAgent);
         verifyActiveNetwork(TRANSPORT_WIFI);
         // Test releasing NetworkRequest disconnects cellular with MMS
         cv = mCellNetworkAgent.getDisconnectedCV();
@@ -1645,7 +1714,7 @@
         MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
         mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
         mmsNetworkAgent.connectWithoutInternet();
-        networkCallback.expectCallback(CallbackState.AVAILABLE, mmsNetworkAgent);
+        networkCallback.expectAvailableCallbacks(mmsNetworkAgent);
         verifyActiveNetwork(TRANSPORT_CELLULAR);
         // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
         cv = mmsNetworkAgent.getDisconnectedCV();
@@ -1671,7 +1740,7 @@
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
         String firstRedirectUrl = "http://example.com/firstPath";
         mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
-        captivePortalCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+        captivePortalCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
         assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
 
         // Take down network.
@@ -1684,7 +1753,7 @@
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
         String secondRedirectUrl = "http://example.com/secondPath";
         mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
-        captivePortalCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+        captivePortalCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
         assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
 
         // Make captive portal disappear then revalidate.
@@ -1694,7 +1763,9 @@
         captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
 
         // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
-        validatedCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+        validatedCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
+        // TODO: Investigate only sending available callbacks.
+        validatedCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
 
         // Break network connectivity.
         // Expect NET_CAPABILITY_VALIDATED onLost callback.
@@ -1739,7 +1810,7 @@
         mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
 
         // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
-        validatedCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+        validatedCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
         // But there should be no CaptivePortal callback.
         captivePortalCallback.assertNoCallback();
     }
@@ -1792,14 +1863,14 @@
         // Bring up cell and expect CALLBACK_AVAILABLE.
         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
         mCellNetworkAgent.connect(true);
-        cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
-        defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+        cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
+        defaultNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
 
         // Bring up wifi and expect CALLBACK_AVAILABLE.
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
         mWiFiNetworkAgent.connect(true);
         cellNetworkCallback.assertNoCallback();
-        defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+        defaultNetworkCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
 
         // Bring down cell. Expect no default network callback, since it wasn't the default.
         mCellNetworkAgent.disconnect();
@@ -1809,7 +1880,7 @@
         // Bring up cell. Expect no default network callback, since it won't be the default.
         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
         mCellNetworkAgent.connect(true);
-        cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+        cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
         defaultNetworkCallback.assertNoCallback();
 
         // Bring down wifi. Expect the default network callback to notified of LOST wifi
@@ -1817,28 +1888,16 @@
         mWiFiNetworkAgent.disconnect();
         cellNetworkCallback.assertNoCallback();
         defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
-        defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+        defaultNetworkCallback.expectAvailableCallbacks(mCellNetworkAgent);
         mCellNetworkAgent.disconnect();
         cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
         defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
     }
 
-    private class TestRequestUpdateCallback extends TestNetworkCallback {
-        @Override
-        public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) {
-            setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap);
-        }
-
-        @Override
-        public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) {
-            setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp);
-        }
-    }
-
     @SmallTest
-    public void testRequestCallbackUpdates() throws Exception {
+    public void testAdditionalStateCallbacks() throws Exception {
         // File a network request for mobile.
-        final TestNetworkCallback cellNetworkCallback = new TestRequestUpdateCallback();
+        final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
         final NetworkRequest cellRequest = new NetworkRequest.Builder()
                 .addTransportType(TRANSPORT_CELLULAR).build();
         mCm.requestNetwork(cellRequest, cellNetworkCallback);
@@ -1847,10 +1906,10 @@
         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
         mCellNetworkAgent.connect(true);
 
-        // We should get onAvailable().
-        cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
-        // We should get onCapabilitiesChanged(), when the mobile network successfully validates.
-        cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, mCellNetworkAgent);
+        // We should get onAvailable(), onCapabilitiesChanged(), and
+        // onLinkPropertiesChanged() in rapid succession. Additionally, we
+        // should get onCapabilitiesChanged() when the mobile network validates.
+        cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
         cellNetworkCallback.assertNoCallback();
 
         // Update LinkProperties.
@@ -1861,23 +1920,17 @@
         cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
         cellNetworkCallback.assertNoCallback();
 
+        // Suspend the network.
+        mCellNetworkAgent.suspend();
+        cellNetworkCallback.expectCallback(CallbackState.SUSPENDED, mCellNetworkAgent);
+        cellNetworkCallback.assertNoCallback();
+
         // Register a garden variety default network request.
-        final TestNetworkCallback dfltNetworkCallback = new TestRequestUpdateCallback();
+        final TestNetworkCallback dfltNetworkCallback = new TestNetworkCallback();
         mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
-        // Only onAvailable() is called; no other information is delivered.
-        dfltNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
-        dfltNetworkCallback.assertNoCallback();
-
-        // Request a NetworkCapabilities update; only the requesting callback is notified.
-        mCm.requestNetworkCapabilities(dfltNetworkCallback);
-        dfltNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, mCellNetworkAgent);
-        cellNetworkCallback.assertNoCallback();
-        dfltNetworkCallback.assertNoCallback();
-
-        // Request a LinkProperties update; only the requesting callback is notified.
-        mCm.requestLinkProperties(dfltNetworkCallback);
-        dfltNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
-        cellNetworkCallback.assertNoCallback();
+        // We should get onAvailable(), onCapabilitiesChanged(), onLinkPropertiesChanged(),
+        // as well as onNetworkSuspended() in rapid succession.
+        dfltNetworkCallback.expectAvailableAndSuspendedCallbacks(mCellNetworkAgent);
         dfltNetworkCallback.assertNoCallback();
 
         mCm.unregisterNetworkCallback(dfltNetworkCallback);
@@ -1917,18 +1970,20 @@
 
         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
         mCellNetworkAgent.connect(true);
-        callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
-        fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+        callback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
+        fgCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
         assertTrue(isForegroundNetwork(mCellNetworkAgent));
 
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
         mWiFiNetworkAgent.connect(true);
 
         // When wifi connects, cell lingers.
-        callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
-        fgCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+        callback.expectAvailableCallbacks(mWiFiNetworkAgent);
         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+        callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
+        fgCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
         fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+        fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
         assertTrue(isForegroundNetwork(mCellNetworkAgent));
         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
 
@@ -1936,7 +1991,8 @@
         mService.waitForIdle();
         int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
         fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, timeoutMs);
-        callback.assertNoCallback();
+        // Expect a network capabilities update sans FOREGROUND.
+        callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
         assertFalse(isForegroundNetwork(mCellNetworkAgent));
         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
 
@@ -1945,9 +2001,15 @@
                 .addTransportType(TRANSPORT_CELLULAR).build();
         final TestNetworkCallback cellCallback = new TestNetworkCallback();
         mCm.requestNetwork(cellRequest, cellCallback);
-        cellCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
-        fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
-        callback.assertNoCallback();  // Because the network is already up.
+        // NOTE: This request causes the network's capabilities to change. This
+        // is currently delivered before the onAvailable() callbacks.
+        // TODO: Fix this.
+        cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
+        cellCallback.expectAvailableCallbacks(mCellNetworkAgent);
+        fgCallback.expectAvailableCallbacks(mCellNetworkAgent);
+        // Expect a network capabilities update with FOREGROUND, because the most recent
+        // request causes its state to change.
+        callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
         assertTrue(isForegroundNetwork(mCellNetworkAgent));
         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
 
@@ -1955,7 +2017,8 @@
         // lingering.
         mCm.unregisterNetworkCallback(cellCallback);
         fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
-        callback.assertNoCallback();
+        // Expect a network capabilities update sans FOREGROUND.
+        callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
         assertFalse(isForegroundNetwork(mCellNetworkAgent));
         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
 
@@ -1963,7 +2026,7 @@
         mWiFiNetworkAgent.disconnect();
         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
         fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
-        fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+        fgCallback.expectAvailableCallbacks(mCellNetworkAgent);
         assertTrue(isForegroundNetwork(mCellNetworkAgent));
 
         mCm.unregisterNetworkCallback(callback);
@@ -2104,7 +2167,7 @@
         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
         testFactory.expectAddRequests(2);  // Because the cell request changes score twice.
         mCellNetworkAgent.connect(true);
-        cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+        cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
         testFactory.waitForNetworkRequests(2);
         assertFalse(testFactory.getMyStartRequested());  // Because the cell network outscores us.
 
@@ -2195,20 +2258,22 @@
         // Bring up validated cell.
         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
         mCellNetworkAgent.connect(true);
-        cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
-        defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+        cellNetworkCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
+        defaultCallback.expectAvailableAndValidatedCallbacks(mCellNetworkAgent);
         Network cellNetwork = mCellNetworkAgent.getNetwork();
 
         // Bring up validated wifi.
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
         mWiFiNetworkAgent.connect(true);
-        defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
-        validatedWifiCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+        defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
+        validatedWifiCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
+        validatedWifiCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
         Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
 
         // Fail validation on wifi.
         mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
         mCm.reportNetworkConnectivity(wifiNetwork, false);
+        defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
         validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
 
         // Because avoid bad wifi is off, we don't switch to cellular.
@@ -2223,18 +2288,18 @@
         // that we switch back to cell.
         tracker.configRestrictsAvoidBadWifi = false;
         tracker.reevaluate();
-        defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+        defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
         assertEquals(mCm.getActiveNetwork(), cellNetwork);
 
         // Switch back to a restrictive carrier.
         tracker.configRestrictsAvoidBadWifi = true;
         tracker.reevaluate();
-        defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+        defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
 
         // Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
         mCm.setAvoidUnvalidated(wifiNetwork);
-        defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+        defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
                 NET_CAPABILITY_VALIDATED));
         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
@@ -2245,13 +2310,15 @@
         mWiFiNetworkAgent.disconnect();
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
         mWiFiNetworkAgent.connect(true);
-        defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
-        validatedWifiCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+        defaultCallback.expectAvailableAndValidatedCallbacks(mWiFiNetworkAgent);
+        validatedWifiCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
+        validatedWifiCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
         wifiNetwork = mWiFiNetworkAgent.getNetwork();
 
         // Fail validation on wifi and expect the dialog to appear.
         mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
         mCm.reportNetworkConnectivity(wifiNetwork, false);
+        defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
         validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
 
         // Simulate the user selecting "switch" and checking the don't ask again checkbox.
@@ -2259,7 +2326,7 @@
         tracker.reevaluate();
 
         // We now switch to cell.
-        defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+        defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
         assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
                 NET_CAPABILITY_VALIDATED));
         assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
@@ -2270,17 +2337,17 @@
         // We switch to wifi and then to cell.
         Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
         tracker.reevaluate();
-        defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+        defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
         assertEquals(mCm.getActiveNetwork(), wifiNetwork);
         Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
         tracker.reevaluate();
-        defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+        defaultCallback.expectAvailableCallbacks(mCellNetworkAgent);
         assertEquals(mCm.getActiveNetwork(), cellNetwork);
 
         // If cell goes down, we switch to wifi.
         mCellNetworkAgent.disconnect();
         defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
-        defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+        defaultCallback.expectAvailableCallbacks(mWiFiNetworkAgent);
         validatedWifiCallback.assertNoCallback();
 
         mCm.unregisterNetworkCallback(cellNetworkCallback);
@@ -2322,7 +2389,7 @@
 
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
         mWiFiNetworkAgent.connect(false);
-        networkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent, timeoutMs);
+        networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, timeoutMs);
 
         // pass timeout and validate that UNAVAILABLE is not called
         networkCallback.assertNoCallback();
@@ -2343,7 +2410,7 @@
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
         mWiFiNetworkAgent.connect(false);
         final int assertTimeoutMs = 150;
-        networkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent, assertTimeoutMs);
+        networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, assertTimeoutMs);
         sleepFor(20);
         mWiFiNetworkAgent.disconnect();
         networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
index 415911e..11105d6 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
@@ -43,6 +43,7 @@
 import java.util.Arrays;
 import junit.framework.TestCase;
 
+// TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto.
 public class IpConnectivityEventBuilderTest extends TestCase {
 
     @SmallTest
@@ -58,8 +59,11 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 1",
+                "  transports: 0",
                 "  default_network_event <",
                 "    network_id <",
                 "      network_id: 102",
@@ -89,8 +93,11 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 1",
+                "  transports: 0",
                 "  dhcp_event <",
                 "    duration_ms: 192",
                 "    if_name: \"wlan0\"",
@@ -112,8 +119,11 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 1",
+                "  transports: 0",
                 "  dhcp_event <",
                 "    duration_ms: 0",
                 "    if_name: \"wlan0\"",
@@ -137,8 +147,11 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 1",
+                "  transports: 0",
                 "  dns_lookup_batch <",
                 "    event_types: 1",
                 "    event_types: 1",
@@ -185,8 +198,11 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 1",
+                "  transports: 0",
                 "  ip_provisioning_event <",
                 "    event_type: 1",
                 "    if_name: \"wlan0\"",
@@ -208,8 +224,11 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 1",
+                "  transports: 0",
                 "  ip_reachability_event <",
                 "    event_type: 512",
                 "    if_name: \"wlan0\"",
@@ -231,8 +250,11 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 1",
+                "  transports: 0",
                 "  network_event <",
                 "    event_type: 5",
                 "    latency_ms: 20410",
@@ -258,8 +280,11 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 1",
+                "  transports: 0",
                 "  validation_probe_event <",
                 "    latency_ms: 40730",
                 "    network_id <",
@@ -287,11 +312,15 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 1",
+                "  transports: 0",
                 "  apf_program_event <",
                 "    current_ras: 9",
                 "    drop_multicast: true",
+                "    effective_lifetime: 0",
                 "    filtered_ras: 7",
                 "    has_ipv4_addr: true",
                 "    lifetime: 200",
@@ -319,8 +348,11 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 1",
+                "  transports: 0",
                 "  apf_statistics <",
                 "    dropped_ras: 2",
                 "    duration_ms: 45000",
@@ -328,6 +360,8 @@
                 "    max_program_size: 2048",
                 "    parse_errors: 2",
                 "    program_updates: 4",
+                "    program_updates_all: 0",
+                "    program_updates_allowing_multicast: 0",
                 "    received_ras: 10",
                 "    zero_lifetime_ras: 1",
                 "  >",
@@ -351,8 +385,11 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 1",
+                "  transports: 0",
                 "  ra_event <",
                 "    dnssl_lifetime: -1",
                 "    prefix_preferred_lifetime: 300",
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
index f56f3f8..1f7c5f4 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
@@ -139,6 +139,7 @@
 
     @SmallTest
     public void testEndToEndLogging() {
+        // TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto.
         IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
 
         Parcelable[] events = {
@@ -158,16 +159,22 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 100",
+                "  transports: 0",
                 "  ip_reachability_event <",
                 "    event_type: 512",
                 "    if_name: \"wlan0\"",
                 "  >",
                 ">",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 200",
+                "  transports: 0",
                 "  dhcp_event <",
                 "    duration_ms: 192",
                 "    if_name: \"wlan0\"",
@@ -175,8 +182,11 @@
                 "  >",
                 ">",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 300",
+                "  transports: 0",
                 "  default_network_event <",
                 "    network_id <",
                 "      network_id: 102",
@@ -191,8 +201,11 @@
                 "  >",
                 ">",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 400",
+                "  transports: 0",
                 "  ip_provisioning_event <",
                 "    event_type: 1",
                 "    if_name: \"wlan0\"",
@@ -200,8 +213,11 @@
                 "  >",
                 ">",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 500",
+                "  transports: 0",
                 "  validation_probe_event <",
                 "    latency_ms: 40730",
                 "    network_id <",
@@ -212,8 +228,11 @@
                 "  >",
                 ">",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 600",
+                "  transports: 0",
                 "  apf_statistics <",
                 "    dropped_ras: 2",
                 "    duration_ms: 45000",
@@ -221,13 +240,18 @@
                 "    max_program_size: 2048",
                 "    parse_errors: 2",
                 "    program_updates: 4",
+                "    program_updates_all: 0",
+                "    program_updates_allowing_multicast: 0",
                 "    received_ras: 10",
                 "    zero_lifetime_ras: 1",
                 "  >",
                 ">",
                 "events <",
+                "  if_name: \"\"",
                 "  link_layer: 0",
+                "  network_id: 0",
                 "  time_ms: 700",
+                "  transports: 0",
                 "  ra_event <",
                 "    dnssl_lifetime: -1",
                 "    prefix_preferred_lifetime: 300",
diff --git a/tests/net/java/com/android/server/connectivity/MetricsTestUtil.java b/tests/net/java/com/android/server/connectivity/MetricsTestUtil.java
index e201012..c5965e8 100644
--- a/tests/net/java/com/android/server/connectivity/MetricsTestUtil.java
+++ b/tests/net/java/com/android/server/connectivity/MetricsTestUtil.java
@@ -17,101 +17,59 @@
 package com.android.server.connectivity;
 
 import android.net.ConnectivityMetricsEvent;
-import android.net.ConnectivityMetricsLogger;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.util.function.Consumer;
+
 abstract public class MetricsTestUtil {
     private MetricsTestUtil() {
     }
 
-    static ConnectivityMetricsEvent ipEv(Parcelable p) {
-        return ev(ConnectivityMetricsLogger.COMPONENT_TAG_CONNECTIVITY, p);
+    static ConnectivityMetricsEvent ev(Parcelable p) {
+        return new ConnectivityMetricsEvent(1L, 0, 0, p);
     }
 
-    static ConnectivityMetricsEvent telephonyEv() {
-        return ev(ConnectivityMetricsLogger.COMPONENT_TAG_TELEPHONY, new Bundle());
-    }
-
-    static ConnectivityMetricsEvent ev(int tag, Parcelable p) {
-        return new ConnectivityMetricsEvent(1L, tag, 0, p);
-    }
-
-    // Utiliy interface for describing the content of a Parcel. This relies on
-    // the implementation defails of Parcelable and on the fact that the fully
-    // qualified Parcelable class names are written as string in the Parcels.
-    interface ParcelField {
-        void write(Parcel p);
-    }
-
-    static ConnectivityMetricsEvent describeIpEvent(ParcelField... fs) {
+    static ConnectivityMetricsEvent describeIpEvent(Consumer<Parcel>... fs) {
         Parcel p = Parcel.obtain();
-        for (ParcelField f : fs) {
-            f.write(p);
+        for (Consumer<Parcel> f : fs) {
+            f.accept(p);
         }
         p.setDataPosition(0);
-        return ipEv(p.readParcelable(ClassLoader.getSystemClassLoader()));
+        return ev(p.readParcelable(ClassLoader.getSystemClassLoader()));
     }
 
-    static ParcelField aType(Class<?> c) {
-        return new ParcelField() {
-            public void write(Parcel p) {
-                p.writeString(c.getName());
-            }
-        };
+    static Consumer<Parcel> aType(Class<?> c) {
+        return aString(c.getName());
     }
 
-    static ParcelField aBool(boolean b) {
+    static Consumer<Parcel> aBool(boolean b) {
         return aByte((byte) (b ? 1 : 0));
     }
 
-    static ParcelField aByte(byte b) {
-        return new ParcelField() {
-            public void write(Parcel p) {
-                p.writeByte(b);
-            }
-        };
+    static Consumer<Parcel> aByte(byte b) {
+        return (p) -> p.writeByte(b);
     }
 
-    static ParcelField anInt(int i) {
-        return new ParcelField() {
-            public void write(Parcel p) {
-                p.writeInt(i);
-            }
-        };
+    static Consumer<Parcel> anInt(int i) {
+        return (p) -> p.writeInt(i);
     }
 
-    static ParcelField aLong(long l) {
-        return new ParcelField() {
-            public void write(Parcel p) {
-                p.writeLong(l);
-            }
-        };
+    static Consumer<Parcel> aLong(long l) {
+        return (p) -> p.writeLong(l);
     }
 
-    static ParcelField aString(String s) {
-        return new ParcelField() {
-            public void write(Parcel p) {
-                p.writeString(s);
-            }
-        };
+    static Consumer<Parcel> aString(String s) {
+        return (p) -> p.writeString(s);
     }
 
-    static ParcelField aByteArray(byte... ary) {
-        return new ParcelField() {
-            public void write(Parcel p) {
-                p.writeByteArray(ary);
-            }
-        };
+    static Consumer<Parcel> aByteArray(byte... ary) {
+        return (p) -> p.writeByteArray(ary);
     }
 
-    static ParcelField anIntArray(int... ary) {
-        return new ParcelField() {
-            public void write(Parcel p) {
-                p.writeIntArray(ary);
-            }
-        };
+    static Consumer<Parcel> anIntArray(int... ary) {
+        return (p) -> p.writeIntArray(ary);
     }
 
     static byte b(int i) {
diff --git a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
index cfd5598..637eaa3 100644
--- a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
+++ b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
@@ -213,9 +213,13 @@
 
         IpConnectivityEvent got = events.get(0);
         String want = String.join("\n",
+                "if_name: \"\"",
                 "link_layer: 0",
+                "network_id: 0",
                 "time_ms: 0",
+                "transports: 0",
                 "connect_statistics <",
+                "  connect_blocking_count: 0",
                 "  connect_count: 12",
                 "  errnos_counters <",
                 "    key: 1",
diff --git a/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java b/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
index 3ed56df..c72efb0 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
@@ -32,6 +32,8 @@
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 
 import android.content.Context;
+import android.os.Handler;
+import android.os.Message;
 import android.net.ConnectivityManager;
 import android.net.ConnectivityManager.NetworkCallback;
 import android.net.IConnectivityManager;
@@ -42,6 +44,10 @@
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
+
+import org.junit.After;
 import org.junit.Before;
 import org.junit.runner.RunWith;
 import org.junit.Test;
@@ -49,6 +55,7 @@
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
@@ -63,6 +70,7 @@
     @Mock private Context mContext;
     @Mock private IConnectivityManager mCS;
 
+    private TestStateMachine mSM;
     private TestConnectivityManager mCM;
     private UpstreamNetworkMonitor mUNM;
 
@@ -72,7 +80,15 @@
         reset(mCS);
 
         mCM = spy(new TestConnectivityManager(mContext, mCS));
-        mUNM = new UpstreamNetworkMonitor(null, EVENT_UNM_UPDATE, (ConnectivityManager) mCM);
+        mSM = new TestStateMachine();
+        mUNM = new UpstreamNetworkMonitor(mSM, EVENT_UNM_UPDATE, (ConnectivityManager) mCM);
+    }
+
+    @After public void tearDown() throws Exception {
+        if (mSM != null) {
+            mSM.quit();
+            mSM = null;
+        }
     }
 
     @Test
@@ -139,15 +155,17 @@
 
         mUNM.start();
         verify(mCM, Mockito.times(1)).registerNetworkCallback(
-                any(NetworkRequest.class), any(NetworkCallback.class));
-        verify(mCM, Mockito.times(1)).registerDefaultNetworkCallback(any(NetworkCallback.class));
+                any(NetworkRequest.class), any(NetworkCallback.class), any(Handler.class));
+        verify(mCM, Mockito.times(1)).registerDefaultNetworkCallback(
+                any(NetworkCallback.class), any(Handler.class));
         assertFalse(mUNM.mobileNetworkRequested());
         assertEquals(0, mCM.requested.size());
 
         mUNM.updateMobileRequiresDun(true);
         mUNM.registerMobileNetworkRequest();
         verify(mCM, Mockito.times(1)).requestNetwork(
-                any(NetworkRequest.class), any(NetworkCallback.class), anyInt(), anyInt());
+                any(NetworkRequest.class), any(NetworkCallback.class), anyInt(), anyInt(),
+                any(Handler.class));
 
         assertTrue(mUNM.mobileNetworkRequested());
         assertUpstreamTypeRequested(TYPE_MOBILE_DUN);
@@ -224,6 +242,7 @@
     }
 
     public static class TestConnectivityManager extends ConnectivityManager {
+        public Map<NetworkCallback, Handler> allCallbacks = new HashMap<>();
         public Set<NetworkCallback> trackingDefault = new HashSet<>();
         public Map<NetworkCallback, NetworkRequest> listening = new HashMap<>();
         public Map<NetworkCallback, NetworkRequest> requested = new HashMap<>();
@@ -234,7 +253,8 @@
         }
 
         boolean hasNoCallbacks() {
-            return trackingDefault.isEmpty() &&
+            return allCallbacks.isEmpty() &&
+                   trackingDefault.isEmpty() &&
                    listening.isEmpty() &&
                    requested.isEmpty() &&
                    legacyTypeMap.isEmpty();
@@ -262,14 +282,23 @@
         }
 
         @Override
-        public void requestNetwork(NetworkRequest req, NetworkCallback cb) {
+        public void requestNetwork(NetworkRequest req, NetworkCallback cb, Handler h) {
+            assertFalse(allCallbacks.containsKey(cb));
+            allCallbacks.put(cb, h);
             assertFalse(requested.containsKey(cb));
             requested.put(cb, req);
         }
 
         @Override
+        public void requestNetwork(NetworkRequest req, NetworkCallback cb) {
+            fail("Should never be called.");
+        }
+
+        @Override
         public void requestNetwork(NetworkRequest req, NetworkCallback cb,
-                int timeoutMs, int legacyType) {
+                int timeoutMs, int legacyType, Handler h) {
+            assertFalse(allCallbacks.containsKey(cb));
+            allCallbacks.put(cb, h);
             assertFalse(requested.containsKey(cb));
             requested.put(cb, req);
             assertFalse(legacyTypeMap.containsKey(cb));
@@ -279,18 +308,32 @@
         }
 
         @Override
-        public void registerNetworkCallback(NetworkRequest req, NetworkCallback cb) {
+        public void registerNetworkCallback(NetworkRequest req, NetworkCallback cb, Handler h) {
+            assertFalse(allCallbacks.containsKey(cb));
+            allCallbacks.put(cb, h);
             assertFalse(listening.containsKey(cb));
             listening.put(cb, req);
         }
 
         @Override
-        public void registerDefaultNetworkCallback(NetworkCallback cb) {
+        public void registerNetworkCallback(NetworkRequest req, NetworkCallback cb) {
+            fail("Should never be called.");
+        }
+
+        @Override
+        public void registerDefaultNetworkCallback(NetworkCallback cb, Handler h) {
+            assertFalse(allCallbacks.containsKey(cb));
+            allCallbacks.put(cb, h);
             assertFalse(trackingDefault.contains(cb));
             trackingDefault.add(cb);
         }
 
         @Override
+        public void registerDefaultNetworkCallback(NetworkCallback cb) {
+            fail("Should never be called.");
+        }
+
+        @Override
         public void unregisterNetworkCallback(NetworkCallback cb) {
             if (trackingDefault.contains(cb)) {
                 trackingDefault.remove(cb);
@@ -302,10 +345,35 @@
             } else {
                 fail("Unexpected callback removed");
             }
+            allCallbacks.remove(cb);
 
+            assertFalse(allCallbacks.containsKey(cb));
             assertFalse(trackingDefault.contains(cb));
             assertFalse(listening.containsKey(cb));
             assertFalse(requested.containsKey(cb));
         }
     }
+
+    public static class TestStateMachine extends StateMachine {
+        public final ArrayList<Message> messages = new ArrayList<>();
+        private final State mLoggingState = new LoggingState();
+
+        class LoggingState extends State {
+            @Override public void enter() { messages.clear(); }
+
+            @Override public void exit() { messages.clear(); }
+
+            @Override public boolean processMessage(Message msg) {
+                messages.add(msg);
+                return true;
+            }
+        }
+
+        public TestStateMachine() {
+            super("UpstreamNetworkMonitor.TestStateMachine");
+            addState(mLoggingState);
+            setInitialState(mLoggingState);
+            super.start();
+        }
+    }
 }
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 0e031e7..15648bd 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -309,6 +309,8 @@
     CATEGORY_ATTR = 0x010103e8,
     BANNER_ATTR = 0x10103f2,
     ISGAME_ATTR = 0x10103f4,
+    REQUIRED_FEATURE_ATTR = 0x1010557,
+    REQUIRED_NOT_FEATURE_ATTR = 0x1010558,
 };
 
 String8 getComponentName(String8 &pkgName, String8 &componentName) {
@@ -366,11 +368,19 @@
     printf("\n");
 }
 
-static void printUsesPermission(const String8& name, bool optional=false, int maxSdkVersion=-1) {
+static void printUsesPermission(const String8& name, bool optional=false, int maxSdkVersion=-1,
+        const String8& requiredFeature = String8::empty(),
+        const String8& requiredNotFeature = String8::empty()) {
     printf("uses-permission: name='%s'", ResTable::normalizeForOutput(name.string()).string());
     if (maxSdkVersion != -1) {
          printf(" maxSdkVersion='%d'", maxSdkVersion);
     }
+    if (requiredFeature.length() > 0) {
+         printf(" requiredFeature='%s'", requiredFeature.string());
+    }
+    if (requiredNotFeature.length() > 0) {
+         printf(" requiredNotFeature='%s'", requiredNotFeature.string());
+    }
     printf("\n");
 
     if (optional) {
@@ -1545,6 +1555,10 @@
 
                         const int32_t maxSdkVersion =
                                 AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, -1);
+                        const String8 requiredFeature = AaptXml::getAttribute(tree,
+                                REQUIRED_FEATURE_ATTR, &error);
+                        const String8 requiredNotFeature = AaptXml::getAttribute(tree,
+                                REQUIRED_NOT_FEATURE_ATTR, &error);
 
                         if (name == "android.permission.WRITE_EXTERNAL_STORAGE") {
                             hasWriteExternalStoragePermission = true;
@@ -1565,7 +1579,7 @@
 
                         printUsesPermission(name,
                                 AaptXml::getIntegerAttribute(tree, REQUIRED_ATTR, 1) == 0,
-                                maxSdkVersion);
+                                maxSdkVersion, requiredFeature, requiredNotFeature);
 
                     } else if (tag == "uses-permission-sdk-23" || tag == "uses-permission-sdk-m") {
                         String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index cf5badc..881ac87 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -721,11 +721,6 @@
     XMLNode::attribute_entry* existingEntry = node->editAttribute(ns, attr);
     if (existingEntry != NULL) {
         if (replaceExisting) {
-            if (kIsDebug) {
-                printf("Info: AndroidManifest.xml already defines %s (in %s);"
-                        " overwriting existing value from manifest.\n",
-                        String8(attr).string(), String8(ns).string());
-            }
             existingEntry->string = String16(value);
             return true;
         }
@@ -737,10 +732,6 @@
             return false;
         }
 
-        fprintf(stderr, "Warning: AndroidManifest.xml already defines %s (in %s);"
-                        " using existing value in manifest.\n",
-                String8(attr).string(), String8(ns).string());
-
         // don't stop the build.
         return true;
     }
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index ff306ce..60f0d56 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -4764,6 +4764,7 @@
                                         const sp<XMLNode>& root) {
     const String16 vector16("vector");
     const String16 animatedVector16("animated-vector");
+    const String16 pathInterpolator16("pathInterpolator");
 
     const int minSdk = getMinSdkVersion(bundle);
     if (minSdk >= SDK_LOLLIPOP_MR1) {
@@ -4789,7 +4790,8 @@
         nodesToVisit.pop();
 
         if (bundle->getNoVersionVectors() && (node->getElementName() == vector16 ||
-                    node->getElementName() == animatedVector16)) {
+                    node->getElementName() == animatedVector16 ||
+                    node->getElementName() == pathInterpolator16)) {
             // We were told not to version vector tags, so skip the children here.
             continue;
         }
diff --git a/tools/aapt/ZipEntry.h b/tools/aapt/ZipEntry.h
index 287a540..669e739 100644
--- a/tools/aapt/ZipEntry.h
+++ b/tools/aapt/ZipEntry.h
@@ -26,6 +26,7 @@
 
 #include <stdlib.h>
 #include <stdio.h>
+#include <time.h>
 
 namespace android {
 
diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp
index dabaca6..57036aa 100644
--- a/tools/aapt2/Android.bp
+++ b/tools/aapt2/Android.bp
@@ -1,5 +1,5 @@
 //
-// Copyright (C) 2015 The Android Open Source Project
+// 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.
@@ -19,7 +19,7 @@
     "diff/Diff.cpp",
     "dump/Dump.cpp",
     "link/Link.cpp",
-    "strip/Strip.cpp",
+    "optimize/Optimize.cpp",
 ]
 
 cc_defaults {
@@ -96,11 +96,11 @@
         "link/ProductFilter.cpp",
         "link/PrivateAttributeMover.cpp",
         "link/ReferenceLinker.cpp",
-        "link/ResourceDeduper.cpp",
         "link/TableMerger.cpp",
-        "link/VersionCollapser.cpp",
         "link/XmlNamespaceRemover.cpp",
         "link/XmlReferenceLinker.cpp",
+        "optimize/ResourceDeduper.cpp",
+        "optimize/VersionCollapser.cpp",
         "process/SymbolTable.cpp",
         "proto/ProtoHelpers.cpp",
         "proto/TableProtoDeserializer.cpp",
diff --git a/tools/aapt2/LoadedApk.cpp b/tools/aapt2/LoadedApk.cpp
index 3d7bd94..1d04b35 100644
--- a/tools/aapt2/LoadedApk.cpp
+++ b/tools/aapt2/LoadedApk.cpp
@@ -58,7 +58,8 @@
   return util::make_unique<LoadedApk>(source, std::move(apk), std::move(table));
 }
 
-bool LoadedApk::WriteToArchive(IAaptContext* context, IArchiveWriter* writer) {
+bool LoadedApk::WriteToArchive(IAaptContext* context, const TableFlattenerOptions& options,
+                               IArchiveWriter* writer) {
   std::set<std::string> referenced_resources;
   // List the files being referenced in the resource table.
   for (auto& pkg : table_->packages) {
@@ -94,7 +95,9 @@
     // The resource table needs to be reserialized since it might have changed.
     if (path == "resources.arsc") {
       BigBuffer buffer = BigBuffer(1024);
-      TableFlattener flattener(&buffer);
+      // TODO(adamlesinski): How to determine if there were sparse entries (and if to encode
+      // with sparse entries) b/35389232.
+      TableFlattener flattener(options, &buffer);
       if (!flattener.Consume(context, table_.get())) {
         return false;
       }
diff --git a/tools/aapt2/LoadedApk.h b/tools/aapt2/LoadedApk.h
index f8878d1..59eb816 100644
--- a/tools/aapt2/LoadedApk.h
+++ b/tools/aapt2/LoadedApk.h
@@ -21,6 +21,7 @@
 
 #include "ResourceTable.h"
 #include "flatten/Archive.h"
+#include "flatten/TableFlattener.h"
 #include "io/ZipArchive.h"
 #include "unflatten/BinaryResourceParser.h"
 
@@ -45,7 +46,8 @@
    * Writes the APK on disk at the given path, while also removing the resource
    * files that are not referenced in the resource table.
    */
-  bool WriteToArchive(IAaptContext* context, IArchiveWriter* writer);
+  bool WriteToArchive(IAaptContext* context, const TableFlattenerOptions& options,
+                      IArchiveWriter* writer);
 
   static std::unique_ptr<LoadedApk> LoadApkFromPath(IAaptContext* context,
                                                     const android::StringPiece& path);
diff --git a/tools/aapt2/Main.cpp b/tools/aapt2/Main.cpp
index ba378d7..456f686 100644
--- a/tools/aapt2/Main.cpp
+++ b/tools/aapt2/Main.cpp
@@ -25,7 +25,7 @@
 static const char* sMajorVersion = "2";
 
 // Update minor version whenever a feature or flag is added.
-static const char* sMinorVersion = "7";
+static const char* sMinorVersion = "10";
 
 int PrintVersion() {
   std::cerr << "Android Asset Packaging Tool (aapt) " << sMajorVersion << "."
@@ -37,7 +37,7 @@
 extern int Link(const std::vector<android::StringPiece>& args);
 extern int Dump(const std::vector<android::StringPiece>& args);
 extern int Diff(const std::vector<android::StringPiece>& args);
-extern int Strip(const std::vector<android::StringPiece>& args);
+extern int Optimize(const std::vector<android::StringPiece>& args);
 
 }  // namespace aapt
 
@@ -60,8 +60,8 @@
       return aapt::Dump(args);
     } else if (command == "diff") {
       return aapt::Diff(args);
-    } else if (command == "strip") {
-      return aapt::Strip(args);
+    } else if (command == "optimize") {
+      return aapt::Optimize(args);
     } else if (command == "version") {
       return aapt::PrintVersion();
     }
@@ -70,7 +70,7 @@
     std::cerr << "no command specified\n";
   }
 
-  std::cerr << "\nusage: aapt2 [compile|link|dump|diff|strip|version] ..."
+  std::cerr << "\nusage: aapt2 [compile|link|dump|diff|optimize|version] ..."
             << std::endl;
   return 1;
 }
diff --git a/tools/aapt2/NameMangler.h b/tools/aapt2/NameMangler.h
index dba2d09..1305a4c 100644
--- a/tools/aapt2/NameMangler.h
+++ b/tools/aapt2/NameMangler.h
@@ -62,6 +62,8 @@
     return policy_.packages_to_mangle.count(package) != 0;
   }
 
+  const std::string& GetTargetPackageName() const { return policy_.target_package_name; }
+
   /**
    * Returns a mangled name that is a combination of `name` and `package`.
    * The mangled name should contain symbols that are illegal to define in XML,
diff --git a/tools/aapt2/Resource.h b/tools/aapt2/Resource.h
index 4d915d9..493f238 100644
--- a/tools/aapt2/Resource.h
+++ b/tools/aapt2/Resource.h
@@ -118,6 +118,9 @@
   bool is_valid() const;
 };
 
+constexpr const uint8_t kAppPackageId = 0x7fu;
+constexpr const uint8_t kFrameworkPackageId = 0x01u;
+
 /**
  * A binary identifier representing a resource. Internally it
  * is a 32bit integer split as follows:
@@ -138,6 +141,10 @@
   ResourceId(uint8_t p, uint8_t t, uint16_t e);
 
   bool is_valid() const;
+
+  // Returns true if the ID is a valid ID or dynamic ID (package ID can be 0).
+  bool is_valid_dynamic() const;
+
   uint8_t package_id() const;
   uint8_t type_id() const;
   uint16_t entry_id() const;
@@ -211,6 +218,8 @@
   return (id & 0xff000000u) != 0 && (id & 0x00ff0000u) != 0;
 }
 
+inline bool ResourceId::is_valid_dynamic() const { return (id & 0x00ff0000u) != 0; }
+
 inline uint8_t ResourceId::package_id() const {
   return static_cast<uint8_t>(id >> 24);
 }
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index 47ca266..8461905 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -701,14 +701,11 @@
 
   out_resource->name.type = *parsed_type;
 
-  if (Maybe<StringPiece> maybe_id_str =
-          xml::FindNonEmptyAttribute(parser, "id")) {
-    Maybe<ResourceId> maybe_id =
-        ResourceUtils::ParseResourceId(maybe_id_str.value());
+  if (Maybe<StringPiece> maybe_id_str = xml::FindNonEmptyAttribute(parser, "id")) {
+    Maybe<ResourceId> maybe_id = ResourceUtils::ParseResourceId(maybe_id_str.value());
     if (!maybe_id) {
-      diag_->Error(DiagMessage(out_resource->source) << "invalid resource ID '"
-                                                     << maybe_id.value()
-                                                     << "' in <public>");
+      diag_->Error(DiagMessage(out_resource->source)
+                   << "invalid resource ID '" << maybe_id_str.value() << "' in <public>");
       return false;
     }
     out_resource->id = maybe_id.value();
diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp
index 67ed476..eefa320 100644
--- a/tools/aapt2/ResourceParser_test.cpp
+++ b/tools/aapt2/ResourceParser_test.cpp
@@ -582,6 +582,16 @@
       "  <item quantity=\"one\">apple</item>\n"
       "</plurals>";
   ASSERT_TRUE(TestParse(input));
+
+  Plural* plural = test::GetValue<Plural>(&table_, "plurals/foo");
+  ASSERT_NE(nullptr, plural);
+  EXPECT_EQ(nullptr, plural->values[Plural::Zero]);
+  EXPECT_EQ(nullptr, plural->values[Plural::Two]);
+  EXPECT_EQ(nullptr, plural->values[Plural::Few]);
+  EXPECT_EQ(nullptr, plural->values[Plural::Many]);
+
+  EXPECT_NE(nullptr, plural->values[Plural::One]);
+  EXPECT_NE(nullptr, plural->values[Plural::Other]);
 }
 
 TEST_F(ResourceParserTest, ParseCommentsWithResource) {
diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp
index dd78750..6e4b450 100644
--- a/tools/aapt2/ResourceTable.cpp
+++ b/tools/aapt2/ResourceTable.cpp
@@ -387,8 +387,7 @@
   }
 
   ResourceTablePackage* package = FindOrCreatePackage(name.package);
-  if (res_id.is_valid() && package->id &&
-      package->id.value() != res_id.package_id()) {
+  if (res_id.is_valid_dynamic() && package->id && package->id.value() != res_id.package_id()) {
     diag->Error(DiagMessage(value->GetSource())
                 << "trying to add resource '" << name << "' with ID " << res_id
                 << " but package '" << package->name << "' already has ID "
@@ -397,7 +396,7 @@
   }
 
   ResourceTableType* type = package->FindOrCreateType(name.type);
-  if (res_id.is_valid() && type->id && type->id.value() != res_id.type_id()) {
+  if (res_id.is_valid_dynamic() && type->id && type->id.value() != res_id.type_id()) {
     diag->Error(DiagMessage(value->GetSource())
                 << "trying to add resource '" << name << "' with ID " << res_id
                 << " but type '" << type->type << "' already has ID "
@@ -406,8 +405,7 @@
   }
 
   ResourceEntry* entry = type->FindOrCreateEntry(name.entry);
-  if (res_id.is_valid() && entry->id &&
-      entry->id.value() != res_id.entry_id()) {
+  if (res_id.is_valid_dynamic() && entry->id && entry->id.value() != res_id.entry_id()) {
     diag->Error(DiagMessage(value->GetSource())
                 << "trying to add resource '" << name << "' with ID " << res_id
                 << " but resource already has ID "
@@ -441,7 +439,7 @@
     }
   }
 
-  if (res_id.is_valid()) {
+  if (res_id.is_valid_dynamic()) {
     package->id = res_id.package_id();
     type->id = res_id.type_id();
     entry->id = res_id.entry_id();
@@ -480,8 +478,7 @@
   }
 
   ResourceTablePackage* package = FindOrCreatePackage(name.package);
-  if (res_id.is_valid() && package->id &&
-      package->id.value() != res_id.package_id()) {
+  if (res_id.is_valid_dynamic() && package->id && package->id.value() != res_id.package_id()) {
     diag->Error(DiagMessage(symbol.source)
                 << "trying to add resource '" << name << "' with ID " << res_id
                 << " but package '" << package->name << "' already has ID "
@@ -490,7 +487,7 @@
   }
 
   ResourceTableType* type = package->FindOrCreateType(name.type);
-  if (res_id.is_valid() && type->id && type->id.value() != res_id.type_id()) {
+  if (res_id.is_valid_dynamic() && type->id && type->id.value() != res_id.type_id()) {
     diag->Error(DiagMessage(symbol.source)
                 << "trying to add resource '" << name << "' with ID " << res_id
                 << " but type '" << type->type << "' already has ID "
@@ -499,8 +496,7 @@
   }
 
   ResourceEntry* entry = type->FindOrCreateEntry(name.entry);
-  if (res_id.is_valid() && entry->id &&
-      entry->id.value() != res_id.entry_id()) {
+  if (res_id.is_valid_dynamic() && entry->id && entry->id.value() != res_id.entry_id()) {
     diag->Error(DiagMessage(symbol.source)
                 << "trying to add resource '" << name << "' with ID " << res_id
                 << " but resource already has ID "
@@ -509,7 +505,7 @@
     return false;
   }
 
-  if (res_id.is_valid()) {
+  if (res_id.is_valid_dynamic()) {
     package->id = res_id.package_id();
     type->id = res_id.type_id();
     entry->id = res_id.entry_id();
diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h
index 0fe966c..6b69aaf 100644
--- a/tools/aapt2/ResourceTable.h
+++ b/tools/aapt2/ResourceTable.h
@@ -158,11 +158,8 @@
   DISALLOW_COPY_AND_ASSIGN(ResourceTableType);
 };
 
-enum class PackageType { System, Vendor, App, Dynamic };
-
 class ResourceTablePackage {
  public:
-  PackageType type = PackageType::App;
   Maybe<uint8_t> id;
   std::string name;
 
@@ -241,6 +238,19 @@
   Maybe<SearchResult> FindResource(const ResourceNameRef& name);
 
   /**
+   * Returns the package struct with the given name, or nullptr if such a
+   * package does not
+   * exist. The empty string is a valid package and typically is used to
+   * represent the
+   * 'current' package before it is known to the ResourceTable.
+   */
+  ResourceTablePackage* FindPackage(const android::StringPiece& name);
+
+  ResourceTablePackage* FindPackageById(uint8_t id);
+
+  ResourceTablePackage* CreatePackage(const android::StringPiece& name, Maybe<uint8_t> id = {});
+
+  /**
    * The string pool used by this resource table. Values that reference strings
    * must use
    * this pool to create their strings.
@@ -259,18 +269,9 @@
    */
   std::vector<std::unique_ptr<ResourceTablePackage>> packages;
 
-  /**
-   * Returns the package struct with the given name, or nullptr if such a
-   * package does not
-   * exist. The empty string is a valid package and typically is used to
-   * represent the
-   * 'current' package before it is known to the ResourceTable.
-   */
-  ResourceTablePackage* FindPackage(const android::StringPiece& name);
-
-  ResourceTablePackage* FindPackageById(uint8_t id);
-
-  ResourceTablePackage* CreatePackage(const android::StringPiece& name, Maybe<uint8_t> id = {});
+  // Set of dynamic packages that this table may reference. Their package names get encoded
+  // into the resources.arsc along with their compile-time assigned IDs.
+  std::map<size_t, std::string> included_packages_;
 
  private:
   ResourceTablePackage* FindOrCreatePackage(const android::StringPiece& name);
diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp
index 150dc58..ca6738b 100644
--- a/tools/aapt2/ResourceUtils.cpp
+++ b/tools/aapt2/ResourceUtils.cpp
@@ -469,7 +469,7 @@
   if (android::ResTable::stringToInt(str16.data(), str16.size(), &value)) {
     if (value.dataType == android::Res_value::TYPE_INT_HEX) {
       ResourceId id(value.data);
-      if (id.is_valid()) {
+      if (id.is_valid_dynamic()) {
         return id;
       }
     }
@@ -533,6 +533,7 @@
     case android::Res_value::TYPE_REFERENCE:
     case android::Res_value::TYPE_ATTRIBUTE:
     case android::Res_value::TYPE_DYNAMIC_REFERENCE:
+    case android::Res_value::TYPE_DYNAMIC_ATTRIBUTE:
       return android::ResTable_map::TYPE_REFERENCE;
 
     case android::Res_value::TYPE_STRING:
diff --git a/tools/aapt2/ResourceValues.cpp b/tools/aapt2/ResourceValues.cpp
index f75ed7a..0cb8c67 100644
--- a/tools/aapt2/ResourceValues.cpp
+++ b/tools/aapt2/ResourceValues.cpp
@@ -88,10 +88,24 @@
 }
 
 bool Reference::Flatten(android::Res_value* out_value) const {
-  out_value->dataType = (reference_type == Reference::Type::kResource)
-                            ? android::Res_value::TYPE_REFERENCE
-                            : android::Res_value::TYPE_ATTRIBUTE;
-  out_value->data = util::HostToDevice32(id ? id.value().id : 0);
+  const ResourceId resid = id.value_or_default(ResourceId(0));
+  const bool dynamic =
+      (resid.package_id() != kFrameworkPackageId && resid.package_id() != kAppPackageId);
+
+  if (reference_type == Reference::Type::kResource) {
+    if (dynamic) {
+      out_value->dataType = android::Res_value::TYPE_DYNAMIC_REFERENCE;
+    } else {
+      out_value->dataType = android::Res_value::TYPE_REFERENCE;
+    }
+  } else {
+    if (dynamic) {
+      out_value->dataType = android::Res_value::TYPE_DYNAMIC_ATTRIBUTE;
+    } else {
+      out_value->dataType = android::Res_value::TYPE_ATTRIBUTE;
+    }
+  }
+  out_value->data = util::HostToDevice32(resid.id);
   return true;
 }
 
@@ -327,7 +341,7 @@
 }
 
 template <typename T>
-T* addPointer(T& val) {
+constexpr T* add_pointer(T& val) {
   return &val;
 }
 
@@ -348,7 +362,7 @@
 
   std::vector<const Symbol*> sorted_a;
   std::transform(symbols.begin(), symbols.end(), std::back_inserter(sorted_a),
-                 addPointer<const Symbol>);
+                 add_pointer<const Symbol>);
   std::sort(sorted_a.begin(), sorted_a.end(),
             [](const Symbol* a, const Symbol* b) -> bool {
               return a->symbol.name < b->symbol.name;
@@ -356,7 +370,7 @@
 
   std::vector<const Symbol*> sorted_b;
   std::transform(other->symbols.begin(), other->symbols.end(),
-                 std::back_inserter(sorted_b), addPointer<const Symbol>);
+                 std::back_inserter(sorted_b), add_pointer<const Symbol>);
   std::sort(sorted_b.begin(), sorted_b.end(),
             [](const Symbol* a, const Symbol* b) -> bool {
               return a->symbol.name < b->symbol.name;
@@ -585,7 +599,7 @@
 
   std::vector<const Entry*> sorted_a;
   std::transform(entries.begin(), entries.end(), std::back_inserter(sorted_a),
-                 addPointer<const Entry>);
+                 add_pointer<const Entry>);
   std::sort(sorted_a.begin(), sorted_a.end(),
             [](const Entry* a, const Entry* b) -> bool {
               return a->key.name < b->key.name;
@@ -593,7 +607,7 @@
 
   std::vector<const Entry*> sorted_b;
   std::transform(other->entries.begin(), other->entries.end(),
-                 std::back_inserter(sorted_b), addPointer<const Entry>);
+                 std::back_inserter(sorted_b), add_pointer<const Entry>);
   std::sort(sorted_b.begin(), sorted_b.end(),
             [](const Entry* a, const Entry* b) -> bool {
               return a->key.name < b->key.name;
@@ -681,18 +695,21 @@
     return false;
   }
 
-  if (values.size() != other->values.size()) {
-    return false;
+  auto one_iter = values.begin();
+  auto one_end_iter = values.end();
+  auto two_iter = other->values.begin();
+  for (; one_iter != one_end_iter; ++one_iter, ++two_iter) {
+    const std::unique_ptr<Item>& a = *one_iter;
+    const std::unique_ptr<Item>& b = *two_iter;
+    if (a != nullptr && b != nullptr) {
+      if (!a->Equals(b.get())) {
+        return false;
+      }
+    } else if (a != b) {
+      return false;
+    }
   }
-
-  return std::equal(values.begin(), values.end(), other->values.begin(),
-                    [](const std::unique_ptr<Item>& a,
-                       const std::unique_ptr<Item>& b) -> bool {
-                      if (bool(a) != bool(b)) {
-                        return false;
-                      }
-                      return bool(a) == bool(b) || a->Equals(b.get());
-                    });
+  return true;
 }
 
 Plural* Plural::Clone(StringPool* new_pool) const {
@@ -729,6 +746,10 @@
   if (values[Many]) {
     *out << " many=" << *values[Many];
   }
+
+  if (values[Other]) {
+    *out << " other=" << *values[Other];
+  }
 }
 
 static ::std::ostream& operator<<(::std::ostream& out,
diff --git a/tools/aapt2/ResourceValues_test.cpp b/tools/aapt2/ResourceValues_test.cpp
new file mode 100644
index 0000000..6922580
--- /dev/null
+++ b/tools/aapt2/ResourceValues_test.cpp
@@ -0,0 +1,151 @@
+/*
+ * 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.
+ */
+
+#include "ResourceValues.h"
+
+#include "test/Test.h"
+
+namespace aapt {
+
+TEST(ResourceValuesTest, PluralEquals) {
+  StringPool pool;
+
+  Plural a;
+  a.values[Plural::One] = util::make_unique<String>(pool.MakeRef("one"));
+  a.values[Plural::Other] = util::make_unique<String>(pool.MakeRef("other"));
+
+  Plural b;
+  b.values[Plural::One] = util::make_unique<String>(pool.MakeRef("une"));
+  b.values[Plural::Other] = util::make_unique<String>(pool.MakeRef("autre"));
+
+  Plural c;
+  c.values[Plural::One] = util::make_unique<String>(pool.MakeRef("one"));
+  c.values[Plural::Other] = util::make_unique<String>(pool.MakeRef("other"));
+
+  EXPECT_FALSE(a.Equals(&b));
+  EXPECT_TRUE(a.Equals(&c));
+}
+
+TEST(ResourceValuesTest, PluralClone) {
+  StringPool pool;
+
+  Plural a;
+  a.values[Plural::One] = util::make_unique<String>(pool.MakeRef("one"));
+  a.values[Plural::Other] = util::make_unique<String>(pool.MakeRef("other"));
+
+  std::unique_ptr<Plural> b(a.Clone(&pool));
+  EXPECT_TRUE(a.Equals(b.get()));
+}
+
+TEST(ResourceValuesTest, ArrayEquals) {
+  StringPool pool;
+
+  Array a;
+  a.items.push_back(util::make_unique<String>(pool.MakeRef("one")));
+  a.items.push_back(util::make_unique<String>(pool.MakeRef("two")));
+
+  Array b;
+  b.items.push_back(util::make_unique<String>(pool.MakeRef("une")));
+  b.items.push_back(util::make_unique<String>(pool.MakeRef("deux")));
+
+  Array c;
+  c.items.push_back(util::make_unique<String>(pool.MakeRef("uno")));
+
+  Array d;
+  d.items.push_back(util::make_unique<String>(pool.MakeRef("one")));
+  d.items.push_back(util::make_unique<String>(pool.MakeRef("two")));
+
+  EXPECT_FALSE(a.Equals(&b));
+  EXPECT_FALSE(a.Equals(&c));
+  EXPECT_FALSE(b.Equals(&c));
+  EXPECT_TRUE(a.Equals(&d));
+}
+
+TEST(ResourceValuesTest, ArrayClone) {
+  StringPool pool;
+
+  Array a;
+  a.items.push_back(util::make_unique<String>(pool.MakeRef("one")));
+  a.items.push_back(util::make_unique<String>(pool.MakeRef("two")));
+
+  std::unique_ptr<Array> b(a.Clone(&pool));
+  EXPECT_TRUE(a.Equals(b.get()));
+}
+
+TEST(ResourceValuesTest, StyleEquals) {
+  StringPool pool;
+
+  std::unique_ptr<Style> a = test::StyleBuilder()
+      .SetParent("android:style/Parent")
+      .AddItem("android:attr/foo", ResourceUtils::TryParseInt("1"))
+      .AddItem("android:attr/bar", ResourceUtils::TryParseInt("2"))
+      .Build();
+
+  std::unique_ptr<Style> b = test::StyleBuilder()
+      .SetParent("android:style/Parent")
+      .AddItem("android:attr/foo", ResourceUtils::TryParseInt("1"))
+      .AddItem("android:attr/bar", ResourceUtils::TryParseInt("3"))
+      .Build();
+
+  std::unique_ptr<Style> c = test::StyleBuilder()
+      .SetParent("android:style/NoParent")
+      .AddItem("android:attr/foo", ResourceUtils::TryParseInt("1"))
+      .AddItem("android:attr/bar", ResourceUtils::TryParseInt("2"))
+      .Build();
+
+  std::unique_ptr<Style> d = test::StyleBuilder()
+      .AddItem("android:attr/foo", ResourceUtils::TryParseInt("1"))
+      .AddItem("android:attr/bar", ResourceUtils::TryParseInt("2"))
+      .Build();
+
+  std::unique_ptr<Style> e = test::StyleBuilder()
+      .SetParent("android:style/Parent")
+      .AddItem("android:attr/foo", ResourceUtils::TryParseInt("1"))
+      .AddItem("android:attr/bat", ResourceUtils::TryParseInt("2"))
+      .Build();
+
+  std::unique_ptr<Style> f = test::StyleBuilder()
+      .SetParent("android:style/Parent")
+      .AddItem("android:attr/foo", ResourceUtils::TryParseInt("1"))
+      .Build();
+
+  std::unique_ptr<Style> g = test::StyleBuilder()
+      .SetParent("android:style/Parent")
+      .AddItem("android:attr/foo", ResourceUtils::TryParseInt("1"))
+      .AddItem("android:attr/bar", ResourceUtils::TryParseInt("2"))
+      .Build();
+
+  EXPECT_FALSE(a->Equals(b.get()));
+  EXPECT_FALSE(a->Equals(c.get()));
+  EXPECT_FALSE(a->Equals(d.get()));
+  EXPECT_FALSE(a->Equals(e.get()));
+  EXPECT_FALSE(a->Equals(f.get()));
+
+  EXPECT_TRUE(a->Equals(g.get()));
+}
+
+TEST(ResourceValuesTest, StyleClone) {
+  std::unique_ptr<Style> a = test::StyleBuilder()
+      .SetParent("android:style/Parent")
+      .AddItem("android:attr/foo", ResourceUtils::TryParseInt("1"))
+      .AddItem("android:attr/bar", ResourceUtils::TryParseInt("2"))
+      .Build();
+
+  std::unique_ptr<Style> b(a->Clone(nullptr));
+  EXPECT_TRUE(a->Equals(b.get()));
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/SdkConstants.h b/tools/aapt2/SdkConstants.h
index 98ba94b..c2ee252 100644
--- a/tools/aapt2/SdkConstants.h
+++ b/tools/aapt2/SdkConstants.h
@@ -25,7 +25,7 @@
 
 namespace aapt {
 
-enum {
+enum : int {
   SDK_CUPCAKE = 3,
   SDK_DONUT = 4,
   SDK_ECLAIR = 5,
@@ -49,7 +49,7 @@
   SDK_MARSHMALLOW = 23,
   SDK_NOUGAT = 24,
   SDK_NOUGAT_MR1 = 25,
-  SDK_O = 26, // STOPSHIP Replace with real version
+  SDK_O = 26,  // STOPSHIP Replace with real version
 };
 
 size_t FindAttributeSdkLevel(const ResourceId& id);
diff --git a/tools/aapt2/ValueVisitor.h b/tools/aapt2/ValueVisitor.h
index 1cb6aa1..2763d49 100644
--- a/tools/aapt2/ValueVisitor.h
+++ b/tools/aapt2/ValueVisitor.h
@@ -29,7 +29,8 @@
 struct RawValueVisitor {
   virtual ~RawValueVisitor() = default;
 
-  virtual void VisitItem(Item* value) {}
+  virtual void VisitAny(Value* value) {}
+  virtual void VisitItem(Item* value) { VisitAny(value); }
   virtual void Visit(Reference* value) { VisitItem(value); }
   virtual void Visit(RawString* value) { VisitItem(value); }
   virtual void Visit(String* value) { VisitItem(value); }
@@ -38,11 +39,11 @@
   virtual void Visit(Id* value) { VisitItem(value); }
   virtual void Visit(BinaryPrimitive* value) { VisitItem(value); }
 
-  virtual void Visit(Attribute* value) {}
-  virtual void Visit(Style* value) {}
-  virtual void Visit(Array* value) {}
-  virtual void Visit(Plural* value) {}
-  virtual void Visit(Styleable* value) {}
+  virtual void Visit(Attribute* value) { VisitAny(value); }
+  virtual void Visit(Style* value) { VisitAny(value); }
+  virtual void Visit(Array* value) { VisitAny(value); }
+  virtual void Visit(Plural* value) { VisitAny(value); }
+  virtual void Visit(Styleable* value) { VisitAny(value); }
 };
 
 // NOLINT, do not add parentheses around T.
diff --git a/tools/aapt2/compile/IdAssigner.h b/tools/aapt2/compile/IdAssigner.h
index 9640eb8..3dcb1eb 100644
--- a/tools/aapt2/compile/IdAssigner.h
+++ b/tools/aapt2/compile/IdAssigner.h
@@ -26,11 +26,8 @@
 
 namespace aapt {
 
-/**
- * Assigns IDs to each resource in the table, respecting existing IDs and
- * filling in gaps
- * in between fixed ID assignments.
- */
+// Assigns IDs to each resource in the table, respecting existing IDs and
+// filling in gaps in between fixed ID assignments.
 class IdAssigner : public IResourceTableConsumer {
  public:
   IdAssigner() = default;
diff --git a/tools/aapt2/diff/Diff.cpp b/tools/aapt2/diff/Diff.cpp
index acebeda..dacf8d9 100644
--- a/tools/aapt2/diff/Diff.cpp
+++ b/tools/aapt2/diff/Diff.cpp
@@ -28,6 +28,8 @@
 
 class DiffContext : public IAaptContext {
  public:
+  DiffContext() : name_mangler_({}), symbol_table_(&name_mangler_) {}
+
   const std::string& GetCompilationPackage() override { return empty_; }
 
   uint8_t GetPackageId() override { return 0x0; }
@@ -45,7 +47,7 @@
  private:
   std::string empty_;
   StdErrDiagnostics diagnostics_;
-  NameMangler name_mangler_ = NameMangler(NameManglerPolicy{});
+  NameMangler name_mangler_;
   SymbolTable symbol_table_;
 };
 
@@ -329,7 +331,7 @@
 
   void Visit(Reference* ref) override {
     if (ref->name && ref->id) {
-      if (ref->id.value().package_id() == 0x7f) {
+      if (ref->id.value().package_id() == kAppPackageId) {
         ref->id = {};
       }
     }
diff --git a/tools/aapt2/flatten/TableFlattener.cpp b/tools/aapt2/flatten/TableFlattener.cpp
index 19d030e..3098458 100644
--- a/tools/aapt2/flatten/TableFlattener.cpp
+++ b/tools/aapt2/flatten/TableFlattener.cpp
@@ -26,6 +26,7 @@
 
 #include "ResourceTable.h"
 #include "ResourceValues.h"
+#include "SdkConstants.h"
 #include "ValueVisitor.h"
 #include "flatten/ChunkWriter.h"
 #include "flatten/ResourceTypeExtensions.h"
@@ -216,13 +217,17 @@
 
 class PackageFlattener {
  public:
-  PackageFlattener(IDiagnostics* diag, ResourceTablePackage* package)
-      : diag_(diag), package_(package) {}
+  PackageFlattener(IAaptContext* context, ResourceTablePackage* package,
+                   const std::map<size_t, std::string>* shared_libs, bool use_sparse_entries)
+      : context_(context),
+        diag_(context->GetDiagnostics()),
+        package_(package),
+        shared_libs_(shared_libs),
+        use_sparse_entries_(use_sparse_entries) {}
 
   bool FlattenPackage(BigBuffer* buffer) {
     ChunkWriter pkg_writer(buffer);
-    ResTable_package* pkg_header =
-        pkg_writer.StartChunk<ResTable_package>(RES_TABLE_PACKAGE_TYPE);
+    ResTable_package* pkg_header = pkg_writer.StartChunk<ResTable_package>(RES_TABLE_PACKAGE_TYPE);
     pkg_header->id = util::HostToDevice32(package_->id.value());
 
     if (package_->name.size() >= arraysize(pkg_header->name)) {
@@ -249,6 +254,11 @@
     // Append the types.
     buffer->AppendBuffer(std::move(type_buffer));
 
+    // If there are libraries (or if the package ID is 0x00), encode a library chunk.
+    if (package_->id.value() == 0x00 || !shared_libs_->empty()) {
+      FlattenLibrarySpec(buffer);
+    }
+
     pkg_writer.Finish();
     return true;
   }
@@ -298,9 +308,12 @@
     return true;
   }
 
-  bool FlattenConfig(const ResourceTableType* type,
-                     const ConfigDescription& config,
-                     std::vector<FlatEntry>* entries, BigBuffer* buffer) {
+  bool FlattenConfig(const ResourceTableType* type, const ConfigDescription& config,
+                     const size_t num_total_entries, std::vector<FlatEntry>* entries,
+                     BigBuffer* buffer) {
+    CHECK(num_total_entries != 0);
+    CHECK(num_total_entries <= std::numeric_limits<uint16_t>::max());
+
     ChunkWriter type_writer(buffer);
     ResTable_type* type_header =
         type_writer.StartChunk<ResTable_type>(RES_TABLE_TYPE_TYPE);
@@ -308,39 +321,60 @@
     type_header->config = config;
     type_header->config.swapHtoD();
 
-    auto max_accum = [](uint32_t max,
-                        const std::unique_ptr<ResourceEntry>& a) -> uint32_t {
-      return std::max(max, (uint32_t)a->id.value());
-    };
+    std::vector<uint32_t> offsets;
+    offsets.resize(num_total_entries, 0xffffffffu);
 
-    // Find the largest entry ID. That is how many entries we will have.
-    const uint32_t entry_count =
-        std::accumulate(type->entries.begin(), type->entries.end(), 0,
-                        max_accum) +
-        1;
-
-    type_header->entryCount = util::HostToDevice32(entry_count);
-    uint32_t* indices = type_writer.NextBlock<uint32_t>(entry_count);
-
-    CHECK((size_t)entry_count <= std::numeric_limits<uint16_t>::max());
-    memset(indices, 0xff, entry_count * sizeof(uint32_t));
-
-    type_header->entriesStart = util::HostToDevice32(type_writer.size());
-
-    const size_t entry_start = type_writer.buffer()->size();
+    BigBuffer values_buffer(512);
     for (FlatEntry& flat_entry : *entries) {
-      CHECK(flat_entry.entry->id.value() < entry_count);
-      indices[flat_entry.entry->id.value()] =
-          util::HostToDevice32(type_writer.buffer()->size() - entry_start);
-      if (!FlattenValue(&flat_entry, type_writer.buffer())) {
+      CHECK(static_cast<size_t>(flat_entry.entry->id.value()) < num_total_entries);
+      offsets[flat_entry.entry->id.value()] = values_buffer.size();
+      if (!FlattenValue(&flat_entry, &values_buffer)) {
         diag_->Error(DiagMessage()
                      << "failed to flatten resource '"
-                     << ResourceNameRef(package_->name, type->type,
-                                        flat_entry.entry->name)
+                     << ResourceNameRef(package_->name, type->type, flat_entry.entry->name)
                      << "' for configuration '" << config << "'");
         return false;
       }
     }
+
+    bool sparse_encode = use_sparse_entries_;
+
+    // Only sparse encode if the entries will be read on platforms O+.
+    sparse_encode =
+        sparse_encode && (context_->GetMinSdkVersion() >= SDK_O || config.sdkVersion >= SDK_O);
+
+    // Only sparse encode if the offsets are representable in 2 bytes.
+    sparse_encode =
+        sparse_encode && (values_buffer.size() / 4u) <= std::numeric_limits<uint16_t>::max();
+
+    // Only sparse encode if the ratio of populated entries to total entries is below some
+    // threshold.
+    sparse_encode =
+        sparse_encode && ((100 * entries->size()) / num_total_entries) < kSparseEncodingThreshold;
+
+    if (sparse_encode) {
+      type_header->entryCount = util::HostToDevice32(entries->size());
+      type_header->flags |= ResTable_type::FLAG_SPARSE;
+      ResTable_sparseTypeEntry* indices =
+          type_writer.NextBlock<ResTable_sparseTypeEntry>(entries->size());
+      for (size_t i = 0; i < num_total_entries; i++) {
+        if (offsets[i] != ResTable_type::NO_ENTRY) {
+          CHECK((offsets[i] & 0x03) == 0);
+          indices->idx = util::HostToDevice16(i);
+          indices->offset = util::HostToDevice16(offsets[i] / 4u);
+          indices++;
+        }
+      }
+    } else {
+      type_header->entryCount = util::HostToDevice32(num_total_entries);
+      uint32_t* indices = type_writer.NextBlock<uint32_t>(num_total_entries);
+      for (size_t i = 0; i < num_total_entries; i++) {
+        indices[i] = util::HostToDevice32(offsets[i]);
+      }
+    }
+
+    type_header->entriesStart = util::HostToDevice32(type_writer.size());
+    type_writer.buffer()->AppendBuffer(std::move(values_buffer));
     type_writer.Finish();
     return true;
   }
@@ -370,8 +404,7 @@
       CHECK(bool(entry->id)) << "entry must have an ID set";
       sorted_entries.push_back(entry.get());
     }
-    std::sort(sorted_entries.begin(), sorted_entries.end(),
-              cmp_ids<ResourceEntry>);
+    std::sort(sorted_entries.begin(), sorted_entries.end(), cmp_ids<ResourceEntry>);
     return sorted_entries;
   }
 
@@ -443,22 +476,26 @@
       type_pool_.MakeRef(ToString(type->type));
 
       std::vector<ResourceEntry*> sorted_entries = CollectAndSortEntries(type);
+      if (sorted_entries.empty()) {
+        continue;
+      }
 
       if (!FlattenTypeSpec(type, &sorted_entries, buffer)) {
         return false;
       }
 
+      // Since the entries are sorted by ID, the last ID will be the largest.
+      const size_t num_entries = sorted_entries.back()->id.value() + 1;
+
       // The binary resource table lists resource entries for each
       // configuration.
       // We store them inverted, where a resource entry lists the values for
       // each
       // configuration available. Here we reverse this to match the binary
       // table.
-      std::map<ConfigDescription, std::vector<FlatEntry>>
-          config_to_entry_list_map;
+      std::map<ConfigDescription, std::vector<FlatEntry>> config_to_entry_list_map;
       for (ResourceEntry* entry : sorted_entries) {
-        const uint32_t key_index =
-            (uint32_t)key_pool_.MakeRef(entry->name).index();
+        const uint32_t key_index = (uint32_t)key_pool_.MakeRef(entry->name).index();
 
         // Group values by configuration.
         for (auto& config_value : entry->values) {
@@ -469,7 +506,7 @@
 
       // Flatten a configuration value.
       for (auto& entry : config_to_entry_list_map) {
-        if (!FlattenConfig(type, entry.first, &entry.second, buffer)) {
+        if (!FlattenConfig(type, entry.first, num_entries, &entry.second, buffer)) {
           return false;
         }
       }
@@ -477,8 +514,39 @@
     return true;
   }
 
+  void FlattenLibrarySpec(BigBuffer* buffer) {
+    ChunkWriter lib_writer(buffer);
+    ResTable_lib_header* lib_header =
+        lib_writer.StartChunk<ResTable_lib_header>(RES_TABLE_LIBRARY_TYPE);
+
+    const size_t num_entries = (package_->id.value() == 0x00 ? 1 : 0) + shared_libs_->size();
+    CHECK(num_entries > 0);
+
+    lib_header->count = util::HostToDevice32(num_entries);
+
+    ResTable_lib_entry* lib_entry = buffer->NextBlock<ResTable_lib_entry>(num_entries);
+    if (package_->id.value() == 0x00) {
+      // Add this package
+      lib_entry->packageId = util::HostToDevice32(0x00);
+      strcpy16_htod(lib_entry->packageName, arraysize(lib_entry->packageName),
+                    util::Utf8ToUtf16(package_->name));
+      ++lib_entry;
+    }
+
+    for (auto& map_entry : *shared_libs_) {
+      lib_entry->packageId = util::HostToDevice32(map_entry.first);
+      strcpy16_htod(lib_entry->packageName, arraysize(lib_entry->packageName),
+                    util::Utf8ToUtf16(map_entry.second));
+      ++lib_entry;
+    }
+    lib_writer.Finish();
+  }
+
+  IAaptContext* context_;
   IDiagnostics* diag_;
   ResourceTablePackage* package_;
+  const std::map<size_t, std::string>* shared_libs_;
+  bool use_sparse_entries_;
   StringPool type_pool_;
   StringPool key_pool_;
 };
@@ -513,7 +581,8 @@
 
   // Flatten each package.
   for (auto& package : table->packages) {
-    PackageFlattener flattener(context->GetDiagnostics(), package.get());
+    PackageFlattener flattener(context, package.get(), &table->included_packages_,
+                               options_.use_sparse_entries);
     if (!flattener.FlattenPackage(&package_buffer)) {
       return false;
     }
diff --git a/tools/aapt2/flatten/TableFlattener.h b/tools/aapt2/flatten/TableFlattener.h
index 53f52c2..223aef8 100644
--- a/tools/aapt2/flatten/TableFlattener.h
+++ b/tools/aapt2/flatten/TableFlattener.h
@@ -25,15 +25,29 @@
 
 namespace aapt {
 
+// The percentage of used entries for a type for which using a sparse encoding is
+// preferred.
+constexpr const size_t kSparseEncodingThreshold = 60;
+
+struct TableFlattenerOptions {
+  // When true, types for configurations with a sparse set of entries are encoded
+  // as a sparse map of entry ID and offset to actual data.
+  // This is only available on platforms O+ and will only be respected when
+  // minSdk is O+.
+  bool use_sparse_entries = false;
+};
+
 class TableFlattener : public IResourceTableConsumer {
  public:
-  explicit TableFlattener(BigBuffer* buffer) : buffer_(buffer) {}
+  explicit TableFlattener(const TableFlattenerOptions& options, BigBuffer* buffer)
+      : options_(options), buffer_(buffer) {}
 
   bool Consume(IAaptContext* context, ResourceTable* table) override;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(TableFlattener);
 
+  TableFlattenerOptions options_;
   BigBuffer* buffer_;
 };
 
diff --git a/tools/aapt2/flatten/TableFlattener_test.cpp b/tools/aapt2/flatten/TableFlattener_test.cpp
index c726240..4196187 100644
--- a/tools/aapt2/flatten/TableFlattener_test.cpp
+++ b/tools/aapt2/flatten/TableFlattener_test.cpp
@@ -16,7 +16,10 @@
 
 #include "flatten/TableFlattener.h"
 
+#include "android-base/stringprintf.h"
+
 #include "ResourceUtils.h"
+#include "SdkConstants.h"
 #include "test/Test.h"
 #include "unflatten/BinaryResourceParser.h"
 #include "util/Util.h"
@@ -34,32 +37,40 @@
                    .Build();
   }
 
-  ::testing::AssertionResult Flatten(ResourceTable* table,
-                                     ResTable* out_table) {
+  ::testing::AssertionResult Flatten(IAaptContext* context, const TableFlattenerOptions& options,
+                                     ResourceTable* table, std::string* out_content) {
     BigBuffer buffer(1024);
-    TableFlattener flattener(&buffer);
-    if (!flattener.Consume(context_.get(), table)) {
+    TableFlattener flattener(options, &buffer);
+    if (!flattener.Consume(context, table)) {
       return ::testing::AssertionFailure() << "failed to flatten ResourceTable";
     }
+    *out_content = buffer.to_string();
+    return ::testing::AssertionSuccess();
+  }
 
-    std::unique_ptr<uint8_t[]> data = util::Copy(buffer);
-    if (out_table->add(data.get(), buffer.size(), -1, true) != NO_ERROR) {
+  ::testing::AssertionResult Flatten(IAaptContext* context, const TableFlattenerOptions& options,
+                                     ResourceTable* table, ResTable* out_table) {
+    std::string content;
+    auto result = Flatten(context, options, table, &content);
+    if (!result) {
+      return result;
+    }
+
+    if (out_table->add(content.data(), content.size(), 1, true) != NO_ERROR) {
       return ::testing::AssertionFailure() << "flattened ResTable is corrupt";
     }
     return ::testing::AssertionSuccess();
   }
 
-  ::testing::AssertionResult Flatten(ResourceTable* table,
-                                     ResourceTable* out_table) {
-    BigBuffer buffer(1024);
-    TableFlattener flattener(&buffer);
-    if (!flattener.Consume(context_.get(), table)) {
-      return ::testing::AssertionFailure() << "failed to flatten ResourceTable";
+  ::testing::AssertionResult Flatten(IAaptContext* context, const TableFlattenerOptions& options,
+                                     ResourceTable* table, ResourceTable* out_table) {
+    std::string content;
+    auto result = Flatten(context, options, table, &content);
+    if (!result) {
+      return result;
     }
 
-    std::unique_ptr<uint8_t[]> data = util::Copy(buffer);
-    BinaryResourceParser parser(context_.get(), out_table, {}, data.get(),
-                                buffer.size());
+    BinaryResourceParser parser(context, out_table, {}, content.data(), content.size());
     if (!parser.Parse()) {
       return ::testing::AssertionFailure() << "flattened ResTable is corrupt";
     }
@@ -127,7 +138,7 @@
     return ::testing::AssertionSuccess();
   }
 
- private:
+ protected:
   std::unique_ptr<IAaptContext> context_;
 };
 
@@ -153,7 +164,7 @@
           .Build();
 
   ResTable res_table;
-  ASSERT_TRUE(Flatten(table.get(), &res_table));
+  ASSERT_TRUE(Flatten(context_.get(), {}, table.get(), &res_table));
 
   EXPECT_TRUE(Exists(&res_table, "com.app.test:id/one", ResourceId(0x7f020000),
                      {}, Res_value::TYPE_INT_BOOLEAN, 0u, 0u));
@@ -200,7 +211,7 @@
           .Build();
 
   ResTable res_table;
-  ASSERT_TRUE(Flatten(table.get(), &res_table));
+  ASSERT_TRUE(Flatten(context_.get(), {}, table.get(), &res_table));
 
   EXPECT_TRUE(Exists(&res_table, "com.app.test:id/one", ResourceId(0x7f020001),
                      {}, Res_value::TYPE_INT_BOOLEAN, 0u, 0u));
@@ -222,7 +233,7 @@
           .Build();
 
   ResourceTable result;
-  ASSERT_TRUE(Flatten(table.get(), &result));
+  ASSERT_TRUE(Flatten(context_.get(), {}, table.get(), &result));
 
   Attribute* actualAttr =
       test::GetValue<Attribute>(&result, "android:attr/foo");
@@ -233,4 +244,171 @@
   EXPECT_EQ(attr.max_int, actualAttr->max_int);
 }
 
+static std::unique_ptr<ResourceTable> BuildTableWithSparseEntries(
+    IAaptContext* context, const ConfigDescription& sparse_config, float load) {
+  std::unique_ptr<ResourceTable> table =
+      test::ResourceTableBuilder()
+          .SetPackageId(context->GetCompilationPackage(), context->GetPackageId())
+          .Build();
+
+  // Add regular entries.
+  int stride = static_cast<int>(1.0f / load);
+  for (int i = 0; i < 100; i++) {
+    const ResourceName name = test::ParseNameOrDie(
+        base::StringPrintf("%s:string/foo_%d", context->GetCompilationPackage().data(), i));
+    const ResourceId resid(context->GetPackageId(), 0x02, static_cast<uint16_t>(i));
+    const auto value =
+        util::make_unique<BinaryPrimitive>(Res_value::TYPE_INT_DEC, static_cast<uint32_t>(i));
+    CHECK(table->AddResource(name, resid, ConfigDescription::DefaultConfig(), "",
+                             std::unique_ptr<Value>(value->Clone(nullptr)),
+                             context->GetDiagnostics()));
+
+    // Every few entries, write out a sparse_config value. This will give us the desired load.
+    if (i % stride == 0) {
+      CHECK(table->AddResource(name, resid, sparse_config, "",
+                               std::unique_ptr<Value>(value->Clone(nullptr)),
+                               context->GetDiagnostics()));
+    }
+  }
+  return table;
+}
+
+TEST_F(TableFlattenerTest, FlattenSparseEntryWithMinSdkO) {
+  std::unique_ptr<IAaptContext> context = test::ContextBuilder()
+                                              .SetCompilationPackage("android")
+                                              .SetPackageId(0x01)
+                                              .SetMinSdkVersion(SDK_O)
+                                              .Build();
+
+  const ConfigDescription sparse_config = test::ParseConfigOrDie("en-rGB");
+  auto table_in = BuildTableWithSparseEntries(context.get(), sparse_config, 0.25f);
+
+  TableFlattenerOptions options;
+  options.use_sparse_entries = true;
+
+  std::string no_sparse_contents;
+  ASSERT_TRUE(Flatten(context.get(), {}, table_in.get(), &no_sparse_contents));
+
+  std::string sparse_contents;
+  ASSERT_TRUE(Flatten(context.get(), options, table_in.get(), &sparse_contents));
+
+  EXPECT_GT(no_sparse_contents.size(), sparse_contents.size());
+
+  // Attempt to parse the sparse contents.
+
+  ResourceTable sparse_table;
+  BinaryResourceParser parser(context.get(), &sparse_table, Source("test.arsc"),
+                              sparse_contents.data(), sparse_contents.size());
+  ASSERT_TRUE(parser.Parse());
+
+  auto value = test::GetValueForConfig<BinaryPrimitive>(&sparse_table, "android:string/foo_0",
+                                                        sparse_config);
+  ASSERT_NE(nullptr, value);
+  EXPECT_EQ(0u, value->value.data);
+
+  ASSERT_EQ(nullptr, test::GetValueForConfig<BinaryPrimitive>(&sparse_table, "android:string/foo_1",
+                                                              sparse_config));
+
+  value = test::GetValueForConfig<BinaryPrimitive>(&sparse_table, "android:string/foo_4",
+                                                   sparse_config);
+  ASSERT_NE(nullptr, value);
+  EXPECT_EQ(4u, value->value.data);
+}
+
+TEST_F(TableFlattenerTest, FlattenSparseEntryWithConfigSdkVersionO) {
+  std::unique_ptr<IAaptContext> context = test::ContextBuilder()
+                                              .SetCompilationPackage("android")
+                                              .SetPackageId(0x01)
+                                              .SetMinSdkVersion(SDK_LOLLIPOP)
+                                              .Build();
+
+  const ConfigDescription sparse_config = test::ParseConfigOrDie("en-rGB-v26");
+  auto table_in = BuildTableWithSparseEntries(context.get(), sparse_config, 0.25f);
+
+  TableFlattenerOptions options;
+  options.use_sparse_entries = true;
+
+  std::string no_sparse_contents;
+  ASSERT_TRUE(Flatten(context.get(), {}, table_in.get(), &no_sparse_contents));
+
+  std::string sparse_contents;
+  ASSERT_TRUE(Flatten(context.get(), options, table_in.get(), &sparse_contents));
+
+  EXPECT_GT(no_sparse_contents.size(), sparse_contents.size());
+}
+
+TEST_F(TableFlattenerTest, DoNotUseSparseEntryForDenseConfig) {
+  std::unique_ptr<IAaptContext> context = test::ContextBuilder()
+                                              .SetCompilationPackage("android")
+                                              .SetPackageId(0x01)
+                                              .SetMinSdkVersion(SDK_O)
+                                              .Build();
+
+  const ConfigDescription sparse_config = test::ParseConfigOrDie("en-rGB");
+  auto table_in = BuildTableWithSparseEntries(context.get(), sparse_config, 0.80f);
+
+  TableFlattenerOptions options;
+  options.use_sparse_entries = true;
+
+  std::string no_sparse_contents;
+  ASSERT_TRUE(Flatten(context.get(), {}, table_in.get(), &no_sparse_contents));
+
+  std::string sparse_contents;
+  ASSERT_TRUE(Flatten(context.get(), options, table_in.get(), &sparse_contents));
+
+  EXPECT_EQ(no_sparse_contents.size(), sparse_contents.size());
+}
+
+TEST_F(TableFlattenerTest, FlattenSharedLibrary) {
+  std::unique_ptr<IAaptContext> context =
+      test::ContextBuilder().SetCompilationPackage("lib").SetPackageId(0x00).Build();
+  std::unique_ptr<ResourceTable> table =
+      test::ResourceTableBuilder()
+          .SetPackageId("lib", 0x00)
+          .AddValue("lib:id/foo", ResourceId(0x00010000), util::make_unique<Id>())
+          .Build();
+  ResourceTable result;
+  ASSERT_TRUE(Flatten(context.get(), {}, table.get(), &result));
+
+  Maybe<ResourceTable::SearchResult> search_result =
+      result.FindResource(test::ParseNameOrDie("lib:id/foo"));
+  AAPT_ASSERT_TRUE(search_result);
+  EXPECT_EQ(0x00u, search_result.value().package->id.value());
+
+  auto iter = result.included_packages_.find(0x00);
+  ASSERT_NE(result.included_packages_.end(), iter);
+  EXPECT_EQ("lib", iter->second);
+}
+
+TEST_F(TableFlattenerTest, FlattenTableReferencingSharedLibraries) {
+  std::unique_ptr<IAaptContext> context =
+      test::ContextBuilder().SetCompilationPackage("app").SetPackageId(0x7f).Build();
+  std::unique_ptr<ResourceTable> table =
+      test::ResourceTableBuilder()
+          .SetPackageId("app", 0x7f)
+          .AddValue("app:id/foo", ResourceId(0x7f010000),
+                    test::BuildReference("lib_one:id/foo", ResourceId(0x02010000)))
+          .AddValue("app:id/bar", ResourceId(0x7f010001),
+                    test::BuildReference("lib_two:id/bar", ResourceId(0x03010000)))
+          .Build();
+  table->included_packages_[0x02] = "lib_one";
+  table->included_packages_[0x03] = "lib_two";
+
+  ResTable result;
+  ASSERT_TRUE(Flatten(context.get(), {}, table.get(), &result));
+
+  const DynamicRefTable* dynamic_ref_table = result.getDynamicRefTableForCookie(1);
+  ASSERT_NE(nullptr, dynamic_ref_table);
+
+  const KeyedVector<String16, uint8_t> entries = dynamic_ref_table->entries();
+
+  ssize_t idx = entries.indexOfKey(android::String16("lib_one"));
+  ASSERT_GE(idx, 0);
+  EXPECT_EQ(0x02u, entries.valueAt(idx));
+
+  idx = entries.indexOfKey(android::String16("lib_two"));
+  ASSERT_GE(idx, 0);
+  EXPECT_EQ(0x03u, entries.valueAt(idx));
+}
+
 }  // namespace aapt
diff --git a/tools/aapt2/flatten/XmlFlattener_test.cpp b/tools/aapt2/flatten/XmlFlattener_test.cpp
index ffc2de1..494d9d2 100644
--- a/tools/aapt2/flatten/XmlFlattener_test.cpp
+++ b/tools/aapt2/flatten/XmlFlattener_test.cpp
@@ -30,23 +30,20 @@
 class XmlFlattenerTest : public ::testing::Test {
  public:
   void SetUp() override {
-    context_ =
-        test::ContextBuilder()
-            .SetCompilationPackage("com.app.test")
-            .SetNameManglerPolicy(NameManglerPolicy{"com.app.test"})
-            .AddSymbolSource(
-                test::StaticSymbolSourceBuilder()
-                    .AddSymbol("android:attr/id", ResourceId(0x010100d0),
-                               test::AttributeBuilder().Build())
-                    .AddSymbol("com.app.test:id/id", ResourceId(0x7f020000))
-                    .AddSymbol("android:attr/paddingStart",
-                               ResourceId(0x010103b3),
-                               test::AttributeBuilder().Build())
-                    .AddSymbol("android:attr/colorAccent",
-                               ResourceId(0x01010435),
-                               test::AttributeBuilder().Build())
-                    .Build())
-            .Build();
+    context_ = test::ContextBuilder()
+                   .SetCompilationPackage("com.app.test")
+                   .SetNameManglerPolicy(NameManglerPolicy{"com.app.test"})
+                   .AddSymbolSource(
+                       test::StaticSymbolSourceBuilder()
+                           .AddSymbol("android:attr/id", ResourceId(0x010100d0),
+                                      test::AttributeBuilder().Build())
+                           .AddSymbol("com.app.test:id/id", ResourceId(0x7f020000))
+                           .AddPublicSymbol("android:attr/paddingStart", ResourceId(0x010103b3),
+                                            test::AttributeBuilder().Build())
+                           .AddPublicSymbol("android:attr/colorAccent", ResourceId(0x01010435),
+                                            test::AttributeBuilder().Build())
+                           .Build())
+                   .Build();
   }
 
   ::testing::AssertionResult Flatten(xml::XmlResource* doc,
@@ -76,7 +73,7 @@
             <View xmlns:test="http://com.test"
                   attr="hey">
               <Layout test:hello="hi" />
-              <Layout>Some text</Layout>
+              <Layout>Some text\\</Layout>
             </View>)EOF");
 
   android::ResXMLTree tree;
@@ -128,7 +125,7 @@
 
   ASSERT_EQ(tree.next(), android::ResXMLTree::TEXT);
   const char16_t* text = tree.getText(&len);
-  EXPECT_EQ(StringPiece16(text, len), u"Some text");
+  EXPECT_EQ(StringPiece16(text, len), u"Some text\\");
 
   ASSERT_EQ(tree.next(), android::ResXMLTree::END_TAG);
   ASSERT_EQ(tree.getElementNamespace(&len), nullptr);
diff --git a/tools/aapt2/java/ClassDefinition.cpp b/tools/aapt2/java/ClassDefinition.cpp
index 53d6ea1..0cec9ae 100644
--- a/tools/aapt2/java/ClassDefinition.cpp
+++ b/tools/aapt2/java/ClassDefinition.cpp
@@ -22,6 +22,23 @@
 
 namespace aapt {
 
+void ClassMember::WriteToStream(const StringPiece& prefix, bool final, std::ostream* out) const {
+  processor_.WriteToStream(out, prefix);
+}
+
+void MethodDefinition::AppendStatement(const StringPiece& statement) {
+  statements_.push_back(statement.to_string());
+}
+
+void MethodDefinition::WriteToStream(const StringPiece& prefix, bool final,
+                                     std::ostream* out) const {
+  *out << prefix << signature_ << " {\n";
+  for (const auto& statement : statements_) {
+    *out << prefix << "  " << statement << "\n";
+  }
+  *out << prefix << "}";
+}
+
 bool ClassDefinition::empty() const {
   for (const std::unique_ptr<ClassMember>& member : members_) {
     if (!member->empty()) {
@@ -40,7 +57,7 @@
   ClassMember::WriteToStream(prefix, final, out);
 
   *out << prefix << "public ";
-  if (qualifier_ == ClassQualifier::Static) {
+  if (qualifier_ == ClassQualifier::kStatic) {
     *out << "static ";
   }
   *out << "final class " << name_ << " {\n";
diff --git a/tools/aapt2/java/ClassDefinition.h b/tools/aapt2/java/ClassDefinition.h
index 64e4b29..ca76421 100644
--- a/tools/aapt2/java/ClassDefinition.h
+++ b/tools/aapt2/java/ClassDefinition.h
@@ -41,10 +41,11 @@
 
   virtual bool empty() const = 0;
 
+  // Writes the class member to the out stream. Subclasses should derive this method
+  // to write their own data. Call this base method from the subclass to write out
+  // this member's comments/annotations.
   virtual void WriteToStream(const android::StringPiece& prefix, bool final,
-                             std::ostream* out) const {
-    processor_.WriteToStream(out, prefix);
-  }
+                             std::ostream* out) const;
 
  private:
   AnnotationProcessor processor_;
@@ -142,7 +143,29 @@
 
 using ResourceArrayMember = PrimitiveArrayMember<ResourceId>;
 
-enum class ClassQualifier { None, Static };
+// Represents a method in a class.
+class MethodDefinition : public ClassMember {
+ public:
+  // Expected method signature example: 'public static void onResourcesLoaded(int p)'.
+  explicit MethodDefinition(const android::StringPiece& signature)
+      : signature_(signature.to_string()) {}
+
+  // Appends a single statement to the method. It should include no newlines or else
+  // formatting may be broken.
+  void AppendStatement(const android::StringPiece& statement);
+
+  // Even if the method is empty, we always want to write the method signature.
+  bool empty() const override { return false; }
+
+  void WriteToStream(const android::StringPiece& prefix, bool final,
+                     std::ostream* out) const override;
+
+ private:
+  std::string signature_;
+  std::vector<std::string> statements_;
+};
+
+enum class ClassQualifier { kNone, kStatic };
 
 class ClassDefinition : public ClassMember {
  public:
diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp
index b71dc48..68bdb95 100644
--- a/tools/aapt2/java/JavaClassGenerator.cpp
+++ b/tools/aapt2/java/JavaClassGenerator.cpp
@@ -23,6 +23,7 @@
 #include <tuple>
 
 #include "android-base/logging.h"
+#include "android-base/stringprintf.h"
 #include "androidfw/StringPiece.h"
 
 #include "NameMangler.h"
@@ -35,6 +36,7 @@
 #include "process/SymbolTable.h"
 
 using android::StringPiece;
+using android::base::StringPrintf;
 
 namespace aapt {
 
@@ -55,11 +57,9 @@
   return sJavaIdentifiers.find(symbol) == sJavaIdentifiers.end();
 }
 
-/*
- * Java symbols can not contain . or -, but those are valid in a resource name.
- * Replace those with '_'.
- */
-static std::string Transform(const StringPiece& symbol) {
+// Java symbols can not contain . or -, but those are valid in a resource name.
+// Replace those with '_'.
+static std::string TransformToFieldName(const StringPiece& symbol) {
   std::string output = symbol.to_string();
   for (char& c : output) {
     if (c == '.' || c == '-') {
@@ -69,34 +69,31 @@
   return output;
 }
 
-/**
- * Transforms an attribute in a styleable to the Java field name:
- *
- * <declare-styleable name="Foo">
- *   <attr name="android:bar" />
- *   <attr name="bar" />
- * </declare-styleable>
- *
- * Foo_android_bar
- * Foo_bar
- */
-static std::string TransformNestedAttr(
-    const ResourceNameRef& attr_name, const std::string& styleable_class_name,
-    const StringPiece& package_name_to_generate) {
+// Transforms an attribute in a styleable to the Java field name:
+//
+// <declare-styleable name="Foo">
+//   <attr name="android:bar" />
+//   <attr name="bar" />
+// </declare-styleable>
+//
+// Foo_android_bar
+// Foo_bar
+static std::string TransformNestedAttr(const ResourceNameRef& attr_name,
+                                       const std::string& styleable_class_name,
+                                       const StringPiece& package_name_to_generate) {
   std::string output = styleable_class_name;
 
   // We may reference IDs from other packages, so prefix the entry name with
   // the package.
   if (!attr_name.package.empty() &&
       package_name_to_generate != attr_name.package) {
-    output += "_" + Transform(attr_name.package);
+    output += "_" + TransformToFieldName(attr_name.package);
   }
-  output += "_" + Transform(attr_name.entry);
+  output += "_" + TransformToFieldName(attr_name.entry);
   return output;
 }
 
-static void AddAttributeFormatDoc(AnnotationProcessor* processor,
-                                  Attribute* attr) {
+static void AddAttributeFormatDoc(AnnotationProcessor* processor, Attribute* attr) {
   const uint32_t type_mask = attr->type_mask;
   if (type_mask & android::ResTable_map::TYPE_REFERENCE) {
     processor->AppendComment(
@@ -128,7 +125,7 @@
     processor->AppendComment(
         "<p>May be a color value, in the form of "
         "\"<code>#<i>rgb</i></code>\",\n"
-        "\"<code>#<i>argb</i></code>\", \"<code>#<i>rrggbb</i></code\", or \n"
+        "\"<code>#<i>argb</i></code>\", \"<code>#<i>rrggbb</i></code>\", or \n"
         "\"<code>#<i>aarrggbb</i></code>\".");
   }
 
@@ -202,18 +199,21 @@
   return true;
 }
 
+// Whether or not to skip writing this symbol.
+bool JavaClassGenerator::SkipSymbol(const Maybe<SymbolTable::Symbol>& symbol) {
+  return !symbol || (options_.types == JavaClassGeneratorOptions::SymbolTypes::kPublic &&
+                     !symbol.value().is_public);
+}
+
 struct StyleableAttr {
-  const Reference* attr_ref;
+  const Reference* attr_ref = nullptr;
   std::string field_name;
-  std::unique_ptr<SymbolTable::Symbol> symbol;
+  Maybe<SymbolTable::Symbol> symbol;
 };
 
-static bool less_styleable_attr(const StyleableAttr& lhs,
-                                const StyleableAttr& rhs) {
-  const ResourceId lhs_id =
-      lhs.attr_ref->id ? lhs.attr_ref->id.value() : ResourceId(0);
-  const ResourceId rhs_id =
-      rhs.attr_ref->id ? rhs.attr_ref->id.value() : ResourceId(0);
+static bool operator<(const StyleableAttr& lhs, const StyleableAttr& rhs) {
+  const ResourceId lhs_id = lhs.attr_ref->id.value_or_default(ResourceId(0));
+  const ResourceId rhs_id = rhs.attr_ref->id.value_or_default(ResourceId(0));
   if (lhs_id < rhs_id) {
     return true;
   } else if (lhs_id > rhs_id) {
@@ -223,72 +223,57 @@
   }
 }
 
-void JavaClassGenerator::AddMembersToStyleableClass(
-    const StringPiece& package_name_to_generate, const std::string& entry_name,
-    const Styleable* styleable, ClassDefinition* out_styleable_class_def) {
-  const std::string class_name = Transform(entry_name);
+void JavaClassGenerator::ProcessStyleable(const ResourceNameRef& name, const ResourceId& id,
+                                          const Styleable& styleable,
+                                          const StringPiece& package_name_to_generate,
+                                          ClassDefinition* out_class_def,
+                                          MethodDefinition* out_rewrite_method) {
+  const std::string array_field_name = TransformToFieldName(name.entry);
+  std::unique_ptr<ResourceArrayMember> array_def =
+      util::make_unique<ResourceArrayMember>(array_field_name);
 
-  std::unique_ptr<ResourceArrayMember> styleable_array_def =
-      util::make_unique<ResourceArrayMember>(class_name);
-
-  // This must be sorted by resource ID.
+  // The array must be sorted by resource ID.
   std::vector<StyleableAttr> sorted_attributes;
-  sorted_attributes.reserve(styleable->entries.size());
-  for (const auto& attr : styleable->entries) {
+  sorted_attributes.reserve(styleable.entries.size());
+  for (const auto& attr : styleable.entries) {
     // If we are not encoding final attributes, the styleable entry may have no
     // ID if we are building a static library.
     CHECK(!options_.use_final || attr.id) << "no ID set for Styleable entry";
     CHECK(bool(attr.name)) << "no name set for Styleable entry";
 
-    // We will need the unmangled, transformed name in the comments and the
-    // field,
+    // We will need the unmangled, transformed name in the comments and the field,
     // so create it once and cache it in this StyleableAttr data structure.
-    StyleableAttr styleable_attr = {};
+    StyleableAttr styleable_attr;
     styleable_attr.attr_ref = &attr;
-    styleable_attr.field_name = TransformNestedAttr(
-        attr.name.value(), class_name, package_name_to_generate);
 
-    Reference mangled_reference;
-    mangled_reference.id = attr.id;
-    mangled_reference.name = attr.name;
-    if (mangled_reference.name.value().package.empty()) {
-      mangled_reference.name.value().package =
-          context_->GetCompilationPackage();
-    }
+    // The field name for this attribute is prefixed by the name of this styleable and
+    // the package it comes from.
+    styleable_attr.field_name =
+        TransformNestedAttr(attr.name.value(), array_field_name, package_name_to_generate);
 
-    if (Maybe<ResourceName> mangled_name =
-            context_->GetNameMangler()->MangleName(
-                mangled_reference.name.value())) {
-      mangled_reference.name = mangled_name;
-    }
-
-    // Look up the symbol so that we can write out in the comments what are
-    // possible
-    // legal values for this attribute.
-    const SymbolTable::Symbol* symbol =
-        context_->GetExternalSymbols()->FindByReference(mangled_reference);
+    // Look up the symbol so that we can write out in the comments what are possible legal values
+    // for this attribute.
+    const SymbolTable::Symbol* symbol = context_->GetExternalSymbols()->FindByReference(attr);
     if (symbol && symbol->attribute) {
-      // Copy the symbol data structure because the returned instance can be
-      // destroyed.
-      styleable_attr.symbol = util::make_unique<SymbolTable::Symbol>(*symbol);
+      // Copy the symbol data structure because the returned instance can be destroyed.
+      styleable_attr.symbol = *symbol;
     }
     sorted_attributes.push_back(std::move(styleable_attr));
   }
 
   // Sort the attributes by ID.
-  std::sort(sorted_attributes.begin(), sorted_attributes.end(),
-            less_styleable_attr);
+  std::sort(sorted_attributes.begin(), sorted_attributes.end());
 
+  // Build the JavaDoc comment for the Styleable array. This has references to child attributes
+  // and what possible values can be used for them.
   const size_t attr_count = sorted_attributes.size();
   if (attr_count > 0) {
-    // Build the comment string for the Styleable. It includes details about the
-    // child attributes.
     std::stringstream styleable_comment;
-    if (!styleable->GetComment().empty()) {
-      styleable_comment << styleable->GetComment() << "\n";
+    if (!styleable.GetComment().empty()) {
+      styleable_comment << styleable.GetComment() << "\n";
     } else {
-      styleable_comment << "Attributes that can be used with a " << class_name
-                        << ".\n";
+      // Apply a default intro comment if the styleable has no comments of its own.
+      styleable_comment << "Attributes that can be used with a " << array_field_name << ".\n";
     }
 
     styleable_comment << "<p>Includes the following attributes:</p>\n"
@@ -297,22 +282,16 @@
                          "<colgroup align=\"left\" />\n"
                          "<tr><th>Attribute</th><th>Description</th></tr>\n";
 
+    // Build the table of attributes with their links and names.
     for (const StyleableAttr& entry : sorted_attributes) {
-      if (!entry.symbol) {
+      if (SkipSymbol(entry.symbol)) {
         continue;
       }
 
-      if (options_.types == JavaClassGeneratorOptions::SymbolTypes::kPublic &&
-          !entry.symbol->is_public) {
-        // Don't write entries for non-public attributes.
-        continue;
-      }
-
-      StringPiece attr_comment_line = entry.symbol->attribute->GetComment();
+      StringPiece attr_comment_line = entry.symbol.value().attribute->GetComment();
       if (attr_comment_line.contains("@removed")) {
         // Removed attributes are public but hidden from the documentation, so
-        // don't emit
-        // them as part of the class documentation.
+        // don't emit them as part of the class documentation.
         continue;
       }
 
@@ -327,71 +306,52 @@
 
       styleable_comment << "<td>";
 
-      // Only use the comment up until the first '.'. This is to stay compatible
-      // with
-      // the way old AAPT did it (presumably to keep it short and to avoid
-      // including
+      // Only use the comment up until the first '.'. This is to stay compatible with
+      // the way old AAPT did it (presumably to keep it short and to avoid including
       // annotations like @hide which would affect this Styleable).
-      auto iter =
-          std::find(attr_comment_line.begin(), attr_comment_line.end(), u'.');
+      auto iter = std::find(attr_comment_line.begin(), attr_comment_line.end(), '.');
       if (iter != attr_comment_line.end()) {
-        attr_comment_line =
-            attr_comment_line.substr(0, (iter - attr_comment_line.begin()) + 1);
+        attr_comment_line = attr_comment_line.substr(0, (iter - attr_comment_line.begin()) + 1);
       }
       styleable_comment << attr_comment_line << "</td></tr>\n";
     }
     styleable_comment << "</table>\n";
 
+    // Generate the @see lines for each attribute.
     for (const StyleableAttr& entry : sorted_attributes) {
-      if (!entry.symbol) {
-        continue;
-      }
-
-      if (options_.types == JavaClassGeneratorOptions::SymbolTypes::kPublic &&
-          !entry.symbol->is_public) {
-        // Don't write entries for non-public attributes.
+      if (SkipSymbol(entry.symbol)) {
         continue;
       }
       styleable_comment << "@see #" << entry.field_name << "\n";
     }
 
-    styleable_array_def->GetCommentBuilder()->AppendComment(
-        styleable_comment.str());
+    array_def->GetCommentBuilder()->AppendComment(styleable_comment.str());
   }
 
   // Add the ResourceIds to the array member.
   for (const StyleableAttr& styleable_attr : sorted_attributes) {
-    styleable_array_def->AddElement(styleable_attr.attr_ref->id
-                                        ? styleable_attr.attr_ref->id.value()
-                                        : ResourceId(0));
+    const ResourceId id = styleable_attr.attr_ref->id.value_or_default(ResourceId(0));
+    array_def->AddElement(id);
   }
 
   // Add the Styleable array to the Styleable class.
-  out_styleable_class_def->AddMember(std::move(styleable_array_def));
+  out_class_def->AddMember(std::move(array_def));
 
   // Now we emit the indices into the array.
   for (size_t i = 0; i < attr_count; i++) {
     const StyleableAttr& styleable_attr = sorted_attributes[i];
-
-    if (!styleable_attr.symbol) {
-      continue;
-    }
-
-    if (options_.types == JavaClassGeneratorOptions::SymbolTypes::kPublic &&
-        !styleable_attr.symbol->is_public) {
-      // Don't write entries for non-public attributes.
+    if (SkipSymbol(styleable_attr.symbol)) {
       continue;
     }
 
     StringPiece comment = styleable_attr.attr_ref->GetComment();
-    if (styleable_attr.symbol->attribute && comment.empty()) {
-      comment = styleable_attr.symbol->attribute->GetComment();
+    if (styleable_attr.symbol.value().attribute && comment.empty()) {
+      comment = styleable_attr.symbol.value().attribute->GetComment();
     }
 
     if (comment.contains("@removed")) {
       // Removed attributes are public but hidden from the documentation, so
-      // don't emit them
-      // as part of the class documentation.
+      // don't emit them as part of the class documentation.
       continue;
     }
 
@@ -414,114 +374,151 @@
       std::stringstream default_comment;
       default_comment << "<p>This symbol is the offset where the "
                       << "{@link " << package_name << ".R.attr#"
-                      << Transform(attr_name.entry) << "}\n"
+                      << TransformToFieldName(attr_name.entry) << "}\n"
                       << "attribute's value can be found in the "
-                      << "{@link #" << class_name << "} array.";
+                      << "{@link #" << array_field_name << "} array.";
       attr_processor->AppendComment(default_comment.str());
     }
 
     attr_processor->AppendNewLine();
-
-    AddAttributeFormatDoc(attr_processor,
-                          styleable_attr.symbol->attribute.get());
+    AddAttributeFormatDoc(attr_processor, styleable_attr.symbol.value().attribute.get());
     attr_processor->AppendNewLine();
+    attr_processor->AppendComment(
+        StringPrintf("@attr name %s:%s", package_name.data(), attr_name.entry.data()));
 
-    std::stringstream doclava_name;
-    doclava_name << "@attr name " << package_name << ":" << attr_name.entry;
+    out_class_def->AddMember(std::move(index_member));
+  }
 
-    attr_processor->AppendComment(doclava_name.str());
-
-    out_styleable_class_def->AddMember(std::move(index_member));
+  // If there is a rewrite method to generate, add the statements that rewrite package IDs
+  // for this styleable.
+  if (out_rewrite_method != nullptr) {
+    out_rewrite_method->AppendStatement(
+        StringPrintf("for (int i = 0; i < styleable.%s.length; i++) {", array_field_name.data()));
+    out_rewrite_method->AppendStatement(
+        StringPrintf("  if ((styleable.%s[i] & 0xff000000) == 0) {", array_field_name.data()));
+    out_rewrite_method->AppendStatement(
+        StringPrintf("    styleable.%s[i] = (styleable.%s[i] & 0x00ffffff) | (p << 24);",
+                     array_field_name.data(), array_field_name.data()));
+    out_rewrite_method->AppendStatement("  }");
+    out_rewrite_method->AppendStatement("}");
   }
 }
 
-bool JavaClassGenerator::AddMembersToTypeClass(
-    const StringPiece& package_name_to_generate,
-    const ResourceTablePackage* package, const ResourceTableType* type,
-    ClassDefinition* out_type_class_def) {
-  for (const auto& entry : type->entries) {
-    if (SkipSymbol(entry->symbol_status.state)) {
+void JavaClassGenerator::ProcessResource(const ResourceNameRef& name, const ResourceId& id,
+                                         const ResourceEntry& entry, ClassDefinition* out_class_def,
+                                         MethodDefinition* out_rewrite_method) {
+  const std::string field_name = TransformToFieldName(name.entry);
+  std::unique_ptr<ResourceMember> resource_member =
+      util::make_unique<ResourceMember>(field_name, id);
+
+  // Build the comments and annotations for this entry.
+  AnnotationProcessor* processor = resource_member->GetCommentBuilder();
+
+  // Add the comments from any <public> tags.
+  if (entry.symbol_status.state != SymbolState::kUndefined) {
+    processor->AppendComment(entry.symbol_status.comment);
+  }
+
+  // Add the comments from all configurations of this entry.
+  for (const auto& config_value : entry.values) {
+    processor->AppendComment(config_value->value->GetComment());
+  }
+
+  // If this is an Attribute, append the format Javadoc.
+  if (!entry.values.empty()) {
+    if (Attribute* attr = ValueCast<Attribute>(entry.values.front()->value.get())) {
+      // We list out the available values for the given attribute.
+      AddAttributeFormatDoc(processor, attr);
+    }
+  }
+
+  out_class_def->AddMember(std::move(resource_member));
+
+  if (out_rewrite_method != nullptr) {
+    const StringPiece& type_str = ToString(name.type);
+    out_rewrite_method->AppendStatement(StringPrintf("%s.%s = (%s.%s & 0x00ffffff) | (p << 24);",
+                                                     type_str.data(), field_name.data(),
+                                                     type_str.data(), field_name.data()));
+  }
+}
+
+Maybe<std::string> JavaClassGenerator::UnmangleResource(const StringPiece& package_name,
+                                                        const StringPiece& package_name_to_generate,
+                                                        const ResourceEntry& entry) {
+  if (SkipSymbol(entry.symbol_status.state)) {
+    return {};
+  }
+
+  std::string unmangled_package;
+  std::string unmangled_name = entry.name;
+  if (NameMangler::Unmangle(&unmangled_name, &unmangled_package)) {
+    // The entry name was mangled, and we successfully unmangled it.
+    // Check that we want to emit this symbol.
+    if (package_name != unmangled_package) {
+      // Skip the entry if it doesn't belong to the package we're writing.
+      return {};
+    }
+  } else if (package_name_to_generate != package_name) {
+    // We are processing a mangled package name,
+    // but this is a non-mangled resource.
+    return {};
+  }
+  return {std::move(unmangled_name)};
+}
+
+bool JavaClassGenerator::ProcessType(const StringPiece& package_name_to_generate,
+                                     const ResourceTablePackage& package,
+                                     const ResourceTableType& type,
+                                     ClassDefinition* out_type_class_def,
+                                     MethodDefinition* out_rewrite_method_def) {
+  for (const auto& entry : type.entries) {
+    const Maybe<std::string> unmangled_name =
+        UnmangleResource(package.name, package_name_to_generate, *entry);
+    if (!unmangled_name) {
       continue;
     }
 
+    // Create an ID if there is one (static libraries don't need one).
     ResourceId id;
-    if (package->id && type->id && entry->id) {
-      id = ResourceId(package->id.value(), type->id.value(), entry->id.value());
+    if (package.id && type.id && entry->id) {
+      id = ResourceId(package.id.value(), type.id.value(), entry->id.value());
     }
 
-    std::string unmangled_package;
-    std::string unmangled_name = entry->name;
-    if (NameMangler::Unmangle(&unmangled_name, &unmangled_package)) {
-      // The entry name was mangled, and we successfully unmangled it.
-      // Check that we want to emit this symbol.
-      if (package->name != unmangled_package) {
-        // Skip the entry if it doesn't belong to the package we're writing.
-        continue;
-      }
-    } else if (package_name_to_generate != package->name) {
-      // We are processing a mangled package name,
-      // but this is a non-mangled resource.
-      continue;
-    }
+    // We need to make sure we hide the fact that we are generating kAttrPrivate attributes.
+    const ResourceNameRef resource_name(
+        package_name_to_generate,
+        type.type == ResourceType::kAttrPrivate ? ResourceType::kAttr : type.type,
+        unmangled_name.value());
 
-    if (!IsValidSymbol(unmangled_name)) {
-      ResourceNameRef resource_name(package_name_to_generate, type->type,
-                                    unmangled_name);
+    // Check to see if the unmangled name is a valid Java name (not a keyword).
+    if (!IsValidSymbol(unmangled_name.value())) {
       std::stringstream err;
       err << "invalid symbol name '" << resource_name << "'";
       error_ = err.str();
       return false;
     }
 
-    if (type->type == ResourceType::kStyleable) {
+    if (resource_name.type == ResourceType::kStyleable) {
       CHECK(!entry->values.empty());
 
       const Styleable* styleable =
           static_cast<const Styleable*>(entry->values.front()->value.get());
 
-      // Comments are handled within this method.
-      AddMembersToStyleableClass(package_name_to_generate, unmangled_name,
-                                 styleable, out_type_class_def);
+      ProcessStyleable(resource_name, id, *styleable, package_name_to_generate, out_type_class_def,
+                       out_rewrite_method_def);
     } else {
-      std::unique_ptr<ResourceMember> resource_member =
-          util::make_unique<ResourceMember>(Transform(unmangled_name), id);
-
-      // Build the comments and annotations for this entry.
-      AnnotationProcessor* processor = resource_member->GetCommentBuilder();
-
-      // Add the comments from any <public> tags.
-      if (entry->symbol_status.state != SymbolState::kUndefined) {
-        processor->AppendComment(entry->symbol_status.comment);
-      }
-
-      // Add the comments from all configurations of this entry.
-      for (const auto& config_value : entry->values) {
-        processor->AppendComment(config_value->value->GetComment());
-      }
-
-      // If this is an Attribute, append the format Javadoc.
-      if (!entry->values.empty()) {
-        if (Attribute* attr =
-                ValueCast<Attribute>(entry->values.front()->value.get())) {
-          // We list out the available values for the given attribute.
-          AddAttributeFormatDoc(processor, attr);
-        }
-      }
-
-      out_type_class_def->AddMember(std::move(resource_member));
+      ProcessResource(resource_name, id, *entry, out_type_class_def, out_rewrite_method_def);
     }
   }
   return true;
 }
 
-bool JavaClassGenerator::Generate(const StringPiece& package_name_to_generate,
-                                  std::ostream* out) {
+bool JavaClassGenerator::Generate(const StringPiece& package_name_to_generate, std::ostream* out) {
   return Generate(package_name_to_generate, package_name_to_generate, out);
 }
 
-static void AppendJavaDocAnnotations(
-    const std::vector<std::string>& annotations,
-    AnnotationProcessor* processor) {
+static void AppendJavaDocAnnotations(const std::vector<std::string>& annotations,
+                                     AnnotationProcessor* processor) {
   for (const std::string& annotation : annotations) {
     std::string proper_annotation = "@";
     proper_annotation += annotation;
@@ -532,37 +529,45 @@
 bool JavaClassGenerator::Generate(const StringPiece& package_name_to_generate,
                                   const StringPiece& out_package_name,
                                   std::ostream* out) {
-  ClassDefinition r_class("R", ClassQualifier::None, true);
+  ClassDefinition r_class("R", ClassQualifier::kNone, true);
+  std::unique_ptr<MethodDefinition> rewrite_method;
+
+  // Generate an onResourcesLoaded() callback if requested.
+  if (options_.rewrite_callback_options) {
+    rewrite_method =
+        util::make_unique<MethodDefinition>("public static void onResourcesLoaded(int p)");
+    for (const std::string& package_to_callback :
+         options_.rewrite_callback_options.value().packages_to_callback) {
+      rewrite_method->AppendStatement(
+          StringPrintf("%s.R.onResourcesLoaded(p);", package_to_callback.data()));
+    }
+  }
 
   for (const auto& package : table_->packages) {
     for (const auto& type : package->types) {
       if (type->type == ResourceType::kAttrPrivate) {
+        // We generate these as part of the kAttr type, so skip them here.
         continue;
       }
 
+      // Stay consistent with AAPT and generate an empty type class if the R class
+      // is public.
       const bool force_creation_if_empty =
           (options_.types == JavaClassGeneratorOptions::SymbolTypes::kPublic);
 
-      std::unique_ptr<ClassDefinition> class_def =
-          util::make_unique<ClassDefinition>(ToString(type->type),
-                                             ClassQualifier::Static,
-                                             force_creation_if_empty);
-
-      bool result = AddMembersToTypeClass(
-          package_name_to_generate, package.get(), type.get(), class_def.get());
-      if (!result) {
+      std::unique_ptr<ClassDefinition> class_def = util::make_unique<ClassDefinition>(
+          ToString(type->type), ClassQualifier::kStatic, force_creation_if_empty);
+      if (!ProcessType(package_name_to_generate, *package, *type, class_def.get(),
+                       rewrite_method.get())) {
         return false;
       }
 
       if (type->type == ResourceType::kAttr) {
         // Also include private attributes in this same class.
-        ResourceTableType* priv_type =
-            package->FindType(ResourceType::kAttrPrivate);
+        const ResourceTableType* priv_type = package->FindType(ResourceType::kAttrPrivate);
         if (priv_type) {
-          result =
-              AddMembersToTypeClass(package_name_to_generate, package.get(),
-                                    priv_type, class_def.get());
-          if (!result) {
+          if (!ProcessType(package_name_to_generate, *package, *priv_type, class_def.get(),
+                           rewrite_method.get())) {
             return false;
           }
         }
@@ -571,23 +576,23 @@
       if (type->type == ResourceType::kStyleable &&
           options_.types == JavaClassGeneratorOptions::SymbolTypes::kPublic) {
         // When generating a public R class, we don't want Styleable to be part
-        // of the API.
-        // It is only emitted for documentation purposes.
+        // of the API. It is only emitted for documentation purposes.
         class_def->GetCommentBuilder()->AppendComment("@doconly");
       }
 
-      AppendJavaDocAnnotations(options_.javadoc_annotations,
-                               class_def->GetCommentBuilder());
+      AppendJavaDocAnnotations(options_.javadoc_annotations, class_def->GetCommentBuilder());
 
       r_class.AddMember(std::move(class_def));
     }
   }
 
-  AppendJavaDocAnnotations(options_.javadoc_annotations,
-                           r_class.GetCommentBuilder());
+  if (rewrite_method != nullptr) {
+    r_class.AddMember(std::move(rewrite_method));
+  }
 
-  if (!ClassDefinition::WriteJavaFile(&r_class, out_package_name,
-                                      options_.use_final, out)) {
+  AppendJavaDocAnnotations(options_.javadoc_annotations, r_class.GetCommentBuilder());
+
+  if (!ClassDefinition::WriteJavaFile(&r_class, out_package_name, options_.use_final, out)) {
     return false;
   }
 
diff --git a/tools/aapt2/java/JavaClassGenerator.h b/tools/aapt2/java/JavaClassGenerator.h
index 5cf556e..4510430 100644
--- a/tools/aapt2/java/JavaClassGenerator.h
+++ b/tools/aapt2/java/JavaClassGenerator.h
@@ -25,19 +25,28 @@
 #include "ResourceTable.h"
 #include "ResourceValues.h"
 #include "process/IResourceTableConsumer.h"
+#include "process/SymbolTable.h"
 
 namespace aapt {
 
 class AnnotationProcessor;
 class ClassDefinition;
+class MethodDefinition;
+
+// Options for generating onResourcesLoaded callback in R.java.
+struct OnResourcesLoadedCallbackOptions {
+  // Other R classes to delegate the same callback to (with the same package ID).
+  std::vector<std::string> packages_to_callback;
+};
 
 struct JavaClassGeneratorOptions {
-  /*
-   * Specifies whether to use the 'final' modifier
-   * on resource entries. Default is true.
-   */
+  // Specifies whether to use the 'final' modifier on resource entries. Default is true.
   bool use_final = true;
 
+  // If set, generates code to rewrite the package ID of resources.
+  // Implies use_final == true. Default is unset.
+  Maybe<OnResourcesLoadedCallbackOptions> rewrite_callback_options;
+
   enum class SymbolTypes {
     kAll,
     kPublicPrivate,
@@ -46,47 +55,54 @@
 
   SymbolTypes types = SymbolTypes::kAll;
 
-  /**
-   * A list of JavaDoc annotations to add to the comments of all generated
-   * classes.
-   */
+  // A list of JavaDoc annotations to add to the comments of all generated classes.
   std::vector<std::string> javadoc_annotations;
 };
 
-/*
- * Generates the R.java file for a resource table.
- */
+// Generates the R.java file for a resource table.
 class JavaClassGenerator {
  public:
   JavaClassGenerator(IAaptContext* context, ResourceTable* table,
                      const JavaClassGeneratorOptions& options);
 
-  /*
-   * Writes the R.java file to `out`. Only symbols belonging to `package` are
-   * written.
-   * All symbols technically belong to a single package, but linked libraries
-   * will
-   * have their names mangled, denoting that they came from a different package.
-   * We need to generate these symbols in a separate file.
-   * Returns true on success.
-   */
-  bool Generate(const android::StringPiece& packageNameToGenerate, std::ostream* out);
+  // Writes the R.java file to `out`. Only symbols belonging to `package` are written.
+  // All symbols technically belong to a single package, but linked libraries will
+  // have their names mangled, denoting that they came from a different package.
+  // We need to generate these symbols in a separate file. Returns true on success.
+  bool Generate(const android::StringPiece& package_name_to_generate, std::ostream* out);
 
-  bool Generate(const android::StringPiece& packageNameToGenerate,
-                const android::StringPiece& outputPackageName, std::ostream* out);
+  bool Generate(const android::StringPiece& package_name_to_generate,
+                const android::StringPiece& output_package_name, std::ostream* out);
 
   const std::string& getError() const;
 
  private:
-  bool AddMembersToTypeClass(const android::StringPiece& packageNameToGenerate,
-                             const ResourceTablePackage* package, const ResourceTableType* type,
-                             ClassDefinition* outTypeClassDef);
-
-  void AddMembersToStyleableClass(const android::StringPiece& packageNameToGenerate,
-                                  const std::string& entryName, const Styleable* styleable,
-                                  ClassDefinition* outStyleableClassDef);
-
   bool SkipSymbol(SymbolState state);
+  bool SkipSymbol(const Maybe<SymbolTable::Symbol>& symbol);
+
+  // Returns the unmangled resource entry name if the unmangled package is the same as
+  // package_name_to_generate. Returns nothing if the resource should be skipped.
+  Maybe<std::string> UnmangleResource(const android::StringPiece& package_name,
+                                      const android::StringPiece& package_name_to_generate,
+                                      const ResourceEntry& entry);
+
+  bool ProcessType(const android::StringPiece& package_name_to_generate,
+                   const ResourceTablePackage& package, const ResourceTableType& type,
+                   ClassDefinition* out_type_class_def, MethodDefinition* out_rewrite_method_def);
+
+  // Writes a resource to the R.java file, optionally writing out a rewrite rule for its package
+  // ID if `out_rewrite_method` is not nullptr.
+  void ProcessResource(const ResourceNameRef& name, const ResourceId& id,
+                       const ResourceEntry& entry, ClassDefinition* out_class_def,
+                       MethodDefinition* out_rewrite_method);
+
+  // Writes a styleable resource to the R.java file, optionally writing out a rewrite rule for
+  // its package ID if `out_rewrite_method` is not nullptr.
+  // `package_name_to_generate` is the package
+  void ProcessStyleable(const ResourceNameRef& name, const ResourceId& id,
+                        const Styleable& styleable,
+                        const android::StringPiece& package_name_to_generate,
+                        ClassDefinition* out_class_def, MethodDefinition* out_rewrite_method);
 
   IAaptContext* context_;
   ResourceTable* table_;
diff --git a/tools/aapt2/java/JavaClassGenerator_test.cpp b/tools/aapt2/java/JavaClassGenerator_test.cpp
index 55c5cb2..271279f 100644
--- a/tools/aapt2/java/JavaClassGenerator_test.cpp
+++ b/tools/aapt2/java/JavaClassGenerator_test.cpp
@@ -293,8 +293,7 @@
 
 TEST(JavaClassGeneratorTest, CommentsForEnumAndFlagAttributesArePresent) {}
 
-TEST(JavaClassGeneratorTest,
-     CommentsForStyleablesAndNestedAttributesArePresent) {
+TEST(JavaClassGeneratorTest, CommentsForStyleablesAndNestedAttributesArePresent) {
   Attribute attr(false);
   attr.SetComment(StringPiece("This is an attribute"));
 
@@ -364,4 +363,37 @@
   EXPECT_EQ(std::string::npos, actual.find("removed", pos + 1));
 }
 
+TEST(JavaClassGeneratorTest, GenerateOnResourcesLoadedCallbackForSharedLibrary) {
+  std::unique_ptr<ResourceTable> table =
+      test::ResourceTableBuilder()
+          .SetPackageId("android", 0x00)
+          .AddValue("android:attr/foo", ResourceId(0x00010000), util::make_unique<Attribute>(false))
+          .AddValue("android:id/foo", ResourceId(0x00020000), util::make_unique<Id>())
+          .AddValue(
+              "android:style/foo", ResourceId(0x00030000),
+              test::StyleBuilder()
+                  .AddItem("android:attr/foo", ResourceId(0x00010000), util::make_unique<Id>())
+                  .Build())
+          .Build();
+
+  std::unique_ptr<IAaptContext> context =
+      test::ContextBuilder().SetPackageId(0x00).SetCompilationPackage("android").Build();
+
+  JavaClassGeneratorOptions options;
+  options.use_final = false;
+  options.rewrite_callback_options = OnResourcesLoadedCallbackOptions{
+      {"com.foo", "com.boo"},
+  };
+  JavaClassGenerator generator(context.get(), table.get(), options);
+
+  std::stringstream out;
+  ASSERT_TRUE(generator.Generate("android", &out));
+
+  std::string actual = out.str();
+
+  EXPECT_NE(std::string::npos, actual.find("void onResourcesLoaded"));
+  EXPECT_NE(std::string::npos, actual.find("com.foo.R.onResourcesLoaded"));
+  EXPECT_NE(std::string::npos, actual.find("com.boo.R.onResourcesLoaded"));
+}
+
 }  // namespace aapt
diff --git a/tools/aapt2/java/ManifestClassGenerator.cpp b/tools/aapt2/java/ManifestClassGenerator.cpp
index de8e59a..f49e498 100644
--- a/tools/aapt2/java/ManifestClassGenerator.cpp
+++ b/tools/aapt2/java/ManifestClassGenerator.cpp
@@ -100,11 +100,9 @@
   }
 
   std::unique_ptr<ClassDefinition> permission_class =
-      util::make_unique<ClassDefinition>("permission", ClassQualifier::Static,
-                                         false);
+      util::make_unique<ClassDefinition>("permission", ClassQualifier::kStatic, false);
   std::unique_ptr<ClassDefinition> permission_group_class =
-      util::make_unique<ClassDefinition>("permission_group",
-                                         ClassQualifier::Static, false);
+      util::make_unique<ClassDefinition>("permission_group", ClassQualifier::kStatic, false);
 
   bool error = false;
   std::vector<xml::Element*> children = el->GetChildElements();
@@ -125,8 +123,7 @@
   }
 
   std::unique_ptr<ClassDefinition> manifest_class =
-      util::make_unique<ClassDefinition>("Manifest", ClassQualifier::None,
-                                         false);
+      util::make_unique<ClassDefinition>("Manifest", ClassQualifier::kNone, false);
   manifest_class->AddMember(std::move(permission_class));
   manifest_class->AddMember(std::move(permission_group_class));
   return manifest_class;
diff --git a/tools/aapt2/link/Link.cpp b/tools/aapt2/link/Link.cpp
index 0501a3b..c8f0217 100644
--- a/tools/aapt2/link/Link.cpp
+++ b/tools/aapt2/link/Link.cpp
@@ -23,6 +23,7 @@
 
 #include "android-base/errors.h"
 #include "android-base/file.h"
+#include "android-base/stringprintf.h"
 #include "androidfw/StringPiece.h"
 #include "google/protobuf/io/coded_stream.h"
 
@@ -46,6 +47,8 @@
 #include "link/ManifestFixer.h"
 #include "link/ReferenceLinker.h"
 #include "link/TableMerger.h"
+#include "optimize/ResourceDeduper.h"
+#include "optimize/VersionCollapser.h"
 #include "process/IResourceTableConsumer.h"
 #include "process/SymbolTable.h"
 #include "proto/ProtoSerialize.h"
@@ -55,11 +58,21 @@
 #include "xml/XmlDom.h"
 
 using android::StringPiece;
+using android::base::StringPrintf;
 using ::google::protobuf::io::CopyingOutputStreamAdaptor;
 
 namespace aapt {
 
+// The type of package to build.
+enum class PackageType {
+  kApp,
+  kSharedLib,
+  kStaticLib,
+};
+
 struct LinkOptions {
+  PackageType package_type = PackageType::kApp;
+
   std::string output_path;
   std::string manifest_path;
   std::vector<std::string> include_paths;
@@ -87,7 +100,6 @@
   std::unordered_set<std::string> extensions_to_not_compress;
 
   // Static lib options.
-  bool static_lib = false;
   bool no_static_lib_packages = false;
 
   // AndroidManifest.xml massaging options.
@@ -96,6 +108,9 @@
   // Products to use/filter on.
   std::unordered_set<std::string> products;
 
+  // Flattening options.
+  TableFlattenerOptions table_flattener_options;
+
   // Split APK options.
   TableSplitterOptions table_splitter_options;
   std::vector<SplitConstraints> split_constraints;
@@ -108,7 +123,7 @@
 
 class LinkContext : public IAaptContext {
  public:
-  LinkContext() : name_mangler_({}) {}
+  LinkContext() : name_mangler_({}), symbols_(&name_mangler_) {}
 
   IDiagnostics* GetDiagnostics() override { return &diagnostics_; }
 
@@ -681,31 +696,35 @@
 
       // First try to load the file as a static lib.
       std::string error_str;
-      std::unique_ptr<ResourceTable> static_include =
-          LoadStaticLibrary(path, &error_str);
-      if (static_include) {
-        if (!options_.static_lib) {
-          // Can't include static libraries when not building a static library.
+      std::unique_ptr<ResourceTable> include_static = LoadStaticLibrary(path, &error_str);
+      if (include_static) {
+        if (options_.package_type != PackageType::kStaticLib) {
+          // Can't include static libraries when not building a static library (they have no IDs
+          // assigned).
           context_->GetDiagnostics()->Error(
-              DiagMessage(path)
-              << "can't include static library when building app");
+              DiagMessage(path) << "can't include static library when not building a static lib");
           return false;
         }
 
         // If we are using --no-static-lib-packages, we need to rename the
-        // package of this
-        // table to our compilation package.
+        // package of this table to our compilation package.
         if (options_.no_static_lib_packages) {
-          if (ResourceTablePackage* pkg =
-                  static_include->FindPackageById(0x7f)) {
+          // Since package names can differ, and multiple packages can exist in a ResourceTable,
+          // we place the requirement that all static libraries are built with the package
+          // ID 0x7f. So if one is not found, this is an error.
+          if (ResourceTablePackage* pkg = include_static->FindPackageById(kAppPackageId)) {
             pkg->name = context_->GetCompilationPackage();
+          } else {
+            context_->GetDiagnostics()->Error(DiagMessage(path)
+                                              << "no package with ID 0x7f found in static library");
+            return false;
           }
         }
 
         context_->GetExternalSymbols()->AppendSource(
-            util::make_unique<ResourceTableSymbolSource>(static_include.get()));
+            util::make_unique<ResourceTableSymbolSource>(include_static.get()));
 
-        static_table_includes_.push_back(std::move(static_include));
+        static_table_includes_.push_back(std::move(include_static));
 
       } else if (!error_str.empty()) {
         // We had an error with reading, so fail.
@@ -714,12 +733,19 @@
       }
 
       if (!asset_source->AddAssetPath(path)) {
-        context_->GetDiagnostics()->Error(DiagMessage(path)
-                                          << "failed to load include path");
+        context_->GetDiagnostics()->Error(DiagMessage(path) << "failed to load include path");
         return false;
       }
     }
 
+    // Capture the shared libraries so that the final resource table can be properly flattened
+    // with support for shared libraries.
+    for (auto& entry : asset_source->GetAssignedPackageIds()) {
+      if (entry.first > kFrameworkPackageId && entry.first < kAppPackageId) {
+        final_table_.included_packages_[entry.first] = entry.second;
+      }
+    }
+
     context_->GetExternalSymbols()->AppendSource(std::move(asset_source));
     return true;
   }
@@ -842,10 +868,9 @@
     for (const auto& package : final_table_.packages) {
       for (const auto& type : package->types) {
         if (type->id) {
-          context_->GetDiagnostics()->Error(
-              DiagMessage() << "type " << type->type << " has ID " << std::hex
-                            << (int)type->id.value() << std::dec
-                            << " assigned");
+          context_->GetDiagnostics()->Error(DiagMessage() << "type " << type->type << " has ID "
+                                                          << StringPrintf("%02x", type->id.value())
+                                                          << " assigned");
           return false;
         }
 
@@ -853,9 +878,8 @@
           if (entry->id) {
             ResourceNameRef res_name(package->name, type->type, entry->name);
             context_->GetDiagnostics()->Error(
-                DiagMessage() << "entry " << res_name << " has ID " << std::hex
-                              << (int)entry->id.value() << std::dec
-                              << " assigned");
+                DiagMessage() << "entry " << res_name << " has ID "
+                              << StringPrintf("%02x", entry->id.value()) << " assigned");
             return false;
           }
         }
@@ -874,7 +898,7 @@
 
   bool FlattenTable(ResourceTable* table, IArchiveWriter* writer) {
     BigBuffer buffer(1024);
-    TableFlattener flattener(&buffer);
+    TableFlattener flattener(options_.table_flattener_options, &buffer);
     if (!flattener.Consume(context_, table)) {
       return false;
     }
@@ -1079,18 +1103,15 @@
       return false;
     }
 
-    std::unique_ptr<ResourceTable> table =
-        LoadTablePbFromCollection(collection.get());
+    std::unique_ptr<ResourceTable> table = LoadTablePbFromCollection(collection.get());
     if (!table) {
-      context_->GetDiagnostics()->Error(DiagMessage(input)
-                                        << "invalid static library");
+      context_->GetDiagnostics()->Error(DiagMessage(input) << "invalid static library");
       return false;
     }
 
-    ResourceTablePackage* pkg = table->FindPackageById(0x7f);
+    ResourceTablePackage* pkg = table->FindPackageById(kAppPackageId);
     if (!pkg) {
-      context_->GetDiagnostics()->Error(DiagMessage(input)
-                                        << "static library has no package");
+      context_->GetDiagnostics()->Error(DiagMessage(input) << "static library has no package");
       return false;
     }
 
@@ -1107,11 +1128,9 @@
 
       pkg->name = "";
       if (override) {
-        result = table_merger_->MergeOverlay(Source(input), table.get(),
-                                             collection.get());
+        result = table_merger_->MergeOverlay(Source(input), table.get(), collection.get());
       } else {
-        result =
-            table_merger_->Merge(Source(input), table.get(), collection.get());
+        result = table_merger_->Merge(Source(input), table.get(), collection.get());
       }
 
     } else {
@@ -1399,7 +1418,7 @@
    */
   bool WriteApk(IArchiveWriter* writer, proguard::KeepSet* keep_set,
                 xml::XmlResource* manifest, ResourceTable* table) {
-    const bool keep_raw_values = options_.static_lib;
+    const bool keep_raw_values = options_.package_type == PackageType::kStaticLib;
     bool result = FlattenXml(manifest, "AndroidManifest.xml", {},
                              keep_raw_values, writer, context_);
     if (!result) {
@@ -1419,25 +1438,21 @@
     file_flattener_options.update_proguard_spec =
         static_cast<bool>(options_.generate_proguard_rules_path);
 
-    ResourceFileFlattener file_flattener(file_flattener_options, context_,
-                                         keep_set);
+    ResourceFileFlattener file_flattener(file_flattener_options, context_, keep_set);
 
     if (!file_flattener.Flatten(table, writer)) {
-      context_->GetDiagnostics()->Error(DiagMessage()
-                                        << "failed linking file resources");
+      context_->GetDiagnostics()->Error(DiagMessage() << "failed linking file resources");
       return false;
     }
 
-    if (options_.static_lib) {
+    if (options_.package_type == PackageType::kStaticLib) {
       if (!FlattenTableToPb(table, writer)) {
-        context_->GetDiagnostics()->Error(
-            DiagMessage() << "failed to write resources.arsc.flat");
+        context_->GetDiagnostics()->Error(DiagMessage() << "failed to write resources.arsc.flat");
         return false;
       }
     } else {
       if (!FlattenTable(table, writer)) {
-        context_->GetDiagnostics()->Error(DiagMessage()
-                                          << "failed to write resources.arsc");
+        context_->GetDiagnostics()->Error(DiagMessage() << "failed to write resources.arsc");
         return false;
       }
     }
@@ -1481,10 +1496,17 @@
 
     context_->SetNameManglerPolicy(
         NameManglerPolicy{context_->GetCompilationPackage()});
+
+    // Override the package ID when it is "android".
     if (context_->GetCompilationPackage() == "android") {
       context_->SetPackageId(0x01);
-    } else {
-      context_->SetPackageId(0x7f);
+
+      // Verify we're building a regular app.
+      if (options_.package_type != PackageType::kApp) {
+        context_->GetDiagnostics()->Error(
+            DiagMessage() << "package 'android' can only be built as a regular app");
+        return 1;
+      }
     }
 
     if (!LoadSymbolsFromIncludePaths()) {
@@ -1498,10 +1520,9 @@
 
     if (context_->IsVerbose()) {
       context_->GetDiagnostics()->Note(DiagMessage()
-                                       << "linking package '"
-                                       << context_->GetCompilationPackage()
-                                       << "' with package ID " << std::hex
-                                       << (int)context_->GetPackageId());
+                                       << StringPrintf("linking package '%s' using package ID %02x",
+                                                       context_->GetCompilationPackage().data(),
+                                                       context_->GetPackageId()));
     }
 
     for (const std::string& input : input_files) {
@@ -1524,7 +1545,7 @@
       return 1;
     }
 
-    if (!options_.static_lib) {
+    if (options_.package_type != PackageType::kStaticLib) {
       PrivateAttributeMover mover;
       if (!mover.Consume(context_, &final_table_)) {
         context_->GetDiagnostics()->Error(
@@ -1535,8 +1556,7 @@
       // Assign IDs if we are building a regular app.
       IdAssigner id_assigner(&options_.stable_id_map);
       if (!id_assigner.Consume(context_, &final_table_)) {
-        context_->GetDiagnostics()->Error(DiagMessage()
-                                          << "failed assigning IDs");
+        context_->GetDiagnostics()->Error(DiagMessage() << "failed assigning IDs");
         return 1;
       }
 
@@ -1583,17 +1603,15 @@
       return 1;
     }
 
-    if (options_.static_lib) {
+    if (options_.package_type == PackageType::kStaticLib) {
       if (!options_.products.empty()) {
-        context_->GetDiagnostics()
-            ->Warn(DiagMessage()
-                   << "can't select products when building static library");
+        context_->GetDiagnostics()->Warn(DiagMessage()
+                                         << "can't select products when building static library");
       }
     } else {
       ProductFilter product_filter(options_.products);
       if (!product_filter.Consume(context_, &final_table_)) {
-        context_->GetDiagnostics()->Error(DiagMessage()
-                                          << "failed stripping products");
+        context_->GetDiagnostics()->Error(DiagMessage() << "failed stripping products");
         return 1;
       }
     }
@@ -1607,7 +1625,7 @@
       }
     }
 
-    if (!options_.static_lib && context_->GetMinSdkVersion() > 0) {
+    if (options_.package_type != PackageType::kStaticLib && context_->GetMinSdkVersion() > 0) {
       if (context_->IsVerbose()) {
         context_->GetDiagnostics()->Note(
             DiagMessage() << "collapsing resource versions for minimum SDK "
@@ -1623,8 +1641,7 @@
     if (!options_.no_resource_deduping) {
       ResourceDeduper deduper;
       if (!deduper.Consume(context_, &final_table_)) {
-        context_->GetDiagnostics()->Error(DiagMessage()
-                                          << "failed deduping resources");
+        context_->GetDiagnostics()->Error(DiagMessage() << "failed deduping resources");
         return 1;
       }
     }
@@ -1632,12 +1649,11 @@
     proguard::KeepSet proguard_keep_set;
     proguard::KeepSet proguard_main_dex_keep_set;
 
-    if (options_.static_lib) {
+    if (options_.package_type == PackageType::kStaticLib) {
       if (options_.table_splitter_options.config_filter != nullptr ||
           !options_.table_splitter_options.preferred_densities.empty()) {
-        context_->GetDiagnostics()
-            ->Warn(DiagMessage()
-                   << "can't strip resources when building static library");
+        context_->GetDiagnostics()->Warn(DiagMessage()
+                                         << "can't strip resources when building static library");
       }
     } else {
       // Adjust the SplitConstraints so that their SDK version is stripped if it
@@ -1771,12 +1787,21 @@
     }
 
     if (options_.generate_java_class_path) {
-      JavaClassGeneratorOptions options;
-      options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
-      options.javadoc_annotations = options_.javadoc_annotations;
+      // The set of packages whose R class to call in the main classes
+      // onResourcesLoaded callback.
+      std::vector<std::string> packages_to_callback;
 
-      if (options_.static_lib || options_.generate_non_final_ids) {
-        options.use_final = false;
+      JavaClassGeneratorOptions template_options;
+      template_options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
+      template_options.javadoc_annotations = options_.javadoc_annotations;
+
+      if (options_.package_type == PackageType::kStaticLib || options_.generate_non_final_ids) {
+        template_options.use_final = false;
+      }
+
+      if (options_.package_type == PackageType::kSharedLib) {
+        template_options.use_final = false;
+        template_options.rewrite_callback_options = OnResourcesLoadedCallbackOptions{};
       }
 
       const StringPiece actual_package = context_->GetCompilationPackage();
@@ -1786,36 +1811,51 @@
         output_package = options_.custom_java_package.value();
       }
 
+      // Generate the private symbols if required.
       if (options_.private_symbols) {
+        packages_to_callback.push_back(options_.private_symbols.value());
+
         // If we defined a private symbols package, we only emit Public symbols
         // to the original package, and private and public symbols to the
         // private package.
-
-        options.types = JavaClassGeneratorOptions::SymbolTypes::kPublic;
-        if (!WriteJavaFile(&final_table_, context_->GetCompilationPackage(),
-                           output_package, options)) {
-          return 1;
-        }
-
+        JavaClassGeneratorOptions options = template_options;
         options.types = JavaClassGeneratorOptions::SymbolTypes::kPublicPrivate;
-        output_package = options_.private_symbols.value();
-      }
-
-      if (!WriteJavaFile(&final_table_, actual_package, output_package,
-                         options)) {
-        return 1;
-      }
-
-      for (const std::string& extra_package : options_.extra_java_packages) {
-        if (!WriteJavaFile(&final_table_, actual_package, extra_package,
+        if (!WriteJavaFile(&final_table_, actual_package, options_.private_symbols.value(),
                            options)) {
           return 1;
         }
       }
+
+      // Generate all the symbols for all extra packages.
+      for (const std::string& extra_package : options_.extra_java_packages) {
+        packages_to_callback.push_back(extra_package);
+
+        JavaClassGeneratorOptions options = template_options;
+        options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
+        if (!WriteJavaFile(&final_table_, actual_package, extra_package, options)) {
+          return 1;
+        }
+      }
+
+      // Generate the main public R class.
+      JavaClassGeneratorOptions options = template_options;
+
+      // Only generate public symbols if we have a private package.
+      if (options_.private_symbols) {
+        options.types = JavaClassGeneratorOptions::SymbolTypes::kPublic;
+      }
+
+      if (options.rewrite_callback_options) {
+        options.rewrite_callback_options.value().packages_to_callback =
+            std::move(packages_to_callback);
+      }
+
+      if (!WriteJavaFile(&final_table_, actual_package, output_package, options)) {
+        return 1;
+      }
     }
 
-    if (!WriteProguardFile(options_.generate_proguard_rules_path,
-                           proguard_keep_set)) {
+    if (!WriteProguardFile(options_.generate_proguard_rules_path, proguard_keep_set)) {
       return 1;
     }
 
@@ -1847,9 +1887,11 @@
   std::vector<std::unique_ptr<io::IFileCollection>> collections_;
 
   // A vector of ResourceTables. This is here to retain ownership, so that the
-  // SymbolTable
-  // can use these.
+  // SymbolTable can use these.
   std::vector<std::unique_ptr<ResourceTable>> static_table_includes_;
+
+  // The set of shared libraries being used, mapping their assigned package ID to package name.
+  std::map<size_t, std::string> shared_libs_;
 };
 
 int Link(const std::vector<StringPiece>& args) {
@@ -1857,12 +1899,15 @@
   LinkOptions options;
   std::vector<std::string> overlay_arg_list;
   std::vector<std::string> extra_java_packages;
+  Maybe<std::string> package_id;
   Maybe<std::string> configs;
   Maybe<std::string> preferred_density;
   Maybe<std::string> product_list;
   bool legacy_x_flag = false;
   bool require_localization = false;
   bool verbose = false;
+  bool shared_lib = false;
+  bool static_lib = false;
   Maybe<std::string> stable_id_file_path;
   std::vector<std::string> split_args;
   Flags flags =
@@ -1870,24 +1915,23 @@
           .RequiredFlag("-o", "Output path", &options.output_path)
           .RequiredFlag("--manifest", "Path to the Android manifest to build",
                         &options.manifest_path)
-          .OptionalFlagList("-I", "Adds an Android APK to link against",
-                            &options.include_paths)
-          .OptionalFlagList(
-              "-R",
-              "Compilation unit to link, using `overlay` semantics.\n"
-              "The last conflicting resource given takes precedence.",
-              &overlay_arg_list)
+          .OptionalFlagList("-I", "Adds an Android APK to link against", &options.include_paths)
+          .OptionalFlagList("-R",
+                            "Compilation unit to link, using `overlay` semantics.\n"
+                            "The last conflicting resource given takes precedence.",
+                            &overlay_arg_list)
+          .OptionalFlag("--package-id",
+                        "Specify the package ID to use for this app. Must be greater or equal to\n"
+                        "0x7f and can't be used with --static-lib or --shared-lib.",
+                        &package_id)
           .OptionalFlag("--java", "Directory in which to generate R.java",
                         &options.generate_java_class_path)
-          .OptionalFlag("--proguard",
-                        "Output file for generated Proguard rules",
+          .OptionalFlag("--proguard", "Output file for generated Proguard rules",
                         &options.generate_proguard_rules_path)
-          .OptionalFlag(
-              "--proguard-main-dex",
-              "Output file for generated Proguard rules for the main dex",
-              &options.generate_main_dex_proguard_rules_path)
-          .OptionalSwitch("--no-auto-version",
-                          "Disables automatic style and layout SDK versioning",
+          .OptionalFlag("--proguard-main-dex",
+                        "Output file for generated Proguard rules for the main dex",
+                        &options.generate_main_dex_proguard_rules_path)
+          .OptionalSwitch("--no-auto-version", "Disables automatic style and layout SDK versioning",
                           &options.no_auto_version)
           .OptionalSwitch("--no-version-vectors",
                           "Disables automatic versioning of vector drawables. "
@@ -1903,25 +1947,22 @@
                           "Disables automatic deduping of resources with\n"
                           "identical values across compatible configurations.",
                           &options.no_resource_deduping)
-          .OptionalSwitch(
-              "-x",
-              "Legacy flag that specifies to use the package identifier 0x01",
-              &legacy_x_flag)
-          .OptionalSwitch("-z",
-                          "Require localization of strings marked 'suggested'",
+          .OptionalSwitch("--enable-sparse-encoding",
+                          "Enables encoding sparse entries using a binary search tree.\n"
+                          "This decreases APK size at the cost of resource retrieval performance.",
+                          &options.table_flattener_options.use_sparse_entries)
+          .OptionalSwitch("-x", "Legacy flag that specifies to use the package identifier 0x01",
+                          &legacy_x_flag)
+          .OptionalSwitch("-z", "Require localization of strings marked 'suggested'",
                           &require_localization)
-          .OptionalFlag(
-              "-c",
-              "Comma separated list of configurations to include. The default\n"
-              "is all configurations",
-              &configs)
-          .OptionalFlag(
-              "--preferred-density",
-              "Selects the closest matching density and strips out all others.",
-              &preferred_density)
-          .OptionalFlag("--product",
-                        "Comma separated list of product names to keep",
-                        &product_list)
+          .OptionalFlag("-c",
+                        "Comma separated list of configurations to include. The default\n"
+                        "is all configurations",
+                        &configs)
+          .OptionalFlag("--preferred-density",
+                        "Selects the closest matching density and strips out all others.",
+                        &preferred_density)
+          .OptionalFlag("--product", "Comma separated list of product names to keep", &product_list)
           .OptionalSwitch("--output-to-dir",
                           "Outputs the APK contents to a directory specified "
                           "by -o",
@@ -1935,11 +1976,10 @@
                         "Default minimum SDK version to use for "
                         "AndroidManifest.xml",
                         &options.manifest_fixer_options.min_sdk_version_default)
-          .OptionalFlag(
-              "--target-sdk-version",
-              "Default target SDK version to use for "
-              "AndroidManifest.xml",
-              &options.manifest_fixer_options.target_sdk_version_default)
+          .OptionalFlag("--target-sdk-version",
+                        "Default target SDK version to use for "
+                        "AndroidManifest.xml",
+                        &options.manifest_fixer_options.target_sdk_version_default)
           .OptionalFlag("--version-code",
                         "Version code (integer) to inject into the "
                         "AndroidManifest.xml if none is present",
@@ -1948,8 +1988,8 @@
                         "Version name to inject into the AndroidManifest.xml "
                         "if none is present",
                         &options.manifest_fixer_options.version_name_default)
-          .OptionalSwitch("--static-lib", "Generate a static Android library",
-                          &options.static_lib)
+          .OptionalSwitch("--shared-lib", "Generates a shared Android runtime library", &shared_lib)
+          .OptionalSwitch("--static-lib", "Generate a static Android library", &static_lib)
           .OptionalSwitch("--no-static-lib-packages",
                           "Merge all library resources under the app's package",
                           &options.no_static_lib_packages)
@@ -1957,14 +1997,12 @@
                           "Generates R.java without the final modifier.\n"
                           "This is implied when --static-lib is specified.",
                           &options.generate_non_final_ids)
-          .OptionalFlag("--stable-ids",
-                        "File containing a list of name to ID mapping.",
+          .OptionalFlag("--stable-ids", "File containing a list of name to ID mapping.",
                         &stable_id_file_path)
-          .OptionalFlag(
-              "--emit-ids",
-              "Emit a file at the given path with a list of name to ID\n"
-              "mappings, suitable for use with --stable-ids.",
-              &options.resource_id_map_path)
+          .OptionalFlag("--emit-ids",
+                        "Emit a file at the given path with a list of name to ID\n"
+                        "mappings, suitable for use with --stable-ids.",
+                        &options.resource_id_map_path)
           .OptionalFlag("--private-symbols",
                         "Package name to use when generating R.java for "
                         "private symbols.\n"
@@ -1972,8 +2010,7 @@
                         "the application's "
                         "package name",
                         &options.private_symbols)
-          .OptionalFlag("--custom-package",
-                        "Custom Java package under which to generate R.java",
+          .OptionalFlag("--custom-package", "Custom Java package under which to generate R.java",
                         &options.custom_java_package)
           .OptionalFlagList("--extra-packages",
                             "Generate the same R.java but with different "
@@ -1987,23 +2024,19 @@
                           "Allows the addition of new resources in "
                           "overlays without <add-resource> tags",
                           &options.auto_add_overlay)
-          .OptionalFlag("--rename-manifest-package",
-                        "Renames the package in AndroidManifest.xml",
+          .OptionalFlag("--rename-manifest-package", "Renames the package in AndroidManifest.xml",
                         &options.manifest_fixer_options.rename_manifest_package)
-          .OptionalFlag(
-              "--rename-instrumentation-target-package",
-              "Changes the name of the target package for instrumentation. "
-              "Most useful "
-              "when used\nin conjunction with --rename-manifest-package",
-              &options.manifest_fixer_options
-                   .rename_instrumentation_target_package)
+          .OptionalFlag("--rename-instrumentation-target-package",
+                        "Changes the name of the target package for instrumentation. "
+                        "Most useful "
+                        "when used\nin conjunction with --rename-manifest-package",
+                        &options.manifest_fixer_options.rename_instrumentation_target_package)
           .OptionalFlagList("-0", "File extensions not to compress",
                             &options.extensions_to_not_compress)
-          .OptionalFlagList(
-              "--split",
-              "Split resources matching a set of configs out to a "
-              "Split APK.\nSyntax: path/to/output.apk:<config>[,<config>[...]]",
-              &split_args)
+          .OptionalFlagList("--split",
+                            "Split resources matching a set of configs out to a "
+                            "Split APK.\nSyntax: path/to/output.apk:<config>[,<config>[...]]",
+                            &split_args)
           .OptionalSwitch("-v", "Enables verbose logging", &verbose);
 
   if (!flags.Parse("aapt2 link", args, &std::cerr)) {
@@ -2044,6 +2077,47 @@
     context.SetVerbose(verbose);
   }
 
+  if (shared_lib && static_lib) {
+    context.GetDiagnostics()->Error(DiagMessage()
+                                    << "only one of --shared-lib and --static-lib can be defined");
+    return 1;
+  }
+
+  if (shared_lib) {
+    options.package_type = PackageType::kSharedLib;
+    context.SetPackageId(0x00);
+  } else if (static_lib) {
+    options.package_type = PackageType::kStaticLib;
+    context.SetPackageId(kAppPackageId);
+  } else {
+    options.package_type = PackageType::kApp;
+    context.SetPackageId(kAppPackageId);
+  }
+
+  if (package_id) {
+    if (options.package_type != PackageType::kApp) {
+      context.GetDiagnostics()->Error(
+          DiagMessage() << "can't specify --package-id when not building a regular app");
+      return 1;
+    }
+
+    const Maybe<uint32_t> maybe_package_id_int = ResourceUtils::ParseInt(package_id.value());
+    if (!maybe_package_id_int) {
+      context.GetDiagnostics()->Error(DiagMessage() << "package ID '" << package_id.value()
+                                                    << "' is not a valid integer");
+      return 1;
+    }
+
+    const uint32_t package_id_int = maybe_package_id_int.value();
+    if (package_id_int < kAppPackageId || package_id_int > std::numeric_limits<uint8_t>::max()) {
+      context.GetDiagnostics()->Error(
+          DiagMessage() << StringPrintf(
+              "invalid package ID 0x%02x. Must be in the range 0x7f-0xff.", package_id_int));
+      return 1;
+    }
+    context.SetPackageId(static_cast<uint8_t>(package_id_int));
+  }
+
   // Populate the set of extra packages for which to generate R.java.
   for (std::string& extra_package : extra_java_packages) {
     // A given package can actually be a colon separated list of packages.
@@ -2110,7 +2184,7 @@
     options.table_splitter_options.preferred_densities.push_back(preferred_density_config.density);
   }
 
-  if (!options.static_lib && stable_id_file_path) {
+  if (options.package_type != PackageType::kStaticLib && stable_id_file_path) {
     if (!LoadStableIdMap(context.GetDiagnostics(), stable_id_file_path.value(),
                          &options.stable_id_map)) {
       return 1;
@@ -2136,7 +2210,7 @@
   }
 
   // Turn off auto versioning for static-libs.
-  if (options.static_lib) {
+  if (options.package_type == PackageType::kStaticLib) {
     options.no_auto_version = true;
     options.no_version_vectors = true;
     options.no_version_transitions = true;
diff --git a/tools/aapt2/link/Linkers.h b/tools/aapt2/link/Linkers.h
index 4687d2c..d00fa73 100644
--- a/tools/aapt2/link/Linkers.h
+++ b/tools/aapt2/link/Linkers.h
@@ -58,29 +58,6 @@
   DISALLOW_COPY_AND_ASSIGN(AutoVersioner);
 };
 
-class VersionCollapser : public IResourceTableConsumer {
- public:
-  VersionCollapser() = default;
-
-  bool Consume(IAaptContext* context, ResourceTable* table) override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(VersionCollapser);
-};
-
-/**
- * Removes duplicated key-value entries from dominated resources.
- */
-class ResourceDeduper : public IResourceTableConsumer {
- public:
-  ResourceDeduper() = default;
-
-  bool Consume(IAaptContext* context, ResourceTable* table) override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ResourceDeduper);
-};
-
 /**
  * If any attribute resource values are defined as public, this consumer will
  * move all private
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index b4cf4f8..313fe45 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -54,16 +54,14 @@
   return true;
 }
 
-static bool OptionalNameIsJavaClassName(xml::Element* el,
-                                        SourcePathDiagnostics* diag) {
+static bool OptionalNameIsJavaClassName(xml::Element* el, SourcePathDiagnostics* diag) {
   if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name")) {
     return NameIsJavaClassName(el, attr, diag);
   }
   return true;
 }
 
-static bool RequiredNameIsJavaClassName(xml::Element* el,
-                                        SourcePathDiagnostics* diag) {
+static bool RequiredNameIsJavaClassName(xml::Element* el, SourcePathDiagnostics* diag) {
   if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name")) {
     return NameIsJavaClassName(el, attr, diag);
   }
@@ -72,6 +70,26 @@
   return false;
 }
 
+static bool RequiredNameIsJavaPackage(xml::Element* el, SourcePathDiagnostics* diag) {
+  if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name")) {
+    return util::IsJavaPackageName(attr->value);
+  }
+  diag->Error(DiagMessage(el->line_number)
+              << "<" << el->name << "> is missing attribute 'android:name'");
+  return false;
+}
+
+static xml::XmlNodeAction::ActionFuncWithDiag RequiredAndroidAttribute(const std::string& attr) {
+  return [=](xml::Element* el, SourcePathDiagnostics* diag) -> bool {
+    if (el->FindAttribute(xml::kSchemaAndroid, attr) == nullptr) {
+      diag->Error(DiagMessage(el->line_number)
+                  << "<" << el->name << "> is missing required attribute 'android:" << attr << "'");
+      return false;
+    }
+    return true;
+  };
+}
+
 static bool VerifyManifest(xml::Element* el, SourcePathDiagnostics* diag) {
   xml::Attribute* attr = el->FindAttribute({}, "package");
   if (!attr) {
@@ -263,7 +281,18 @@
   xml::XmlNodeAction& application_action = manifest_action["application"];
   application_action.Action(OptionalNameIsJavaClassName);
 
-  application_action["uses-library"];
+  application_action["uses-library"].Action(RequiredNameIsJavaPackage);
+  application_action["library"].Action(RequiredNameIsJavaPackage);
+
+  xml::XmlNodeAction& static_library_action = application_action["static-library"];
+  static_library_action.Action(RequiredNameIsJavaPackage);
+  static_library_action.Action(RequiredAndroidAttribute("version"));
+
+  xml::XmlNodeAction& uses_static_library_action = application_action["uses-static-library"];
+  uses_static_library_action.Action(RequiredNameIsJavaPackage);
+  uses_static_library_action.Action(RequiredAndroidAttribute("version"));
+  uses_static_library_action.Action(RequiredAndroidAttribute("certDigest"));
+
   application_action["meta-data"] = meta_data_action;
   application_action["activity"] = component_action;
   application_action["activity-alias"] = component_action;
diff --git a/tools/aapt2/link/PrivateAttributeMover.cpp b/tools/aapt2/link/PrivateAttributeMover.cpp
index cc07a6e..eee4b60 100644
--- a/tools/aapt2/link/PrivateAttributeMover.cpp
+++ b/tools/aapt2/link/PrivateAttributeMover.cpp
@@ -26,11 +26,9 @@
 namespace aapt {
 
 template <typename InputContainer, typename OutputIterator, typename Predicate>
-OutputIterator move_if(InputContainer& input_container, OutputIterator result,
-                       Predicate pred) {
+OutputIterator move_if(InputContainer& input_container, OutputIterator result, Predicate pred) {
   const auto last = input_container.end();
-  auto new_end =
-      std::find_if(input_container.begin(), input_container.end(), pred);
+  auto new_end = std::find_if(input_container.begin(), input_container.end(), pred);
   if (new_end == last) {
     return result;
   }
@@ -57,8 +55,7 @@
   return result;
 }
 
-bool PrivateAttributeMover::Consume(IAaptContext* context,
-                                    ResourceTable* table) {
+bool PrivateAttributeMover::Consume(IAaptContext* context, ResourceTable* table) {
   for (auto& package : table->packages) {
     ResourceTableType* type = package->FindType(ResourceType::kAttr);
     if (!type) {
@@ -68,18 +65,24 @@
     if (type->symbol_status.state != SymbolState::kPublic) {
       // No public attributes, so we can safely leave these private attributes
       // where they are.
-      return true;
+      continue;
     }
 
-    ResourceTableType* priv_attr_type =
-        package->FindOrCreateType(ResourceType::kAttrPrivate);
-    CHECK(priv_attr_type->entries.empty());
+    std::vector<std::unique_ptr<ResourceEntry>> private_attr_entries;
 
-    move_if(type->entries, std::back_inserter(priv_attr_type->entries),
+    move_if(type->entries, std::back_inserter(private_attr_entries),
             [](const std::unique_ptr<ResourceEntry>& entry) -> bool {
               return entry->symbol_status.state != SymbolState::kPublic;
             });
-    break;
+
+    if (private_attr_entries.empty()) {
+      // No private attributes.
+      continue;
+    }
+
+    ResourceTableType* priv_attr_type = package->FindOrCreateType(ResourceType::kAttrPrivate);
+    CHECK(priv_attr_type->entries.empty());
+    priv_attr_type->entries = std::move(private_attr_entries);
   }
   return true;
 }
diff --git a/tools/aapt2/link/PrivateAttributeMover_test.cpp b/tools/aapt2/link/PrivateAttributeMover_test.cpp
index 90c4922..7fcf6e7 100644
--- a/tools/aapt2/link/PrivateAttributeMover_test.cpp
+++ b/tools/aapt2/link/PrivateAttributeMover_test.cpp
@@ -54,8 +54,7 @@
   EXPECT_NE(type->FindEntry("privateB"), nullptr);
 }
 
-TEST(PrivateAttributeMoverTest,
-     LeavePrivateAttributesWhenNoPublicAttributesDefined) {
+TEST(PrivateAttributeMoverTest, LeavePrivateAttributesWhenNoPublicAttributesDefined) {
   std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
 
   std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
@@ -77,4 +76,23 @@
   ASSERT_EQ(type, nullptr);
 }
 
+TEST(PrivateAttributeMoverTest, DoNotCreatePrivateAttrsIfNoneExist) {
+  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
+  std::unique_ptr<ResourceTable> table =
+      test::ResourceTableBuilder()
+          .AddSimple("android:attr/pub")
+          .SetSymbolState("android:attr/pub", ResourceId(0x01010000), SymbolState::kPublic)
+          .Build();
+
+  ResourceTablePackage* package = table->FindPackage("android");
+  ASSERT_NE(nullptr, package);
+
+  ASSERT_EQ(nullptr, package->FindType(ResourceType::kAttrPrivate));
+
+  PrivateAttributeMover mover;
+  ASSERT_TRUE(mover.Consume(context.get(), table.get()));
+
+  ASSERT_EQ(nullptr, package->FindType(ResourceType::kAttrPrivate));
+}
+
 }  // namespace aapt
diff --git a/tools/aapt2/link/ReferenceLinker.cpp b/tools/aapt2/link/ReferenceLinker.cpp
index ea68b61..833ae69 100644
--- a/tools/aapt2/link/ReferenceLinker.cpp
+++ b/tools/aapt2/link/ReferenceLinker.cpp
@@ -51,18 +51,16 @@
  public:
   using ValueVisitor::Visit;
 
-  ReferenceLinkerVisitor(IAaptContext* context, SymbolTable* symbols,
-                         StringPool* string_pool, xml::IPackageDeclStack* decl,
-                         CallSite* callsite)
-      : context_(context),
+  ReferenceLinkerVisitor(const CallSite& callsite, IAaptContext* context, SymbolTable* symbols,
+                         StringPool* string_pool, xml::IPackageDeclStack* decl)
+      : callsite_(callsite),
+        context_(context),
         symbols_(symbols),
         package_decls_(decl),
-        string_pool_(string_pool),
-        callsite_(callsite) {}
+        string_pool_(string_pool) {}
 
   void Visit(Reference* ref) override {
-    if (!ReferenceLinker::LinkReference(ref, context_, symbols_, package_decls_,
-                                        callsite_)) {
+    if (!ReferenceLinker::LinkReference(callsite_, ref, context_, symbols_, package_decls_)) {
       error_ = true;
     }
   }
@@ -96,10 +94,8 @@
 
       // Find the attribute in the symbol table and check if it is visible from
       // this callsite.
-      const SymbolTable::Symbol* symbol =
-          ReferenceLinker::ResolveAttributeCheckVisibility(
-              transformed_reference, context_->GetNameMangler(), symbols_,
-              callsite_, &err_str);
+      const SymbolTable::Symbol* symbol = ReferenceLinker::ResolveAttributeCheckVisibility(
+          transformed_reference, callsite_, symbols_, &err_str);
       if (symbol) {
         // Assign our style key the correct ID.
         // The ID may not exist.
@@ -107,8 +103,7 @@
 
         // Try to convert the value to a more specific, typed value based on the
         // attribute it is set to.
-        entry.value = ParseValueWithAttribute(std::move(entry.value),
-                                              symbol->attribute.get());
+        entry.value = ParseValueWithAttribute(std::move(entry.value), symbol->attribute.get());
 
         // Link/resolve the final value (mostly if it's a reference).
         entry.value->Accept(this);
@@ -124,8 +119,7 @@
           DiagMessage msg(entry.key.GetSource());
 
           // Call the matches method again, this time with a DiagMessage so we
-          // fill
-          // in the actual error message.
+          // fill in the actual error message.
           symbol->attribute->Matches(entry.value.get(), &msg);
           context_->GetDiagnostics()->Error(msg);
           error_ = true;
@@ -134,8 +128,7 @@
       } else {
         DiagMessage msg(entry.key.GetSource());
         msg << "style attribute '";
-        ReferenceLinker::WriteResourceName(&msg, entry.key,
-                                           transformed_reference);
+        ReferenceLinker::WriteResourceName(&msg, entry.key, transformed_reference);
         msg << "' " << err_str;
         context_->GetDiagnostics()->Error(msg);
         error_ = true;
@@ -161,28 +154,26 @@
           ResourceUtils::TryParseItemForAttribute(*raw_string->value, attr);
 
       // If we could not parse as any specific type, try a basic STRING.
-      if (!transformed &&
-          (attr->type_mask & android::ResTable_map::TYPE_STRING)) {
+      if (!transformed && (attr->type_mask & android::ResTable_map::TYPE_STRING)) {
         util::StringBuilder string_builder;
         string_builder.Append(*raw_string->value);
         if (string_builder) {
-          transformed = util::make_unique<String>(
-              string_pool_->MakeRef(string_builder.ToString()));
+          transformed = util::make_unique<String>(string_pool_->MakeRef(string_builder.ToString()));
         }
       }
 
       if (transformed) {
         return transformed;
       }
-    };
+    }
     return value;
   }
 
+  const CallSite& callsite_;
   IAaptContext* context_;
   SymbolTable* symbols_;
   xml::IPackageDeclStack* package_decls_;
   StringPool* string_pool_;
-  CallSite* callsite_;
   bool error_ = false;
 };
 
@@ -225,12 +216,10 @@
   return true;
 }
 
-const SymbolTable::Symbol* ReferenceLinker::ResolveSymbol(
-    const Reference& reference, NameMangler* mangler, SymbolTable* symbols) {
+const SymbolTable::Symbol* ReferenceLinker::ResolveSymbol(const Reference& reference,
+                                                          SymbolTable* symbols) {
   if (reference.name) {
-    Maybe<ResourceName> mangled = mangler->MangleName(reference.name.value());
-    return symbols->FindByName(mangled ? mangled.value()
-                                       : reference.name.value());
+    return symbols->FindByName(reference.name.value());
   } else if (reference.id) {
     return symbols->FindById(reference.id.value());
   } else {
@@ -238,17 +227,17 @@
   }
 }
 
-const SymbolTable::Symbol* ReferenceLinker::ResolveSymbolCheckVisibility(
-    const Reference& reference, NameMangler* name_mangler, SymbolTable* symbols,
-    CallSite* callsite, std::string* out_error) {
-  const SymbolTable::Symbol* symbol =
-      ResolveSymbol(reference, name_mangler, symbols);
+const SymbolTable::Symbol* ReferenceLinker::ResolveSymbolCheckVisibility(const Reference& reference,
+                                                                         const CallSite& callsite,
+                                                                         SymbolTable* symbols,
+                                                                         std::string* out_error) {
+  const SymbolTable::Symbol* symbol = ResolveSymbol(reference, symbols);
   if (!symbol) {
     if (out_error) *out_error = "not found";
     return nullptr;
   }
 
-  if (!IsSymbolVisible(*symbol, reference, *callsite)) {
+  if (!IsSymbolVisible(*symbol, reference, callsite)) {
     if (out_error) *out_error = "is private";
     return nullptr;
   }
@@ -256,10 +245,10 @@
 }
 
 const SymbolTable::Symbol* ReferenceLinker::ResolveAttributeCheckVisibility(
-    const Reference& reference, NameMangler* name_mangler, SymbolTable* symbols,
-    CallSite* callsite, std::string* out_error) {
-  const SymbolTable::Symbol* symbol = ResolveSymbolCheckVisibility(
-      reference, name_mangler, symbols, callsite, out_error);
+    const Reference& reference, const CallSite& callsite, SymbolTable* symbols,
+    std::string* out_error) {
+  const SymbolTable::Symbol* symbol =
+      ResolveSymbolCheckVisibility(reference, callsite, symbols, out_error);
   if (!symbol) {
     return nullptr;
   }
@@ -271,13 +260,13 @@
   return symbol;
 }
 
-Maybe<xml::AaptAttribute> ReferenceLinker::CompileXmlAttribute(
-    const Reference& reference, NameMangler* name_mangler, SymbolTable* symbols,
-    CallSite* callsite, std::string* out_error) {
+Maybe<xml::AaptAttribute> ReferenceLinker::CompileXmlAttribute(const Reference& reference,
+                                                               const CallSite& callsite,
+                                                               SymbolTable* symbols,
+                                                               std::string* out_error) {
   const SymbolTable::Symbol* symbol =
-      ResolveSymbol(reference, name_mangler, symbols);
+      ResolveAttributeCheckVisibility(reference, callsite, symbols, out_error);
   if (!symbol) {
-    if (out_error) *out_error = "not found";
     return {};
   }
 
@@ -303,21 +292,18 @@
   }
 }
 
-bool ReferenceLinker::LinkReference(Reference* reference, IAaptContext* context,
-                                    SymbolTable* symbols,
-                                    xml::IPackageDeclStack* decls,
-                                    CallSite* callsite) {
+bool ReferenceLinker::LinkReference(const CallSite& callsite, Reference* reference,
+                                    IAaptContext* context, SymbolTable* symbols,
+                                    xml::IPackageDeclStack* decls) {
   CHECK(reference != nullptr);
   CHECK(reference->name || reference->id);
 
   Reference transformed_reference = *reference;
-  TransformReferenceFromNamespace(decls, context->GetCompilationPackage(),
-                                  &transformed_reference);
+  TransformReferenceFromNamespace(decls, context->GetCompilationPackage(), &transformed_reference);
 
   std::string err_str;
-  const SymbolTable::Symbol* s = ResolveSymbolCheckVisibility(
-      transformed_reference, context->GetNameMangler(), symbols, callsite,
-      &err_str);
+  const SymbolTable::Symbol* s =
+      ResolveSymbolCheckVisibility(transformed_reference, callsite, symbols, &err_str);
   if (s) {
     // The ID may not exist. This is fine because of the possibility of building
     // against libraries without assigned IDs.
@@ -352,11 +338,9 @@
           error = true;
         }
 
-        CallSite callsite = {
-            ResourceNameRef(package->name, type->type, entry->name)};
-        ReferenceLinkerVisitor visitor(context, context->GetExternalSymbols(),
-                                       &table->string_pool, &decl_stack,
-                                       &callsite);
+        CallSite callsite = {ResourceNameRef(package->name, type->type, entry->name)};
+        ReferenceLinkerVisitor visitor(callsite, context, context->GetExternalSymbols(),
+                                       &table->string_pool, &decl_stack);
 
         for (auto& config_value : entry->values) {
           config_value->value->Accept(&visitor);
diff --git a/tools/aapt2/link/ReferenceLinker.h b/tools/aapt2/link/ReferenceLinker.h
index bdabf24..b3d0196 100644
--- a/tools/aapt2/link/ReferenceLinker.h
+++ b/tools/aapt2/link/ReferenceLinker.h
@@ -51,18 +51,17 @@
    * Performs name mangling and looks up the resource in the symbol table.
    * Returns nullptr if the symbol was not found.
    */
-  static const SymbolTable::Symbol* ResolveSymbol(const Reference& reference,
-                                                  NameMangler* mangler,
-                                                  SymbolTable* symbols);
+  static const SymbolTable::Symbol* ResolveSymbol(const Reference& reference, SymbolTable* symbols);
 
   /**
    * Performs name mangling and looks up the resource in the symbol table. If
    * the symbol is not visible by the reference at the callsite, nullptr is
    * returned. out_error holds the error message.
    */
-  static const SymbolTable::Symbol* ResolveSymbolCheckVisibility(
-      const Reference& reference, NameMangler* name_mangler,
-      SymbolTable* symbols, CallSite* callsite, std::string* out_error);
+  static const SymbolTable::Symbol* ResolveSymbolCheckVisibility(const Reference& reference,
+                                                                 const CallSite& callsite,
+                                                                 SymbolTable* symbols,
+                                                                 std::string* out_error);
 
   /**
    * Same as resolveSymbolCheckVisibility(), but also makes sure the symbol is
@@ -70,18 +69,20 @@
    * That is, the return value will have a non-null value for
    * ISymbolTable::Symbol::attribute.
    */
-  static const SymbolTable::Symbol* ResolveAttributeCheckVisibility(
-      const Reference& reference, NameMangler* name_mangler,
-      SymbolTable* symbols, CallSite* callsite, std::string* out_error);
+  static const SymbolTable::Symbol* ResolveAttributeCheckVisibility(const Reference& reference,
+                                                                    const CallSite& callsite,
+                                                                    SymbolTable* symbols,
+                                                                    std::string* out_error);
 
   /**
    * Resolves the attribute reference and returns an xml::AaptAttribute if
    * successful.
    * If resolution fails, outError holds the error message.
    */
-  static Maybe<xml::AaptAttribute> CompileXmlAttribute(
-      const Reference& reference, NameMangler* name_mangler,
-      SymbolTable* symbols, CallSite* callsite, std::string* out_error);
+  static Maybe<xml::AaptAttribute> CompileXmlAttribute(const Reference& reference,
+                                                       const CallSite& callsite,
+                                                       SymbolTable* symbols,
+                                                       std::string* out_error);
 
   /**
    * Writes the resource name to the DiagMessage, using the
@@ -99,9 +100,8 @@
    * Returns false on failure, and an error message is logged to the
    * IDiagnostics in the context.
    */
-  static bool LinkReference(Reference* reference, IAaptContext* context,
-                            SymbolTable* symbols, xml::IPackageDeclStack* decls,
-                            CallSite* callsite);
+  static bool LinkReference(const CallSite& callsite, Reference* reference, IAaptContext* context,
+                            SymbolTable* symbols, xml::IPackageDeclStack* decls);
 
   /**
    * Links all references in the ResourceTable.
diff --git a/tools/aapt2/link/ReferenceLinker_test.cpp b/tools/aapt2/link/ReferenceLinker_test.cpp
index 4ca36a9..d8e33a4 100644
--- a/tools/aapt2/link/ReferenceLinker_test.cpp
+++ b/tools/aapt2/link/ReferenceLinker_test.cpp
@@ -53,21 +53,20 @@
   ReferenceLinker linker;
   ASSERT_TRUE(linker.Consume(context.get(), table.get()));
 
-  Reference* ref =
-      test::GetValue<Reference>(table.get(), "com.app.test:string/foo");
-  ASSERT_NE(ref, nullptr);
+  Reference* ref = test::GetValue<Reference>(table.get(), "com.app.test:string/foo");
+  ASSERT_NE(nullptr, ref);
   AAPT_ASSERT_TRUE(ref->id);
-  EXPECT_EQ(ref->id.value(), ResourceId(0x7f020001));
+  EXPECT_EQ(ResourceId(0x7f020001), ref->id.value());
 
   ref = test::GetValue<Reference>(table.get(), "com.app.test:string/bar");
-  ASSERT_NE(ref, nullptr);
+  ASSERT_NE(nullptr, ref);
   AAPT_ASSERT_TRUE(ref->id);
-  EXPECT_EQ(ref->id.value(), ResourceId(0x7f020002));
+  EXPECT_EQ(ResourceId(0x7f020002), ref->id.value());
 
   ref = test::GetValue<Reference>(table.get(), "com.app.test:string/baz");
-  ASSERT_NE(ref, nullptr);
+  ASSERT_NE(nullptr, ref);
   AAPT_ASSERT_TRUE(ref->id);
-  EXPECT_EQ(ref->id.value(), ResourceId(0x01040034));
+  EXPECT_EQ(ResourceId(0x01040034), ref->id.value());
 }
 
 TEST(ReferenceLinkerTest, LinkStyleAttributes) {
@@ -87,9 +86,8 @@
     // We need to fill in the value for the attribute android:attr/bar after we
     // build the
     // table, because we need access to the string pool.
-    Style* style =
-        test::GetValue<Style>(table.get(), "com.app.test:style/Theme");
-    ASSERT_NE(style, nullptr);
+    Style* style = test::GetValue<Style>(table.get(), "com.app.test:style/Theme");
+    ASSERT_NE(nullptr, style);
     style->entries.back().value =
         util::make_unique<RawString>(table->string_pool.MakeRef("one|two"));
   }
@@ -120,20 +118,20 @@
   ASSERT_TRUE(linker.Consume(context.get(), table.get()));
 
   Style* style = test::GetValue<Style>(table.get(), "com.app.test:style/Theme");
-  ASSERT_NE(style, nullptr);
+  ASSERT_NE(nullptr, style);
   AAPT_ASSERT_TRUE(style->parent);
   AAPT_ASSERT_TRUE(style->parent.value().id);
-  EXPECT_EQ(style->parent.value().id.value(), ResourceId(0x01060000));
+  EXPECT_EQ(ResourceId(0x01060000), style->parent.value().id.value());
 
   ASSERT_EQ(2u, style->entries.size());
 
   AAPT_ASSERT_TRUE(style->entries[0].key.id);
-  EXPECT_EQ(style->entries[0].key.id.value(), ResourceId(0x01010001));
-  ASSERT_NE(ValueCast<BinaryPrimitive>(style->entries[0].value.get()), nullptr);
+  EXPECT_EQ(ResourceId(0x01010001), style->entries[0].key.id.value());
+  ASSERT_NE(nullptr, ValueCast<BinaryPrimitive>(style->entries[0].value.get()));
 
   AAPT_ASSERT_TRUE(style->entries[1].key.id);
-  EXPECT_EQ(style->entries[1].key.id.value(), ResourceId(0x01010002));
-  ASSERT_NE(ValueCast<BinaryPrimitive>(style->entries[1].value.get()), nullptr);
+  EXPECT_EQ(ResourceId(0x01010002), style->entries[1].key.id.value());
+  ASSERT_NE(nullptr, ValueCast<BinaryPrimitive>(style->entries[1].value.get()));
 }
 
 TEST(ReferenceLinkerTest, LinkMangledReferencesAndAttributes) {
@@ -167,10 +165,10 @@
   ASSERT_TRUE(linker.Consume(context.get(), table.get()));
 
   Style* style = test::GetValue<Style>(table.get(), "com.app.test:style/Theme");
-  ASSERT_NE(style, nullptr);
+  ASSERT_NE(nullptr, style);
   ASSERT_EQ(1u, style->entries.size());
   AAPT_ASSERT_TRUE(style->entries.front().key.id);
-  EXPECT_EQ(style->entries.front().key.id.value(), ResourceId(0x7f010000));
+  EXPECT_EQ(ResourceId(0x7f010000), style->entries.front().key.id.value());
 }
 
 TEST(ReferenceLinkerTest, FailToLinkPrivateSymbols) {
@@ -257,4 +255,42 @@
   ASSERT_FALSE(linker.Consume(context.get(), table.get()));
 }
 
+TEST(ReferenceLinkerTest, AppsWithSamePackageButDifferentIdAreVisibleNonPublic) {
+  NameMangler mangler(NameManglerPolicy{"com.app.test"});
+  SymbolTable table(&mangler);
+  table.AppendSource(test::StaticSymbolSourceBuilder()
+                         .AddSymbol("com.app.test:string/foo", ResourceId(0x7f010000))
+                         .Build());
+
+  std::string error;
+  const CallSite call_site{ResourceNameRef("com.app.test", ResourceType::kString, "foo")};
+  const SymbolTable::Symbol* symbol = ReferenceLinker::ResolveSymbolCheckVisibility(
+      *test::BuildReference("com.app.test:string/foo"), call_site, &table, &error);
+  ASSERT_NE(nullptr, symbol);
+  EXPECT_TRUE(error.empty());
+}
+
+TEST(ReferenceLinkerTest, AppsWithDifferentPackageCanNotUseEachOthersAttribute) {
+  NameMangler mangler(NameManglerPolicy{"com.app.ext"});
+  SymbolTable table(&mangler);
+  table.AppendSource(test::StaticSymbolSourceBuilder()
+                         .AddSymbol("com.app.test:attr/foo", ResourceId(0x7f010000),
+                                    test::AttributeBuilder().Build())
+                         .AddPublicSymbol("com.app.test:attr/public_foo", ResourceId(0x7f010001),
+                                          test::AttributeBuilder().Build())
+                         .Build());
+
+  std::string error;
+  const CallSite call_site{ResourceNameRef("com.app.ext", ResourceType::kLayout, "foo")};
+
+  AAPT_EXPECT_FALSE(ReferenceLinker::CompileXmlAttribute(
+      *test::BuildReference("com.app.test:attr/foo"), call_site, &table, &error));
+  EXPECT_FALSE(error.empty());
+
+  error = "";
+  AAPT_ASSERT_TRUE(ReferenceLinker::CompileXmlAttribute(
+      *test::BuildReference("com.app.test:attr/public_foo"), call_site, &table, &error));
+  EXPECT_TRUE(error.empty());
+}
+
 }  // namespace aapt
diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp
index 7e7b9fb..9311091 100644
--- a/tools/aapt2/link/TableMerger.cpp
+++ b/tools/aapt2/link/TableMerger.cpp
@@ -39,14 +39,12 @@
 
 bool TableMerger::Merge(const Source& src, ResourceTable* table,
                         io::IFileCollection* collection) {
-  return MergeImpl(src, table, collection, false /* overlay */,
-                   true /* allow new */);
+  return MergeImpl(src, table, collection, false /* overlay */, true /* allow new */);
 }
 
 bool TableMerger::MergeOverlay(const Source& src, ResourceTable* table,
                                io::IFileCollection* collection) {
-  return MergeImpl(src, table, collection, true /* overlay */,
-                   options_.auto_add_overlay);
+  return MergeImpl(src, table, collection, true /* overlay */, options_.auto_add_overlay);
 }
 
 /**
@@ -55,25 +53,13 @@
 bool TableMerger::MergeImpl(const Source& src, ResourceTable* table,
                             io::IFileCollection* collection, bool overlay,
                             bool allow_new) {
-  const uint8_t desired_package_id = context_->GetPackageId();
-
   bool error = false;
   for (auto& package : table->packages) {
-    // Warn of packages with an unrelated ID.
-    const Maybe<ResourceId>& id = package->id;
-    if (id && id.value() != 0x0 && id.value() != desired_package_id) {
-      context_->GetDiagnostics()->Warn(DiagMessage(src) << "ignoring package "
-                                                        << package->name);
-      continue;
-    }
-
     // Only merge an empty package or the package we're building.
     // Other packages may exist, which likely contain attribute definitions.
     // This is because at compile time it is unknown if the attributes are
-    // simply
-    // uses of the attribute or definitions.
-    if (package->name.empty() ||
-        context_->GetCompilationPackage() == package->name) {
+    // simply uses of the attribute or definitions.
+    if (package->name.empty() || context_->GetCompilationPackage() == package->name) {
       FileMergeCallback callback;
       if (collection) {
         callback = [&](const ResourceNameRef& name,
@@ -83,8 +69,7 @@
           io::IFile* f = collection->FindFile(*old_file->path);
           if (!f) {
             context_->GetDiagnostics()->Error(DiagMessage(src)
-                                              << "file '" << *old_file->path
-                                              << "' not found");
+                                              << "file '" << *old_file->path << "' not found");
             return false;
           }
 
diff --git a/tools/aapt2/link/XmlReferenceLinker.cpp b/tools/aapt2/link/XmlReferenceLinker.cpp
index 1dbe53c..94bdccd 100644
--- a/tools/aapt2/link/XmlReferenceLinker.cpp
+++ b/tools/aapt2/link/XmlReferenceLinker.cpp
@@ -42,12 +42,12 @@
  public:
   using ValueVisitor::Visit;
 
-  ReferenceVisitor(IAaptContext* context, SymbolTable* symbols, xml::IPackageDeclStack* decls,
-                   CallSite* callsite)
-      : context_(context), symbols_(symbols), decls_(decls), callsite_(callsite), error_(false) {}
+  ReferenceVisitor(const CallSite& callsite, IAaptContext* context, SymbolTable* symbols,
+                   xml::IPackageDeclStack* decls)
+      : callsite_(callsite), context_(context), symbols_(symbols), decls_(decls), error_(false) {}
 
   void Visit(Reference* ref) override {
-    if (!ReferenceLinker::LinkReference(ref, context_, symbols_, decls_, callsite_)) {
+    if (!ReferenceLinker::LinkReference(callsite_, ref, context_, symbols_, decls_)) {
       error_ = true;
     }
   }
@@ -57,10 +57,10 @@
  private:
   DISALLOW_COPY_AND_ASSIGN(ReferenceVisitor);
 
+  const CallSite& callsite_;
   IAaptContext* context_;
   SymbolTable* symbols_;
   xml::IPackageDeclStack* decls_;
-  CallSite* callsite_;
   bool error_;
 };
 
@@ -71,14 +71,14 @@
  public:
   using xml::PackageAwareVisitor::Visit;
 
-  XmlVisitor(IAaptContext* context, SymbolTable* symbols, const Source& source,
-             std::set<int>* sdk_levels_found, CallSite* callsite)
-      : context_(context),
-        symbols_(symbols),
-        source_(source),
-        sdk_levels_found_(sdk_levels_found),
+  XmlVisitor(const Source& source, const CallSite& callsite, IAaptContext* context,
+             SymbolTable* symbols, std::set<int>* sdk_levels_found)
+      : source_(source),
         callsite_(callsite),
-        reference_visitor_(context, symbols, this, callsite) {}
+        context_(context),
+        symbols_(symbols),
+        sdk_levels_found_(sdk_levels_found),
+        reference_visitor_(callsite, context, symbols, this) {}
 
   void Visit(xml::Element* el) override {
     // The default Attribute allows everything except enums or flags.
@@ -107,8 +107,8 @@
         attr_ref.private_reference = maybe_package.value().private_namespace;
 
         std::string err_str;
-        attr.compiled_attribute = ReferenceLinker::CompileXmlAttribute(
-            attr_ref, context_->GetNameMangler(), symbols_, callsite_, &err_str);
+        attr.compiled_attribute =
+            ReferenceLinker::CompileXmlAttribute(attr_ref, callsite_, symbols_, &err_str);
 
         if (!attr.compiled_attribute) {
           context_->GetDiagnostics()->Error(DiagMessage(source) << "attribute '"
@@ -159,11 +159,12 @@
  private:
   DISALLOW_COPY_AND_ASSIGN(XmlVisitor);
 
+  Source source_;
+  const CallSite& callsite_;
   IAaptContext* context_;
   SymbolTable* symbols_;
-  Source source_;
+
   std::set<int>* sdk_levels_found_;
-  CallSite* callsite_;
   ReferenceVisitor reference_visitor_;
   bool error_ = false;
 };
@@ -172,9 +173,9 @@
 
 bool XmlReferenceLinker::Consume(IAaptContext* context, xml::XmlResource* resource) {
   sdk_levels_found_.clear();
-  CallSite callsite = {resource->file.name};
-  XmlVisitor visitor(context, context->GetExternalSymbols(), resource->file.source,
-                     &sdk_levels_found_, &callsite);
+  const CallSite callsite = {resource->file.name};
+  XmlVisitor visitor(resource->file.source, callsite, context, context->GetExternalSymbols(),
+                     &sdk_levels_found_);
   if (resource->root) {
     resource->root->Accept(&visitor);
     return !visitor.HasError();
diff --git a/tools/aapt2/optimize/Optimize.cpp b/tools/aapt2/optimize/Optimize.cpp
new file mode 100644
index 0000000..9615962
--- /dev/null
+++ b/tools/aapt2/optimize/Optimize.cpp
@@ -0,0 +1,201 @@
+/*
+ * 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.
+ */
+
+#include <memory>
+#include <vector>
+
+#include "androidfw/StringPiece.h"
+
+#include "Diagnostics.h"
+#include "Flags.h"
+#include "LoadedApk.h"
+#include "SdkConstants.h"
+#include "flatten/TableFlattener.h"
+#include "optimize/ResourceDeduper.h"
+#include "optimize/VersionCollapser.h"
+#include "split/TableSplitter.h"
+
+using android::StringPiece;
+
+namespace aapt {
+
+struct OptimizeOptions {
+  // Path to the output APK.
+  std::string output_path;
+
+  // List of screen density configurations the APK will be optimized for.
+  std::vector<ConfigDescription> target_configs;
+
+  TableFlattenerOptions table_flattener_options;
+};
+
+class OptimizeContext : public IAaptContext {
+ public:
+  IDiagnostics* GetDiagnostics() override { return &diagnostics_; }
+
+  NameMangler* GetNameMangler() override {
+    abort();
+    return nullptr;
+  }
+
+  const std::string& GetCompilationPackage() override {
+    static std::string empty;
+    return empty;
+  }
+
+  uint8_t GetPackageId() override { return 0; }
+
+  SymbolTable* GetExternalSymbols() override {
+    abort();
+    return nullptr;
+  }
+
+  bool IsVerbose() override { return verbose_; }
+
+  void SetVerbose(bool val) { verbose_ = val; }
+
+  void SetMinSdkVersion(int sdk_version) { sdk_version_ = sdk_version; }
+
+  int GetMinSdkVersion() override { return sdk_version_; }
+
+ private:
+  StdErrDiagnostics diagnostics_;
+  bool verbose_ = false;
+  int sdk_version_ = 0;
+};
+
+class OptimizeCommand {
+ public:
+  OptimizeCommand(OptimizeContext* context, const OptimizeOptions& options)
+      : options_(options),
+        context_(context) {}
+
+  int Run(std::unique_ptr<LoadedApk> apk) {
+    if (context_->IsVerbose()) {
+      context_->GetDiagnostics()->Note(DiagMessage() << "Optimizing APK...");
+    }
+
+    VersionCollapser collapser;
+    if (!collapser.Consume(context_, apk->GetResourceTable())) {
+      return 1;
+    }
+
+    ResourceDeduper deduper;
+    if (!deduper.Consume(context_, apk->GetResourceTable())) {
+      context_->GetDiagnostics()->Error(DiagMessage() << "failed deduping resources");
+      return 1;
+    }
+
+    // Stripping the APK using the TableSplitter with no splits and the target
+    // densities as the preferred densities. The resource table is modified in
+    // place in the LoadedApk.
+    TableSplitterOptions splitter_options;
+    for (auto& config : options_.target_configs) {
+      splitter_options.preferred_densities.push_back(config.density);
+    }
+    std::vector<SplitConstraints> splits;
+    TableSplitter splitter(splits, splitter_options);
+    splitter.SplitTable(apk->GetResourceTable());
+
+    std::unique_ptr<IArchiveWriter> writer =
+        CreateZipFileArchiveWriter(context_->GetDiagnostics(), options_.output_path);
+    if (!apk->WriteToArchive(context_, options_.table_flattener_options, writer.get())) {
+      return 1;
+    }
+
+    return 0;
+  }
+
+ private:
+  OptimizeOptions options_;
+  OptimizeContext* context_;
+};
+
+int Optimize(const std::vector<StringPiece>& args) {
+  OptimizeContext context;
+  OptimizeOptions options;
+  Maybe<std::string> target_densities;
+  bool verbose = false;
+  Flags flags =
+      Flags()
+          .RequiredFlag("-o", "Path to the output APK.", &options.output_path)
+          .OptionalFlag(
+              "--target-densities",
+              "Comma separated list of the screen densities that the APK will "
+              "be optimized for. All the resources that would be unused on "
+              "devices of the given densities will be removed from the APK.",
+              &target_densities)
+          .OptionalSwitch("--enable-sparse-encoding",
+                          "Enables encoding sparse entries using a binary search tree.\n"
+                          "This decreases APK size at the cost of resource retrieval performance.",
+                          &options.table_flattener_options.use_sparse_entries)
+          .OptionalSwitch("-v", "Enables verbose logging", &verbose);
+
+  if (!flags.Parse("aapt2 optimize", args, &std::cerr)) {
+    return 1;
+  }
+
+  if (flags.GetArgs().size() != 1u) {
+    std::cerr << "must have one APK as argument.\n\n";
+    flags.Usage("aapt2 optimize", &std::cerr);
+    return 1;
+  }
+
+  std::unique_ptr<LoadedApk> apk =
+      LoadedApk::LoadApkFromPath(&context, flags.GetArgs()[0]);
+  if (!apk) {
+    return 1;
+  }
+
+  if (verbose) {
+    context.SetVerbose(verbose);
+  }
+
+  if (target_densities) {
+    // Parse the target screen densities.
+    for (const StringPiece& config_str : util::Tokenize(target_densities.value(), ',')) {
+      ConfigDescription config;
+      if (!ConfigDescription::Parse(config_str, &config) || config.density == 0) {
+        context.GetDiagnostics()->Error(
+            DiagMessage() << "invalid density '" << config_str
+                          << "' for --target-densities option");
+        return 1;
+      }
+
+      // Clear the version that can be automatically added.
+      config.sdkVersion = 0;
+
+      if (config.diff(ConfigDescription::DefaultConfig()) !=
+          ConfigDescription::CONFIG_DENSITY) {
+        context.GetDiagnostics()->Error(
+            DiagMessage() << "invalid density '" << config_str
+                          << "' for --target-densities option. Must be only a "
+                          << "density value.");
+        return 1;
+      }
+
+      options.target_configs.push_back(config);
+    }
+  }
+
+  // TODO(adamlesinski): Read manfiest and set the proper minSdkVersion.
+  // context.SetMinSdkVersion(SDK_O);
+
+  OptimizeCommand cmd(&context, options);
+  return cmd.Run(std::move(apk));
+}
+
+}  // namespace aapt
diff --git a/tools/aapt2/link/ResourceDeduper.cpp b/tools/aapt2/optimize/ResourceDeduper.cpp
similarity index 95%
rename from tools/aapt2/link/ResourceDeduper.cpp
rename to tools/aapt2/optimize/ResourceDeduper.cpp
index 9431dce..9d16268 100644
--- a/tools/aapt2/link/ResourceDeduper.cpp
+++ b/tools/aapt2/optimize/ResourceDeduper.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "link/Linkers.h"
+#include "optimize/ResourceDeduper.h"
 
 #include <algorithm>
 
@@ -77,6 +77,8 @@
           DiagMessage(node_value->value->GetSource())
           << "removing dominated duplicate resource with name \""
           << entry_->name << "\"");
+      context_->GetDiagnostics()->Note(
+          DiagMessage(parent_value->value->GetSource()) << "dominated here");
     }
     node_value->value = {};
   }
diff --git a/tools/aapt2/optimize/ResourceDeduper.h b/tools/aapt2/optimize/ResourceDeduper.h
new file mode 100644
index 0000000..4a669d4
--- /dev/null
+++ b/tools/aapt2/optimize/ResourceDeduper.h
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+#ifndef AAPT_OPTIMIZE_RESOURCEDEDUPER_H
+#define AAPT_OPTIMIZE_RESOURCEDEDUPER_H
+
+#include "android-base/macros.h"
+
+#include "process/IResourceTableConsumer.h"
+
+namespace aapt {
+
+class ResourceTable;
+
+// Removes duplicated key-value entries from dominated resources.
+class ResourceDeduper : public IResourceTableConsumer {
+ public:
+  ResourceDeduper() = default;
+
+  bool Consume(IAaptContext* context, ResourceTable* table) override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ResourceDeduper);
+};
+
+} // namespace aapt
+
+#endif  // AAPT_OPTIMIZE_RESOURCEDEDUPER_H
diff --git a/tools/aapt2/link/ResourceDeduper_test.cpp b/tools/aapt2/optimize/ResourceDeduper_test.cpp
similarity index 98%
rename from tools/aapt2/link/ResourceDeduper_test.cpp
rename to tools/aapt2/optimize/ResourceDeduper_test.cpp
index d38059d..4d00fa6 100644
--- a/tools/aapt2/link/ResourceDeduper_test.cpp
+++ b/tools/aapt2/optimize/ResourceDeduper_test.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "link/Linkers.h"
+#include "optimize/ResourceDeduper.h"
 
 #include "ResourceTable.h"
 #include "test/Test.h"
diff --git a/tools/aapt2/link/VersionCollapser.cpp b/tools/aapt2/optimize/VersionCollapser.cpp
similarity index 98%
rename from tools/aapt2/link/VersionCollapser.cpp
rename to tools/aapt2/optimize/VersionCollapser.cpp
index 3df5899..d941b48 100644
--- a/tools/aapt2/link/VersionCollapser.cpp
+++ b/tools/aapt2/optimize/VersionCollapser.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "link/Linkers.h"
+#include "optimize/VersionCollapser.h"
 
 #include <algorithm>
 #include <vector>
diff --git a/tools/aapt2/optimize/VersionCollapser.h b/tools/aapt2/optimize/VersionCollapser.h
new file mode 100644
index 0000000..5ab3b25
--- /dev/null
+++ b/tools/aapt2/optimize/VersionCollapser.h
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+#ifndef AAPT_OPTIMIZE_VERSIONCOLLAPSER_H
+#define AAPT_OPTIMIZE_VERSIONCOLLAPSER_H
+
+#include "android-base/macros.h"
+
+#include "process/IResourceTableConsumer.h"
+
+namespace aapt {
+
+class ResourceTable;
+
+class VersionCollapser : public IResourceTableConsumer {
+ public:
+  VersionCollapser() = default;
+
+  bool Consume(IAaptContext* context, ResourceTable* table) override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(VersionCollapser);
+};
+
+} // namespace aapt
+
+#endif  // AAPT_OPTIMIZE_VERSIONCOLLAPSER_H
diff --git a/tools/aapt2/link/VersionCollapser_test.cpp b/tools/aapt2/optimize/VersionCollapser_test.cpp
similarity index 98%
rename from tools/aapt2/link/VersionCollapser_test.cpp
rename to tools/aapt2/optimize/VersionCollapser_test.cpp
index 44babb2..aa0d0c0 100644
--- a/tools/aapt2/link/VersionCollapser_test.cpp
+++ b/tools/aapt2/optimize/VersionCollapser_test.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "link/Linkers.h"
+#include "optimize/VersionCollapser.h"
 
 #include "test/Test.h"
 
diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp
index 1a3da73..bcafbca 100644
--- a/tools/aapt2/process/SymbolTable.cpp
+++ b/tools/aapt2/process/SymbolTable.cpp
@@ -16,10 +16,15 @@
 
 #include "process/SymbolTable.h"
 
+#include <iostream>
+
+#include "android-base/logging.h"
+#include "android-base/stringprintf.h"
 #include "androidfw/AssetManager.h"
 #include "androidfw/ResourceTypes.h"
 
 #include "ConfigDescription.h"
+#include "NameMangler.h"
 #include "Resource.h"
 #include "ResourceUtils.h"
 #include "ValueVisitor.h"
@@ -45,25 +50,49 @@
 }
 
 const SymbolTable::Symbol* SymbolTable::FindByName(const ResourceName& name) {
-  if (const std::shared_ptr<Symbol>& s = cache_.get(name)) {
+  const ResourceName* name_with_package = &name;
+
+  // Fill in the package name if necessary.
+  // If there is no package in `name`, we will need to copy the ResourceName
+  // and store it somewhere; we use the Maybe<> class to reserve storage.
+  Maybe<ResourceName> name_with_package_impl;
+  if (name.package.empty()) {
+    name_with_package_impl = ResourceName(mangler_->GetTargetPackageName(), name.type, name.entry);
+    name_with_package = &name_with_package_impl.value();
+  }
+
+  // We store the name unmangled in the cache, so look it up as-is.
+  if (const std::shared_ptr<Symbol>& s = cache_.get(*name_with_package)) {
     return s.get();
   }
 
-  // We did not find it in the cache, so look through the sources.
+  // The name was not found in the cache. Mangle it (if necessary) and find it in our sources.
+  // Again, here we use a Maybe<> object to reserve storage if we need to mangle.
+  const ResourceName* mangled_name = name_with_package;
+  Maybe<ResourceName> mangled_name_impl;
+  if (mangler_->ShouldMangle(name_with_package->package)) {
+    mangled_name_impl = mangler_->MangleName(*name_with_package);
+    mangled_name = &mangled_name_impl.value();
+  }
+
   for (auto& symbolSource : sources_) {
-    std::unique_ptr<Symbol> symbol = symbolSource->FindByName(name);
+    std::unique_ptr<Symbol> symbol = symbolSource->FindByName(*mangled_name);
     if (symbol) {
       // Take ownership of the symbol into a shared_ptr. We do this because
-      // LruCache
-      // doesn't support unique_ptr.
-      std::shared_ptr<Symbol> shared_symbol =
-          std::shared_ptr<Symbol>(symbol.release());
-      cache_.put(name, shared_symbol);
+      // LruCache doesn't support unique_ptr.
+      std::shared_ptr<Symbol> shared_symbol(std::move(symbol));
+
+      // Since we look in the cache with the unmangled, but package prefixed
+      // name, we must put the same name into the cache.
+      cache_.put(*name_with_package, shared_symbol);
 
       if (shared_symbol->id) {
         // The symbol has an ID, so we can also cache this!
         id_cache_.put(shared_symbol->id.value(), shared_symbol);
       }
+
+      // Returns the raw pointer. Callers are not expected to hold on to this
+      // between calls to Find*.
       return shared_symbol.get();
     }
   }
@@ -79,12 +108,13 @@
   for (auto& symbolSource : sources_) {
     std::unique_ptr<Symbol> symbol = symbolSource->FindById(id);
     if (symbol) {
-      // Take ownership of the symbol into a shared_ptr. We do this because
-      // LruCache
+      // Take ownership of the symbol into a shared_ptr. We do this because LruCache
       // doesn't support unique_ptr.
-      std::shared_ptr<Symbol> shared_symbol =
-          std::shared_ptr<Symbol>(symbol.release());
+      std::shared_ptr<Symbol> shared_symbol(std::move(symbol));
       id_cache_.put(id, shared_symbol);
+
+      // Returns the raw pointer. Callers are not expected to hold on to this
+      // between calls to Find*.
       return shared_symbol.get();
     }
   }
@@ -92,16 +122,12 @@
 }
 
 const SymbolTable::Symbol* SymbolTable::FindByReference(const Reference& ref) {
-  // First try the ID. This is because when we lookup by ID, we only fill in the
-  // ID cache.
-  // Looking up by name fills in the name and ID cache. So a cache miss will
-  // cause a failed
-  // ID lookup, then a successful name lookup. Subsequent look ups will hit
-  // immediately
+  // First try the ID. This is because when we lookup by ID, we only fill in the ID cache.
+  // Looking up by name fills in the name and ID cache. So a cache miss will cause a failed
+  // ID lookup, then a successful name lookup. Subsequent look ups will hit immediately
   // because the ID is cached too.
   //
-  // If we looked up by name first, a cache miss would mean we failed to lookup
-  // by name, then
+  // If we looked up by name first, a cache miss would mean we failed to lookup by name, then
   // succeeded to lookup by ID. Subsequent lookups will miss then hit.
   const SymbolTable::Symbol* symbol = nullptr;
   if (ref.id) {
@@ -120,25 +146,21 @@
   if (!result) {
     if (name.type == ResourceType::kAttr) {
       // Recurse and try looking up a private attribute.
-      return FindByName(
-          ResourceName(name.package, ResourceType::kAttrPrivate, name.entry));
+      return FindByName(ResourceName(name.package, ResourceType::kAttrPrivate, name.entry));
     }
     return {};
   }
 
   ResourceTable::SearchResult sr = result.value();
 
-  std::unique_ptr<SymbolTable::Symbol> symbol =
-      util::make_unique<SymbolTable::Symbol>();
+  std::unique_ptr<SymbolTable::Symbol> symbol = util::make_unique<SymbolTable::Symbol>();
   symbol->is_public = (sr.entry->symbol_status.state == SymbolState::kPublic);
 
   if (sr.package->id && sr.type->id && sr.entry->id) {
-    symbol->id = ResourceId(sr.package->id.value(), sr.type->id.value(),
-                            sr.entry->id.value());
+    symbol->id = ResourceId(sr.package->id.value(), sr.type->id.value(), sr.entry->id.value());
   }
 
-  if (name.type == ResourceType::kAttr ||
-      name.type == ResourceType::kAttrPrivate) {
+  if (name.type == ResourceType::kAttr || name.type == ResourceType::kAttrPrivate) {
     const ConfigDescription kDefaultConfig;
     ResourceConfigValue* config_value = sr.entry->FindValue(kDefaultConfig);
     if (config_value) {
@@ -155,8 +177,18 @@
 
 bool AssetManagerSymbolSource::AddAssetPath(const StringPiece& path) {
   int32_t cookie = 0;
-  return assets_.addAssetPath(android::String8(path.data(), path.size()),
-                              &cookie);
+  return assets_.addAssetPath(android::String8(path.data(), path.size()), &cookie);
+}
+
+std::map<size_t, std::string> AssetManagerSymbolSource::GetAssignedPackageIds() const {
+  std::map<size_t, std::string> package_map;
+  const android::ResTable& table = assets_.getResources(false);
+  const size_t package_count = table.getBasePackageCount();
+  for (size_t i = 0; i < package_count; i++) {
+    package_map[table.getBasePackageId(i)] =
+        util::Utf16ToUtf8(android::StringPiece16(table.getBasePackageName(i).string()));
+  }
+  return package_map;
 }
 
 static std::unique_ptr<SymbolTable::Symbol> LookupAttributeInTable(
@@ -170,8 +202,7 @@
   }
 
   // We found a resource.
-  std::unique_ptr<SymbolTable::Symbol> s =
-      util::make_unique<SymbolTable::Symbol>();
+  std::unique_ptr<SymbolTable::Symbol> s = util::make_unique<SymbolTable::Symbol>();
   s->id = id;
 
   // Check to see if it is an attribute.
@@ -204,8 +235,7 @@
         return nullptr;
       }
 
-      Maybe<ResourceName> parsed_name =
-          ResourceUtils::ToResourceName(entry_name);
+      Maybe<ResourceName> parsed_name = ResourceUtils::ToResourceName(entry_name);
       if (!parsed_name) {
         return nullptr;
       }
@@ -246,8 +276,7 @@
   }
 
   if (s) {
-    s->is_public =
-        (type_spec_flags & android::ResTable_typeSpec::SPEC_PUBLIC) != 0;
+    s->is_public = (type_spec_flags & android::ResTable_typeSpec::SPEC_PUBLIC) != 0;
     return s;
   }
   return {};
@@ -264,6 +293,11 @@
 
 std::unique_ptr<SymbolTable::Symbol> AssetManagerSymbolSource::FindById(
     ResourceId id) {
+  if (!id.is_valid()) {
+    // Exit early and avoid the error logs from AssetManager.
+    return {};
+  }
+
   const android::ResTable& table = assets_.getResources(false);
   Maybe<ResourceName> maybe_name = GetResourceName(table, id);
   if (!maybe_name) {
@@ -282,8 +316,7 @@
   }
 
   if (s) {
-    s->is_public =
-        (type_spec_flags & android::ResTable_typeSpec::SPEC_PUBLIC) != 0;
+    s->is_public = (type_spec_flags & android::ResTable_typeSpec::SPEC_PUBLIC) != 0;
     return s;
   }
   return {};
diff --git a/tools/aapt2/process/SymbolTable.h b/tools/aapt2/process/SymbolTable.h
index cf597bb..298da4d 100644
--- a/tools/aapt2/process/SymbolTable.h
+++ b/tools/aapt2/process/SymbolTable.h
@@ -47,6 +47,7 @@
 }
 
 class ISymbolSource;
+class NameMangler;
 
 class SymbolTable {
  public:
@@ -72,25 +73,32 @@
     bool is_public = false;
   };
 
-  SymbolTable() : cache_(200), id_cache_(200) {}
+  SymbolTable(NameMangler* mangler) : mangler_(mangler), cache_(200), id_cache_(200) {}
 
+  // Appends a symbol source. The cache is not cleared since entries that
+  // have already been found would take precedence due to ordering.
   void AppendSource(std::unique_ptr<ISymbolSource> source);
+
+  // Prepends a symbol source so that its symbols take precedence. This will
+  // cause the existing cache to be cleared.
   void PrependSource(std::unique_ptr<ISymbolSource> source);
 
-  /**
-   * Never hold on to the result between calls to FindByName or FindById. The
-   * results stored in a cache which may evict entries.
-   */
+  // NOTE: Never hold on to the result between calls to FindByXXX. The
+  // results are stored in a cache which may evict entries on subsequent calls.
   const Symbol* FindByName(const ResourceName& name);
+
+  // NOTE: Never hold on to the result between calls to FindByXXX. The
+  // results are stored in a cache which may evict entries on subsequent calls.
   const Symbol* FindById(const ResourceId& id);
 
-  /**
-   * Let's the ISymbolSource decide whether looking up by name or ID is faster,
-   * if both are available.
-   */
+  // Let's the ISymbolSource decide whether looking up by name or ID is faster,
+  // if both are available.
+  // NOTE: Never hold on to the result between calls to FindByXXX. The
+  // results are stored in a cache which may evict entries on subsequent calls.
   const Symbol* FindByReference(const Reference& ref);
 
  private:
+  NameMangler* mangler_;
   std::vector<std::unique_ptr<ISymbolSource>> sources_;
 
   // We use shared_ptr because unique_ptr is not supported and
@@ -155,6 +163,7 @@
   AssetManagerSymbolSource() = default;
 
   bool AddAssetPath(const android::StringPiece& path);
+  std::map<size_t, std::string> GetAssignedPackageIds() const;
 
   std::unique_ptr<SymbolTable::Symbol> FindByName(
       const ResourceName& name) override;
diff --git a/tools/aapt2/process/SymbolTable_test.cpp b/tools/aapt2/process/SymbolTable_test.cpp
index 9ea0786..fd8a508 100644
--- a/tools/aapt2/process/SymbolTable_test.cpp
+++ b/tools/aapt2/process/SymbolTable_test.cpp
@@ -30,10 +30,8 @@
           .Build();
 
   ResourceTableSymbolSource symbol_source(table.get());
-  EXPECT_NE(nullptr,
-            symbol_source.FindByName(test::ParseNameOrDie("android:id/foo")));
-  EXPECT_NE(nullptr,
-            symbol_source.FindByName(test::ParseNameOrDie("android:id/bar")));
+  EXPECT_NE(nullptr, symbol_source.FindByName(test::ParseNameOrDie("android:id/foo")));
+  EXPECT_NE(nullptr, symbol_source.FindByName(test::ParseNameOrDie("android:id/bar")));
 
   std::unique_ptr<SymbolTable::Symbol> s =
       symbol_source.FindByName(test::ParseNameOrDie("android:attr/foo"));
@@ -55,4 +53,19 @@
   EXPECT_NE(nullptr, s->attribute);
 }
 
+TEST(SymbolTableTest, FindByName) {
+  std::unique_ptr<ResourceTable> table =
+      test::ResourceTableBuilder()
+          .AddSimple("com.android.app:id/foo")
+          .AddSimple("com.android.app:id/" + NameMangler::MangleEntry("com.android.lib", "foo"))
+          .Build();
+
+  NameMangler mangler(NameManglerPolicy{"com.android.app", {"com.android.lib"}});
+  SymbolTable symbol_table(&mangler);
+  symbol_table.AppendSource(util::make_unique<ResourceTableSymbolSource>(table.get()));
+
+  EXPECT_NE(nullptr, symbol_table.FindByName(test::ParseNameOrDie("id/foo")));
+  EXPECT_NE(nullptr, symbol_table.FindByName(test::ParseNameOrDie("com.android.lib:id/foo")));
+}
+
 }  // namespace aapt
diff --git a/tools/aapt2/readme.md b/tools/aapt2/readme.md
index 8bc4e8c..1c9a75d 100644
--- a/tools/aapt2/readme.md
+++ b/tools/aapt2/readme.md
@@ -1,7 +1,35 @@
 # Android Asset Packaging Tool 2.0 (AAPT2) release notes
 
+## Version 2.10
+### `aapt2 link ...`
+- Add ability to specify package ID to compile with for regular apps (not shared or static libs).
+  This package ID is limited to the range 0x7f-0xff inclusive. Specified with the --package-id
+  flag.
+- Fixed issue with <plurals> resources being stripped for locales and other configuration.
+- Fixed issue with escaping strings in XML resources.
+
+## Version 2.9
+### `aapt2 link ...`
+- Added sparse resource type encoding, which encodes resource entries that are sparse with
+  a binary search tree representation. Only available when minSdkVersion >= API O or resource
+  qualifier of resource types is >= v26 (or whatever API level O becomes). Enabled with
+  `--enable-sparse-encoding` flag.
+### `aapt2 optimize ...`
+- Adds an optimization pass that supports:
+    - stripping out any density assets that do not match the `--target-densities` list of
+      densities.
+    - resource deduping when the resources are dominated and identical (already happens during
+      `link` phase but this covers apps built with `aapt`).
+    - new sparse resource type encoding with the `--enable-sparse-encoding` flag if possible
+      (minSdkVersion >= O or resource qualifier >= v26).
+
+## Version 2.8
+### `aapt2 link ...`
+- Adds shared library support. Build a shared library with the `--shared-lib` flag.
+  Build a client of a shared library by simply including it via `-I`.
+
 ## Version 2.7
-### `aapt2 compile`
+### `aapt2 compile ...`
 - Fixes bug where psuedolocalization auto-translated strings marked 'translateable="false"'.
 
 ## Version 2.6
diff --git a/tools/aapt2/strip/Strip.cpp b/tools/aapt2/strip/Strip.cpp
deleted file mode 100644
index 7260649..0000000
--- a/tools/aapt2/strip/Strip.cpp
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * 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.
- */
-
-#include <memory>
-#include <vector>
-
-#include "androidfw/StringPiece.h"
-
-#include "Diagnostics.h"
-#include "Flags.h"
-#include "LoadedApk.h"
-#include "split/TableSplitter.h"
-
-using android::StringPiece;
-
-namespace aapt {
-
-struct StripOptions {
-  /** Path to the output APK. */
-  std::string output_path;
-
-  /** List of screen density configurations the APK will be optimized for. */
-  std::vector<ConfigDescription> target_configs;
-};
-
-class StripContext : public IAaptContext {
- public:
-  IDiagnostics* GetDiagnostics() override { return &diagnostics_; }
-
-  NameMangler* GetNameMangler() override {
-    abort();
-    return nullptr;
-  }
-
-  const std::string& GetCompilationPackage() override {
-    static std::string empty;
-    return empty;
-  }
-
-  uint8_t GetPackageId() override { return 0; }
-
-  SymbolTable* GetExternalSymbols() override {
-    abort();
-    return nullptr;
-  }
-
-  bool IsVerbose() override { return verbose_; }
-
-  void SetVerbose(bool val) { verbose_ = val; }
-
-  int GetMinSdkVersion() override { return 0; }
-
- private:
-  StdErrDiagnostics diagnostics_;
-  bool verbose_ = false;
-};
-
-class StripCommand {
- public:
-  StripCommand(StripContext* context, const StripOptions& options)
-      : options_(options),
-        context_(context) {}
-
-  int Run(std::unique_ptr<LoadedApk> apk) {
-    if (context_->IsVerbose()) {
-      context_->GetDiagnostics()->Note(DiagMessage() << "Stripping APK...");
-    }
-
-    // Stripping the APK using the TableSplitter with no splits and the target
-    // densities as the preferred densities. The resource table is modified in
-    // place in the LoadedApk.
-    TableSplitterOptions splitter_options;
-    for (auto& config : options_.target_configs) {
-      splitter_options.preferred_densities.push_back(config.density);
-    }
-    std::vector<SplitConstraints> splits;
-    TableSplitter splitter(splits, splitter_options);
-    splitter.SplitTable(apk->GetResourceTable());
-
-    std::unique_ptr<IArchiveWriter> writer =
-        CreateZipFileArchiveWriter(context_->GetDiagnostics(), options_.output_path);
-    if (!apk->WriteToArchive(context_, writer.get())) {
-      return 1;
-    }
-
-    return 0;
-  }
-
- private:
-  StripOptions options_;
-  StripContext* context_;
-};
-
-int Strip(const std::vector<StringPiece>& args) {
-  StripContext context;
-  StripOptions options;
-  std::string target_densities;
-  bool verbose = false;
-  Flags flags =
-      Flags()
-          .RequiredFlag("-o", "Path to the output APK.", &options.output_path)
-          .RequiredFlag(
-              "--target-densities",
-              "Comma separated list of the screen densities that the APK will "
-              "be optimized for. All the resources that would be unused on "
-              "devices of the given densities will be removed from the APK.",
-              &target_densities)
-          .OptionalSwitch("-v", "Enables verbose logging", &verbose);
-
-  if (!flags.Parse("aapt2 strip", args, &std::cerr)) {
-    return 1;
-  }
-
-  if (flags.GetArgs().size() != 1u) {
-    std::cerr << "must have one APK as argument.\n\n";
-    flags.Usage("aapt2 strip", &std::cerr);
-    return 1;
-  }
-
-  std::unique_ptr<LoadedApk> apk =
-      LoadedApk::LoadApkFromPath(&context, flags.GetArgs()[0]);
-  if (!apk) {
-    return 1;
-  }
-
-  if (verbose) {
-    context.SetVerbose(verbose);
-  }
-
-  // Parse the target screen densities.
-  for (const StringPiece& config_str : util::Tokenize(target_densities, ',')) {
-    ConfigDescription config;
-    if (!ConfigDescription::Parse(config_str, &config) || config.density == 0) {
-      context.GetDiagnostics()->Error(
-          DiagMessage() << "invalid density '" << config_str
-                        << "' for --target-densities option");
-      return 1;
-    }
-
-    // Clear the version that can be automatically added.
-    config.sdkVersion = 0;
-
-    if (config.diff(ConfigDescription::DefaultConfig()) !=
-        ConfigDescription::CONFIG_DENSITY) {
-      context.GetDiagnostics()->Error(
-          DiagMessage() << "invalid density '" << config_str
-                        << "' for --target-densities option. Must be only a "
-                        << "density value.");
-      return 1;
-    }
-
-    options.target_configs.push_back(config);
-  }
-
-  StripCommand cmd(&context, options);
-  return cmd.Run(std::move(apk));
-}
-
-}  // namespace aapt
diff --git a/tools/aapt2/test/Context.h b/tools/aapt2/test/Context.h
index 63e5f16..557cd1b 100644
--- a/tools/aapt2/test/Context.h
+++ b/tools/aapt2/test/Context.h
@@ -33,7 +33,7 @@
 
 class Context : public IAaptContext {
  public:
-  Context() = default;
+  Context() : name_mangler_({}), symbols_(&name_mangler_), min_sdk_version_(0) {}
 
   SymbolTable* GetExternalSymbols() override { return &symbols_; }
 
@@ -63,9 +63,9 @@
   Maybe<std::string> compilation_package_;
   Maybe<uint8_t> package_id_;
   StdErrDiagnostics diagnostics_;
+  NameMangler name_mangler_;
   SymbolTable symbols_;
-  NameMangler name_mangler_ = NameMangler({});
-  int min_sdk_version_ = 0;
+  int min_sdk_version_;
 };
 
 class ContextBuilder {
diff --git a/tools/aapt2/unflatten/BinaryResourceParser.cpp b/tools/aapt2/unflatten/BinaryResourceParser.cpp
index 7098fe9..66bcfa0 100644
--- a/tools/aapt2/unflatten/BinaryResourceParser.cpp
+++ b/tools/aapt2/unflatten/BinaryResourceParser.cpp
@@ -248,6 +248,12 @@
         }
         break;
 
+      case android::RES_TABLE_LIBRARY_TYPE:
+        if (!ParseLibrary(parser.chunk())) {
+          return false;
+        }
+        break;
+
       default:
         context_->GetDiagnostics()->Warn(
             DiagMessage(source_)
@@ -307,7 +313,9 @@
     return false;
   }
 
-  const ResTable_type* type = ConvertTo<ResTable_type>(chunk);
+  // Specify a manual size, because ResTable_type contains ResTable_config, which changes
+  // a lot and has its own code to handle variable size.
+  const ResTable_type* type = ConvertTo<ResTable_type, kResTableTypeMinSize>(chunk);
   if (!type) {
     context_->GetDiagnostics()->Error(DiagMessage(source_)
                                       << "corrupt ResTable_type chunk");
@@ -395,6 +403,21 @@
   return true;
 }
 
+bool BinaryResourceParser::ParseLibrary(const ResChunk_header* chunk) {
+  DynamicRefTable dynamic_ref_table;
+  if (dynamic_ref_table.load(reinterpret_cast<const ResTable_lib_header*>(chunk)) != NO_ERROR) {
+    return false;
+  }
+
+  const KeyedVector<String16, uint8_t>& entries = dynamic_ref_table.entries();
+  const size_t count = entries.size();
+  for (size_t i = 0; i < count; i++) {
+    table_->included_packages_[entries.valueAt(i)] =
+        util::Utf16ToUtf8(StringPiece16(entries.keyAt(i).string()));
+  }
+  return true;
+}
+
 std::unique_ptr<Item> BinaryResourceParser::ParseValue(
     const ResourceNameRef& name, const ConfigDescription& config,
     const Res_value* value, uint16_t flags) {
@@ -437,10 +460,14 @@
   }
 
   if (value->dataType == Res_value::TYPE_REFERENCE ||
-      value->dataType == Res_value::TYPE_ATTRIBUTE) {
-    const Reference::Type type = (value->dataType == Res_value::TYPE_REFERENCE)
-                                     ? Reference::Type::kResource
-                                     : Reference::Type::kAttribute;
+      value->dataType == Res_value::TYPE_ATTRIBUTE ||
+      value->dataType == Res_value::TYPE_DYNAMIC_REFERENCE ||
+      value->dataType == Res_value::TYPE_DYNAMIC_ATTRIBUTE) {
+    Reference::Type type = Reference::Type::kResource;
+    if (value->dataType == Res_value::TYPE_ATTRIBUTE ||
+        value->dataType == Res_value::TYPE_DYNAMIC_ATTRIBUTE) {
+      type = Reference::Type::kAttribute;
+    }
 
     if (data == 0) {
       // A reference of 0, must be the magic @null reference.
diff --git a/tools/aapt2/unflatten/BinaryResourceParser.h b/tools/aapt2/unflatten/BinaryResourceParser.h
index dc668fd..e3dd802 100644
--- a/tools/aapt2/unflatten/BinaryResourceParser.h
+++ b/tools/aapt2/unflatten/BinaryResourceParser.h
@@ -61,6 +61,7 @@
   bool ParseTypeSpec(const android::ResChunk_header* chunk);
   bool ParseType(const ResourceTablePackage* package,
                  const android::ResChunk_header* chunk);
+  bool ParseLibrary(const android::ResChunk_header* chunk);
 
   std::unique_ptr<Item> ParseValue(const ResourceNameRef& name,
                                    const ConfigDescription& config,
diff --git a/tools/aapt2/unflatten/ResChunkPullParser.h b/tools/aapt2/unflatten/ResChunkPullParser.h
index 437fc5c..5827753 100644
--- a/tools/aapt2/unflatten/ResChunkPullParser.h
+++ b/tools/aapt2/unflatten/ResChunkPullParser.h
@@ -78,9 +78,9 @@
   std::string error_;
 };
 
-template <typename T>
+template <typename T, size_t MinSize = sizeof(T)>
 inline static const T* ConvertTo(const android::ResChunk_header* chunk) {
-  if (util::DeviceToHost16(chunk->headerSize) < sizeof(T)) {
+  if (util::DeviceToHost16(chunk->headerSize) < MinSize) {
     return nullptr;
   }
   return reinterpret_cast<const T*>(chunk);
diff --git a/tools/aapt2/util/BigBuffer.cpp b/tools/aapt2/util/BigBuffer.cpp
index ef99dca..75fa789 100644
--- a/tools/aapt2/util/BigBuffer.cpp
+++ b/tools/aapt2/util/BigBuffer.cpp
@@ -76,4 +76,12 @@
   return blocks_.back().buffer.get();
 }
 
+std::string BigBuffer::to_string() const {
+  std::string result;
+  for (const Block& block : blocks_) {
+    result.append(block.buffer.get(), block.buffer.get() + block.size);
+  }
+  return result;
+}
+
 }  // namespace aapt
diff --git a/tools/aapt2/util/BigBuffer.h b/tools/aapt2/util/BigBuffer.h
index d23c41d..3045255 100644
--- a/tools/aapt2/util/BigBuffer.h
+++ b/tools/aapt2/util/BigBuffer.h
@@ -19,6 +19,7 @@
 
 #include <cstring>
 #include <memory>
+#include <string>
 #include <type_traits>
 #include <vector>
 
@@ -116,6 +117,8 @@
   const_iterator begin() const;
   const_iterator end() const;
 
+  std::string to_string() const;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(BigBuffer);
 
diff --git a/tools/aapt2/util/Util.h b/tools/aapt2/util/Util.h
index f8fa80e..7210d21 100644
--- a/tools/aapt2/util/Util.h
+++ b/tools/aapt2/util/Util.h
@@ -164,6 +164,7 @@
   StringBuilder& Append(const android::StringPiece& str);
   const std::string& ToString() const;
   const std::string& Error() const;
+  bool IsEmpty() const;
 
   // When building StyledStrings, we need UTF-16 indices into the string,
   // which is what the Java layer expects when dealing with java
@@ -185,6 +186,8 @@
 
 inline const std::string& StringBuilder::Error() const { return error_; }
 
+inline bool StringBuilder::IsEmpty() const { return str_.empty(); }
+
 inline size_t StringBuilder::Utf16Len() const { return utf16_len_; }
 
 inline StringBuilder::operator bool() const { return error_.empty(); }
diff --git a/tools/aapt2/xml/XmlDom.cpp b/tools/aapt2/xml/XmlDom.cpp
index fab2f19..d9ea1bc 100644
--- a/tools/aapt2/xml/XmlDom.cpp
+++ b/tools/aapt2/xml/XmlDom.cpp
@@ -18,7 +18,6 @@
 
 #include <expat.h>
 
-#include <cassert>
 #include <memory>
 #include <stack>
 #include <string>
@@ -41,6 +40,8 @@
   std::unique_ptr<xml::Node> root;
   std::stack<xml::Node*> node_stack;
   std::string pending_comment;
+  std::unique_ptr<xml::Text> last_text_node;
+  util::StringBuilder pending_text;
 };
 
 /**
@@ -62,6 +63,19 @@
   }
 }
 
+static void FinishPendingText(Stack* stack) {
+  if (stack->last_text_node != nullptr) {
+    if (!stack->pending_text.IsEmpty()) {
+      stack->last_text_node->text = stack->pending_text.ToString();
+      stack->pending_text = {};
+      stack->node_stack.top()->AppendChild(std::move(stack->last_text_node));
+    } else {
+      // Drop an empty text node.
+      stack->last_text_node = nullptr;
+    }
+  }
+}
+
 static void AddToStack(Stack* stack, XML_Parser parser,
                        std::unique_ptr<Node> node) {
   node->line_number = XML_GetCurrentLineNumber(parser);
@@ -83,6 +97,7 @@
                                           const char* uri) {
   XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
   Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
+  FinishPendingText(stack);
 
   std::unique_ptr<Namespace> ns = util::make_unique<Namespace>();
   if (prefix) {
@@ -99,6 +114,7 @@
 static void XMLCALL EndNamespaceHandler(void* user_data, const char* prefix) {
   XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
   Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
+  FinishPendingText(stack);
 
   CHECK(!stack->node_stack.empty());
   stack->node_stack.pop();
@@ -113,6 +129,7 @@
                                         const char** attrs) {
   XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
   Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
+  FinishPendingText(stack);
 
   std::unique_ptr<Element> el = util::make_unique<Element>();
   SplitName(name, &el->namespace_uri, &el->name);
@@ -120,7 +137,9 @@
   while (*attrs) {
     Attribute attribute;
     SplitName(*attrs++, &attribute.namespace_uri, &attribute.name);
-    attribute.value = *attrs++;
+    util::StringBuilder builder;
+    builder.Append(*attrs++);
+    attribute.value = builder.ToString();
 
     // Insert in sorted order.
     auto iter = std::lower_bound(el->attributes.begin(), el->attributes.end(),
@@ -135,41 +154,38 @@
 static void XMLCALL EndElementHandler(void* user_data, const char* name) {
   XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
   Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
+  FinishPendingText(stack);
 
   CHECK(!stack->node_stack.empty());
   // stack->nodeStack.top()->comment = std::move(stack->pendingComment);
   stack->node_stack.pop();
 }
 
-static void XMLCALL CharacterDataHandler(void* user_data, const char* s,
-                                         int len) {
+static void XMLCALL CharacterDataHandler(void* user_data, const char* s, int len) {
   XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
   Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
 
-  if (!s || len <= 0) {
+  const StringPiece str(s, len);
+  if (str.empty()) {
     return;
   }
 
   // See if we can just append the text to a previous text node.
-  if (!stack->node_stack.empty()) {
-    Node* currentParent = stack->node_stack.top();
-    if (!currentParent->children.empty()) {
-      Node* last_child = currentParent->children.back().get();
-      if (Text* text = NodeCast<Text>(last_child)) {
-        text->text.append(s, len);
-        return;
-      }
-    }
+  if (stack->last_text_node != nullptr) {
+    stack->pending_text.Append(str);
+    return;
   }
 
-  std::unique_ptr<Text> text = util::make_unique<Text>();
-  text->text.assign(s, len);
-  AddToStack(stack, parser, std::move(text));
+  stack->last_text_node = util::make_unique<Text>();
+  stack->last_text_node->line_number = XML_GetCurrentLineNumber(parser);
+  stack->last_text_node->column_number = XML_GetCurrentColumnNumber(parser);
+  stack->pending_text.Append(str);
 }
 
 static void XMLCALL CommentDataHandler(void* user_data, const char* comment) {
   XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
   Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
+  FinishPendingText(stack);
 
   if (!stack->pending_comment.empty()) {
     stack->pending_comment += '\n';
diff --git a/tools/aapt2/xml/XmlDom_test.cpp b/tools/aapt2/xml/XmlDom_test.cpp
index a414afe..0fc3cec6 100644
--- a/tools/aapt2/xml/XmlDom_test.cpp
+++ b/tools/aapt2/xml/XmlDom_test.cpp
@@ -49,4 +49,23 @@
   EXPECT_EQ(ns->namespace_prefix, "android");
 }
 
+TEST(XmlDomTest, HandleEscapes) {
+  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(
+      R"EOF(<shortcode pattern="\\d{5}">\\d{5}</shortcode>)EOF");
+
+  xml::Element* el = xml::FindRootElement(doc->root.get());
+  ASSERT_NE(nullptr, el);
+
+  xml::Attribute* attr = el->FindAttribute({}, "pattern");
+  ASSERT_NE(nullptr, attr);
+
+  EXPECT_EQ("\\d{5}", attr->value);
+
+  ASSERT_EQ(1u, el->children.size());
+
+  xml::Text* text = xml::NodeCast<xml::Text>(el->children[0].get());
+  ASSERT_NE(nullptr, text);
+  EXPECT_EQ("\\d{5}", text->text);
+}
+
 }  // namespace aapt
diff --git a/tools/fonts/fontchain_lint.py b/tools/fonts/fontchain_lint.py
index f193ea4..eb8a1cc 100755
--- a/tools/fonts/fontchain_lint.py
+++ b/tools/fonts/fontchain_lint.py
@@ -14,7 +14,9 @@
 
 LANG_TO_SCRIPT = {
     'as': 'Beng',
+    'bg': 'Cyrl',
     'bn': 'Beng',
+    'cu': 'Cyrl',
     'cy': 'Latn',
     'da': 'Latn',
     'de': 'Latn',
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
index 9bc8e18..2c7e936 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
@@ -638,6 +638,9 @@
                 return mContext.getProjectResourceValue(ResourceType.ID, idName, defValue);
             }
         }
+        else if (value.startsWith("@aapt:_aapt")) {
+            return mContext.getLayoutlibCallback().getResourceId(ResourceType.AAPT, value);
+        }
 
         // not a direct id valid reference. First check if it's an enum (this is a corner case
         // for attributes that have a reference|enum type), then fallback to resolve
diff --git a/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java
index 6e3a8e8..c20ee12 100644
--- a/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java
@@ -131,9 +131,16 @@
         if (resourceInfo != null) {
             String attributeName = resourceInfo.getSecond();
             RenderResources renderResources = resources.mContext.getRenderResources();
-            return Pair.of(attributeName, platformResFlag_out[0] ?
+            ResourceValue value = platformResFlag_out[0] ?
                     renderResources.getFrameworkResource(resourceInfo.getFirst(), attributeName) :
-                    renderResources.getProjectResource(resourceInfo.getFirst(), attributeName));
+                    renderResources.getProjectResource(resourceInfo.getFirst(), attributeName);
+
+            if (value == null) {
+                // Unable to resolve the attribute, just leave the unresolved value
+                value = new ResourceValue(resourceInfo.getFirst(), attributeName, attributeName,
+                        platformResFlag_out[0]);
+            }
+            return Pair.of(attributeName, value);
         }
 
         return null;
diff --git a/tools/layoutlib/bridge/src/android/graphics/BaseCanvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BaseCanvas_Delegate.java
index df85806..b1e71b2 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BaseCanvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BaseCanvas_Delegate.java
@@ -161,17 +161,22 @@
     @LayoutlibDelegate
     /*package*/ static void nDrawPoint(long nativeCanvas, float x, float y,
             long nativePaint) {
-        // FIXME
-        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
-                "Canvas.drawPoint is not supported.", null, null /*data*/);
+        // TODO: need to support the attribute (e.g. stroke width) of paint
+        draw(nativeCanvas, nativePaint, false /*compositeOnly*/, false /*forceSrcMode*/,
+                (graphics, paintDelegate) -> graphics.fillRect((int)x, (int)y, 1, 1));
     }
 
     @LayoutlibDelegate
     /*package*/ static void nDrawPoints(long nativeCanvas, float[] pts, int offset, int count,
             long nativePaint) {
-        // FIXME
-        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
-                "Canvas.drawPoint is not supported.", null, null /*data*/);
+        if (offset < 0 || count < 0 || offset + count > pts.length) {
+            throw new IllegalArgumentException("Invalid argument set");
+        }
+        // ignore the last point if the count is odd (It means it is not paired).
+        count = (count >> 1) << 1;
+        for (int i = offset; i < offset + count; i += 2) {
+            nDrawPoint(nativeCanvas, pts[i], pts[i + 1], nativePaint);
+        }
     }
 
     @LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
index 8c6740c..43c95f4 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
@@ -650,6 +650,20 @@
         return null;
     }
 
+    @LayoutlibDelegate
+    /*package*/ static boolean nativeIsSRGB(long nativeBitmap) {
+        Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
+                "Color spaces are not supported", null /*data*/);
+        return false;
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static boolean nativeGetColorSpace(long nativePtr, float[] xyz, float[] params) {
+        Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
+                "Color spaces are not supported", null /*data*/);
+        return false;
+    }
+
     // ---- Private delegate/helper methods ----
 
     private Bitmap_Delegate(BufferedImage image, Config config) {
diff --git a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
index fb24c01..ff5a5e9 100644
--- a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
@@ -314,7 +314,7 @@
 
     @LayoutlibDelegate
     /*package*/ static boolean nAddFontFromAssetManager(long builderPtr, AssetManager mgr, String path,
-            int cookie, boolean isAsset) {
+            int cookie, boolean isAsset, int weight, boolean isItalic) {
         FontFamily_Delegate ffd = sManager.getDelegate(builderPtr);
         if (ffd == null) {
             return false;
@@ -355,8 +355,12 @@
                 Font font = Font.createFont(Font.TRUETYPE_FONT, fontStream);
                 fontInfo = new FontInfo();
                 fontInfo.mFont = font;
-                fontInfo.mWeight = font.isBold() ? BOLD_FONT_WEIGHT : DEFAULT_FONT_WEIGHT;
-                fontInfo.mIsItalic = font.isItalic();
+                if (weight == 0) {
+                    fontInfo.mWeight = font.isBold() ? BOLD_FONT_WEIGHT : DEFAULT_FONT_WEIGHT;
+                } else {
+                    fontInfo.mWeight = weight;
+                }
+                fontInfo.mIsItalic = weight == 0 ? font.isItalic() : isItalic;
                 ffd.addFont(fontInfo);
                 return true;
             } catch (IOException e) {
diff --git a/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
index 174bbcf..cc7631a 100644
--- a/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
@@ -571,6 +571,8 @@
         @NonNull
         public Consumer<Float> getFloatPropertySetter(int propertyIdx) {
             switch (propertyIdx) {
+                case STROKE_WIDTH_INDEX:
+                    return this::setStrokeWidth;
                 case STROKE_ALPHA_INDEX:
                     return this::setStrokeAlpha;
                 case FILL_ALPHA_INDEX:
diff --git a/tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java b/tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java
index fcd63ea..499e58a 100644
--- a/tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java
@@ -40,7 +40,7 @@
     }
 
     /*package*/ @SuppressWarnings("UnusedParameters")  // TODO implement this.
-    static long loadHyphenator(ByteBuffer buffer, int offset) {
+    static long loadHyphenator(ByteBuffer buffer, int offset, int minPrefix, int minSuffix) {
         return sDelegateManager.addNewDelegate(new Hyphenator_Delegate());
     }
 }
diff --git a/tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java b/tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java
index 970c7d5..1b99015 100644
--- a/tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java
@@ -53,8 +53,9 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static long nLoadHyphenator(ByteBuffer buf, int offset) {
-        return Hyphenator_Delegate.loadHyphenator(buf, offset);
+    /*package*/ static long nLoadHyphenator(ByteBuffer buf, int offset, int minPrefix,
+            int minSuffix) {
+        return Hyphenator_Delegate.loadHyphenator(buf, offset, minPrefix, minSuffix);
     }
 
     @LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java b/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java
index fad35d2..8130bc2 100644
--- a/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java
+++ b/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java
@@ -52,6 +52,8 @@
             throw new IllegalArgumentException("Outline is not a rect shadow");
         }
 
+        // TODO replacing the algorithm here to create better shadow
+
         float shadowSize = elevationToShadow(elevation);
         int saved = modifyCanvas(canvas, shadowSize);
         if (saved == -1) {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java
index 91668af..e10f20d 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java
@@ -100,7 +100,8 @@
         mView.setText(text);
     }
 
-    private void setGravity(int gravity) {
+    @SuppressWarnings("WeakerAccess") // This method is used from Studio
+    public void setGravity(int gravity) {
         mView.setGravity(gravity);
     }
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 2c9fe29..04fdae9 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -65,6 +65,7 @@
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteDatabase.CursorFactory;
 import android.graphics.Bitmap;
+import android.graphics.Color;
 import android.graphics.drawable.Drawable;
 import android.hardware.display.DisplayManager;
 import android.net.Uri;
@@ -105,7 +106,7 @@
 import java.util.List;
 import java.util.Map;
 
-import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
+import static android.os._Original_Build.VERSION_CODES.JELLY_BEAN_MR1;
 import static com.android.layoutlib.bridge.android.RenderParamsFlags.FLAG_KEY_APPLICATION_PACKAGE;
 
 /**
@@ -381,6 +382,18 @@
             return true;
         }
 
+        String stringValue = value.getValue();
+        if (!stringValue.isEmpty()) {
+            if (stringValue.charAt(0) == '#') {
+                outValue.type = TypedValue.TYPE_INT_COLOR_ARGB8;
+                outValue.data = Color.parseColor(value.getValue());
+            }
+            else if (stringValue.charAt(0) == '@') {
+                outValue.type = TypedValue.TYPE_REFERENCE;
+            }
+
+        }
+
         int a;
         // if this is a framework value.
         if (value.isFramework()) {
@@ -399,7 +412,7 @@
         }
 
         // If the value is not a valid reference, fallback to pass the value as a string.
-        outValue.string = value.getValue();
+        outValue.string = stringValue;
         return true;
     }
 
@@ -627,6 +640,10 @@
             return AccessibilityManager.getInstance(this);
         }
 
+        if (AUTO_FILL_MANAGER_SERVICE.equals(service)) {
+            return null;
+        }
+
         throw new UnsupportedOperationException("Unsupported Service: " + service);
     }
 
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
index 0039476..2274b90 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
@@ -321,6 +321,11 @@
     }
 
     @Override
+    public boolean isInstantApp(String packageName) {
+        return false;
+    }
+
+    @Override
     public int getInstantAppCookieMaxSize() {
         return 0;
     }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
index 9f73d79..339019d 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
@@ -18,6 +18,7 @@
 
 import android.os.IBinder;
 import android.os.IPowerManager;
+import android.os.PowerSaveState;
 import android.os.RemoteException;
 import android.os.WorkSource;
 
@@ -42,6 +43,10 @@
         return false;
     }
 
+    public PowerSaveState getPowerSaveState(int serviceType) {
+        return null;
+    }
+
     @Override
     public IBinder asBinder() {
         // pass for now.
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java
index 5386b17..7f8d992 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java
@@ -16,13 +16,13 @@
 
 package com.android.layoutlib.bridge.bars;
 
-import android.os.Build.VERSION_CODES;
+import android.os._Original_Build.VERSION_CODES;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
-import static android.os.Build.VERSION_CODES.*;
+import static android.os._Original_Build.VERSION_CODES.*;
 
 /**
  * Various helper methods to simulate older versions of platform.
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
index a6e5fb8..8bb2c59 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
@@ -49,7 +49,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 
-import static android.os.Build.VERSION_CODES.LOLLIPOP;
+import static android.os._Original_Build.VERSION_CODES.LOLLIPOP;
 
 /**
  * Base "bar" class for the window decor around the the edited layout.
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
index b3a2d3e..f1e7b51 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
@@ -286,18 +286,15 @@
 
         Density density = Density.MEDIUM;
         if (value instanceof DensityBasedResourceValue) {
-            density =
-                ((DensityBasedResourceValue)value).getResourceDensity();
+            density = ((DensityBasedResourceValue) value).getResourceDensity();
         }
 
-
         if (lowerCaseValue.endsWith(NinePatch.EXTENSION_9PATCH)) {
             File file = new File(stringValue);
             if (file.isFile()) {
                 try {
-                    return getNinePatchDrawable(
-                            new FileInputStream(file), density, value.isFramework(),
-                            stringValue, context);
+                    return getNinePatchDrawable(new FileInputStream(file), density,
+                            value.isFramework(), stringValue, context);
                 } catch (IOException e) {
                     // failed to read the file, we'll return null below.
                     Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
@@ -306,30 +303,28 @@
             }
 
             return null;
-        } else if (lowerCaseValue.endsWith(".xml")) {
+        } else if (lowerCaseValue.endsWith(".xml") || stringValue.startsWith("@aapt:_aapt/")) {
             // create a block parser for the file
-            File f = new File(stringValue);
-            if (f.isFile()) {
-                try {
-                    // let the framework inflate the Drawable from the XML file.
-                    XmlPullParser parser = ParserFactory.create(f);
-
-                    BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(
-                            parser, context, value.isFramework());
-                    try {
-                        return Drawable.createFromXml(context.getResources(), blockParser, theme);
-                    } finally {
-                        blockParser.ensurePopped();
+            try {
+                XmlPullParser parser = context.getLayoutlibCallback().getParser(value);
+                if (parser == null) {
+                    File drawableFile = new File(stringValue);
+                    if (drawableFile.isFile()) {
+                        parser = ParserFactory.create(drawableFile);
                     }
-                } catch (Exception e) {
-                    // this is an error and not warning since the file existence is checked before
-                    // attempting to parse it.
-                    Bridge.getLog().error(null, "Failed to parse file " + stringValue,
-                            e, null /*data*/);
                 }
-            } else {
-                Bridge.getLog().error(LayoutLog.TAG_BROKEN,
-                        String.format("File %s does not exist (or is not a file)", stringValue),
+
+                BridgeXmlBlockParser blockParser =
+                        new BridgeXmlBlockParser(parser, context, value.isFramework());
+                try {
+                    return Drawable.createFromXml(context.getResources(), blockParser, theme);
+                } finally {
+                    blockParser.ensurePopped();
+                }
+            } catch (Exception e) {
+                // this is an error and not warning since the file existence is checked before
+                // attempting to parse it.
+                Bridge.getLog().error(null, "Failed to parse file " + stringValue, e,
                         null /*data*/);
             }
 
@@ -342,8 +337,8 @@
                             value.isFramework() ? null : context.getProjectKey());
 
                     if (bitmap == null) {
-                        bitmap = Bitmap_Delegate.createBitmap(bmpFile, false /*isMutable*/,
-                                density);
+                        bitmap =
+                                Bitmap_Delegate.createBitmap(bmpFile, false /*isMutable*/, density);
                         Bridge.setCachedBitmap(stringValue, bitmap,
                                 value.isFramework() ? null : context.getProjectKey());
                     }
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
index a53dcba..f15d669 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/shadows_test.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/shadows_test.png
new file mode 100644
index 0000000..4f3ed60
--- /dev/null
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/shadows_test.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml
index 05a3665..456b5f6 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml
@@ -263,7 +263,8 @@
             android:id="@id/radioButton2"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:text="New RadioButton" />
+            android:text="New RadioButton"
+            android:checked="true" />
 
     </RadioGroup>
 
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/shadows_test.xml b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/shadows_test.xml
new file mode 100644
index 0000000..59dbbec
--- /dev/null
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/shadows_test.xml
@@ -0,0 +1,97 @@
+<?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.
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:orientation="vertical"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent" >
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_weight="1">
+
+        <Button
+            android:layout_marginLeft="40dp"
+            android:layout_width="48dp"
+            android:layout_height="40dp"
+            android:layout_alignParentLeft="true"
+            android:layout_centerVertical="true"
+            android:elevation="48dp"
+            android:stateListAnimator="@null"/>
+
+        <Button
+            android:layout_marginRight="40dp"
+            android:layout_width="48dp"
+            android:layout_height="40dp"
+            android:layout_alignParentRight="true"
+            android:layout_centerVertical="true"
+            android:elevation="48dp"
+            android:stateListAnimator="@null"/>
+
+    </RelativeLayout>
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_weight="1">
+
+        <Button
+            android:layout_marginLeft="40dp"
+            android:layout_width="48dp"
+            android:layout_height="40dp"
+            android:layout_alignParentLeft="true"
+            android:layout_centerVertical="true"
+            android:elevation="0dp"
+            android:stateListAnimator="@null"/>
+
+        <Button
+            android:layout_marginRight="40dp"
+            android:layout_width="48dp"
+            android:layout_height="40dp"
+            android:layout_alignParentRight="true"
+            android:layout_centerVertical="true"
+            android:elevation="100dp"
+            android:stateListAnimator="@null"/>
+
+    </RelativeLayout>
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_weight="1">
+
+        <Button
+            android:layout_marginLeft="40dp"
+            android:layout_width="48dp"
+            android:layout_height="40dp"
+            android:layout_alignParentLeft="true"
+            android:layout_centerVertical="true"
+            android:elevation="12dp"
+            android:stateListAnimator="@null"/>
+
+        <Button
+            android:layout_marginRight="40dp"
+            android:layout_width="48dp"
+            android:layout_height="40dp"
+            android:layout_alignParentRight="true"
+            android:layout_centerVertical="true"
+            android:elevation="36dp"
+            android:stateListAnimator="@null"/>
+
+    </RelativeLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
index b15ee95..c83d2e4 100644
--- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
+++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
@@ -34,7 +34,7 @@
 @SuiteClasses({
         RenderTests.class, LayoutParserWrapperTest.class,
         BridgeXmlBlockParserTest.class, BridgeXmlPullAttributesTest.class,
-        Matrix_DelegateTest.class, TestDelegates.class
+        Matrix_DelegateTest.class, TestDelegates.class, PerformanceTests.class
 })
 public class Main {
 }
diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTests.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTests.java
index 913519c..7199781 100644
--- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTests.java
+++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTests.java
@@ -36,6 +36,7 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.util.DisplayMetrics;
+import android.util.TypedValue;
 
 import java.lang.reflect.Field;
 import java.util.concurrent.TimeUnit;
@@ -43,6 +44,7 @@
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
@@ -334,6 +336,7 @@
         AssetManager assetManager = AssetManager.getSystem();
         DisplayMetrics metrics = new DisplayMetrics();
         Configuration configuration = RenderAction.getConfiguration(params);
+        //noinspection deprecation
         Resources resources = new Resources(assetManager, metrics, configuration);
         resources.mLayoutlibCallback = params.getLayoutlibCallback();
         resources.mContext =
@@ -370,6 +373,7 @@
         AssetManager assetManager = AssetManager.getSystem();
         DisplayMetrics metrics = new DisplayMetrics();
         Configuration configuration = RenderAction.getConfiguration(params);
+        //noinspection deprecation
         Resources resources = new Resources(assetManager, metrics, configuration);
         resources.mLayoutlibCallback = params.getLayoutlibCallback();
         resources.mContext =
@@ -390,4 +394,39 @@
         // TODO: styles seem to be broken in TextView
         renderAndVerify("fonts_test.xml", "font_test.png");
     }
+
+    @Test
+    public void testColorTypedValue() throws Exception {
+        // Setup
+        // Create the layout pull parser for our resources (empty.xml can not be part of the test
+        // app as it won't compile).
+        LayoutPullParser parser = new LayoutPullParser("/empty.xml");
+        // Create LayoutLibCallback.
+        LayoutLibTestCallback layoutLibCallback =
+                new LayoutLibTestCallback(RenderTestBase.getLogger(), mDefaultClassLoader);
+        layoutLibCallback.initResources();
+        SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_4,
+                layoutLibCallback, "AppTheme", true, RenderingMode.NORMAL, 22);
+        AssetManager assetManager = AssetManager.getSystem();
+        DisplayMetrics metrics = new DisplayMetrics();
+        Configuration configuration = RenderAction.getConfiguration(params);
+        //noinspection deprecation
+        Resources resources = new Resources(assetManager, metrics, configuration);
+        resources.mLayoutlibCallback = params.getLayoutlibCallback();
+        resources.mContext =
+                new BridgeContext(params.getProjectKey(), metrics, params.getResources(),
+                        params.getAssets(), params.getLayoutlibCallback(), configuration,
+                        params.getTargetSdkVersion(), params.isRtlSupported());
+
+        TypedValue outValue = new TypedValue();
+        resources.mContext.resolveThemeAttribute(android.R.attr.colorPrimary, outValue, true);
+        assertEquals(TypedValue.TYPE_INT_COLOR_ARGB8, outValue.type);
+        assertNotEquals(0, outValue.data);
+        assertTrue(sRenderMessages.isEmpty());
+    }
+
+    @Test
+    public void testRectangleShadow() throws Exception {
+        renderAndVerify("shadows_test.xml", "shadows_test.png");
+    }
 }
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
index bed5806a..d59b419 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
@@ -37,6 +37,7 @@
 import java.util.jar.JarEntry;
 import java.util.jar.JarOutputStream;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 /**
  * Class that generates a new JAR from a list of classes, some of which are to be kept as-is
@@ -127,7 +128,10 @@
         // Create the map of classes to rename.
         mRenameClasses = new HashMap<>();
         mClassesNotRenamed = new HashSet<>();
-        String[] renameClasses = createInfo.getRenamedClasses();
+        String[] renameClasses = Stream.concat(
+                Arrays.stream(createInfo.getRenamedClasses()),
+                Arrays.stream(createInfo.getRefactoredClasses()))
+                .toArray(String[]::new);
         int n = renameClasses.length;
         for (int i = 0; i < n; i += 2) {
             assert i + 1 < n;
@@ -140,7 +144,10 @@
 
         // Create a map of classes to be refactored.
         mRefactorClasses = new HashMap<>();
-        String[] refactorClasses = createInfo.getJavaPkgClasses();
+        String[] refactorClasses = Stream.concat(
+                Arrays.stream(createInfo.getJavaPkgClasses()),
+                Arrays.stream(createInfo.getRefactoredClasses()))
+                .toArray(String[]::new);
         n = refactorClasses.length;
         for (int i = 0; i < n; i += 2) {
             assert i + 1 < n;
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index a8582c6..b0aa3c2 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -36,66 +36,42 @@
  */
 public final class CreateInfo implements ICreateInfo {
 
-    /**
-     * Returns the list of class from layoutlib_create to inject in layoutlib.
-     * The list can be empty but must not be null.
-     */
     @Override
     public Class<?>[] getInjectedClasses() {
         return INJECTED_CLASSES;
     }
 
-    /**
-     * Returns the list of methods to rewrite as delegates.
-     * The list can be empty but must not be null.
-     */
     @Override
     public String[] getDelegateMethods() {
         return DELEGATE_METHODS;
     }
 
-    /**
-     * Returns the list of classes on which to delegate all native methods.
-     * The list can be empty but must not be null.
-     */
     @Override
     public String[] getDelegateClassNatives() {
         return DELEGATE_CLASS_NATIVES;
     }
 
-    /**
-     * Returns the list of classes to rename, must be an even list: the binary FQCN
-     * of class to replace followed by the new FQCN.
-     * The list can be empty but must not be null.
-     */
     @Override
     public String[] getRenamedClasses() {
         return RENAMED_CLASSES;
     }
 
-    /**
-     * Returns the list of classes for which the methods returning them should be deleted.
-     * The array contains a list of null terminated section starting with the name of the class
-     * to rename in which the methods are deleted, followed by a list of return types identifying
-     * the methods to delete.
-     * The list can be empty but must not be null.
-     */
     @Override
     public String[] getDeleteReturns() {
         return DELETE_RETURNS;
     }
 
-    /**
-     * Returns the list of classes to refactor, must be an even list: the binary FQCN of class to
-     * replace followed by the new FQCN. All references to the old class should be updated to the
-     * new class. The list can be empty but must not be null.
-     */
     @Override
     public String[] getJavaPkgClasses() {
       return JAVA_PKG_CLASSES;
     }
 
     @Override
+    public String[] getRefactoredClasses() {
+        return REFACTOR_CLASSES;
+    }
+
+    @Override
     public Set<String> getExcludedClasses() {
         String[] refactoredClasses = getJavaPkgClasses();
         int count = refactoredClasses.length / 2 + EXCLUDED_CLASSES.length;
@@ -333,10 +309,22 @@
             "java.text.SimpleDateFormat",                      "android.icu.text.SimpleDateFormat",
         };
 
+    /**
+     * List of classes to refactor. This is similar to combining {@link #getRenamedClasses()} and
+     * {@link #getJavaPkgClasses()}.
+     * Classes included here will be renamed and then all their references in any other classes
+     * will be also modified.
+     * FQCN of class to refactor followed by its new FQCN.
+     */
+    private final static String[] REFACTOR_CLASSES =
+            new String[] {
+                    "android.os.Build",                                "android.os._Original_Build",
+            };
+
     private final static String[] EXCLUDED_CLASSES =
         new String[] {
             "android.preference.PreferenceActivity",
-            "org.kxml2.io.KXmlParser"
+            "org.kxml2.io.KXmlParser",
         };
 
     /**
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ICreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ICreateInfo.java
index 48abde4..eca1c07 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ICreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ICreateInfo.java
@@ -52,6 +52,15 @@
     String[] getRenamedClasses();
 
     /**
+     * List of classes to refactor. This is similar to combining {@link #getRenamedClasses()} and
+     * {@link #getJavaPkgClasses()}.
+     * Classes included here will be renamed and then all their references in any other classes
+     * will be also modified.
+     * FQCN of class to refactor followed by its new FQCN.
+     */
+    String[] getRefactoredClasses();
+
+    /**
      * Returns the list of classes for which the methods returning them should be deleted.
      * The array contains a list of null terminated section starting with the name of the class
      * to rename in which the methods are deleted, followed by a list of return types identifying
diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmGeneratorTest.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmGeneratorTest.java
index 4d5d5d2..e718fb9 100644
--- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmGeneratorTest.java
+++ b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmGeneratorTest.java
@@ -35,6 +35,7 @@
 import java.lang.reflect.Method;
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashSet;
@@ -54,8 +55,6 @@
  * Unit tests for some methods of {@link AsmGenerator}.
  */
 public class AsmGeneratorTest {
-
-    private static final String[] EMPTY_STRING_ARRAY = new String[0];
     private MockLog mLog;
     private ArrayList<String> mOsJarPath;
     private String mOsDestJar;
@@ -81,6 +80,7 @@
     @After
     public void tearDown() throws Exception {
         if (mTempFile != null) {
+            //noinspection ResultOfMethodCallIgnored
             mTempFile.delete();
             mTempFile = null;
         }
@@ -89,23 +89,7 @@
     @Test
     public void testClassRenaming() throws IOException, LogAbortException {
 
-        ICreateInfo ci = new ICreateInfo() {
-            @Override
-            public Class<?>[] getInjectedClasses() {
-                // classes to inject in the final JAR
-                return new Class<?>[0];
-            }
-
-            @Override
-            public String[] getDelegateMethods() {
-                return EMPTY_STRING_ARRAY;
-            }
-
-            @Override
-            public String[] getDelegateClassNatives() {
-                return EMPTY_STRING_ARRAY;
-            }
-
+        ICreateInfo ci = new CreateInfoAdapter() {
             @Override
             public String[] getRenamedClasses() {
                 // classes to rename (so that we can replace them)
@@ -114,37 +98,6 @@
                         "not.an.actual.ClassName", "anoter.fake.NewClassName",
                 };
             }
-
-            @Override
-            public String[] getJavaPkgClasses() {
-              return EMPTY_STRING_ARRAY;
-            }
-
-            @Override
-            public Set<String> getExcludedClasses() {
-                return null;
-            }
-
-            @Override
-            public String[] getDeleteReturns() {
-                 // methods deleted from their return type.
-                return EMPTY_STRING_ARRAY;
-            }
-
-            @Override
-            public String[] getPromotedFields() {
-                return EMPTY_STRING_ARRAY;
-            }
-
-            @Override
-            public String[] getPromotedClasses() {
-                return EMPTY_STRING_ARRAY;
-            }
-
-            @Override
-            public Map<String, InjectMethodRunnable> getInjectedMethodsMap() {
-                return Collections.emptyMap();
-            }
         };
 
         AsmGenerator agen = new AsmGenerator(mLog, mOsDestJar, ci);
@@ -154,7 +107,7 @@
                 new String[] {        // include classes
                     "**"
                 },
-                Collections.<String>emptySet() /* excluded classes */,
+                Collections.emptySet() /* excluded classes */,
                 new String[]{} /* include files */);
         aa.analyze();
         agen.generate();
@@ -165,8 +118,8 @@
     }
 
     @Test
-    public void testClassRefactoring() throws IOException, LogAbortException {
-        ICreateInfo ci = new ICreateInfo() {
+    public void testJavaClassRefactoring() throws IOException, LogAbortException {
+        ICreateInfo ci = new CreateInfoAdapter() {
             @Override
             public Class<?>[] getInjectedClasses() {
                 // classes to inject in the final JAR
@@ -176,22 +129,6 @@
             }
 
             @Override
-            public String[] getDelegateMethods() {
-                return EMPTY_STRING_ARRAY;
-            }
-
-            @Override
-            public String[] getDelegateClassNatives() {
-                return EMPTY_STRING_ARRAY;
-            }
-
-            @Override
-            public String[] getRenamedClasses() {
-                // classes to rename (so that we can replace them)
-                return EMPTY_STRING_ARRAY;
-            }
-
-            @Override
             public String[] getJavaPkgClasses() {
              // classes to refactor (so that we can replace them)
                 return new String[] {
@@ -203,27 +140,6 @@
             public Set<String> getExcludedClasses() {
                 return Collections.singleton("java.lang.JavaClass");
             }
-
-            @Override
-            public String[] getDeleteReturns() {
-                 // methods deleted from their return type.
-                return EMPTY_STRING_ARRAY;
-            }
-
-            @Override
-            public String[] getPromotedFields() {
-                return EMPTY_STRING_ARRAY;
-            }
-
-            @Override
-            public String[] getPromotedClasses() {
-                return EMPTY_STRING_ARRAY;
-            }
-
-            @Override
-            public Map<String, InjectMethodRunnable> getInjectedMethodsMap() {
-                return Collections.emptyMap();
-            }
         };
 
         AsmGenerator agen = new AsmGenerator(mLog, mOsDestJar, ci);
@@ -233,7 +149,7 @@
                 new String[] {        // include classes
                     "**"
                 },
-                Collections.<String>emptySet(),
+                Collections.emptySet(),
                 new String[] {        /* include files */
                     "mock_android/data/data*"
                 });
@@ -242,47 +158,64 @@
         Map<String, ClassReader> output = new TreeMap<>();
         Map<String, InputStream> filesFound = new TreeMap<>();
         parseZip(mOsDestJar, output, filesFound);
-        boolean injectedClassFound = false;
+        RecordingClassVisitor cv = new RecordingClassVisitor();
         for (ClassReader cr: output.values()) {
-            TestClassVisitor cv = new TestClassVisitor();
             cr.accept(cv, 0);
-            injectedClassFound |= cv.mInjectedClassFound;
         }
-        assertTrue(injectedClassFound);
+        assertTrue(cv.mVisitedClasses.contains(
+                "com/android/tools/layoutlib/create/dataclass/JavaClass"));
+        assertFalse(cv.mVisitedClasses.contains(
+                JAVA_CLASS_NAME));
         assertArrayEquals(new String[] {"mock_android/data/dataFile"},
                 filesFound.keySet().toArray());
     }
 
     @Test
-    public void testClassExclusion() throws IOException, LogAbortException {
-        ICreateInfo ci = new ICreateInfo() {
+    public void testClassRefactoring() throws IOException, LogAbortException {
+        ICreateInfo ci = new CreateInfoAdapter() {
             @Override
             public Class<?>[] getInjectedClasses() {
-                return new Class<?>[0];
+                // classes to inject in the final JAR
+                return new Class<?>[] {
+                        com.android.tools.layoutlib.create.dataclass.JavaClass.class
+                };
             }
 
             @Override
-            public String[] getDelegateMethods() {
-                return EMPTY_STRING_ARRAY;
-            }
-
-            @Override
-            public String[] getDelegateClassNatives() {
-                return EMPTY_STRING_ARRAY;
-            }
-
-            @Override
-            public String[] getRenamedClasses() {
-                // classes to rename (so that we can replace them)
-                return EMPTY_STRING_ARRAY;
-            }
-
-            @Override
-            public String[] getJavaPkgClasses() {
+            public String[] getRefactoredClasses() {
                 // classes to refactor (so that we can replace them)
-                return EMPTY_STRING_ARRAY;
+                return new String[] {
+                        "mock_android.view.View", "mock_android.view._Original_View",
+                };
             }
+        };
 
+        AsmGenerator agen = new AsmGenerator(mLog, mOsDestJar, ci);
+
+        AsmAnalyzer aa = new AsmAnalyzer(mLog, mOsJarPath, agen,
+                null,                 // derived from
+                new String[] {        // include classes
+                        "**"
+                },
+                Collections.emptySet(),
+                new String[] {});
+        aa.analyze();
+        agen.generate();
+        Map<String, ClassReader> output = new TreeMap<>();
+        parseZip(mOsDestJar, output, new TreeMap<>());
+        RecordingClassVisitor cv = new RecordingClassVisitor();
+        for (ClassReader cr: output.values()) {
+            cr.accept(cv, 0);
+        }
+        assertTrue(cv.mVisitedClasses.contains(
+                "mock_android/view/_Original_View"));
+        assertFalse(cv.mVisitedClasses.contains(
+                "mock_android/view/View"));
+    }
+
+    @Test
+    public void testClassExclusion() throws IOException, LogAbortException {
+        ICreateInfo ci = new CreateInfoAdapter() {
             @Override
             public Set<String> getExcludedClasses() {
                 Set<String> set = new HashSet<>(2);
@@ -290,27 +223,6 @@
                 set.add("java.lang.JavaClass");
                 return set;
             }
-
-            @Override
-            public String[] getDeleteReturns() {
-                // methods deleted from their return type.
-                return EMPTY_STRING_ARRAY;
-            }
-
-            @Override
-            public String[] getPromotedFields() {
-                return EMPTY_STRING_ARRAY;
-            }
-
-            @Override
-            public String[] getPromotedClasses() {
-                return EMPTY_STRING_ARRAY;
-            }
-
-            @Override
-            public Map<String, InjectMethodRunnable> getInjectedMethodsMap() {
-                return Collections.emptyMap();
-            }
         };
 
         AsmGenerator agen = new AsmGenerator(mLog, mOsDestJar, ci);
@@ -340,55 +252,7 @@
     public void testMethodInjection() throws IOException, LogAbortException,
             ClassNotFoundException, IllegalAccessException, InstantiationException,
             NoSuchMethodException, InvocationTargetException {
-        ICreateInfo ci = new ICreateInfo() {
-            @Override
-            public Class<?>[] getInjectedClasses() {
-                return new Class<?>[0];
-            }
-
-            @Override
-            public String[] getDelegateMethods() {
-                return EMPTY_STRING_ARRAY;
-            }
-
-            @Override
-            public String[] getDelegateClassNatives() {
-                return EMPTY_STRING_ARRAY;
-            }
-
-            @Override
-            public String[] getRenamedClasses() {
-                // classes to rename (so that we can replace them)
-                return EMPTY_STRING_ARRAY;
-            }
-
-            @Override
-            public String[] getJavaPkgClasses() {
-                // classes to refactor (so that we can replace them)
-                return EMPTY_STRING_ARRAY;
-            }
-
-            @Override
-            public Set<String> getExcludedClasses() {
-                return Collections.emptySet();
-            }
-
-            @Override
-            public String[] getDeleteReturns() {
-                // methods deleted from their return type.
-                return EMPTY_STRING_ARRAY;
-            }
-
-            @Override
-            public String[] getPromotedFields() {
-                return EMPTY_STRING_ARRAY;
-            }
-
-            @Override
-            public String[] getPromotedClasses() {
-                return EMPTY_STRING_ARRAY;
-            }
-
+        ICreateInfo ci = new CreateInfoAdapter() {
             @Override
             public Map<String, InjectMethodRunnable> getInjectedMethodsMap() {
                 return Collections.singletonMap("mock_android.util.EmptyArray",
@@ -474,97 +338,94 @@
         }
     }
 
-    private class TestClassVisitor extends ClassVisitor {
+    /**
+     * {@link ClassVisitor} that records every class that sees.
+     */
+    private static class RecordingClassVisitor extends ClassVisitor {
+        private Set<String> mVisitedClasses = new HashSet<>();
 
-        boolean mInjectedClassFound = false;
-
-        TestClassVisitor() {
+        private RecordingClassVisitor() {
             super(Main.ASM_VERSION);
         }
 
-        @Override
-        public void visit(int version, int access, String name, String signature,
-                String superName, String[] interfaces) {
-            assertTrue(!getBase(name).equals(JAVA_CLASS_NAME));
-            if (name.equals("com/android/tools/layoutlib/create/dataclass/JavaClass")) {
-                mInjectedClassFound = true;
+        private void addClass(String className) {
+            if (className == null) {
+                return;
             }
-            super.visit(version, access, name, signature, superName, interfaces);
+
+            int pos = className.indexOf('$');
+            if (pos > 0) {
+                // For inner classes, add also the base class
+                mVisitedClasses.add(className.substring(0, pos));
+            }
+            mVisitedClasses.add(className);
         }
 
         @Override
-        public FieldVisitor visitField(int access, String name, String desc,
-                String signature, Object value) {
-            assertTrue(testType(Type.getType(desc)));
+        public void visit(int version, int access, String name, String signature, String superName,
+                String[] interfaces) {
+            addClass(superName);
+            Arrays.stream(interfaces).forEach(this::addClass);
+        }
+
+        private void processType(Type type) {
+            switch (type.getSort()) {
+                case Type.OBJECT:
+                    addClass(type.getInternalName());
+                    break;
+                case Type.ARRAY:
+                    addClass(type.getElementType().getInternalName());
+                    break;
+                case Type.METHOD:
+                    processType(type.getReturnType());
+                    Arrays.stream(type.getArgumentTypes()).forEach(this::processType);
+                    break;
+            }
+        }
+
+        @Override
+        public FieldVisitor visitField(int access, String name, String desc, String signature,
+                Object value) {
+            processType(Type.getType(desc));
             return super.visitField(access, name, desc, signature, value);
         }
 
-        @SuppressWarnings("hiding")
         @Override
-        public MethodVisitor visitMethod(int access, String name, String desc,
-                String signature, String[] exceptions) {
+        public MethodVisitor visitMethod(int access, String name, String desc, String signature,
+                String[] exceptions) {
             MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
             return new MethodVisitor(Main.ASM_VERSION, mv) {
 
                 @Override
-                public void visitFieldInsn(int opcode, String owner, String name,
-                        String desc) {
-                    assertTrue(!getBase(owner).equals(JAVA_CLASS_NAME));
-                    assertTrue(testType(Type.getType(desc)));
+                public void visitFieldInsn(int opcode, String owner, String name, String desc) {
+                    addClass(owner);
+                    processType(Type.getType(desc));
                     super.visitFieldInsn(opcode, owner, name, desc);
                 }
 
                 @Override
                 public void visitLdcInsn(Object cst) {
                     if (cst instanceof Type) {
-                        assertTrue(testType((Type)cst));
+                        processType((Type) cst);
                     }
                     super.visitLdcInsn(cst);
                 }
 
                 @Override
                 public void visitTypeInsn(int opcode, String type) {
-                    assertTrue(!getBase(type).equals(JAVA_CLASS_NAME));
+                    addClass(type);
                     super.visitTypeInsn(opcode, type);
                 }
 
                 @Override
-                public void visitMethodInsn(int opcode, String owner, String name,
-                        String desc, boolean itf) {
-                    assertTrue(!getBase(owner).equals(JAVA_CLASS_NAME));
-                    assertTrue(testType(Type.getType(desc)));
+                public void visitMethodInsn(int opcode, String owner, String name, String desc,
+                        boolean itf) {
+                    addClass(owner);
+                    processType(Type.getType(desc));
                     super.visitMethodInsn(opcode, owner, name, desc, itf);
                 }
 
             };
         }
-
-        private boolean testType(Type type) {
-            int sort = type.getSort();
-            if (sort == Type.OBJECT) {
-                assertTrue(!getBase(type.getInternalName()).equals(JAVA_CLASS_NAME));
-            } else if (sort == Type.ARRAY) {
-                assertTrue(!getBase(type.getElementType().getInternalName())
-                        .equals(JAVA_CLASS_NAME));
-            } else if (sort == Type.METHOD) {
-                boolean r = true;
-                for (Type t : type.getArgumentTypes()) {
-                    r &= testType(t);
-                }
-                return r & testType(type.getReturnType());
-            }
-            return true;
-        }
-
-        private String getBase(String className) {
-            if (className == null) {
-                return null;
-            }
-            int pos = className.indexOf('$');
-            if (pos > 0) {
-                return className.substring(0, pos);
-            }
-            return className;
-        }
     }
 }
diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/CreateInfoAdapter.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/CreateInfoAdapter.java
new file mode 100644
index 0000000..ad7cb9a
--- /dev/null
+++ b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/CreateInfoAdapter.java
@@ -0,0 +1,80 @@
+/*
+ * 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.tools.layoutlib.create;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+class CreateInfoAdapter implements ICreateInfo {
+    private static final String[] EMPTY_STRING_ARRAY = new String[0];
+
+    @Override
+    public Class<?>[] getInjectedClasses() {
+        return new Class<?>[0];
+    }
+
+    @Override
+    public String[] getDelegateMethods() {
+        return EMPTY_STRING_ARRAY;
+    }
+
+    @Override
+    public String[] getDelegateClassNatives() {
+        return EMPTY_STRING_ARRAY;
+    }
+
+    @Override
+    public String[] getRenamedClasses() {
+        return EMPTY_STRING_ARRAY;
+    }
+
+    @Override
+    public String[] getRefactoredClasses() {
+        return EMPTY_STRING_ARRAY;
+    }
+
+    @Override
+    public String[] getDeleteReturns() {
+        return EMPTY_STRING_ARRAY;
+    }
+
+    @Override
+    public String[] getJavaPkgClasses() {
+        return EMPTY_STRING_ARRAY;
+    }
+
+    @Override
+    public Set<String> getExcludedClasses() {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public String[] getPromotedFields() {
+        return EMPTY_STRING_ARRAY;
+    }
+
+    @Override
+    public String[] getPromotedClasses() {
+        return EMPTY_STRING_ARRAY;
+    }
+
+    @Override
+    public Map<String, InjectMethodRunnable> getInjectedMethodsMap() {
+        return Collections.emptyMap();
+    }
+}
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 3eb9934..a1099f8 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -376,7 +376,9 @@
 
     /**
      * Flag indicating if this network is provided by a home Passpoint provider or a roaming
-     * Passpoint provider.
+     * Passpoint provider.  This flag will be {@code true} if this network is provided by
+     * a home Passpoint provider and {@code false} if is provided by a roaming Passpoint provider
+     * or is a non-Passpoint network.
      */
     public boolean isHomeProviderNetwork;
 
@@ -1305,6 +1307,7 @@
             setConnectChoice(source.getConnectChoice());
             setConnectChoiceTimestamp(source.getConnectChoiceTimestamp());
             setHasEverConnected(source.getHasEverConnected());
+            setNotRecommended(source.isNotRecommended());
         }
 
         public void writeToParcel(Parcel dest) {
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index f790332..4268f24 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -236,11 +236,11 @@
         public static final int TTLS    = 2;
         /** EAP-Password */
         public static final int PWD     = 3;
-        /** EAP-Subscriber Identity Module */
+        /** EAP-Subscriber Identity Module [RFC-4186] */
         public static final int SIM     = 4;
-        /** EAP-Authentication and Key Agreement */
+        /** EAP-Authentication and Key Agreement [RFC-4187] */
         public static final int AKA     = 5;
-        /** EAP-Authentication and Key Agreement Prime */
+        /** EAP-Authentication and Key Agreement Prime [RFC-5448] */
         public static final int AKA_PRIME = 6;
         /** Hotspot 2.0 r2 OSEN */
         public static final int UNAUTH_TLS = 7;
@@ -263,11 +263,11 @@
         public static final int MSCHAPV2    = 3;
         /** Generic Token Card */
         public static final int GTC         = 4;
-        /** EAP-Subscriber Identity Module */
+        /** EAP-Subscriber Identity Module [RFC-4186] */
         public static final int SIM         = 5;
-        /** EAP-Authentication and Key Agreement */
+        /** EAP-Authentication and Key Agreement [RFC-4187] */
         public static final int AKA         = 6;
-        /** EAP-Authentication and Key Agreement Prime */
+        /** EAP-Authentication and Key Agreement Prime [RFC-5448] */
         public static final int AKA_PRIME   = 7;
         private static final String AUTH_PREFIX = "auth=";
         private static final String AUTHEAP_PREFIX = "autheap=";
@@ -756,8 +756,8 @@
      * key entry when the config is saved and removing the key entry when
      * the config is removed.
 
-     * @param privateKey
-     * @param clientCertificate
+     * @param privateKey a PrivateKey instance for the end certificate.
+     * @param clientCertificate an X509Certificate representing the end certificate.
      * @throws IllegalArgumentException for an invalid key or certificate.
      */
     public void setClientKeyEntry(PrivateKey privateKey, X509Certificate clientCertificate) {
@@ -775,9 +775,11 @@
      * with this configuration.  The framework takes care of installing the
      * key entry when the config is saved and removing the key entry when
      * the config is removed.
-
-     * @param privateKey
-     * @param clientCertificateChain
+     *
+     * @param privateKey a PrivateKey instance for the end certificate.
+     * @param clientCertificateChain an array of X509Certificate instances which starts with
+     *         end certificate and continues with additional CA certificates necessary to
+     *         link the end certificate with some root certificate known by the authenticator.
      * @throws IllegalArgumentException for an invalid key or certificate.
      */
     public void setClientKeyEntryWithCertificateChain(PrivateKey privateKey,
@@ -835,7 +837,15 @@
     }
 
     /**
-     * Get the complete client certificate chain
+     * Get the complete client certificate chain in the same order as it was last supplied.
+     *
+     * <p>If the chain was last supplied by a call to
+     * {@link #setClientKeyEntry(java.security.PrivateKey, java.security.cert.X509Certificate)}
+     * with a non-null * certificate instance, a single-element array containing the certificate
+     * will be * returned. If {@link #setClientKeyEntryWithCertificateChain(
+     * java.security.PrivateKey, java.security.cert.X509Certificate[])} was last called with a
+     * non-empty array, this array will be returned in the same order as it was supplied.
+     * Otherwise, {@code null} will be returned.
      *
      * @return X.509 client certificates
      */
diff --git a/wifi/java/android/net/wifi/aware/DiscoverySession.java b/wifi/java/android/net/wifi/aware/DiscoverySession.java
index adf189b..156c3fd 100644
--- a/wifi/java/android/net/wifi/aware/DiscoverySession.java
+++ b/wifi/java/android/net/wifi/aware/DiscoverySession.java
@@ -31,8 +31,7 @@
  * {@link PublishDiscoverySession} and {@link SubscribeDiscoverySession}. This
  * class provides functionality common to both publish and subscribe discovery sessions:
  * <ul>
- *     <li>Sending messages: {@link #sendMessage(PeerHandle, int, byte[])} or
- *     {@link #sendMessage(PeerHandle, int, byte[], int)} methods.
+ *     <li>Sending messages: {@link #sendMessage(PeerHandle, int, byte[])} method.
  *     <li>Creating a network-specifier when requesting a Aware connection:
  *     {@link #createNetworkSpecifier(PeerHandle, byte[])}.
  * </ul>
@@ -62,6 +61,8 @@
      * {@link #sendMessage(PeerHandle, int, byte[], int)}.
      *
      * @return Maximum retry count when sending messages.
+     *
+     * @hide
      */
     public static int getMaxSendRetryCount() {
         return MAX_SEND_RETRY_COUNT;
@@ -115,6 +116,7 @@
             Log.w(TAG, "terminate: already terminated.");
             return;
         }
+
         mTerminated = true;
         mMgr.clear();
         mCloseGuard.close();
@@ -163,21 +165,23 @@
      *            or MAC level) retries should be attempted if there is no ACK from the receiver
      *            (note: no retransmissions are attempted in other failure cases). A value of 0
      *            indicates no retries. Max permitted value is {@link #getMaxSendRetryCount()}.
+     *
+     * @hide
      */
     public void sendMessage(@NonNull PeerHandle peerHandle, int messageId,
             @Nullable byte[] message, int retryCount) {
         if (mTerminated) {
             Log.w(TAG, "sendMessage: called on terminated session");
             return;
-        } else {
-            WifiAwareManager mgr = mMgr.get();
-            if (mgr == null) {
-                Log.w(TAG, "sendMessage: called post GC on WifiAwareManager");
-                return;
-            }
-
-            mgr.sendMessage(mClientId, mSessionId, peerHandle, message, messageId, retryCount);
         }
+
+        WifiAwareManager mgr = mMgr.get();
+        if (mgr == null) {
+            Log.w(TAG, "sendMessage: called post GC on WifiAwareManager");
+            return;
+        }
+
+        mgr.sendMessage(mClientId, mSessionId, peerHandle, message, messageId, retryCount);
     }
 
     /**
@@ -195,8 +199,6 @@
      * The peer will get a callback indicating a message was received using
      * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
      * byte[])}.
-     * Equivalent to {@link #sendMessage(PeerHandle, int, byte[], int)}
-     * with a {@code retryCount} of 0.
      *
      * @param peerHandle The peer's handle for the message. Must be a result of an
      * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle,
@@ -234,20 +236,20 @@
         if (mTerminated) {
             Log.w(TAG, "startRanging: called on terminated session");
             return;
-        } else {
-            WifiAwareManager mgr = mMgr.get();
-            if (mgr == null) {
-                Log.w(TAG, "startRanging: called post GC on WifiAwareManager");
-                return;
-            }
-
-            mgr.startRanging(mClientId, mSessionId, params, listener);
         }
+
+        WifiAwareManager mgr = mMgr.get();
+        if (mgr == null) {
+            Log.w(TAG, "startRanging: called post GC on WifiAwareManager");
+            return;
+        }
+
+        mgr.startRanging(mClientId, mSessionId, params, listener);
     }
 
     /**
-     * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} for a
-     * WiFi Aware connection to the specified peer. The
+     * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} for an
+     * unencrypted WiFi Aware connection (link) to the specified peer. The
      * {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
      * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
      * <p>
@@ -255,48 +257,193 @@
      * discovery or communication (in such scenarios the MAC address of the peer is shielded by
      * an opaque peer ID handle). If a Aware connection is needed to a peer discovered using other
      * OOB (out-of-band) mechanism then use the alternative
-     * {@link WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])} method - which uses the
+     * {@link WifiAwareSession#createNetworkSpecifierOpen(int, byte[])} method - which uses the
      * peer's MAC address.
      * <p>
      * Note: per the Wi-Fi Aware specification the roles are fixed - a Subscriber is an INITIATOR
      * and a Publisher is a RESPONDER.
+     * <p>
+     * To set up an encrypted link use the {@link #createNetworkSpecifierPmk(PeerHandle, byte[])}
+     * or {@link #createNetworkSpecifierPassphrase(PeerHandle, String)} APIs.
+     *
+     * @param peerHandle The peer's handle obtained through
+     * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, byte[], java.util.List)}
+     *                   or
+     *                   {@link DiscoverySessionCallback#onMessageReceived(PeerHandle, byte[])}.
+     *                   On a RESPONDER this value is used to gate the acceptance of a connection
+     *                   request from only that peer. A RESPONDER may specify a null - indicating
+     *                   that it will accept connection requests from any device.
+     *
+     * @return A string to be used to construct
+     * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
+     * {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
+     * android.net.ConnectivityManager.NetworkCallback)}
+     * [or other varieties of that API].
+     *
+     * @hide
+     */
+    public String createNetworkSpecifierOpen(@Nullable PeerHandle peerHandle) {
+        if (mTerminated) {
+            Log.w(TAG, "createNetworkSpecifierOpen: called on terminated session");
+            return null;
+        }
+
+        WifiAwareManager mgr = mMgr.get();
+        if (mgr == null) {
+            Log.w(TAG, "createNetworkSpecifierOpen: called post GC on WifiAwareManager");
+            return null;
+        }
+
+        int role = this instanceof SubscribeDiscoverySession
+                ? WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
+                : WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER;
+
+        return mgr.createNetworkSpecifier(mClientId, role, mSessionId, peerHandle, null, null);
+    }
+
+    /**
+     * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} for an
+     * encrypted WiFi Aware connection (link) to the specified peer. The
+     * {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
+     * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
+     * <p>
+     * This method should be used when setting up a connection with a peer discovered through Aware
+     * discovery or communication (in such scenarios the MAC address of the peer is shielded by
+     * an opaque peer ID handle). If a Aware connection is needed to a peer discovered using other
+     * OOB (out-of-band) mechanism then use the alternative
+     * {@link WifiAwareSession#createNetworkSpecifierPassphrase(int, byte[], String)} method -
+     * which uses the peer's MAC address.
+     * <p>
+     * Note: per the Wi-Fi Aware specification the roles are fixed - a Subscriber is an INITIATOR
+     * and a Publisher is a RESPONDER.
      *
      * @param peerHandle The peer's handle obtained through
      * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle,
      * byte[], java.util.List)} or
      * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
      * byte[])}. On a RESPONDER this value is used to gate the acceptance of a connection request
-     *                   from only that peer. A RESPONDER may specified a null - indicating that
+     *                   from only that peer. A RESPONDER may specify a null - indicating that
      *                   it will accept connection requests from any device.
-     * @param token An arbitrary token (message) to be used to match connection initiation request
-     *              to a responder setup. A RESPONDER is set up with a {@code token} which must
-     *              be matched by the token provided by the INITIATOR. A null token is permitted
-     *              on the RESPONDER and matches any peer token. An empty ({@code ""}) token is
-     *              not the same as a null token and requires the peer token to be empty as well.
+     * @param passphrase The passphrase to be used to encrypt the link. The PMK is generated from
+     *                   the passphrase. Use the
+     *                   {@link #createNetworkSpecifierPmk(PeerHandle, byte[])} to specify the
+     *                   PMK directly or {@link #createNetworkSpecifierOpen(PeerHandle)} to
+     *                   specify an open (unencrypted) link.
      *
      * @return A string to be used to construct
      * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
      * {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
      * android.net.ConnectivityManager.NetworkCallback)}
      * [or other varieties of that API].
+     *
+     * * @hide
      */
-    public String createNetworkSpecifier(@Nullable PeerHandle peerHandle,
-            @Nullable byte[] token) {
-        if (mTerminated) {
-            Log.w(TAG, "createNetworkSpecifier: called on terminated session");
-            return null;
-        } else {
-            WifiAwareManager mgr = mMgr.get();
-            if (mgr == null) {
-                Log.w(TAG, "createNetworkSpecifier: called post GC on WifiAwareManager");
-                return null;
-            }
-
-            int role = this instanceof SubscribeDiscoverySession
-                    ? WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
-                    : WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER;
-
-            return mgr.createNetworkSpecifier(mClientId, role, mSessionId, peerHandle, token);
+    public String createNetworkSpecifierPassphrase(@Nullable PeerHandle peerHandle,
+            @NonNull String passphrase) {
+        if (passphrase == null || passphrase.length() == 0) {
+            throw new IllegalArgumentException("Passphrase must not be null or empty");
         }
+
+        if (mTerminated) {
+            Log.w(TAG, "createNetworkSpecifierPassphrase: called on terminated session");
+            return null;
+        }
+
+        WifiAwareManager mgr = mMgr.get();
+        if (mgr == null) {
+            Log.w(TAG, "createNetworkSpecifierPassphrase: called post GC on WifiAwareManager");
+            return null;
+        }
+
+        int role = this instanceof SubscribeDiscoverySession
+                ? WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
+                : WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER;
+
+        return mgr.createNetworkSpecifier(mClientId, role, mSessionId, peerHandle, null,
+                passphrase);
+    }
+
+    /**
+     * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} for an
+     * encrypted WiFi Aware connection (link) to the specified peer. The
+     * {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
+     * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
+     * <p>
+     * This method should be used when setting up a connection with a peer discovered through Aware
+     * discovery or communication (in such scenarios the MAC address of the peer is shielded by
+     * an opaque peer ID handle). If a Aware connection is needed to a peer discovered using other
+     * OOB (out-of-band) mechanism then use the alternative
+     * {@link WifiAwareSession#createNetworkSpecifierPmk(int, byte[], byte[])} method - which uses
+     * the peer's MAC address.
+     * <p>
+     * Note: per the Wi-Fi Aware specification the roles are fixed - a Subscriber is an INITIATOR
+     * and a Publisher is a RESPONDER.
+     *
+     * @param peerHandle The peer's handle obtained through
+     * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle,
+     * byte[], java.util.List)} or
+     * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
+     * byte[])}. On a RESPONDER this value is used to gate the acceptance of a connection request
+     *                   from only that peer. A RESPONDER may specify a null - indicating that
+     *                   it will accept connection requests from any device.
+     * @param pmk A PMK (pairwise master key, see IEEE 802.11i) specifying the key to use for
+     *            encrypting the data-path. Use the
+     *            {@link #createNetworkSpecifierPassphrase(PeerHandle, String)} to specify a
+     *            Passphrase or {@link #createNetworkSpecifierOpen(PeerHandle)} to specify an
+     *            open (unencrypted) link.
+     *
+     * @return A string to be used to construct
+     * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
+     * {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
+     * android.net.ConnectivityManager.NetworkCallback)}
+     * [or other varieties of that API].
+     *
+     * @hide
+     */
+    public String createNetworkSpecifierPmk(@Nullable PeerHandle peerHandle,
+            @NonNull byte[] pmk) {
+        if (pmk == null || pmk.length == 0) {
+            throw new IllegalArgumentException("PMK must not be null or empty");
+        }
+
+        if (mTerminated) {
+            Log.w(TAG, "createNetworkSpecifierPmk: called on terminated session");
+            return null;
+        }
+
+        WifiAwareManager mgr = mMgr.get();
+        if (mgr == null) {
+            Log.w(TAG, "createNetworkSpecifierPmk: called post GC on WifiAwareManager");
+            return null;
+        }
+
+        int role = this instanceof SubscribeDiscoverySession
+                ? WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
+                : WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER;
+
+        return mgr.createNetworkSpecifier(mClientId, role, mSessionId, peerHandle, pmk, null);
+    }
+
+    /**
+     * Place-holder for {@code createNetworkSpecifierOpen(PeerHandle)}. Present to enable
+     * development of replacements CL without causing an API change. Will be removed when new
+     * APIs are exposed.
+     *
+     * @param peerHandle The peer's handle obtained through
+     * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle,
+     * byte[], java.util.List)} or
+     * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
+     * byte[])}. On a RESPONDER this value is used to gate the acceptance of a connection request
+     *                   from only that peer. A RESPONDER may specify a null - indicating that
+     *                   it will accept connection requests from any device.
+     * @param token Deprecated and ignored.
+     * @return A string to be used to construct
+     * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
+     * {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
+     * android.net.ConnectivityManager.NetworkCallback)}
+     * [or other varieties of that API].
+     */
+    public String createNetworkSpecifier(@Nullable PeerHandle peerHandle, @Nullable byte[] token) {
+        return createNetworkSpecifierOpen(peerHandle);
     }
 }
diff --git a/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
index 33da182..9645b1d 100644
--- a/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
+++ b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
@@ -124,10 +124,9 @@
     }
 
     /**
-     * Called when message transmission fails - when no ACK is received from the peer.
-     * Retries when ACKs are not received are done by hardware, MAC, and in the Aware stack (using
-     * the {@link DiscoverySession#sendMessage(PeerHandle, int,
-     * byte[], int)} method) - this event is received after all retries are exhausted.
+     * Called when message transmission initiated with
+     * {@link DiscoverySession#sendMessage(PeerHandle, int, byte[])} fails. E.g. when no ACK is
+     * received from the peer.
      * <p>
      * Note that either this callback or
      * {@link DiscoverySessionCallback#onMessageSendSucceeded(int)} will be received
@@ -141,9 +140,7 @@
 
     /**
      * Called when a message is received from a discovery session peer - in response to the
-     * peer's {@link DiscoverySession#sendMessage(PeerHandle, int,
-     * byte[])} or {@link DiscoverySession#sendMessage(PeerHandle,
-     * int, byte[], int)}.
+     * peer's {@link DiscoverySession#sendMessage(PeerHandle, int, byte[])}.
      *
      * @param peerHandle An opaque handle to the peer matching our discovery operation.
      * @param message A byte array containing the message.
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
index 0eb6a3d..7b6805c 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
@@ -130,55 +130,34 @@
      */
 
     /**
-     * TYPE_1A: role, client_id, session_id, peer_id, token
+     * TYPE: in band, specific peer: role, client_id, session_id, peer_id, pmk/passphrase optional
      * @hide
      */
-    public static final int NETWORK_SPECIFIER_TYPE_1A = 0;
+    public static final int NETWORK_SPECIFIER_TYPE_IB = 0;
 
     /**
-     * TYPE_1B: role, client_id, session_id, peer_id [only permitted for RESPONDER]
+     * TYPE: in band, any peer: role, client_id, session_id, pmk/passphrase optional
+     * [only permitted for RESPONDER]
      * @hide
      */
-    public static final int NETWORK_SPECIFIER_TYPE_1B = 1;
+    public static final int NETWORK_SPECIFIER_TYPE_IB_ANY_PEER = 1;
 
     /**
-     * TYPE_1C: role, client_id, session_id, token [only permitted for RESPONDER]
+     * TYPE: out-of-band: role, client_id, peer_mac, pmk/passphrase optional
      * @hide
      */
-    public static final int NETWORK_SPECIFIER_TYPE_1C = 2;
+    public static final int NETWORK_SPECIFIER_TYPE_OOB = 2;
 
     /**
-     * TYPE_1C: role, client_id, session_id [only permitted for RESPONDER]
+     * TYPE: out-of-band, any peer: role, client_id, pmk/passphrase optional
+     * [only permitted for RESPONDER]
      * @hide
      */
-    public static final int NETWORK_SPECIFIER_TYPE_1D = 3;
+    public static final int NETWORK_SPECIFIER_TYPE_OOB_ANY_PEER = 3;
 
-    /**
-     * TYPE_2A: role, client_id, peer_mac, token
-     * @hide
-     */
-    public static final int NETWORK_SPECIFIER_TYPE_2A = 4;
-
-    /**
-     * TYPE_2B: role, client_id, peer_mac [only permitted for RESPONDER]
-     * @hide
-     */
-    public static final int NETWORK_SPECIFIER_TYPE_2B = 5;
-
-    /**
-     * TYPE_2C: role, client_id, token [only permitted for RESPONDER]
-     * @hide
-     */
-    public static final int NETWORK_SPECIFIER_TYPE_2C = 6;
-
-    /**
-     * TYPE_2D: role, client_id [only permitted for RESPONDER]
-     * @hide
-     */
-    public static final int NETWORK_SPECIFIER_TYPE_2D = 7;
 
     /** @hide */
-    public static final int NETWORK_SPECIFIER_TYPE_MAX_VALID = NETWORK_SPECIFIER_TYPE_2D;
+    public static final int NETWORK_SPECIFIER_TYPE_MAX_VALID = NETWORK_SPECIFIER_TYPE_OOB_ANY_PEER;
 
     /** @hide */
     public static final String NETWORK_SPECIFIER_KEY_TYPE = "type";
@@ -199,7 +178,10 @@
     public static final String NETWORK_SPECIFIER_KEY_PEER_MAC = "peer_mac";
 
     /** @hide */
-    public static final String NETWORK_SPECIFIER_KEY_TOKEN = "token";
+    public static final String NETWORK_SPECIFIER_KEY_PMK = "pmk";
+
+    /** @hide */
+    public static final String NETWORK_SPECIFIER_KEY_PASSPHRASE = "passphrase";
 
     /**
      * Broadcast intent action to indicate that the state of Wi-Fi Aware availability has changed.
@@ -494,23 +476,16 @@
 
     /** @hide */
     public String createNetworkSpecifier(int clientId, int role, int sessionId,
-            PeerHandle peerHandle, byte[] token) {
+            PeerHandle peerHandle, @Nullable byte[] pmk, @Nullable String passphrase) {
         if (VDBG) {
             Log.v(TAG, "createNetworkSpecifier: role=" + role + ", sessionId=" + sessionId
                     + ", peerHandle=" + ((peerHandle == null) ? peerHandle : peerHandle.peerId)
-                    + ", token=" + token);
+                    + ", pmk=" + ((pmk == null) ? "null" : "non-null")
+                    + ", passphrase=" + ((passphrase == null) ? "null" : "non-null"));
         }
 
-        int type;
-        if (token != null && peerHandle != null) {
-            type = NETWORK_SPECIFIER_TYPE_1A;
-        } else if (token == null && peerHandle != null) {
-            type = NETWORK_SPECIFIER_TYPE_1B;
-        } else if (token != null && peerHandle == null) {
-            type = NETWORK_SPECIFIER_TYPE_1C;
-        } else {
-            type = NETWORK_SPECIFIER_TYPE_1D;
-        }
+        int type = (peerHandle == null) ? NETWORK_SPECIFIER_TYPE_IB_ANY_PEER
+                : NETWORK_SPECIFIER_TYPE_IB;
 
         if (role != WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
                 && role != WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) {
@@ -519,10 +494,6 @@
                             + "specifier");
         }
         if (role == WIFI_AWARE_DATA_PATH_ROLE_INITIATOR) {
-            if (token == null) {
-                throw new IllegalArgumentException(
-                        "createNetworkSpecifier: Invalid null token - not permitted on INITIATOR");
-            }
             if (peerHandle == null) {
                 throw new IllegalArgumentException(
                         "createNetworkSpecifier: Invalid peer handle (value of null) - not "
@@ -540,10 +511,16 @@
             if (peerHandle != null) {
                 json.put(NETWORK_SPECIFIER_KEY_PEER_ID, peerHandle.peerId);
             }
-            if (token != null) {
-                json.put(NETWORK_SPECIFIER_KEY_TOKEN,
-                        Base64.encodeToString(token, 0, token.length, Base64.DEFAULT));
+            if (pmk == null) {
+                pmk = new byte[0];
             }
+            json.put(NETWORK_SPECIFIER_KEY_PMK,
+                    Base64.encodeToString(pmk, 0, pmk.length, Base64.DEFAULT));
+            if (passphrase == null) {
+                passphrase = new String();
+            }
+            json.put(NETWORK_SPECIFIER_KEY_PASSPHRASE, passphrase);
+
         } catch (JSONException e) {
             return "";
         }
@@ -553,21 +530,15 @@
 
     /** @hide */
     public String createNetworkSpecifier(int clientId, @DataPathRole int role,
-            @Nullable byte[] peer, @Nullable byte[] token) {
+            @Nullable byte[] peer, @Nullable byte[] pmk, @Nullable String passphrase) {
         if (VDBG) {
-            Log.v(TAG, "createNetworkSpecifier: role=" + role + ", token=" + token);
+            Log.v(TAG, "createNetworkSpecifier: role=" + role
+                    + ", pmk=" + ((pmk == null) ? "null" : "non-null")
+                    + ", passphrase=" + ((passphrase == null) ? "null" : "non-null"));
         }
 
-        int type;
-        if (token != null && peer != null) {
-            type = NETWORK_SPECIFIER_TYPE_2A;
-        } else if (token == null && peer != null) {
-            type = NETWORK_SPECIFIER_TYPE_2B;
-        } else if (token != null && peer == null) {
-            type = NETWORK_SPECIFIER_TYPE_2C;
-        } else { // both are null
-            type = NETWORK_SPECIFIER_TYPE_2D;
-        }
+        int type = (peer == null) ?
+                NETWORK_SPECIFIER_TYPE_OOB_ANY_PEER : NETWORK_SPECIFIER_TYPE_OOB;
 
         if (role != WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
                 && role != WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) {
@@ -576,19 +547,13 @@
                             + "specifier");
         }
         if (role == WIFI_AWARE_DATA_PATH_ROLE_INITIATOR) {
-            if (peer == null || peer.length != 6) {
-                throw new IllegalArgumentException(
-                        "createNetworkSpecifier: Invalid peer MAC address");
+            if (peer == null) {
+                throw new IllegalArgumentException("createNetworkSpecifier: Invalid peer MAC "
+                        + "address - null not permitted on INITIATOR");
             }
-            if (token == null) {
-                throw new IllegalArgumentException(
-                        "createNetworkSpecifier: Invalid null token - not permitted on INITIATOR");
-            }
-        } else {
-            if (peer != null && peer.length != 6) {
-                throw new IllegalArgumentException(
-                        "createNetworkSpecifier: Invalid peer MAC address");
-            }
+        }
+        if (peer != null && peer.length != 6) {
+            throw new IllegalArgumentException("createNetworkSpecifier: Invalid peer MAC address");
         }
 
         JSONObject json;
@@ -600,10 +565,15 @@
             if (peer != null) {
                 json.put(NETWORK_SPECIFIER_KEY_PEER_MAC, new String(HexEncoding.encode(peer)));
             }
-            if (token != null) {
-                json.put(NETWORK_SPECIFIER_KEY_TOKEN,
-                        Base64.encodeToString(token, 0, token.length, Base64.DEFAULT));
+            if (pmk == null) {
+                pmk = new byte[0];
             }
+            json.put(NETWORK_SPECIFIER_KEY_PMK,
+                    Base64.encodeToString(pmk, 0, pmk.length, Base64.DEFAULT));
+            if (passphrase == null) {
+                passphrase = new String();
+            }
+            json.put(NETWORK_SPECIFIER_KEY_PASSPHRASE, passphrase);
         } catch (JSONException e) {
             return "";
         }
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareSession.java b/wifi/java/android/net/wifi/aware/WifiAwareSession.java
index 8696920..f48f641 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareSession.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareSession.java
@@ -183,47 +183,168 @@
     }
 
     /**
-     * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} for a
-     * WiFi Aware connection to the specified peer. The
+     * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} for an
+     * unencrypted WiFi Aware connection (link) to the specified peer. The
      * {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
      * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
      * <p>
      *     This API is targeted for applications which can obtain the peer MAC address using OOB
      *     (out-of-band) discovery. Aware discovery does not provide the MAC address of the peer -
      *     when using Aware discovery use the alternative network specifier method -
-     *     {@link DiscoverySession#createNetworkSpecifier(PeerHandle,
-     *     byte[])}.
+     *     {@link DiscoverySession#createNetworkSpecifierOpen(PeerHandle)}.
+     * <p>
+     * To set up an encrypted link use the {@link #createNetworkSpecifierPmk(int, byte[], byte[])}
+     * or {@link #createNetworkSpecifierPassphrase(int, byte[], String)} APIs.
      *
      * @param role  The role of this device:
      *              {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_INITIATOR} or
      *              {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_RESPONDER}
      * @param peer  The MAC address of the peer's Aware discovery interface. On a RESPONDER this
      *              value is used to gate the acceptance of a connection request from only that
-     *              peer. A RESPONDER may specified a null - indicating that it will accept
+     *              peer. A RESPONDER may specify a null - indicating that it will accept
      *              connection requests from any device.
-     * @param token An arbitrary token (message) to be used to match connection initiation request
-     *              to a responder setup. A RESPONDER is set up with a {@code token} which must
-     *              be matched by the token provided by the INITIATOR. A null token is permitted
-     *              on the RESPONDER and matches any peer token. An empty ({@code ""}) token is
-     *              not the same as a null token and requires the peer token to be empty as well.
      *
      * @return A string to be used to construct
      * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
      * {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
      * android.net.ConnectivityManager.NetworkCallback)}
      * [or other varieties of that API].
+     *
+     * @hide
+     */
+    public String createNetworkSpecifierOpen(@WifiAwareManager.DataPathRole int role,
+            @Nullable byte[] peer) {
+        WifiAwareManager mgr = mMgr.get();
+        if (mgr == null) {
+            Log.e(TAG, "createNetworkSpecifierOpen: called post GC on WifiAwareManager");
+            return "";
+        }
+        if (mTerminated) {
+            Log.e(TAG, "createNetworkSpecifierOpen: called after termination");
+            return "";
+        }
+        return mgr.createNetworkSpecifier(mClientId, role, peer, null, null);
+    }
+
+    /**
+     * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} for an
+     * encrypted WiFi Aware connection (link) to the specified peer. The
+     * {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
+     * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
+     * <p>
+     *     This API is targeted for applications which can obtain the peer MAC address using OOB
+     *     (out-of-band) discovery. Aware discovery does not provide the MAC address of the peer -
+     *     when using Aware discovery use the alternative network specifier method -
+     *     {@link DiscoverySession#createNetworkSpecifierPassphrase(PeerHandle, String)}.
+     *
+     * @param role  The role of this device:
+     *              {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_INITIATOR} or
+     *              {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_RESPONDER}
+     * @param peer  The MAC address of the peer's Aware discovery interface. On a RESPONDER this
+     *              value is used to gate the acceptance of a connection request from only that
+     *              peer. A RESPONDER may specify a null - indicating that it will accept
+     *              connection requests from any device.
+     * @param passphrase The passphrase to be used to encrypt the link. The PMK is generated from
+     *                   the passphrase. Use the
+     *                   {@link #createNetworkSpecifierPmk(int, byte[], byte[])} to specify the
+     *                   PMK directly or {@link #createNetworkSpecifierOpen(int, byte[])} to
+     *                   specify an open (unencrypted) link.
+     *
+     * @return A string to be used to construct
+     * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
+     * {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
+     * android.net.ConnectivityManager.NetworkCallback)}
+     * [or other varieties of that API].
+     *
+     * @hide
+     */
+    public String createNetworkSpecifierPassphrase(@WifiAwareManager.DataPathRole int role,
+            @Nullable byte[] peer, @NonNull String passphrase) {
+        WifiAwareManager mgr = mMgr.get();
+        if (mgr == null) {
+            Log.e(TAG, "createNetworkSpecifierPassphrase: called post GC on WifiAwareManager");
+            return "";
+        }
+        if (mTerminated) {
+            Log.e(TAG, "createNetworkSpecifierPassphrase: called after termination");
+            return "";
+        }
+        if (passphrase == null || passphrase.length() == 0) {
+            throw new IllegalArgumentException("Passphrase must not be null or empty");
+        }
+        return mgr.createNetworkSpecifier(mClientId, role, peer, null, passphrase);
+    }
+
+    /**
+     * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} for an
+     * encrypted WiFi Aware connection (link) to the specified peer. The
+     * {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
+     * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
+     * <p>
+     *     This API is targeted for applications which can obtain the peer MAC address using OOB
+     *     (out-of-band) discovery. Aware discovery does not provide the MAC address of the peer -
+     *     when using Aware discovery use the alternative network specifier method -
+     *     {@link DiscoverySession#createNetworkSpecifierPassphrase(PeerHandle, String)}.
+     *
+     * @param role  The role of this device:
+     *              {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_INITIATOR} or
+     *              {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_RESPONDER}
+     * @param peer  The MAC address of the peer's Aware discovery interface. On a RESPONDER this
+     *              value is used to gate the acceptance of a connection request from only that
+     *              peer. A RESPONDER may specify a null - indicating that it will accept
+     *              connection requests from any device.
+     * @param pmk A PMK (pairwise master key, see IEEE 802.11i) specifying the key to use for
+     *            encrypting the data-path. Use the
+     *            {@link #createNetworkSpecifierPassphrase(int, byte[], String)} to specify a
+     *            Passphrase or {@link #createNetworkSpecifierOpen(int, byte[])} to specify an
+     *            open (unencrypted) link.
+     *
+     * @return A string to be used to construct
+     * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
+     * {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
+     * android.net.ConnectivityManager.NetworkCallback)}
+     * [or other varieties of that API].
+     *
+     * @hide
+     */
+    public String createNetworkSpecifierPmk(@WifiAwareManager.DataPathRole int role,
+            @Nullable byte[] peer, @NonNull byte[] pmk) {
+        WifiAwareManager mgr = mMgr.get();
+        if (mgr == null) {
+            Log.e(TAG, "createNetworkSpecifierPmk: called post GC on WifiAwareManager");
+            return "";
+        }
+        if (mTerminated) {
+            Log.e(TAG, "createNetworkSpecifierPmk: called after termination");
+            return "";
+        }
+        if (pmk == null || pmk.length == 0) {
+            throw new IllegalArgumentException("PMK must not be null or empty");
+        }
+        return mgr.createNetworkSpecifier(mClientId, role, peer, pmk, null);
+    }
+
+    /**
+     * Place-holder for {@code #createNetworkSpecifierOpen(int, byte[])}. Present to enable
+     * development of replacements CL without causing an API change. Will be removed when new
+     * APIs are exposed.
+     *
+     * @param role  The role of this device:
+     *              {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_INITIATOR} or
+     *              {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_RESPONDER}
+     * @param peer  The MAC address of the peer's Aware discovery interface. On a RESPONDER this
+     *              value is used to gate the acceptance of a connection request from only that
+     *              peer. A RESPONDER may specify a null - indicating that it will accept
+     *              connection requests from any device.
+     * @param token Deprecated and ignored.
+     * @return A string to be used to construct
+     * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
+     * {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
+     * android.net.ConnectivityManager.NetworkCallback)}
+     * [or other varieties of that API].
      */
     public String createNetworkSpecifier(@WifiAwareManager.DataPathRole int role,
             @Nullable byte[] peer, @Nullable byte[] token) {
-        WifiAwareManager mgr = mMgr.get();
-        if (mgr == null) {
-            Log.e(TAG, "createNetworkSpecifier: called post GC on WifiAwareManager");
-            return "";
-        }
-        if (mTerminated) {
-            Log.e(TAG, "createNetworkSpecifier: called after termination");
-            return "";
-        }
-        return mgr.createNetworkSpecifier(mClientId, role, peer, token);
+        return createNetworkSpecifierOpen(role, peer);
     }
 }
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
index 620759d..2388841 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
@@ -122,12 +122,22 @@
         private static final int MAX_PASSWORD_BYTES = 255;
 
         /**
+         * Supported authentication methods.
+         * @hide
+         */
+        public static final String AUTH_METHOD_PAP = "PAP";
+        /** @hide */
+        public static final String AUTH_METHOD_MSCHAP = "MS-CHAP";
+        /** @hide */
+        public static final String AUTH_METHOD_MSCHAPV2 = "MS-CHAP-V2";
+
+        /**
          * Supported Non-EAP inner methods.  Refer to
          * Credential/UsernamePassword/EAPMethod/InnerEAPType in Hotspot 2.0 Release 2 Technical
          * Specification Section 9.1 for more info.
          */
-        private static final Set<String> SUPPORTED_AUTH =
-                new HashSet<String>(Arrays.asList("PAP", "CHAP", "MS-CHAP", "MS-CHAP-V2"));
+        private static final Set<String> SUPPORTED_AUTH = new HashSet<String>(
+                Arrays.asList(AUTH_METHOD_PAP, AUTH_METHOD_MSCHAP, AUTH_METHOD_MSCHAPV2));
 
         /**
          * Username of the credential.
@@ -348,8 +358,9 @@
     public static final class CertificateCredential implements Parcelable {
         /**
          * Supported certificate types.
+         * @hide
          */
-        private static final String CERT_TYPE_X509V3 = "x509v3";
+        public static final String CERT_TYPE_X509V3 = "x509v3";
 
         /**
          * Certificate SHA-256 fingerprint length.
diff --git a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
index 5f949747..632cfaf 100644
--- a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
@@ -20,6 +20,7 @@
 import static org.junit.Assert.assertEquals;
 
 import android.os.Parcel;
+import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -66,4 +67,35 @@
 
         assertArrayEquals(bytes, rebytes);
     }
+
+    @Test
+    public void testNetworkSelectionStatusCopy() {
+        NetworkSelectionStatus networkSelectionStatus = new NetworkSelectionStatus();
+        networkSelectionStatus.setNotRecommended(true);
+
+        NetworkSelectionStatus copy = new NetworkSelectionStatus();
+        copy.copy(networkSelectionStatus);
+
+        assertEquals(networkSelectionStatus.isNotRecommended(), copy.isNotRecommended());
+    }
+
+    @Test
+    public void testNetworkSelectionStatusParcel() {
+        NetworkSelectionStatus networkSelectionStatus = new NetworkSelectionStatus();
+        networkSelectionStatus.setNotRecommended(true);
+
+        Parcel parcelW = Parcel.obtain();
+        networkSelectionStatus.writeToParcel(parcelW);
+        byte[] bytes = parcelW.marshall();
+        parcelW.recycle();
+
+        Parcel parcelR = Parcel.obtain();
+        parcelR.unmarshall(bytes, 0, bytes.length);
+        parcelR.setDataPosition(0);
+
+        NetworkSelectionStatus copy = new NetworkSelectionStatus();
+        copy.readFromParcel(parcelR);
+
+        assertEquals(networkSelectionStatus.isNotRecommended(), copy.isNotRecommended());
+    }
 }
diff --git a/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java b/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java
index c4d2d32..d0aedba 100644
--- a/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java
@@ -89,11 +89,29 @@
     @Test
     public void testSetClientKeyEntryWithNull() {
         mEnterpriseConfig.setClientKeyEntry(null, null);
-        assertEquals(null, mEnterpriseConfig.getClientCertificateChain());
-        assertEquals(null, mEnterpriseConfig.getClientCertificate());
+        assertNull(mEnterpriseConfig.getClientCertificateChain());
+        assertNull(mEnterpriseConfig.getClientCertificate());
         mEnterpriseConfig.setClientKeyEntryWithCertificateChain(null, null);
-        assertEquals(null, mEnterpriseConfig.getClientCertificateChain());
-        assertEquals(null, mEnterpriseConfig.getClientCertificate());
+        assertNull(mEnterpriseConfig.getClientCertificateChain());
+        assertNull(mEnterpriseConfig.getClientCertificate());
+
+        // Setting the client certificate to null should clear the existing chain.
+        PrivateKey clientKey = FakeKeys.RSA_KEY1;
+        X509Certificate clientCert0 = FakeKeys.CLIENT_CERT;
+        X509Certificate clientCert1 = FakeKeys.CA_CERT1;
+        mEnterpriseConfig.setClientKeyEntry(clientKey, clientCert0);
+        assertNotNull(mEnterpriseConfig.getClientCertificate());
+        mEnterpriseConfig.setClientKeyEntry(null, null);
+        assertNull(mEnterpriseConfig.getClientCertificate());
+        assertNull(mEnterpriseConfig.getClientCertificateChain());
+
+        // Setting the chain to null should clear the existing chain.
+        X509Certificate[] clientChain = new X509Certificate[] {clientCert0, clientCert1};
+        mEnterpriseConfig.setClientKeyEntryWithCertificateChain(clientKey, clientChain);
+        assertNotNull(mEnterpriseConfig.getClientCertificateChain());
+        mEnterpriseConfig.setClientKeyEntryWithCertificateChain(null, null);
+        assertNull(mEnterpriseConfig.getClientCertificate());
+        assertNull(mEnterpriseConfig.getClientCertificateChain());
     }
 
     @Test
diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
index 7f68f6f..eceb365 100644
--- a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
@@ -973,11 +973,12 @@
         final int sessionId = 123;
         final PeerHandle peerHandle = new PeerHandle(123412);
         final int role = WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER;
-        final String token = "Some arbitrary token string - can really be anything";
+        final byte[] pmk = "Some arbitrary byte array".getBytes();
+        final String passphrase = "A really bad password";
         final ConfigRequest configRequest = new ConfigRequest.Builder().build();
         final PublishConfig publishConfig = new PublishConfig.Builder().build();
 
-        String tokenB64 = Base64.encodeToString(token.getBytes(), Base64.DEFAULT);
+        String pmkB64 = Base64.encodeToString(pmk, Base64.DEFAULT);
 
         ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(
                 WifiAwareSession.class);
@@ -1008,9 +1009,8 @@
         mMockLooper.dispatchAll();
         inOrder.verify(mockSessionCallback).onPublishStarted(publishSession.capture());
 
-        // (3) request a network specifier from the session
-        String networkSpecifier = publishSession.getValue().createNetworkSpecifier(peerHandle,
-                token.getBytes());
+        // (3) request an open (unencrypted) network specifier from the session
+        String networkSpecifier = publishSession.getValue().createNetworkSpecifierOpen(peerHandle);
 
         // validate format
         JSONObject jsonObject = new JSONObject(networkSpecifier);
@@ -1022,8 +1022,39 @@
                 equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_SESSION_ID)));
         collector.checkThat("peer_id", peerHandle.peerId,
                 equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_ID)));
-        collector.checkThat("token", tokenB64,
-                equalTo(jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_TOKEN)));
+
+        // (4) request an encrypted (PMK) network specifier from the session
+        networkSpecifier = publishSession.getValue().createNetworkSpecifierPmk(peerHandle, pmk);
+
+        // validate format
+        jsonObject = new JSONObject(networkSpecifier);
+        collector.checkThat("role", role,
+                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE)));
+        collector.checkThat("client_id", clientId,
+                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID)));
+        collector.checkThat("session_id", sessionId,
+                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_SESSION_ID)));
+        collector.checkThat("peer_id", peerHandle.peerId,
+                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_ID)));
+        collector.checkThat("pmk", pmkB64 ,
+                equalTo(jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PMK)));
+
+        // (5) request an encrypted (Passphrase) network specifier from the session
+        networkSpecifier = publishSession.getValue().createNetworkSpecifierPassphrase(peerHandle,
+                passphrase);
+
+        // validate format
+        jsonObject = new JSONObject(networkSpecifier);
+        collector.checkThat("role", role,
+                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE)));
+        collector.checkThat("client_id", clientId,
+                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID)));
+        collector.checkThat("session_id", sessionId,
+                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_SESSION_ID)));
+        collector.checkThat("peer_id", peerHandle.peerId,
+                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_ID)));
+        collector.checkThat("passphrase", passphrase,
+                equalTo(jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PASSPHRASE)));
 
         verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService,
                 mockPublishSession, mockRttListener);
@@ -1039,9 +1070,10 @@
         final ConfigRequest configRequest = new ConfigRequest.Builder().build();
         final byte[] someMac = HexEncoding.decode("000102030405".toCharArray(), false);
         final int role = WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR;
-        final String token = "Some arbitrary token string - can really be anything";
+        final byte[] pmk = "Some arbitrary pmk data".getBytes();
+        final String passphrase = "A really bad password";
 
-        String tokenB64 = Base64.encodeToString(token.getBytes(), Base64.DEFAULT);
+        String pmkB64 = Base64.encodeToString(pmk, Base64.DEFAULT);
 
         ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(
                 WifiAwareSession.class);
@@ -1060,10 +1092,10 @@
         inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
         WifiAwareSession session = sessionCaptor.getValue();
 
-        /* (2) request a direct network specifier*/
-        String networkSpecifier = session.createNetworkSpecifier(role, someMac, token.getBytes());
+        // (2) request an open (unencrypted) direct network specifier
+        String networkSpecifier = session.createNetworkSpecifierOpen(role, someMac);
 
-        /* validate format*/
+        // validate format
         JSONObject jsonObject = new JSONObject(networkSpecifier);
         collector.checkThat("role", role,
                 equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE)));
@@ -1072,8 +1104,36 @@
         collector.checkThat("peer_mac", someMac, equalTo(HexEncoding.decode(
                 jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_MAC).toCharArray(),
                 false)));
-        collector.checkThat("token", tokenB64,
-                equalTo(jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_TOKEN)));
+
+        // (3) request an encrypted (PMK) direct network specifier
+        networkSpecifier = session.createNetworkSpecifierPmk(role, someMac, pmk);
+
+        // validate format
+        jsonObject = new JSONObject(networkSpecifier);
+        collector.checkThat("role", role,
+                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE)));
+        collector.checkThat("client_id", clientId,
+                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID)));
+        collector.checkThat("peer_mac", someMac, equalTo(HexEncoding.decode(
+                jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_MAC).toCharArray(),
+                false)));
+        collector.checkThat("pmk", pmkB64,
+                equalTo(jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PMK)));
+
+        // (4) request an encrypted (Passphrase) direct network specifier
+        networkSpecifier = session.createNetworkSpecifierPassphrase(role, someMac, passphrase);
+
+        // validate format
+        jsonObject = new JSONObject(networkSpecifier);
+        collector.checkThat("role", role,
+                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE)));
+        collector.checkThat("client_id", clientId,
+                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID)));
+        collector.checkThat("peer_mac", someMac, equalTo(HexEncoding.decode(
+                jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_MAC).toCharArray(),
+                false)));
+        collector.checkThat("passphrase", passphrase,
+                equalTo(jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PASSPHRASE)));
 
         verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService,
                 mockPublishSession, mockRttListener);